tagen 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +36 -1
- data/Rakefile +8 -1
- data/TODO +1 -0
- data/lib/tagen/audioinfo.rb +1 -0
- data/lib/tagen/cairo.rb +2 -0
- data/lib/tagen/core.rb +2 -0
- data/lib/tagen/core/array.rb +58 -0
- data/lib/tagen/core/enumerable.rb +20 -0
- data/lib/tagen/core/enumerator.rb +29 -0
- data/lib/tagen/core/module.rb +5 -4
- data/lib/tagen/core/pa.rb +53 -75
- data/lib/tagen/core/pa/cmd.rb +59 -52
- data/lib/tagen/core/pa/dir.rb +41 -20
- data/lib/tagen/core/pa/path.rb +132 -31
- data/lib/tagen/core/pa/state.rb +17 -6
- data/lib/tagen/core/string/pyformat.rb +2 -2
- data/lib/tagen/erb.rb +35 -0
- data/lib/tagen/magick.rb +1 -0
- data/lib/tagen/ncurses.rb +1 -0
- data/lib/tagen/pathname.rb +1 -0
- data/lib/tagen/poppler.rb +1 -0
- data/lib/tagen/socket.rb +2 -0
- data/lib/tagen/tree.rb +2 -0
- data/lib/tagen/xmpp4r.rb +1 -0
- data/lib/tagen/yaml.rb +36 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/tagen/core/array_spec.rb +37 -0
- data/spec/tagen/core/enumerator_spec.rb +21 -0
- data/spec/tagen/core/pa/cmd_spec.rb +17 -14
- data/spec/tagen/core/pa/dir_spec.rb +20 -5
- data/spec/tagen/core/pa/path_spec.rb +117 -0
- data/spec/tagen/core/pa/state_spec.rb +7 -0
- data/spec/tagen/erb_spec.rb +19 -0
- data/spec/tagen/yaml_spec.rb +32 -0
- data/version.rb +1 -1
- metadata +13 -2
    
        data/README.md
    CHANGED
    
    | @@ -32,7 +32,42 @@ use extra extension | |
| 32 32 | 
             
            	require "pathname"
         | 
| 33 33 | 
             
            	require "tagen/pathname"
         | 
| 34 34 |  | 
| 35 | 
            -
             | 
| 35 | 
            +
            or
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            	require "tagen/pathname" # auto require "pathname"
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            this will add #path method to Pathname, see API doc.
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            An Introduction to Pa 
         | 
| 42 | 
            +
            ---------------------
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            	require "tagen/core"
         | 
| 45 | 
            +
            	pa = Pa('/home/foo')
         | 
| 46 | 
            +
            	pa.exists? #=> false
         | 
| 47 | 
            +
            	pa.dir #=> '/home'
         | 
| 48 | 
            +
            	pa.base #=> 'foo'
         | 
| 49 | 
            +
            	pa.join('a.ogg') #=> '/home/a.ogg'
         | 
| 50 | 
            +
            	pa.join(a.ogg).exists? #=> true.
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            	Pa.exists?('/home/foo') # alternate way
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            which rspec
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            	Pa('/home/foo').should be_exists
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            more see API doc
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            An Introduction to PyFormat
         | 
| 61 | 
            +
            ---------------------------
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            	require "tagen/core"
         | 
| 64 | 
            +
            	"I like %{fruit} and %{sport}".format('apple', 'football') 
         | 
| 65 | 
            +
            	"I like %{fruit} and %{sport}".format(apple: 'apple', footbal: 'football') 
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            	"it costs %{howmatch:.2f} dollars".format(1.123) #=> "it costs 1.12 dollars"
         | 
| 68 | 
            +
            	
         | 
| 69 | 
            +
            more see API doc
         | 
| 70 | 
            +
             | 
| 36 71 |  | 
| 37 72 | 
             
            Documentation
         | 
| 38 73 | 
             
            -------------
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -6,11 +6,18 @@ task :release do | |
| 6 6 | 
             
            	sh "rm *.gem"
         | 
| 7 7 | 
             
            end
         | 
| 8 8 |  | 
| 9 | 
            -
            desc " | 
| 9 | 
            +
            desc "autotest with watchr"
         | 
| 10 10 | 
             
            task :test do
         | 
| 11 11 | 
             
            	sh "watchr tagen.watchr"
         | 
| 12 12 | 
             
            end
         | 
| 13 13 |  | 
| 14 | 
            +
            namespace :test do
         | 
| 15 | 
            +
            	desc "testing the whole library"
         | 
| 16 | 
            +
            	task :all do
         | 
| 17 | 
            +
            		sh "rspec --color spec"
         | 
| 18 | 
            +
            	end
         | 
| 19 | 
            +
            end
         | 
| 20 | 
            +
             | 
| 14 21 | 
             
            def sh cmd
         | 
| 15 22 | 
             
            	puts cmd
         | 
