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 CHANGED
@@ -32,7 +32,42 @@ use extra extension
32
32
  require "pathname"
33
33
  require "tagen/pathname"
34
34
 
35
- add #path method to Pathname, see API doc.
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 "testing the library"
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/TODO ADDED
@@ -0,0 +1 @@
1
+ * Pa support home path. e.g. '~/.vimrc'
@@ -1,3 +1,4 @@
1
+ require "audioinfo"
1
2
  =begin
2
3
  * **gem**: ruby-audioinfo
3
4
  =end
@@ -1,3 +1,5 @@
1
+ require "cairo"
2
+
1
3
  # gdk_pixbuf2 for
2
4
  # Context#set_source
3
5
  # set_source_pixbuf
@@ -19,6 +19,8 @@ require "pd"
19
19
  core/object
20
20
  core/module
21
21
 
22
+ core/enumerable
23
+ core/enumerator
22
24
  core/numeric
23
25
  core/string
24
26
  core/array
@@ -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
@@ -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 ClassMethods to class methods.
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 # after include Guten, method 'foo' becomes a class method.
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
@@ -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
- attr_accessor :path
63
- attr_reader :absolute, :dir, :base, :name, :ext, :fext
64
- alias p path
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 = case path.class.to_s
76
- when "Pathname"
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
- # @param [String,Pa,Pathname]
93
- # @return [Pa] the same Pa object
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
- # add string to path
99
- #
100
- # @example
101
- # pa = Pa('/home/foo/a.txt')
102
- # pa+'~' #=> new Pa('/home/foo/a.txt~')
103
- #
104
- # @param [String] str
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=\"#{@path}\", @absolute=\"#{@absolute}\""
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
- # join path
128
- #
129
- # param [String] *names
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
- # get parent path
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
- require_relative "pa/path"
154
- require_relative "pa/cmd"
155
- require_relative "pa/dir"
156
- require_relative "pa/state"
124
+ end
125
+
157
126
  class Pa
158
- class << self
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
- return if args.size>1
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
- extend Path
171
- extend Directory
172
- extend State
173
- extend Cmd
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
@@ -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 {|p|
43
- if exists?(p)
44
- o[:force] ? next : raise(Errno::EEXIST, "File exist -- #{p}")
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
- path = orgi_path+ collision.to_s
142
- collision +=1
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 pa.exists?
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 pa.directory?
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 pa.exists?
179
- pa.directory? ? _rmdir(pa) : File.delete(pa.p)
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 pa.exists?
202
+ return if not File.exists?(pa.p)
205
203
  pa.each {|pa1|
206
- pa1.directory? ? _rmdir(pa1, o) : File.delete(pa1.p)
204
+ File.directory?(pa1.p) ? _rmdir(pa1, o) : File.delete(pa1.p)
207
205
  }
208
- pa.directory? ? Dir.rmdir(pa.p) : File.delete(pa.p)
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 dest.exists?)
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 dest.directory?)
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 = dest.directory? ? dest.join(src.b) : dest
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 [Pa] src
269
- # @param [Pa] dest
267
+ # @param [String] src
268
+ # @param [String] dest
270
269
  def _copy(src, dest, o={})
271
- raise Errno::EEXIST, "dest exists -- #{dest}" if dest.exists? and (not o[:overwrite])
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.p, dest.p)
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, dest.join(pa.b), o)
289
+ _copy(pa.p, File.join(dest, File.basename(pa.p)), o)
285
290
  }
286
- when "symlink"
291
+
292
+ when "link" # symbol link
287
293
  if o[:folsymlink]
288
- _copy(src.readlink, dest)
294
+ _copy(Pa.readlink(src), dest)
289
295
  else
290
- symln(src.readlink, dest, force: true)
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 = Pa(dest)
324
+ srcs = glob(*Array.wrap(src_s)).map{|v| get(v)}
325
+ dest = get(dest)
319
326
 
320
- if o[:mkdir] and (not dest.exists?)
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 dest.directory?)
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 = dest.directory? ? dest.join(src.b) : dest
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 [Pa] src
346
- # @param [Pa] dest
352
+ # @param [String] src
353
+ # @param [String] dest
347
354
  def _move(src, dest, o)
348
- raise Errno::EEXIST, "dest exists -- #{dest}" if dest.exists? and (not o[:overwrite])
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 dest.exists? and dest.directory?
358
+ if File.exists?(dest) and File.directory?(dest)
352
359
  ls(src) { |pa|
353
- dest1 = dest.join(pa.b)
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 dest.exists?
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.p, dest.p)
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