lib/rvc/fs.rb in rvc-1.1.0 vs lib/rvc/fs.rb in rvc-1.2.0
- old
+ new
@@ -50,11 +50,13 @@
end
class FS
attr_reader :root, :loc, :marks
- MARK_REGEX = /^~(?:([\d\w]*|~|@))$/
+ MARK_PATTERN = /^~(?:([\d\w]*|~|@))$/
+ REGEX_PATTERN = /^%/
+ GLOB_PATTERN = /\*/
def initialize root
@root = root
@loc = Location.new root
@marks = {}
@@ -66,58 +68,81 @@
def display_path
@loc.path * '/'
end
- def lookup path
- (lookup_loc(path) || return).obj
- end
-
- def cd path
- new_loc = lookup_loc(path) or return false
+ def cd new_loc
mark '~', @loc
@loc = new_loc
- true
end
+ def lookup path
+ lookup_loc(path).map(&:obj)
+ end
+
def lookup_loc path
els, absolute, trailing_slash = Path.parse path
base_loc = absolute ? Location.new(@root) : @loc
traverse(base_loc, els)
end
- def traverse base_loc, els
- loc = base_loc.dup
- els.each_with_index do |el,i|
- case el
- when '.'
- when '..'
- loc.pop unless loc.obj == @root
- when '...'
- loc.push(el, loc.obj.parent) unless loc.obj == @root
- when MARK_REGEX
- return unless i == 0
- loc = @marks[$1] or return
- loc = loc.dup
+ def traverse_one loc, el, first
+ case el
+ when '.'
+ [loc]
+ when '..'
+ loc.pop unless loc.obj == @root
+ [loc]
+ when '...'
+ loc.push(el, loc.obj.parent) unless loc.obj == @root
+ [loc]
+ when MARK_PATTERN
+ return unless first
+ loc = @marks[$1] or return []
+ [loc.dup]
+ when REGEX_PATTERN
+ regex = Regexp.new($')
+ loc.obj.children.
+ select { |k,v| k =~ regex }.
+ map { |k,v| loc.dup.tap { |x| x.push(k, v) } }
+ when GLOB_PATTERN
+ regex = glob_to_regex el
+ loc.obj.children.
+ select { |k,v| k =~ regex }.
+ map { |k,v| loc.dup.tap { |x| x.push(k, v) } }
+ else
+ # XXX check for ambiguous child
+ if first and el =~ /^\d+$/ and @marks.member? el
+ loc = @marks[el].dup
else
- # XXX check for ambiguous child
- if i == 0 and el =~ /^\d+$/ and @marks.member? el
- loc = @marks[el].dup
- else
- x = loc.obj.traverse_one(el) or return
- loc.push el, x
- end
+ x = loc.obj.traverse_one(el) or return []
+ loc.push el, x
end
+ [loc]
end
- loc
end
+ # Starting from base_loc, traverse each path element in els. Since the path
+ # may contain wildcards, this function returns a list of matches.
+ def traverse base_loc, els
+ locs = [base_loc.dup]
+ els.each_with_index do |el,i|
+ locs.map! { |loc| traverse_one loc, el, i==0 }
+ locs.flatten!
+ end
+ locs
+ end
+
def mark key, loc
if loc == nil
@marks.delete key
else
@marks[key] = loc
end
+ end
+
+ def glob_to_regex str
+ Regexp.new "^#{Regexp.escape(str.gsub('*', "\0")).gsub("\0", ".*")}$"
end
end
end