lib/hx.rb in hx-0.7.4 vs lib/hx.rb in hx-0.8.2
- old
+ new
@@ -19,16 +19,16 @@
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-require 'rubygems'
require 'thread'
require 'set'
require 'pathname'
require 'tempfile'
require 'yaml'
+require 'hx/path'
module Hx
VERSION = (Pathname.new(__FILE__).parent.parent + 'VERSION').read.strip
@@ -36,119 +36,105 @@
end
class EditingNotSupportedError < RuntimeError
end
+# minimal complete definition: each_entry_path + get_entry, or each_entry
module Filter
def edit_entry(path, prototype=nil)
raise EditingNotSupportedError, "Editing not supported for #{path}"
end
- def each_entry_path
- each_entry { |path, entry| yield path }
+ def each_entry_path(selector)
+ each_entry(selector) { |path, entry| yield path }
end
- def each_entry
- each_entry_path do |path|
+ def each_entry(selector)
+ each_entry_path(selector) do |path|
begin
entry = get_entry(path)
rescue NoSuchEntryError
next # entries may come and go during the enumeration
end
yield path, entry
end
end
def get_entry(path)
- each_entry do |entry_path, entry|
- return entry if entry_path == path
+ each_entry(Path.literal(path)) do |entry_path, entry|
+ return entry
end
raise NoSuchEntryError, path
end
end
class NullInput
include Filter
- def each_entry
+ def each_entry(selector)
self
end
end
NULL_INPUT = NullInput.new
class PathSubset
include Filter
+ def patterns_to_selector(patterns)
+ patterns.map { |p| Path::parse_pattern(p) }.inject { |a, b| a | b }
+ end
+ private :patterns_to_selector
+
def initialize(input, options)
@input = input
- @path_filter = Predicate.new(options[:only], options[:except])
+ only = patterns_to_selector(Array(options[:only] || []))
+ except = patterns_to_selector(Array(options[:except] || []))
+ except = ~except if except
+ if only and except
+ @selector = only & except
+ else
+ @selector = only || except || Path::ALL
+ end
end
def edit_entry(path, prototype=nil)
- if @path_filter.accept? path
+ if @selector.accept? path
@input.edit_entry(path, prototype) { |text| yield text }
else
raise EditingNotSupportedError, "Editing not supported for #{path}"
end
self
end
- def each_entry_path
- @input.each_entry_path do |path|
- yield path if @path_filter.accept? path
- end
+ def each_entry_path(selector, &block)
+ @input.each_entry_path(@selector & selector, &block)
self
end
+ def each_entry(selector, &block)
+ @input.each_entry(@selector & selector, &block)
+ self
+ end
+
def get_entry(path)
- raise NoSuchEntryError, path unless @path_filter.accept? path
+ raise NoSuchEntryError, path unless @selector.accept? path
@input.get_entry(path)
end
end
-class PathSubset::Predicate
- def initialize(accept, reject)
- @accept_re = patterns_to_re(accept)
- @reject_re = patterns_to_re(reject)
- end
-
- def accept?(path)
- (not @accept_re or path =~ @accept_re) and
- (not @reject_re or path !~ @reject_re)
- end
-
- def patterns_to_re(patterns)
- return nil if patterns.nil? or patterns.empty?
- patterns = Array(patterns)
- Regexp.new("(?:#{patterns.map { |p| pattern_to_re(p) }.join("|")})")
- end
- private :patterns_to_re
-
- def pattern_to_re(pattern)
- "^#{pattern.scan(/(\*\*?|[^*]+)/).map { |s,|
- case s
- when "**"; ".*"
- when "*"; "[^/]*"
- else Regexp.quote(s)
- end
- }}$"
- end
- private :pattern_to_re
-end
-
class Overlay
include Filter
def initialize(*inputs)
@inputs = inputs
end
- def each_entry_path
+ def each_entry_path(selector)
seen = Set[]
@inputs.each do |input|
- input.each_entry_path do |path|
+ input.each_entry_path(selector) do |path|
yield path unless seen.include? path
seen.add path
end
end
self
@@ -195,12 +181,15 @@
raise EditingNotSupportedError, "Editing not supported for #{path}" unless path
@input.edit_entry(path, prototype) { |text| yield text }
self
end
- def each_entry_path
- @input.each_entry_path { |path| yield add_circumfix(path) }
+ def each_entry_path(selector)
+ @input.each_entry_path(Path::ALL) do |path|
+ path = add_circumfix(path)
+ yield path if selector.accept? path
+ end
self
end
def get_entry(path)
path = strip_circumfix(path)
@@ -216,14 +205,14 @@
path = add_circumfix(path)
@input.edit_entry(path, prototype) { |text| yield text }
self
end
- def each_entry_path
- @input.each_entry_path do |path|
+ def each_entry_path(selector)
+ @input.each_entry_path(Path::ALL) do |path|
path = strip_circumfix(path)
- yield path if path
+ yield path if path and selector.accept? path
end
self
end
def get_entry(path)
@@ -244,26 +233,26 @@
def edit_entry(path, prototype=nil)
@input.edit_entry(path, prototype) { |text| yield text }
self
end
- def each_entry
+ def each_entry(selector)
entries = nil
@lock.synchronize do
if @entries
entries = @entries
else
entries = []
- @input.each_entry do |path, entry|
+ @input.each_entry(Path::ALL) do |path, entry|
@entries_by_path[path] = entry
entries << [path, entry]
end
@entries = entries
end
end
entries.each do |path, entry|
- yield path, entry.dup
+ yield path, entry.dup if selector.accept? path
end
self
end
def get_entry(path)
@@ -292,13 +281,13 @@
def edit_entry(path, prototype=nil)
@input.edit_entry(path, prototype) { |text| yield text }
self
end
- def each_entry
+ def each_entry(selector)
entries = []
- @input.each_entry do |path, entry|
+ @input.each_entry(selector) do |path, entry|
entries << [path, entry]
end
unless @key_fields.empty?
entries = entries.sort_by do |path, entry|
@key_fields.map { |f| entry[f] }
@@ -540,11 +529,11 @@
def edit_entry(path, prototype=nil)
@combined_output.edit_entry(path, prototype) { |text| yield text }
self
end
- def each_entry_path
- @combined_output.each_entry_path { |path| yield path }
+ def each_entry_path(selector)
+ @combined_output.each_entry_path(selector) { |path| yield path }
self
end
def get_entry(path)
@combined_output.get_entry(path)