tagen 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +2 -0
  2. data/.yardopts +5 -0
  3. data/Gemfile +7 -0
  4. data/Gemfile.lock +24 -0
  5. data/README.md +60 -0
  6. data/Rakefile +9 -0
  7. data/docs/Architecture.md +17 -0
  8. data/docs/CoreExtensions.md +56 -0
  9. data/docs/ExtraExtensions.md +20 -0
  10. data/lib/tagen/audioinfo.rb +21 -0
  11. data/lib/tagen/cairo.rb +809 -0
  12. data/lib/tagen/core.rb +34 -0
  13. data/lib/tagen/core/array.rb +41 -0
  14. data/lib/tagen/core/array/extract_options.rb +40 -0
  15. data/lib/tagen/core/hash.rb +17 -0
  16. data/lib/tagen/core/io.rb +29 -0
  17. data/lib/tagen/core/kernel.rb +73 -0
  18. data/lib/tagen/core/marshal.rb +34 -0
  19. data/lib/tagen/core/module.rb +25 -0
  20. data/lib/tagen/core/numeric.rb +10 -0
  21. data/lib/tagen/core/object.rb +21 -0
  22. data/lib/tagen/core/pa.rb +187 -0
  23. data/lib/tagen/core/pa/cmd.rb +374 -0
  24. data/lib/tagen/core/pa/dir.rb +144 -0
  25. data/lib/tagen/core/pa/path.rb +190 -0
  26. data/lib/tagen/core/pa/state.rb +56 -0
  27. data/lib/tagen/core/process.rb +11 -0
  28. data/lib/tagen/core/re.rb +8 -0
  29. data/lib/tagen/core/string.rb +43 -0
  30. data/lib/tagen/core/string/pyformat.rb +322 -0
  31. data/lib/tagen/core/time.rb +8 -0
  32. data/lib/tagen/gdk_pixbuf2.rb +26 -0
  33. data/lib/tagen/gtk2.rb +122 -0
  34. data/lib/tagen/magick.rb +23 -0
  35. data/lib/tagen/ncurses.rb +245 -0
  36. data/lib/tagen/net/http.rb +34 -0
  37. data/lib/tagen/pathname.rb +8 -0
  38. data/lib/tagen/poppler.rb +47 -0
  39. data/lib/tagen/socket.rb +20 -0
  40. data/lib/tagen/tree.rb +75 -0
  41. data/lib/tagen/vim.rb +19 -0
  42. data/lib/tagen/xmpp4r.rb +1 -0
  43. data/lib/tagen/xmpp4r/roster.rb +20 -0
  44. data/spec/cairo_spec.rb +137 -0
  45. data/spec/core/pa/cmd_spec.rb +251 -0
  46. data/spec/core/pa/dir_spec.rb +59 -0
  47. data/spec/core/string/pyformat_spec.rb +86 -0
  48. data/spec/spec_helper.rb +0 -0
  49. data/tagen.gemspec +20 -0
  50. data/version.rb +7 -0
  51. metadata +117 -0