| 16 23 | 
             
            	system cmd
         | 
    
        data/lib/tagen/audioinfo.rb
    CHANGED
    
    
    
        data/lib/tagen/cairo.rb
    CHANGED
    
    
    
        data/lib/tagen/core.rb
    CHANGED
    
    
    
        data/lib/tagen/core/array.rb
    CHANGED
    
    | @@ -38,4 +38,62 @@ class Array | |
| 38 38 | 
             
            		end
         | 
| 39 39 | 
             
            		indexs.length==1 ? values[0] : values
         | 
| 40 40 | 
             
            	end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
             | 
| 43 | 
            +
            	# first n values, not works at Range, Range don't have #replace method
         | 
| 44 | 
            +
            	# @note modify IN PLACE
         | 
| 45 | 
            +
            	#
         | 
| 46 | 
            +
            	# @example
         | 
| 47 | 
            +
            	#   a = %w(1 2 3)
         | 
| 48 | 
            +
            	#   a.first!(2)  #=> [1, 2]
         | 
| 49 | 
            +
            	#   a            #=> [3]
         | 
| 50 | 
            +
            	#   @return Array
         | 
| 51 | 
            +
            	def first! n=1
         | 
| 52 | 
            +
            		i = 0 
         | 
| 53 | 
            +
            		j = i + n
         | 
| 54 | 
            +
            		k = -1
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            		ret = self[i...j]
         | 
| 57 | 
            +
            		self.replace self[j..k]
         | 
| 58 | 
            +
            		ret
         | 
| 59 | 
            +
            	end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            	# last n values
         | 
| 62 | 
            +
            	# @see first!
         | 
| 63 | 
            +
            	def last! n=1
         | 
| 64 | 
            +
            		i = -1 
         | 
| 65 | 
            +
            		j = -1 - n + 1
         | 
| 66 | 
            +
            		k = 0
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            		ret = self[j..i]
         | 
| 69 | 
            +
            		self.replace self[k...j]
         | 
| 70 | 
            +
            		ret
         | 
| 71 | 
            +
            	end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
             | 
| 74 | 
            +
             | 
| 75 | 
            +
            	# same as find, but delete the finded value 
         | 
| 76 | 
            +
            	def find! &blk
         | 
| 77 | 
            +
            		idx = self.find_index(&blk)
         | 
| 78 | 
            +
            		if idx
         | 
| 79 | 
            +
            			self.delete_at(idx)
         | 
| 80 | 
            +
            		else
         | 
| 81 | 
            +
            			nil
         | 
| 82 | 
            +
            		end
         | 
| 83 | 
            +
            	end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            	# same as find_all, but delete all finded values
         | 
| 86 | 
            +
            	def find_all! &blk
         | 
| 87 | 
            +
            		ret, rest = [], []
         | 
| 88 | 
            +
            		self.each do |k|
         | 
| 89 | 
            +
            			if blk.call(k)
         | 
| 90 | 
            +
            				ret << k
         | 
| 91 | 
            +
            			else
         | 
| 92 | 
            +
            				rest << k
         | 
| 93 | 
            +
            			end
         | 
| 94 | 
            +
            		end
         | 
| 95 | 
            +
            		self.replace rest
         | 
| 96 | 
            +
            		ret
         | 
| 97 | 
            +
            	end
         | 
| 98 | 
            +
             | 
| 41 99 | 
             
            end # class Array
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            =begin
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            == enumerate it
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * collect{k,v}  Array#map!
         | 
| 6 | 
            +
            * each_cons(n),{}=>nil each_slice
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            == retrive value
         | 
| 9 | 
            +
            * [slice]
         | 
| 10 | 
            +
            * first/last(),(n)   Array#first!
         | 
| 11 | 
            +
            * find{} find_index(v),{} find_all Array#find! Array#find_all!
         | 
| 12 | 
            +
            * grep(obj),{=>v} 
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            * Array#delete(v) delete_at(i) clear()
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            =end
         | 
| 17 | 
            +
            module Enumerable
         | 
| 18 | 
            +
             | 
| 19 | 
            +
             | 
| 20 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            class Enumerator
         | 
| 2 | 
            +
            	# combine with_index and with_object
         | 
| 3 | 
            +
            	# @see with_index, with_object
         | 
| 4 | 
            +
            	#
         | 
| 5 | 
            +
            	# @example
         | 
| 6 | 
            +
            	#   (1..7).each.with_iobject([]){|(*args), idx, memo|}
         | 
| 7 | 
            +
            	#   (1..7).each.with_iobject(2, []){|(*args), idx, memo|} # offset is 2
         | 
| 8 | 
            +
            	#
         | 
| 9 | 
            +
            	# @overload with_iobject(*args)
         | 
| 10 | 
            +
            	#   @param [Fixnum,Object] *args pass Fixnum as offset, otherwise as memo_obj
         | 
