tagen 0.1.0

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.
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