lib/pa/dir.rb in pa-1.0.3 vs lib/pa/dir.rb in pa-1.1.3

- old
+ new

@@ -8,188 +8,228 @@ === Example tmp/ filea dira/fileb - ls("tmp") => ["filea", "dira"] - ls_r("tmp") => ["filea", "dira", "dira/fileb"] - ls_r("tmp"){|pa, rel| rel.count('/')==1} => ["dira/fileb"] + ls2("tmp") => ["filea", "dira"] + ls2_r("tmp") => ["filea", "dira", "dira/fileb"] + ls2_r("tmp"){|path, rel| rel.count('/')==1} => ["dira/fileb"] each("tmp") => Enumerate<Pa> each("tmp") {|pa| Pa.rm pa if pa.file?} each("tmp").with_object([]){|pa,m| m<<pa.dir} #=> ["tmp", "tmp/dira"] =end class Pa -module ClassMethods::Dir + module Dir + extend Util::Concern - # path globbing, exclude '.' '..' for :dotmatch - # @note glob is * ** ? [set] {a,b} - # - # @overload glob(*paths, o={}) - # @param [String] path - # @param [Hash] o option - # @option o [Boolean] :dotmatch glob not match dot file by default. - # @option o [Boolean] :pathname wildcard doesn't match / - # @option o [Boolean] :noescape makes '\\' ordinary - # @return [Array<Pa>] - # @overload glob(*paths, o={}) - # @yieldparam [Pa] path - # @return [nil] - def glob(*args, &blk) - paths, o = args.extract_options - paths.map!{|v|get(v)} + module ClassMethods + # path globbing, exclude '.' '..' for :dotmatch + # @note glob is * ** ? [set] {a,b} + # + # @overload glob2(*paths, o={}) + # @param [String] path + # @param [Hash] o option + # @option o [Boolean] :dotmatch glob not match dot file by default. + # @option o [Boolean] :pathname wildcard doesn't match / + # @option o [Boolean] :noescape makes '\\' ordinary + # @return [Array<String>] + # @overload glob2(*paths, o={}) + # @yieldparam [String] path + # @return [nil] + def glob2(*args, &blk) + paths, o = Util.extract_options(args) + paths.map!{|v|get(v)} - flag = 0 - o.each do |option, value| - flag |= File.const_get("FNM_#{option.upcase}") if value - end + flag = 0 + o.each do |option, value| + next if option==:use_pa + flag |= File.const_get("FNM_#{option.upcase}") if value + end - ret = Dir.glob(paths, flag) + ret = ::Dir.glob(paths, flag) - # delete . .. for '.*' - ret.tap{|paths| %w(. ..).each{|v| paths.delete(v)}} - ret.map!{|path|Pa(path)} + # delete . .. for '.*' + %w(. ..).each {|v| ret.delete(v)} + ret = ret.map{|v| Pa(v)} if o[:use_pa] - if blk - ret.each {|pa| - blk.call pa - } - else - ret - end - end + if blk + ret.each {|pa| + blk.call pa + } + else + ret + end + end - # is directory empty? - # - # @param [String] path - # @return [Boolean] - def empty?(path) Dir.entries(get(path)).empty? end + def glob(*args, &blk) + args, o = Util.extract_options(args) + o[:use_pa] = true + glob2(*args, o, &blk) + end - # traverse directory - # @note raise Errno::ENOTDIR, Errno::ENOENT - # - # @example - # each '.' do |pa| - # p pa.path #=> "foo" not "./foo" - # end - # # => '/home' .. - # - # each('.', error: true).with_object([]) do |(pa,err),m| - # ... - # end - # - # @overload each(path=".", o={}) - # @param [String,Pa] path - # @prarm [Hash] o - # @option o [Boolean] :nodot (false) include dot file - # @option o [Boolean] :nobackup (false) include backup file - # @option o [Boolean] :error (false) yield(pa, err) instead of raise Errno::EPERM when Dir.open(dir) - # @return [Enumerator<Pa>] - # @overload each(path=".", o={}) - # @yieldparam [Pa] path - # @return [nil] - def each(*args, &blk) - return Pa.to_enum(:each, *args) unless blk + # is directory empty? + # + # @param [String] path + # @return [Boolean] + def empty?(path) + ::Dir.entries(get(path)).empty? + end - (path,), o = args.extract_options - path = path ? get(path) : "." - raise Errno::ENOENT, "`#{path}' doesn't exists." unless File.exists?(path) - raise Errno::ENOTDIR, "`#{path}' not a directoyr." unless File.directory?(path) + # traverse directory + # @note raise Errno::ENOTDIR, Errno::ENOENT + # + # @example + # each '.' do |pa| + # p pa.path #=> "foo" not "./foo" + # end + # # => '/home' .. + # + # each('.', error: true).with_object([]) do |(pa,err),m| + # ... + # end + # + # @overload each(path=".", o={}) + # @param [String,Pa] path + # @prarm [Hash] o + # @option o [Boolean] :nodot (false) include dot file + # @option o [Boolean] :nobackup (false) include backup file + # @option o [Boolean] :error (false) yield(pa, err) instead of raise Errno::EPERM when Dir.open(dir) + # @return [Enumerator<String>] + # @overload each(path=".", o={}) + # @yieldparam [String] path + # @return [nil] + def each2(*args, &blk) + return Pa.to_enum(:each2, *args) unless blk - begin - dir = Dir.open(path) - rescue Errno::EPERM => err - end - raise err if err and !o[:error] + (path,), o = Util.extract_options(args) + path = path ? get(path) : "." + raise Errno::ENOENT, "`#{path}' doesn't exists." unless File.exists?(path) + raise Errno::ENOTDIR, "`#{path}' not a directoy." unless File.directory?(path) - while (entry=dir.read) - next if %w(. ..).include? entry - next if o[:nodot] and entry=~/^\./ - next if o[:nobackup] and entry=~/~$/ + begin + dir = ::Dir.open(path) + rescue Errno::EPERM => err + end + raise err if err and !o[:error] - # => "foo" not "./foo" - pa = path=="." ? Pa(entry) : Pa(File.join(path, entry)) - if o[:error] - blk.call pa, err - else - blk.call pa - end - end - end + while (entry=dir.read) + next if %w(. ..).include? entry + next if o[:nodot] and entry=~/^\./ + next if o[:nobackup] and entry=~/~$/ - # each with recursive - # @see each - # - # * each_r() skip Exception - # * each_r(){pa, err} - # - # @overload each_r(path=".", o={}) - # @return [Enumerator<Pa>] - # @overload each_r(path=".", o={}) - # @yieldparam [Pa] pa - # @yieldparam [String] relative relative path - # @yieldparam [Errno::ENOENT,Errno::EPERM] err - # @return [nil] - def each_r(*args, &blk) - return Pa.to_enum(:each_r, *args) if not blk + # => "foo" not "./foo" + pa = path=="." ? entry : File.join(path, entry) + pa = Pa(pa) if o[:use_pa] + if o[:error] + blk.call pa, err + else + blk.call pa + end + end + end - (path,), o = args.extract_options - path ||= "." + def each(*args, &blk) + args, o = Util.extract_options(args) + o[:use_pa] = true + each2(*args, o, &blk) + end - _each_r(path, "", o, &blk) - end + # each with recursive + # @see each2 + # + # * each2_r() skip Exception + # * each2_r(){path, relative, err} + # + # @overload each2_r(path=".", o={}) + # @return [Enumerator<String>] + # @overload each2_r(path=".", o={}) + # @yieldparam [String] path + # @yieldparam [String] relative relative path + # @yieldparam [Errno::ENOENT,Errno::EPERM] err + # @return [nil] + def each2_r(*args, &blk) + return Pa.to_enum(:each2_r, *args) if not blk - # @param [String] path - def _each_r path, relative, o, &blk - o.merge!(error: true) - Pa.each(path, o) do |pa1, err| - relative1 = Pa.join(relative, pa1.b) + (path,), o = Util.extract_options(args) + path ||= "." - blk.call pa1, relative1, err + _each2_r(path, "", o, &blk) + end - if pa1.directory? - _each_r(pa1.p, relative1, o, &blk) - end - end - end - private :_each_r + def each_r(*args, &blk) + args, o = Util.extract_options(args) + o[:use_pa] = true + each2_r(*args, o, &blk) + end - # list directory contents - # @see each - # - # block form is a filter. - # - # @Example - # Pa.ls(".") {|pa, fname| pa.directory?} # list only directories - # - # @overload ls(path=".", o={}) - # @return [Array<String>] - # @overload ls(path=".", o={}) - # @yieldparam [Pa] pa - # @yieldparam [String] fname - # @return [Array<String>] - def ls *args, &blk - blk ||= proc {true} - each(*args).with_object([]) { |pa,m| - m<<pa.fname if blk.call(pa, pa.fname) - } - end + # list directory contents + # @see each2 + # + # block form is a filter. + # + # @Example + # Pa.ls2(".") {|path, fname| Pa.directory?(path)} # list only directories + # + # @overload ls2(path=".", o={}) + # @return [Array<String>] + # @overload ls2(path=".", o={}) + # @yieldparam [String] path + # @yieldparam [String] fname + # @return [Array<String>] + def ls2(*args, &blk) + blk ||= proc {true} + each2(*args).with_object([]) { |path,m| + base = File.basename(path) + ret = blk.call(path, base) + m << base if ret + } + end - # ls with recursive - # @see ls - # - # @overload ls_r(path=".", o={}) - # @return [Array<String>] - # @overload ls_r(path=".", o={}) - # @yieldparam [Pa] pa - # @yieldparam [String] rel - # @return [Array<String>] - def ls_r *args, &blk - blk ||= proc {true} - each_r(*args).with_object([]) { |(pa,rel),m| - m<<rel if blk.call(pa, rel) - } - end + def ls(*args, &blk) + args, o = Util.extract_options(args) + o[:use_pa] = true + ls2(*args, o, &blk) + end -end + # ls2 with recursive + # @see ls2 + # + # @overload ls2_r(path=".", o={}) + # @return [Array<String>] + # @overload ls2_r(path=".", o={}) + # @yieldparam [Pa] pa + # @yieldparam [String] rel + # @return [Array<String>] + def ls2_r(*args, &blk) + blk ||= proc {true} + each2_r(*args).with_object([]) { |(path,rel),m| + m<<rel if blk.call(path, rel) + } + end + + def ls_r(*args, &blk) + args, o = Util.extract_options(args) + ls2_r(*args, o, &blk) + end + + private + # @param [String] path + def _each2_r(path, relative, o, &blk) + o.merge!(error: true) + Pa.each2(path, o) do |path1, err| + # fix for File.join with empty string + joins=[ relative=="" ? nil : relative, File.basename(path1)].compact + relative1 = File.join(*joins) + + path1 = Pa(path1) if o[:use_pa] + blk.call path1, relative1, err + + if File.directory?(path1) + _each2_r(path1, relative1, o, &blk) + end + end + end + end + end end