| 11 | 
            +
            	#   @return Enumerator
         | 
| 12 | 
            +
            	#
         | 
| 13 | 
            +
            	# @overload with_iobject(*args)
         | 
| 14 | 
            +
            	#   @yieldparam [Object] (*args)
         | 
| 15 | 
            +
            	#   @yieldparam [Fixnum] idx index
         | 
| 16 | 
            +
            	#   @yieldparam [Object] memo_obj 
         | 
| 17 | 
            +
            	def with_iobject *args, &blk
         | 
| 18 | 
            +
            		return self.to_enum(:with_iobject, *args) unless blk
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            		offset = args.find!{|v| Fixnum===v} || 0
         | 
| 21 | 
            +
            		raise ArgumentError "must provide memo_obj" if args.empty?
         | 
| 22 | 
            +
            		memo = args[0]
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            		i = offset-1
         | 
| 25 | 
            +
            		self.with_object memo do |args, m|
         | 
| 26 | 
            +
            			blk.call args,i+=1,m
         | 
| 27 | 
            +
            		end
         | 
| 28 | 
            +
            	end
         | 
| 29 | 
            +
            end
         | 
    
        data/lib/tagen/core/module.rb
    CHANGED
    
    | @@ -2,20 +2,21 @@ class Module | |
| 2 2 |  | 
| 3 3 | 
             
            	alias :original_append_features :append_features
         | 
| 4 4 |  | 
| 5 | 
            -
            	# after include module, convert methods in | 
| 5 | 
            +
            	# after include module, convert methods in ClassMethods to class methods. a very clean design.
         | 
| 6 6 | 
             
            	# @see ruby-core Module#append_features
         | 
| 7 7 | 
             
            	#
         | 
| 8 8 | 
             
            	# @example
         | 
| 9 9 | 
             
            	#   module Guten
         | 
| 10 10 | 
             
            	#   	module ClassMethods
         | 
| 11 | 
            -
            	#   		def foo; end | 
| 11 | 
            +
            	#   		def foo; end      # this is class method.
         | 
| 12 12 | 
             
            	#   	end
         | 
| 13 | 
            +
            	#
         | 
| 14 | 
            +
            	#    def bar; end # this is instance method. 
         | 
| 13 15 | 
             
            	#	  end
         | 
| 14 16 | 
             
            	#  
         | 
| 15 17 | 
             
            	#   class Tag
         | 
| 16 | 
            -
            	#   	include Guten
         | 
| 18 | 
            +
            	#   	include Guten  # will auto Tag.extend(Guten::Classmethods)
         | 
| 17 19 | 
             
            	#	  end
         | 
| 18 | 
            -
            	#	  Tag.foo
         | 
| 19 20 | 
             
            	#
         | 
| 20 21 | 
             
            	def append_features base
         | 
| 21 22 | 
             
            		original_append_features base
         | 
    
        data/lib/tagen/core/pa.rb
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            =begin
         | 
| 1 | 
            +
            =begin rdoc
         | 
| 2 2 | 
             
            Pa(Path) is similary to Pathname, but more powerful.
         | 
| 3 3 | 
             
            it combines fileutils, tmpdir, find, tempfile, File, Dir, Pathname
         | 
| 4 4 |  | 
| @@ -53,58 +53,37 @@ Example3: | |
| 53 53 | 
             
              name      n      filename of a path
         | 
| 54 54 | 
             
              ext       e      extname of a path,  return "" or "ogg"  
         | 
| 55 55 | 
             
              fext      fe     return "" or ".ogg"
         | 
| 56 | 
            -
            =end
         | 
| 57 56 |  | 
| 57 | 
            +
            == used with rspec
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            	File.exists?(path).should be_true
         | 
| 60 | 
            +
            	Pa(path).should be_exists
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            =end
         | 
| 58 63 | 
             
            class Pa 
         | 
| 59 64 | 
             
            	Error = Class.new Exception
         | 
| 60 65 | 
             
            	EUnkonwType = Class.new Error
         | 
| 61 66 |  | 
| 62 | 
            -
            	 | 
| 63 | 
            -
             | 
| 64 | 
            -
            	 | 
| 65 | 
            -
            	alias a absolute
         | 
| 66 | 
            -
            	alias d dir
         | 
| 67 | 
            -
            	alias	b base
         | 
| 68 | 
            -
            	alias n name
         | 
| 69 | 
            -
            	alias e ext
         | 
| 70 | 
            -
            	alias fe fext
         | 
| 71 | 
            -
             | 
| 72 | 
            -
            	# @param [String,Pa,Pathname] path
         | 
| 73 | 
            -
            	# @api also used by replace
         | 
| 67 | 
            +
            	attr_reader :path
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            	# @param [String,#path] path
         | 
| 74 70 | 
             
            	def initialize path
         | 
| 75 | 
            -
            		@path =  | 
| 76 | 
            -
             | 