@@ -0,0 +1,374 @@
1
+ =begin
2
+ rm family
3
+ * rm _rm file only_
4
+ * rmdir _rm directory only_
5
+ * rm_r _rm recurive, both file and directory_
6
+ * rm_if _with condition, use rm_r_
7
+ === Example
8
+ rm path # it's clear: remove a file
9
+ rmdir path # it's clear: remove a directory
10
+ =end
11
+ class Pa
12
+ module Cmd
13
+
14
+ # chroot
15
+ # @see {Dir.chroot}
16
+ #
17
+ # @param [String] path
18
+ # @return [nil]
19
+ def chroot(path) Dir.chroot(get(path)) end
20
+
21
+ # touch a blank file
22
+ #
23
+ # @overload touch(*paths, o={})
24
+ # @param [String] *paths
25
+ # @param [Hash] o option
26
+ # @option o [Fixnum,String] :mode
27
+ # @option o [Boolean] :mkdir auto mkdir if path contained directory not exists.
28
+ # @option o [Boolean] :force
29
+ # @return [nil]
30
+ def touch(*args) paths, o = args.extract_options; _touch(*paths, o) end
31
+
32
+ # touch force
33
+ # @see touch
34
+ #
35
+ # @overload touch_f(*paths, o={})
36
+ # @return [nil]
37
+ def touch_f(*args) paths, o = args.extract_options; o[:force]=true; _touch(*paths, o) end
38
+
39
+ def _touch(paths, o)
40
+ o[:mode] ||= 0644
41
+ paths.map!{|v|get(v)}
42
+ paths.each {|p|
43
+ if exists?(p)
44
+ o[:force] ? next : raise(Errno::EEXIST, "File exist -- #{p}")
45
+ end
46
+
47
+ if o[:mkdir]
48
+ mkdir(dirname(p))
49
+ end
50
+
51
+ if win32?
52
+ # win32 BUG. must f.write("") then file can be deleted.
53
+ File.open(p, "w"){|f| f.chmod(o[:mode]); f.write("")}
54
+ else
55
+ File.open(p, "w"){|f| f.chmod(o[:mode])}
56
+ end
57
+ }
58
+ end
59
+ private :_touch
60
+
61
+ # make a directory
62
+ #
63
+ # @overload mkdir(*paths, o={})
64
+ # @param [String] *paths
65
+ # @param [Hash] o option
66
+ # @option o [Fixnum] :mode
67
+ # @option o [Boolean] :force
68
+ # @return [nil]
69
+ def mkdir(*args) paths, o = args.extract_options; _mkdir(paths, o) end
70
+
71
+ # mkdir force
72
+ # @see mkdir
73
+ #
74
+ # @overload mkdir_f(*paths, o={})
75
+ # @return [nil]
76
+ def mkdir_f(*args) paths, o = args.extract_options; o[:force]=true; _mkdir(*paths, o) end
77
+
78
+ def _mkdir(paths, o)
79
+ o[:mode] ||= 0744
80
+ paths.map!{|v|get(v)}
81
+ paths.each {|p|
82
+ if File.exists?(p)
83
+ o[:force] ? next : raise(Errno::EEXIST, "File exist -- #{p}")
84
+ end
85
+
86
+ stack = []
87
+ until p == stack.last
88
+ break if File.exists?(p)
89
+ stack << p
90
+ p = File.dirname(p)
91
+ end
92
+
93
+ stack.reverse.each do |path|
94
+ Dir.mkdir(path)
95
+ File.chmod(o[:mode], path)
96
+ end
97
+ }
98
+ end
99
+ private :_mkdir
100
+
101
+ # make temp directory
102
+ #
103
+ # @param [Hash] o options
104
+ # @option o [Symbol] :prefix ("")
105
+ # @option o [Symbol] :suffix ("")
106
+ # @option o [Symbol] :tmpdir (ENV["TEMP"])
107
+ # @return [String] path
108
+ def mktmpdir(o={}, &blk)
109
+ p = _mktmpname(o)
110
+ File.mkdir(p)
111
+ begin blk.call(p) ensure Dir.delete(p) end if blk
112
+ p
113
+ end # def mktmpdir
114
+
115
+ def home(user=nil) Dir.home end
116
+
117
+ # make temp file
118
+ # @see mktmpdir
119
+ #
120
+ # @param [Hash] o options
121
+ # @return [String] path
122
+ def mktmpfile(o={}, &blk)
123
+ p = _mktmpname(o)
124
+ begin blk.call(p) ensure File.delete(p) end if blk
125
+ p
126
+ end # mktmpfile
127
+
128
+ def _mktmpname(o={})
129
+ # :prefix :suffix :tmpdir
130
+ # $$-(time*100_000).to_i.to_s(36)
131
+ # parse o
132
+ o[:dir] ||= ENV["TEMP"]
133
+ o[:prefix] ||= ""
134
+ o[:suffix] ||= ""
135
+
136
+ # begin
137
+ collision = 0
138
+ path = "#{o[:dir]}/#{o[:prefix]}#{$$}-#{(Time.time*100_000).to_i.to_s(36)}"
139
+ orgi_path = path.dup
140
+ while exists?(path)
141
+ path = orgi_path+ collision.to_s
142
+ collision +=1
143
+ end
144
+ path << o[:suffix]
145
+
146
+ path
147
+ end # def mktmpname
148
+ private :_mktmpname
149
+
150
+ # rm file only
151
+ #
152
+ # @param [String] *paths support globbing
153
+ # @return [nil]
154
+ def rm(*paths)
155
+ glob(*paths) { |pa|
156
+ next if not pa.exists?
157
+ File.delete(pa.p)
158
+ }
159
+ end
160
+
161
+ # rm directory only. still remove if directory is not empty.
162
+ #
163
+ # @param [String] *paths support globbing
164
+ # @return [nil]
165
+ def rmdir *paths
166
+ glob(*paths) { |pa|
167
+ raise Errno::ENOTDIR, "-- #{pa}" if not pa.directory?
168
+ _rmdir(pa)
169
+ }
170
+ end
171
+
172
+ # rm recusive, rm both file and directory
173
+ #
174
+ # @see rm
175
+ # @return [nil]
176
+ def rm_r(*paths)
177
+ glob(*paths){ |pa|
178
+ next if not pa.exists?
179
+ pa.directory? ? _rmdir(pa) : File.delete(pa.p)
180
+ }
181
+ end
182
+
183
+ # rm_r(path) if condition is true
184
+ #
185
+ # @example
186
+ # Pa.rm_if '/tmp/**/*.rb' do |pa|
187
+ # pa.name == 'old'
188
+ # end
189
+ #
190
+ # @param [String] *paths support globbing
191
+ # @yield [path]
192
+ # @yieldparam [Pa] path
193
+ # @yieldreturn [Boolean] rm_r path if true
194
+ # @return [nil]
195
+ def rm_if(*paths, &blk)
196
+ glob(*paths) do |pa|
197
+ rm_r pa if blk.call(pa)
198
+ end
199
+ end
200
+
201
+ # I'm recusive
202
+ # param@ [Pa] path
203
+ def _rmdir(pa, o={})
204
+ return if not pa.exists?
205
+ pa.each {|pa1|
206
+ pa1.directory? ? _rmdir(pa1, o) : File.delete(pa1.p)
207
+ }
208
+ pa.directory? ? Dir.rmdir(pa.p) : File.delete(pa.p)
209
+ end
210
+ private :_rmdir
211
+
212
+ # copy
213
+ #
214
+ # cp file dir
215
+ # cp 'a', 'dir' #=> dir/a
216
+ # cp 'a', 'dir/a' #=> dir/a
217
+ #
218
+ # cp file1 file2 .. dir
219
+ # cp ['a','b'], 'dir' #=> dir/a dir/b
220
+ #
221
+ # @example
222
+ # cp '*', 'dir' do |src, dest, o|
223
+ # skip if src.name=~'.o$'
224
+ # dest.replace 'dirc' if src.name=="foo"
225
+ # yield # use yield to do the actuactal cp work
226
+ # end
227
+ #
228
+ # @overload cp(src_s, dest, o)
229
+ # @param [Array<String>, String] src_s support globbing
230
+ # @param [String,Pa] dest
231
+ # @param [Hash] o option
232
+ # @option o [Boolean] :mkdir mkdir(dest) if dest not exists.
233
+ # @option o [Boolean] :verbose puts cmd when execute
234
+ # @option o [Boolean] :folsymlink follow symlink
235
+ # @option o [Boolean] :overwrite overwrite dest file if dest is a file
236
+ # @return [nil]
237
+ # @overload cp(src_s, dest, o)
238
+ # @yield [src,dest,o]
239
+ # @return [nil]
240
+ def cp(src_s, dest, o={}, &blk)
241
+ srcs = glob(*Array.wrap(src_s))
242
+ dest = Pa(dest)
243
+
244
+ if o[:mkdir] and (not dest.exists?)
245
+ mkdir dest
246
+ end
247
+
248
+ # cp file1 file2 .. dir
249
+ if srcs.size>1 and (not dest.directory?)
250
+ raise Errno::ENOTDIR, "dest not a directory when cp more than one src -- #{dest}"
251
+ end
252
+
253
+ srcs.each do |src|
254
+ dest1 = dest.directory? ? dest.join(src.b) : dest
255
+
256
+ if blk
257
+ blk.call src, dest1, o, proc{_copy(src, dest1, o)}
258
+ else
259
+ _copy src, dest1, o
260
+ end
261
+
262
+ end
263
+ end
264
+
265
+
266
+ # I'm recursive
267
+ #
268
+ # @param [Pa] src
269
+ # @param [Pa] dest
270
+ def _copy(src, dest, o={})
271
+ raise Errno::EEXIST, "dest exists -- #{dest}" if dest.exists? and (not o[:overwrite])
272
+
273
+ case type=src.type
274
+ when "file", "socket"
275
+ puts "cp #{src} #{dest}" if o[:verbose]
276
+ File.copy_stream(src.p, dest.p)
277
+ when "directory"
278
+ begin
279
+ mkdir dest
280
+ puts "mkdir #{dest}" if o[:verbose]
281
+ rescue Errno::EEXIST
282
+ end
283
+ each(src) { |pa|
284
+ _copy(pa, dest.join(pa.b), o)
285
+ }
286
+ when "symlink"
287
+ if o[:folsymlink]
288
+ _copy(src.readlink, dest)
289
+ else
290
+ symln(src.readlink, dest, force: true)
291
+ puts "symlink #{src} #{dest}" if o[:verbose]
292
+ end
293
+ when "unknow"
294
+ raise EUnKnownType, "Can't handle unknow type(#{:type}) -- #{src}"
295
+ end
296
+
297
+ # chmod chown utime
298
+ src_stat = o[:folsymlink] ? stat(src) : lstat(src)
299
+ 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)
303
+ rescue Errno::ENOENT
304
+ end
305
+ end # _copy
306
+ private :_copy
307
+
308
+ # move, use rename for same device. and cp for cross device.
309
+ # @see cp
310
+ #
311
+ # @param [Hash] o option
312
+ # @option o [Boolean] :verbose
313
+ # @option o [Boolean] :mkdir
314
+ # @option o [Boolean] :overwrite
315
+ # @return [nil]
316
+ def mv(src_s, dest, o={}, &blk)
317
+ srcs = glob(*Array.wrap(src_s))
318
+ dest = Pa(dest)
319
+
320
+ if o[:mkdir] and (not dest.exists?)
321
+ mkdir dest
322
+ end
323
+
324
+ # mv file1 file2 .. dir
325
+ if srcs.size>1 and (not dest.directory?)
326
+ raise Errno::ENOTDIR, "dest not a directory when mv more than one src -- #{dest}"
327
+ end
328
+
329
+ srcs.each do |src|
330
+ dest1 = dest.directory? ? dest.join(src.b) : dest
331
+
332
+ if blk
333
+ blk.call src, dest1, o, proc{_move(src, dest1, o)}
334
+ else
335
+ _move src, dest1, o
336
+ end
337
+
338
+ end
339
+ end
340
+
341
+ # I'm recusive
342
+ #
343
+ # _move "file", "dir/file"
344
+ #
345
+ # @param [Pa] src
346
+ # @param [Pa] dest
347
+ def _move(src, dest, o)
348
+ raise Errno::EEXIST, "dest exists -- #{dest}" if dest.exists? and (not o[:overwrite])
349
+
350
+ # overwrite. mv "dir", "dira" and 'dira' exists and is a directory.
351
+ if dest.exists? and dest.directory?
352
+ ls(src) { |pa|
353
+ dest1 = dest.join(pa.b)
354
+ _move pa, dest1, o
355
+ }
356
+ rm_r src
357
+
358
+ else
359
+ begin
360
+ rm_r dest if o[:overwrite] and dest.exists?
361
+ puts "rename #{src} #{dest}" if o[:verbose]
362
+ File.rename(src.p, dest.p)
363
+ rescue Errno::EXDEV # cross-device
364
+ _copy(src, dest, o)
365
+ rm_r src
366
+ end
367
+
368
+ end
369
+ end # def _move
370
+ private :_move
371
+
372
+
373
+ end
374
+ end
@@ -0,0 +1,144 @@
1
+ =begin
2
+ == ls family
3
+ * Dir[*path] _support globbing_
4
+ * Pa.glob(*path,o),(){} _support globbing with option and block_
5
+ * each(path),(){} each_r(),(){} _support Enumerator. not support globbing_
6
+ * ls(path) ls_r(path) _sample ls. not support globbing._
7
+ === Example
8
+ each(".") do |pa|
9
+ p pa
10
+ end
11
+
12
+ each(".").with_index(2){|pa,i| ... }
13
+ =end
14
+ class Pa
15
+ module Directory
16
+
17
+ # path globbing, exclude '.' '..' for :dotmatch
18
+ # @note glob is * ** ? [set] {a,b}
19
+ #
20
+ # @overload glob(*paths, o={})
21
+ # @param [String] path
22
+ # @param [Hash] o option
23
+ # @option o [Boolean] :dotmatch glob not match dot file by default.
24
+ # @option o [Boolean] :pathname wildcard doesn't match /
25
+ # @option o [Boolean] :noescape makes '\\' ordinary
26
+ # @return [Array<Pa>]
27
+ # @overload glob(*paths, o={})
28
+ # @yieldparam [Pa] path
29
+ # @return [nil]
30
+ def glob(*args, &blk)
31
+ paths, o = args.extract_options
32
+ paths.map!{|v|get(v)}
33
+
34
+ flag = 0
35
+ o.each do |option, value|
36
+ flag |= File.const_get("FNM_#{option.upcase}") if value
37
+ end
38
+
39
+ ret = Dir.glob(paths, flag)
40
+
41
+ # delete . .. for '.*'
42
+ ret.tap{|v|v.delete(*%w(. ..))}
43
+ ret.map!{|v|Pa(v)}
44
+
45
+ if blk
46
+ ret.each {|pa|
47
+ blk.call pa
48
+ }
49
+ else
50
+ ret
51
+ end
52
+ end
53
+
54
+ # is directory empty?
55
+ #
56
+ # @param [String] path
57
+ # @return [Boolean]
58
+ def empty?(path) Dir.entries(get(path)).empty? end
59
+
60
+ # traverse directory
61
+ # @note return if not a directory.
62
+ #
63
+ # @example
64
+ # each '.' do |pa|
65
+ # p pa.path
66
+ # end
67
+ # # => '/home' ..
68
+ #
69
+ # @overload each(path=".", o={})
70
+ # @param [String,Pa] path
71
+ # @prarm [Hash] o
72
+ # @option o [Boolean] :nodot (nil) include dot file
73
+ # @option o [Boolean] :nobackup (nil) include backup file
74
+ # @return [Enumerator<Pa>]
75
+ # @overload each(path=".", o={})
76
+ # @yieldparam [Pa] path
77
+ # @return [nil]
78
+ def each(*args, &blk)
79
+ return Pa.to_enum(:each, *args) if not blk
80
+
81
+ (path,), o = args.extract_options
82
+ pa = Pa(path || ".")
83
+ return if not pa.directory?
84
+
85
+ Dir.foreach pa.p do |name|
86
+ next if %w(. ..).include? name
87
+ next if o[:nodot] and name=~/^\./
88
+ next if o[:nobackup] and name=~/~$/
89
+
90
+ blk.call pa.join(name)
91
+ end
92
+ end
93
+
94
+ # each with recursive
95
+ # @see each
96
+ #
97
+ # * each_r() skip Exception
98
+ # * each_r(){pa, err}
99
+ #
100
+ # @overload each_r(path=".", o={})
101
+ # @return [Enumerator<Pa>]
102
+ # @overload each_r(path=".", o={})
103
+ # @yield [pa,err]
104
+ # @return [nil]
105
+ def each_r(*args, &blk)
106
+ return Pa.to_enum(:each_r, *args) if not blk
107
+
108
+ (path,), o = args.extract_options
109
+ path ||= "."
110
+
111
+ _each_r(Pa(path), "", o, &blk)
112
+ end
113
+
114
+ def _each_r pa, relative, o, &blk
115
+ each(pa, o) do |pa1|
116
+ relative1 = Pa.join(relative, pa1.b)
117
+ blk.call pa1, relative1
118
+ if pa1.directory?
119
+ _each_r(pa1, relative1, o, &blk)
120
+ end
121
+ end
122
+ rescue Errno::ENOENT, Errno::EPERM => e
123
+ blk.call pa, relative, e
124
+ end
125
+ private :_each_r
126
+
127
+ # list directory contents
128
+ # @see each
129
+ #
130
+ # @return [Array<String>]
131
+ def ls(*args)
132
+ each(*args).with_object([]){|pa,m| m<<pa.b}
133
+ end
134
+
135
+ # ls with recursive
136
+ # @see each
137
+ #
138
+ # @return [Array<String>]
139
+ def ls_r(*args)
140
+ each_r(*args).with_object([]){|pa,m| m<<pa.b}
141
+ end
142
+
143
+ end
144
+ end