| 77 | 
            -
            				path.to_s
         | 
| 78 | 
            -
            			when "Pa"
         | 
| 79 | 
            -
            				path.path
         | 
| 80 | 
            -
            			when "String"
         | 
| 81 | 
            -
            				path
         | 
| 82 | 
            -
            			else
         | 
| 83 | 
            -
            				raise ArgumentError, path.inspect
         | 
| 84 | 
            -
            			end
         | 
| 85 | 
            -
            		@absolute = Pa.absolute(@path) 
         | 
| 86 | 
            -
            		@dir = Pa.dirname(@path)
         | 
| 87 | 
            -
            		@base = Pa.basename(@path) 
         | 
| 88 | 
            -
            		@name, @ext = Pa.basename(@path, ext: true)
         | 
| 89 | 
            -
            		@fext = @ext.empty? ? "" : "."+@ext
         | 
| 71 | 
            +
            		@path = path.respond_to?(:path) ? path.path : path
         | 
| 72 | 
            +
            		initialize_variables
         | 
| 90 73 | 
             
            	end
         | 
| 91 74 |  | 
| 92 | 
            -
            	 | 
| 93 | 
            -
             | 
| 94 | 
            -
            	def replace path
         | 
| 95 | 
            -
            		initialize path
         | 
| 75 | 
            +
            	chainable = Module.new do
         | 
| 76 | 
            +
            		def initialize_variables; end
         | 
| 96 77 | 
             
            	end
         | 
| 78 | 
            +
            	include chainable
         | 
| 97 79 |  | 
| 98 | 
            -
            	 | 
| 99 | 
            -
             | 
| 100 | 
            -
            	# @ | 
| 101 | 
            -
            	# | 
| 102 | 
            -
            	 | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
            	# @return [Pa]
         | 
| 106 | 
            -
            	def + str
         | 
| 107 | 
            -
            		Pa(@path+str)
         | 
| 80 | 
            +
            	alias p path
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            	# @param [String,#path]
         | 
| 83 | 
            +
            	# @return [Pa] the same Pa object
         | 
| 84 | 
            +
            	def replace path
         | 
| 85 | 
            +
            		@path = path.respond_to?(:path) ? path.path : path
         | 
| 86 | 
            +
            		initialize_variables
         | 
| 108 87 | 
             
            	end
         | 
| 109 88 |  | 
| 110 89 | 
             
            	# return '#<Pa @path="foo", @absolute="/home/foo">'
         | 
| @@ -112,7 +91,7 @@ class Pa | |
| 112 91 | 
             
            	# @return [String]
         | 
| 113 92 | 
             
            	def inspect
         | 
| 114 93 | 
             
            		ret="#<" + self.class.to_s + " "
         | 
| 115 | 
            -
            		ret += "@path=\"#{ | 
| 94 | 
            +
            		ret += "@path=\"#{path}\", @absolute=\"#{absolute}\""
         | 
| 116 95 | 
             
            		ret += " >"
         | 
| 117 96 | 
             
            		ret
         | 
| 118 97 | 
             
            	end
         | 
| @@ -124,53 +103,52 @@ class Pa | |
| 124 103 | 
             
            		@path
         | 
| 125 104 | 
             
            	end
         | 
| 126 105 |  | 
| 127 | 
            -
            	#  | 
| 128 | 
            -
            	 | 
| 129 | 
            -
             | 
| 130 | 
            -
            	# return [Pa]
         | 
| 131 | 
            -
            	def join(*names)
         | 
| 132 | 
            -
            		Pa(Pa.join(@path, *names))
         | 
| 133 | 
            -
            	end
         | 
| 106 | 
            +
            	# missing method goes to Pa.class-method 
         | 
| 107 | 
            +
            	def method_missing(name, *args, &blk)
         | 
| 108 | 
            +
            		ret = self.class.__send__(name, path, *args, &blk)
         | 
| 134 109 |  | 
| 135 | 
            -
            	 | 
| 136 | 
            -
            	# 
         | 
| 137 | 
            -
            	# return [Pa] 
         | 
| 138 | 
            -
            	def parent
         | 
| 139 | 
            -
            		Pa(Pa.join(@path, '..'))
         | 
| 140 | 
            -
            	end
         | 
| 110 | 
            +
            		case ret	
         | 
| 141 111 |  | 
| 112 | 
            +
            		# e.g. readlink ..
         | 
| 113 | 
            +
            		when String
         | 
| 114 | 
            +
            			Pa(ret)
         | 
| 115 | 
            +
             | 
| 116 | 
            +
            		# e.g. directory? 
         | 
| 117 | 
            +
            		else
         | 
| 118 | 
            +
            			ret
         | 
| 119 | 
            +
            		end
         | 
| 142 120 |  | 
| 143 | 
            -
            	# missing method goes to Pa.class-method 
         | 
| 144 | 
            -
            	# return@ [Pa,..] return Pa for some methods.
         | 
| 145 | 
            -
            	def method_missing(name, *args, &blk)
         | 
| 146 | 
            -
            		ret = self.class.__send__(name, *args, @path, &blk)
         | 
| 147 | 
            -
            		[ :readlink ]
         | 
| 148 | 
            -
            			.include?(name) ? Pa(ret) : ret
         | 
| 149 121 | 
             
            	end
         | 
| 150 | 
            -
            end
         | 
| 151 122 |  | 
| 152 123 |  | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
            require_relative "pa/dir"
         | 
| 156 | 
            -
            require_relative "pa/state"
         | 
| 124 | 
            +
            end
         | 
| 125 | 
            +
             | 
| 157 126 | 
             
            class Pa
         | 
| 158 | 
            -
             | 
| 127 | 
            +
            module ClassMethods
         | 
| 128 | 
            +
            	UNDEFS = [:open, :fstat]
         | 
| 159 129 |  | 
| 160 130 | 
             
            	# missing method goes to File class method
         | 
| 161 131 | 
             
            	def method_missing name, *args, &blk
         | 
| 162 | 
            -
            		 | 
| 132 | 
            +
            		raise NoMethodError, name.inspect if UNDEFS.include?(name)
         | 
| 133 | 
            +
            		return if args.size>1 
         | 
| 163 134 | 
             
            		File.__send__ name, get(args[0]), &blk
         | 
| 164 135 | 
             
            	end
         | 
| 165 | 
            -
             | 
| 166 136 | 
             
            end
         | 
| 167 137 | 
             
            end
         | 
| 168 138 |  | 
| 139 | 
            +
            require_relative "pa/path"
         | 
| 140 | 
            +
            require_relative "pa/cmd"
         | 
| 141 | 
            +
            require_relative "pa/dir"
         | 
| 142 | 
            +
            require_relative "pa/state"
         | 
| 169 143 | 
             
            class Pa
         | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 144 | 
            +
              extend ClassMethods
         | 
| 145 | 
            +
              extend ClassMethods::Path
         | 
| 146 | 
            +
              extend ClassMethods::Dir
         | 
| 147 | 
            +
              extend ClassMethods::State
         | 
| 148 | 
            +
              extend ClassMethods::Cmd
         | 
| 149 | 
            +
             | 
| 150 | 
            +
              include Path
         | 
| 151 | 
            +
              include State
         | 
| 174 152 | 
             
            end
         | 
| 175 153 |  | 
| 176 154 | 
             
            module Kernel
         | 
    
        data/lib/tagen/core/pa/cmd.rb
    CHANGED
    
    | @@ -9,7 +9,7 @@ rm family | |
| 9 9 | 
             
              rmdir path #  it's clear: remove a directory
         | 
| 10 10 | 
             
            =end
         | 
| 11 11 | 
             
            class Pa
         | 
| 12 | 
            -
            module Cmd
         | 
| 12 | 
            +
            module ClassMethods::Cmd
         | 
| 13 13 |  | 
| 14 14 | 
             
            	# chroot
         | 
| 15 15 | 
             
            	# @see {Dir.chroot}
         | 
| @@ -39,14 +39,12 @@ module Cmd | |
| 39 39 | 
             
            	def _touch(paths, o)
         | 
| 40 40 | 
             
            		o[:mode] ||= 0644
         | 
| 41 41 | 
             
            		paths.map!{|v|get(v)}
         | 
| 42 | 
            -
            		paths.each {| | 
| 43 | 
            -
            			if exists?( | 
| 44 | 
            -
            				o[:force] ? next : raise(Errno::EEXIST, "File exist -- #{ | 
| 42 | 
            +
            		paths.each {|path|
         | 
| 43 | 
            +
            			if File.exists?(path) 
         | 
| 44 | 
            +
            				o[:force] ? next : raise(Errno::EEXIST, "File exist -- #{path}")
         | 
| 45 45 | 
             
            			end
         | 
| 46 46 |  | 
| 47 | 
            -
            			if o[:mkdir]
         | 
| 48 | 
            -
            				mkdir(dirname(p))
         | 
| 49 | 
            -
            			end
         | 
| 47 | 
            +
            			mkdir(File.dirname(p)) if o[:mkdir]
         | 
| 50 48 |  | 
| 51 49 | 
             
            			if win32?
         | 
| 52 50 | 
             
            				# win32 BUG. must f.write("") then file can be deleted.
         | 
| @@ -137,9 +135,9 @@ module Cmd | |
| 137 135 | 
             
            		collision = 0
         | 
| 138 136 | 
             
            		path = "#{o[:dir]}/#{o[:prefix]}#{$$}-#{(Time.time*100_000).to_i.to_s(36)}"
         | 
| 139 137 | 
             
            		orgi_path = path.dup
         | 
| 140 | 
            -
            		while exists?(path)
         | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 138 | 
            +
            		while File.exists?(path)
         | 
| 139 | 
            +
            			path = orgi_path+ collision.to_s
         | 
| 140 | 
            +
            			collision +=1
         | 
| 143 141 | 
             
            		end
         | 
| 144 142 | 
             
            		path << o[:suffix]
         | 
| 145 143 |  | 
| @@ -153,7 +151,7 @@ module Cmd | |
| 153 151 | 
             
            	# @return [nil]
         | 
| 154 152 | 
             
            	def rm(*paths) 
         | 
| 155 153 | 
             
            		glob(*paths) { |pa|
         | 
| 156 | 
            -
            			next if not  | 
| 154 | 
            +
            			next if not File.exists?(pa.p)
         | 
| 157 155 | 
             
            			File.delete(pa.p)
         | 
| 158 156 | 
             
            		}
         | 
| 159 157 | 
             
            	end
         | 
| @@ -164,7 +162,7 @@ module Cmd | |
| 164 162 | 
             
            	# @return [nil]
         | 
| 165 163 | 
             
            	def rmdir *paths
         | 
| 166 164 | 
             
            		glob(*paths) { |pa|
         | 
| 167 | 
            -
            			raise Errno::ENOTDIR, "-- #{pa}" if not  | 
| 165 | 
            +
            			raise Errno::ENOTDIR, "-- #{pa}" if not File.directory?(pa.p)
         | 
| 168 166 | 
             
            			_rmdir(pa)
         | 
| 169 167 | 
             
            		}
         | 
| 170 168 | 
             
            	end
         | 
| @@ -175,8 +173,8 @@ module Cmd | |
| 175 173 | 
             
            	# @return [nil]
         | 
| 176 174 | 
             
            	def rm_r(*paths)
         | 
| 177 175 | 
             
            		glob(*paths){ |pa|
         | 
| 178 | 
            -
            			next if not  | 
| 179 | 
            -
            			 | 
| 176 | 
            +
            			next if not File.exists?(pa.p)
         | 
| 177 | 
            +
            			File.directory?(pa.p)  ? _rmdir(pa) : File.delete(pa.p)
         | 
| 180 178 | 
             
            		}
         | 
| 181 179 | 
             
            	end
         | 
| 182 180 |  | 
| @@ -201,11 +199,11 @@ module Cmd | |
| 201 199 | 
             
            	# I'm recusive 
         | 
| 202 200 | 
             
            	# param@ [Pa] path
         | 
| 203 201 | 
             
            	def _rmdir(pa, o={})
         | 
| 204 | 
            -
            		return if not  | 
| 202 | 
            +
            		return if not File.exists?(pa.p)
         | 
| 205 203 | 
             
            		pa.each {|pa1|
         | 
| 206 | 
            -
            			 | 
| 204 | 
            +
            			File.directory?(pa1.p) ? _rmdir(pa1, o) : File.delete(pa1.p)
         | 
| 207 205 | 
             
            		}
         | 
| 208 | 
            -
            		 | 
| 206 | 
            +
            		File.directory?(pa.p) ? Dir.rmdir(pa.p) : File.delete(pa.p)
         | 
| 209 207 | 
             
            	end
         | 
| 210 208 | 
             
            	private :_rmdir
         | 
| 211 209 |  | 
| @@ -233,25 +231,26 @@ module Cmd | |
| 233 231 | 
             
            	#   @option o [Boolean] :verbose puts cmd when execute
         | 
| 234 232 | 
             
            	#   @option o [Boolean] :folsymlink follow symlink
         | 
| 235 233 | 
             
            	#   @option o [Boolean] :overwrite overwrite dest file if dest is a file
         | 
| 234 | 
            +
            	#   @option o [Boolean] :special special copy, when cp a directory, only mkdir, not cp the directory's content, usefull in Pa.each_r
         | 
| 236 235 | 
             
            	#   @return [nil]
         | 
| 237 236 | 
             
            	# @overload cp(src_s, dest, o)
         | 
| 238 237 | 
             
            	#   @yield [src,dest,o]
         | 
| 239 238 | 
             
            	#   @return [nil]
         | 
| 240 239 | 
             
            	def cp(src_s, dest, o={}, &blk)
         | 
| 241 | 
            -
            		srcs = glob(*Array.wrap(src_s))
         | 
| 242 | 
            -
            		dest = Pa(dest)
         | 
| 240 | 
            +
            		srcs = glob(*Array.wrap(src_s)).map{|v| v.path}
         | 
| 241 | 
            +
            		dest = Pa.get(dest)
         | 
| 243 242 |  | 
| 244 | 
            -
            		if o[:mkdir] and (not  | 
| 245 | 
            -
            			mkdir dest
         | 
| 243 | 
            +
            		if o[:mkdir] and (not File.exists?(dest))
         | 
| 244 | 
            +
            			Pa.mkdir dest
         | 
| 246 245 | 
             
            		end
         | 
| 247 246 |  | 
| 248 247 | 
             
            		# cp file1 file2 .. dir
         | 
| 249 | 
            -
            		if srcs.size>1 and (not  | 
| 248 | 
            +
            		if srcs.size>1 and (not File.directory?(dest))
         | 
| 250 249 | 
             
            			raise Errno::ENOTDIR, "dest not a directory when cp more than one src -- #{dest}"  
         | 
| 251 250 | 
             
            		end
         | 
| 252 251 |  | 
| 253 252 | 
             
            		srcs.each do |src|
         | 
| 254 | 
            -
            			dest1 =  | 
| 253 | 
            +
            			dest1 = File.directory?(dest) ? File.join(dest, File.basename(src)) : dest
         | 
| 255 254 |  | 
| 256 255 | 
             
            			if blk
         | 
| 257 256 | 
             
            				blk.call src, dest1, o, proc{_copy(src, dest1, o)}
         | 
| @@ -265,41 +264,49 @@ module Cmd | |
| 265 264 |  | 
| 266 265 | 
             
            	# I'm recursive 
         | 
| 267 266 | 
             
            	#
         | 
| 268 | 
            -
            	# @param [ | 
| 269 | 
            -
            	# @param [ | 
| 267 | 
            +
            	# @param [String] src
         | 
| 268 | 
            +
            	# @param [String] dest
         | 
| 270 269 | 
             
            	def _copy(src, dest, o={})  
         | 
| 271 | 
            -
            		raise Errno::EEXIST, "dest exists -- #{dest}" if  | 
| 270 | 
            +
            		raise Errno::EEXIST, "dest exists -- #{dest}" if File.exists?(dest) and (not o[:overwrite])
         | 
| 271 | 
            +
             | 
| 272 | 
            +
             | 
| 273 | 
            +
            		case type=File.ftype(src)
         | 
| 272 274 |  | 
| 273 | 
            -
            		case type=src.type
         | 
| 274 275 | 
             
            		when "file", "socket"
         | 
| 275 276 | 
             
            			puts "cp #{src} #{dest}" if o[:verbose]
         | 
| 276 | 
            -
            			File.copy_stream(src | 
| 277 | 
            +
            			File.copy_stream(src, dest)
         | 
| 278 | 
            +
             | 
| 277 279 | 
             
            		when "directory"
         | 
| 278 280 | 
             
            			begin
         | 
| 279 | 
            -
            				mkdir dest
         | 
| 281 | 
            +
            				Pa.mkdir dest
         | 
| 280 282 | 
             
            				puts "mkdir #{dest}" if o[:verbose]
         | 
| 281 283 | 
             
            			rescue Errno::EEXIST
         | 
| 282 284 | 
             
            			end
         | 
| 285 | 
            +
             | 
| 286 | 
            +
            			return if o[:special]
         | 
| 287 | 
            +
             | 
| 283 288 | 
             
            			each(src) { |pa|
         | 
| 284 | 
            -
            				_copy(pa,  | 
| 289 | 
            +
            				_copy(pa.p, File.join(dest, File.basename(pa.p)), o)
         | 
| 285 290 | 
             
            			}
         | 
| 286 | 
            -
             | 
| 291 | 
            +
             | 
| 292 | 
            +
            		when "link" # symbol link
         | 
| 287 293 | 
             
            			if o[:folsymlink] 
         | 
| 288 | 
            -
            				_copy( | 
| 294 | 
            +
            				_copy(Pa.readlink(src), dest) 
         | 
| 289 295 | 
             
            			else
         | 
| 290 | 
            -
            				symln( | 
| 296 | 
            +
            				Pa.symln(Pa.readlink(src), dest, force: true)	
         | 
| 291 297 | 
             
            				puts "symlink #{src} #{dest}" if o[:verbose]
         | 
| 292 298 | 
             
            			end
         | 
| 299 | 
            +
             | 
| 293 300 | 
             
            		when "unknow"
         | 
| 294 301 | 
             
            			raise EUnKnownType, "Can't handle unknow type(#{:type}) -- #{src}"
         | 
| 295 302 | 
             
            		end
         | 
| 296 303 |  | 
| 297 304 | 
             
            		# chmod chown utime
         | 
| 298 | 
            -
            		src_stat = o[:folsymlink] ? stat(src) : lstat(src)
         | 
| 305 | 
            +
            		src_stat = o[:folsymlink] ? File.stat(src) : File.lstat(src)
         | 
| 299 306 | 
             
            		begin
         | 
| 300 | 
            -
            			chmod(src_stat.mode, dest)
         | 
| 301 | 
            -
            			chown(src_stat.uid, src_stat.gid, dest)
         | 
| 302 | 
            -
            			utime(src_stat.atime, src_stat.mtime, dest)
         | 
| 307 | 
            +
            			File.chmod(src_stat.mode, dest)
         | 
| 308 | 
            +
            			#File.chown(src_stat.uid, src_stat.gid, dest)
         | 
| 309 | 
            +
            			File.utime(src_stat.atime, src_stat.mtime, dest)
         | 
| 303 310 | 
             
            		rescue Errno::ENOENT
         | 
| 304 311 | 
             
            		end
         | 
| 305 312 | 
             
            	end # _copy
         | 
| @@ -314,20 +321,20 @@ module Cmd | |
| 314 321 | 
             
            	# @option o [Boolean] :overwrite
         | 
| 315 322 | 
             
            	# @return [nil]
         | 
| 316 323 | 
             
            	def mv(src_s, dest, o={}, &blk)
         | 
| 317 | 
            -
            		srcs = glob(*Array.wrap(src_s))
         | 
| 318 | 
            -
            		dest =  | 
| 324 | 
            +
            		srcs = glob(*Array.wrap(src_s)).map{|v| get(v)}
         | 
| 325 | 
            +
            		dest = get(dest)
         | 
| 319 326 |  | 
| 320 | 
            -
            		if o[:mkdir] and (not  | 
| 327 | 
            +
            		if o[:mkdir] and (not File.exists?(dest))
         | 
| 321 328 | 
             
            			mkdir dest
         | 
| 322 329 | 
             
            		end
         | 
| 323 330 |  | 
| 324 331 | 
             
            		# mv file1 file2 .. dir
         | 
| 325 | 
            -
            		if srcs.size>1 and (not  | 
| 332 | 
            +
            		if srcs.size>1 and (not File.directory?(dest))
         | 
| 326 333 | 
             
            			raise Errno::ENOTDIR, "dest not a directory when mv more than one src -- #{dest}"  
         | 
| 327 334 | 
             
            		end
         | 
| 328 335 |  | 
| 329 336 | 
             
            		srcs.each do |src|
         | 
| 330 | 
            -
            			dest1 =  | 
| 337 | 
            +
            			dest1 = File.directory?(dest) ? File.join(dest, File.basename(src)) : dest
         | 
| 331 338 |  | 
| 332 339 | 
             
            			if blk
         | 
| 333 340 | 
             
            				blk.call src, dest1, o, proc{_move(src, dest1, o)}
         | 
| @@ -342,27 +349,27 @@ module Cmd | |
| 342 349 | 
             
            	#
         | 
| 343 350 | 
             
            	# _move "file", "dir/file"
         | 
| 344 351 | 
             
            	#
         | 
| 345 | 
            -
            	# @param [ | 
| 346 | 
            -
            	# @param [ | 
| 352 | 
            +
            	# @param [String] src
         | 
| 353 | 
            +
            	# @param [String] dest
         | 
| 347 354 | 
             
            	def _move(src, dest, o)
         | 
| 348 | 
            -
            		raise Errno::EEXIST, "dest exists -- #{dest}" if  | 
| 355 | 
            +
            		raise Errno::EEXIST, "dest exists -- #{dest}" if File.exists?(dest) and (not o[:overwrite])
         | 
| 349 356 |  | 
| 350 357 | 
             
            		# overwrite. mv "dir", "dira" and 'dira' exists and is a directory. 
         | 
| 351 | 
            -
            		if  | 
| 358 | 
            +
            		if File.exists?(dest) and File.directory?(dest)
         | 
| 352 359 | 
             
            				ls(src) { |pa|
         | 
| 353 | 
            -
            					dest1 =  | 
| 354 | 
            -
            					_move pa, dest1, o
         | 
| 360 | 
            +
            					dest1 = File.join(dest, File.basename(pa.p))
         | 
| 361 | 
            +
            					_move pa.p, dest1, o
         | 
| 355 362 | 
             
            				}
         | 
| 356 | 
            -
            				rm_r src
         | 
| 363 | 
            +
            				Pa.rm_r src
         | 
| 357 364 |  | 
| 358 365 | 
             
            		else
         | 
| 359 366 | 
             
            			begin
         | 
| 360 | 
            -
            				rm_r dest if o[:overwrite] and  | 
| 367 | 
            +
            				Pa.rm_r dest if o[:overwrite] and File.exists?(dest)
         | 
| 361 368 | 
             
            				puts "rename #{src} #{dest}" if o[:verbose]
         | 
| 362 | 
            -
            				File.rename(src | 
| 369 | 
            +
            				File.rename(src, dest)
         | 
| 363 370 | 
             
            			rescue Errno::EXDEV # cross-device
         | 
| 364 371 | 
             
            				_copy(src, dest, o)
         | 
| 365 | 
            -
            				rm_r src
         | 
| 372 | 
            +
            				Pa.rm_r src
         | 
| 366 373 | 
             
            			end
         | 
| 367 374 |  | 
| 368 375 | 
             
            		end
         |