tagen 0.2.1 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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/lib/tagen/core/pa/dir.rb
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
each(".").with_index(2){|pa,i| ... }
|
13
13
|
=end
|
14
14
|
class Pa
|
15
|
-
module
|
15
|
+
module ClassMethods::Dir
|
16
16
|
|
17
17
|
# path globbing, exclude '.' '..' for :dotmatch
|
18
18
|
# @note glob is * ** ? [set] {a,b}
|
@@ -58,7 +58,7 @@ module Directory
|
|
58
58
|
def empty?(path) Dir.entries(get(path)).empty? end
|
59
59
|
|
60
60
|
# traverse directory
|
61
|
-
# @note
|
61
|
+
# @note raise Errno::ENOTDIR, Errno::ENOENT
|
62
62
|
#
|
63
63
|
# @example
|
64
64
|
# each '.' do |pa|
|
@@ -66,29 +66,46 @@ module Directory
|
|
66
66
|
# end
|
67
67
|
# # => '/home' ..
|
68
68
|
#
|
69
|
+
# each('.', error: true).with_object([]) do |(pa,err),m|
|
70
|
+
# ...
|
71
|
+
# end
|
72
|
+
#
|
69
73
|
# @overload each(path=".", o={})
|
70
74
|
# @param [String,Pa] path
|
71
75
|
# @prarm [Hash] o
|
72
|
-
# @option o [Boolean] :nodot (
|
73
|
-
# @option o [Boolean] :nobackup (
|
76
|
+
# @option o [Boolean] :nodot (false) include dot file
|
77
|
+
# @option o [Boolean] :nobackup (false) include backup file
|
78
|
+
# @option o [Boolean] :error (false) yield(pa, err) instead of raise Errno::EPERM when Dir.open(dir)
|
74
79
|
# @return [Enumerator<Pa>]
|
75
80
|
# @overload each(path=".", o={})
|
76
81
|
# @yieldparam [Pa] path
|
77
82
|
# @return [nil]
|
78
83
|
def each(*args, &blk)
|
79
|
-
return Pa.to_enum(:each, *args)
|
84
|
+
return Pa.to_enum(:each, *args) unless blk
|
80
85
|
|
81
86
|
(path,), o = args.extract_options
|
82
|
-
|
83
|
-
|
87
|
+
path = path ? get(path) : "."
|
88
|
+
raise Errno::ENOENT, "`#{path}' doesn't exists." unless File.exists?(path)
|
89
|
+
raise Errno::ENOTDIR, "`#{path}' not a directoyr." unless File.directory?(path)
|
90
|
+
|
91
|
+
begin
|
92
|
+
dir = Dir.open(path)
|
93
|
+
rescue Errno::EPERM => err
|
94
|
+
end
|
95
|
+
raise err if err and !o[:error]
|
84
96
|
|
85
|
-
|
86
|
-
next if %w(. ..).include?
|
87
|
-
next if o[:nodot] and
|
88
|
-
next if o[:nobackup] and
|
97
|
+
while (entry=dir.read)
|
98
|
+
next if %w(. ..).include? entry
|
99
|
+
next if o[:nodot] and entry=~/^\./
|
100
|
+
next if o[:nobackup] and entry=~/~$/
|
89
101
|
|
90
102
|
# => "foo" not "./foo"
|
91
|
-
|
103
|
+
pa = path=="." ? Pa(entry) : Pa(File.join(path, entry))
|
104
|
+
if o[:error]
|
105
|
+
blk.call pa, err
|
106
|
+
else
|
107
|
+
blk.call pa
|
108
|
+
end
|
92
109
|
end
|
93
110
|
end
|
94
111
|
|
@@ -101,7 +118,9 @@ module Directory
|
|
101
118
|
# @overload each_r(path=".", o={})
|
102
119
|
# @return [Enumerator<Pa>]
|
103
120
|
# @overload each_r(path=".", o={})
|
104
|
-
# @
|
121
|
+
# @yieldparam [Pa] pa
|
122
|
+
# @yieldparam [String] relative relative path
|
123
|
+
# @yieldparam [Errno::ENOENT,Errno::EPERM] err
|
105
124
|
# @return [nil]
|
106
125
|
def each_r(*args, &blk)
|
107
126
|
return Pa.to_enum(:each_r, *args) if not blk
|
@@ -109,19 +128,21 @@ module Directory
|
|
109
128
|
(path,), o = args.extract_options
|
110
129
|
path ||= "."
|
111
130
|
|
112
|
-
_each_r(
|
131
|
+
_each_r(path, "", o, &blk)
|
113
132
|
end
|
114
133
|
|
115
|
-
|
116
|
-
|
134
|
+
# @param [String] path
|
135
|
+
def _each_r path, relative, o, &blk
|
136
|
+
o.merge!(error: true)
|
137
|
+
Pa.each(path, o) do |pa1, err|
|
117
138
|
relative1 = Pa.join(relative, pa1.b)
|
118
|
-
|
139
|
+
|
140
|
+
blk.call pa1, relative1, err
|
141
|
+
|
119
142
|
if pa1.directory?
|
120
|
-
_each_r(pa1, relative1, o, &blk)
|
143
|
+
_each_r(pa1.p, relative1, o, &blk)
|
121
144
|
end
|
122
145
|
end
|
123
|
-
rescue Errno::ENOENT, Errno::EPERM => e
|
124
|
-
blk.call pa, relative, e
|
125
146
|
end
|
126
147
|
private :_each_r
|
127
148
|
|
data/lib/tagen/core/pa/path.rb
CHANGED
@@ -1,37 +1,47 @@
|
|
1
1
|
class Pa
|
2
|
-
|
2
|
+
NAME_EXT_PAT = /^(.+?)(?:\.([^.]+))?$/
|
3
|
+
module ClassMethods::Path
|
3
4
|
|
4
5
|
# alias from File.absolute_path
|
5
|
-
# @param [String] path
|
6
|
+
# @param [String,Pa] path
|
6
7
|
# @return [String]
|
7
8
|
def absolute(path); File.absolute_path(get(path)) end
|
8
9
|
|
9
10
|
# alias from File.expand_path
|
10
|
-
# @param [String] path
|
11
|
+
# @param [String,Pa] path
|
11
12
|
# @return [String]
|
12
13
|
def expand(path); File.expand_path(get(path)) end
|
13
14
|
|
15
|
+
# shorten a path,
|
16
|
+
# convert /home/user/file to ~/file
|
17
|
+
#
|
18
|
+
# @param [String,Pa] path
|
19
|
+
# @return [String]
|
20
|
+
def shorten(path);
|
21
|
+
get(path).sub(%r!^#{Regexp.escape(ENV["HOME"])}!, "~")
|
22
|
+
end
|
23
|
+
|
14
24
|
# print current work directory
|
15
25
|
# @return [String] path
|
16
26
|
def pwd() Dir.getwd end
|
17
27
|
|
18
28
|
# change directory
|
19
29
|
#
|
20
|
-
# @param [String] path
|
30
|
+
# @param [String,Pa] path
|
21
31
|
def cd(path=ENV["HOME"], &blk) Dir.chdir(get(path), &blk) end
|
22
32
|
|
23
33
|
# get path of an object.
|
24
34
|
#
|
25
35
|
# return obj#path if object has a 'path' instance method
|
26
36
|
#
|
27
|
-
# @param [String
|
37
|
+
# @param [String,#path] obj
|
28
38
|
# @return [String,nil] path
|
29
39
|
def get obj
|
30
|
-
|
31
|
-
|
32
|
-
begin
|
40
|
+
if obj.respond_to?(:path)
|
33
41
|
obj.path
|
34
|
-
|
42
|
+
elsif String === obj
|
43
|
+
obj
|
44
|
+
else
|
35
45
|
raise Error, "not support type -- #{obj.inspect}(#{obj.class})"
|
36
46
|
end
|
37
47
|
end
|
@@ -42,7 +52,7 @@ class Pa
|
|
42
52
|
# "a.ogg" => "ogg"
|
43
53
|
# "a" => nil
|
44
54
|
#
|
45
|
-
# @param [String] path
|
55
|
+
# @param [String,Pa] path
|
46
56
|
# @return [String]
|
47
57
|
def extname path
|
48
58
|
_, ext = get(path).match(/\.([^.]+)$/).to_a
|
@@ -51,22 +61,25 @@ class Pa
|
|
51
61
|
|
52
62
|
# is path an absolute path ?
|
53
63
|
#
|
54
|
-
# @param [String] path
|
64
|
+
# @param [String,Pa] path
|
55
65
|
# @return [Boolean]
|
56
|
-
def absolute?(path)
|
66
|
+
def absolute?(path) path=get(path); File.absolute_path(path) == path end
|
57
67
|
|
58
68
|
# get a basename of a path
|
59
69
|
#
|
60
|
-
# @
|
70
|
+
# @example
|
71
|
+
# Pa.basename("foo.bar.c", ext: true) #=> \["foo.bar", "c"]
|
72
|
+
#
|
73
|
+
# @param [String,Pa] name
|
61
74
|
# @param [Hash] o options
|
62
75
|
# @option o [Boolean, String] :ext (false) return \[name, ext] if true
|
63
76
|
#
|
64
|
-
# @return [String] basename of a path
|
65
|
-
# @return [Array<String
|
77
|
+
# @return [String] basename of a path unless o[:ext]
|
78
|
+
# @return [Array<String>] \[name, ext] if o[:ext].
|
66
79
|
def basename(name, o={})
|
67
80
|
name = File.basename(get(name))
|
68
81
|
if o[:ext]
|
69
|
-
|
82
|
+
name, ext = name.match(NAME_EXT_PAT).captures
|
70
83
|
[ name, (ext || "")]
|
71
84
|
else
|
72
85
|
name
|
@@ -80,7 +93,7 @@ class Pa
|
|
80
93
|
# split(path) #=> "/home/a", "file"
|
81
94
|
# split(path, :all) #=> "/", "home", "a", "file"
|
82
95
|
#
|
83
|
-
# @param [String] name
|
96
|
+
# @param [String,Pa] name
|
84
97
|
# @param [Hash] o option
|
85
98
|
# @option o [Boolean] :all split all parts
|
86
99
|
# @return [Array<String>]
|
@@ -118,10 +131,15 @@ class Pa
|
|
118
131
|
|
119
132
|
# get parent path
|
120
133
|
#
|
121
|
-
# @param [String] path
|
134
|
+
# @param [String,Pa] path
|
135
|
+
# @param [Fixnum] n up level
|
122
136
|
# @return [String]
|
123
|
-
def parent path
|
124
|
-
|
137
|
+
def parent path, n=1
|
138
|
+
path = get(path)
|
139
|
+
n.times do
|
140
|
+
path = File.dirname(path)
|
141
|
+
end
|
142
|
+
path
|
125
143
|
end
|
126
144
|
|
127
145
|
# link
|
@@ -130,7 +148,7 @@ class Pa
|
|
130
148
|
# @overload ln([src,..], directory)
|
131
149
|
#
|
132
150
|
# @param [Array<String>, String] src_s support globbing
|
133
|
-
# @param [String] dest
|
151
|
+
# @param [String,Pa] dest
|
134
152
|
# @param [Hash] o option
|
135
153
|
# @option o [Boolean] :force overwrite if exists.
|
136
154
|
# @return [nil]
|
@@ -155,13 +173,15 @@ class Pa
|
|
155
173
|
# @return [nil]
|
156
174
|
def symln_f(src_s, dest, o) o[:force]=true; _ln(File.method(:symlink), src_s, dest, o) end
|
157
175
|
|
158
|
-
# param
|
176
|
+
# @param [Array,String,#path] src_s
|
177
|
+
# @param [String,#path] dest
|
159
178
|
def _ln(method, src_s, dest, o={})
|
160
|
-
dest =
|
179
|
+
dest = get(dest)
|
161
180
|
glob(*Array.wrap(src_s)) {|src|
|
162
|
-
|
163
|
-
|
164
|
-
|
181
|
+
src = get(src)
|
182
|
+
dest = File.join(dest, File.basename(src)) if File.directory?(dest)
|
183
|
+
Pa.rm_r(dest) if o[:force] and File.exists?(dest)
|
184
|
+
method.call(src, dest)
|
165
185
|
}
|
166
186
|
end
|
167
187
|
private :_ln
|
@@ -169,22 +189,103 @@ class Pa
|
|
169
189
|
# @see File.readlink
|
170
190
|
def readlink(path) File.readlink(get(path)) end
|
171
191
|
|
172
|
-
|
173
192
|
# is path a dangling symlink?
|
174
193
|
#
|
175
194
|
# a dangling symlink is a dead symlink.
|
176
195
|
#
|
177
|
-
# @param [String] path
|
196
|
+
# @param [String,Pa] path
|
178
197
|
# @return [Boolean]
|
179
198
|
def dangling? path
|
180
199
|
path=get(path)
|
181
|
-
if symlink?(path)
|
182
|
-
src = readlink(path)
|
183
|
-
not exists?(src)
|
200
|
+
if File.symlink?(path)
|
201
|
+
src = File.readlink(path)
|
202
|
+
not File.exists?(src)
|
184
203
|
else
|
185
204
|
nil
|
186
205
|
end
|
187
206
|
end # def dsymlink?
|
188
207
|
|
208
|
+
def realpath(path) File.realpath(get(path)) end
|
209
|
+
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class Pa
|
214
|
+
=begin
|
215
|
+
|
216
|
+
attribute absolute and dir return String, method absolute_path(), dirname() return Pa
|
217
|
+
|
218
|
+
Pa("/home/a").dir #=> "/home"
|
219
|
+
Pa("/home/a").dirname #=> Pa("/home")
|
220
|
+
|
221
|
+
== methods from String
|
222
|
+
* +
|
223
|
+
* [g]sub[!] match =~
|
224
|
+
* start_with? end_with?
|
225
|
+
|
226
|
+
=end
|
227
|
+
module Path
|
228
|
+
# @return [String]
|
229
|
+
attr_reader :absolute, :dir, :base, :name, :ext, :fext, :short
|
230
|
+
|
231
|
+
def initialize_variables
|
232
|
+
super
|
233
|
+
@absolute = Pa.absolute(@path)
|
234
|
+
@dir = Pa.dirname(@path)
|
235
|
+
@base = Pa.basename(@path)
|
236
|
+
@name, @ext = Pa.basename(@path, ext: true)
|
237
|
+
@fext = @ext.empty? ? "" : "."+@ext
|
238
|
+
@short = Pa.shorten(@path)
|
239
|
+
end
|
240
|
+
|
241
|
+
alias a absolute
|
242
|
+
alias d dir
|
243
|
+
alias b base
|
244
|
+
alias n name
|
245
|
+
alias e ext
|
246
|
+
alias fe fext
|
247
|
+
|
248
|
+
# @return [Pa] absolute path
|
249
|
+
def absolute_path() Pa(absolute) end
|
250
|
+
# @return [Pa] dirname
|
251
|
+
# @example
|
252
|
+
# Pa(__FILE__).dirname.join('.opts')
|
253
|
+
def dirname() Pa(dir) end
|
254
|
+
|
255
|
+
# add string to path
|
256
|
+
#
|
257
|
+
# @example
|
258
|
+
# pa = Pa('/home/foo/a.txt')
|
259
|
+
# pa+'~' #=> new Pa('/home/foo/a.txt~')
|
260
|
+
#
|
261
|
+
# @param [String] str
|
262
|
+
# @return [Pa]
|
263
|
+
def +(str) Pa(path+str) end
|
264
|
+
|
265
|
+
# @return [Pa]
|
266
|
+
def sub(*args,&blk) Pa(path.sub(*args,&blk)) end
|
267
|
+
|
268
|
+
# @return [Pa]
|
269
|
+
def gsub(*args,&blk) Pa(path.gsub(*args,&blk)) end
|
270
|
+
|
271
|
+
# @return [Pa]
|
272
|
+
def sub!(*args,&blk) self.replace path.sub(*args,&blk) end
|
273
|
+
|
274
|
+
# @return [Pa]
|
275
|
+
def gsub!(*args,&blk) self.replace path.gsub(*args,&blk) end
|
276
|
+
|
277
|
+
# @return [MatchData]
|
278
|
+
def match(*args,&blk) path.match(*args,&blk) end
|
279
|
+
|
280
|
+
# @return [Boolean]
|
281
|
+
def start_with?(*args) path.start_with?(*args) end
|
282
|
+
|
283
|
+
# @return [Boolean]
|
284
|
+
def end_with?(*args) path.end_with?(*args) end
|
285
|
+
|
286
|
+
def =~(regexp) path =~ regexp end
|
287
|
+
|
288
|
+
def ==(other) self.path == other.path end
|
189
289
|
end
|
190
290
|
end
|
291
|
+
|
data/lib/tagen/core/pa/state.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Pa
|
2
|
-
module State
|
2
|
+
module ClassMethods::State
|
3
3
|
|
4
4
|
# @see File.chmod
|
5
5
|
def chmod(mode, *paths) paths.map!{|v|get(v)}; File.chmod(mode, *paths) end
|
@@ -8,10 +8,10 @@ module State
|
|
8
8
|
def lchmod(mode, *paths) paths.map!{|v|get(v)}; File.lchmod(mode, *paths) end
|
9
9
|
|
10
10
|
# @see File.chown
|
11
|
-
def chown(user, group, *paths) paths.map!{|v|get(v)}; File.chown(user, group, *paths) end
|
11
|
+
def chown(user, group=nil, *paths) paths.map!{|v|get(v)}; File.chown(user, group, *paths) end
|
12
12
|
|
13
13
|
# @see File.lchown
|
14
|
-
def lchown(user, group, *paths) paths.map!{|v|get(v)}; File.lchown(user, group, *paths) end
|
14
|
+
def lchown(user, group=nil, *paths) paths.map!{|v|get(v)}; File.lchown(user, group, *paths) end
|
15
15
|
|
16
16
|
# @see File.utime
|
17
17
|
def utime(atime, mtime, *paths) paths.map!{|v|get(v)}; File.utime(atime, mtime, *paths) end
|
@@ -25,7 +25,7 @@ module State
|
|
25
25
|
# @param [String] path
|
26
26
|
# @return [String]
|
27
27
|
def type(path)
|
28
|
-
case (t=ftype(get(path)))
|
28
|
+
case (t=File.ftype(get(path)))
|
29
29
|
when "characterSpecial"
|
30
30
|
"chardev"
|
31
31
|
when "blockSpecial"
|
@@ -45,12 +45,23 @@ module State
|
|
45
45
|
def mountpoint? path
|
46
46
|
path=get(path)
|
47
47
|
begin
|
48
|
-
stat1 =
|
49
|
-
stat2 =
|
48
|
+
stat1 = File.lstat(path)
|
49
|
+
stat2 = File.lstat(File.join(path, '..'))
|
50
50
|
stat1.dev == stat2.dev && stat1.ino == stat2.ino || stat1.dev != stat2.dev
|
51
51
|
rescue Errno::ENOENT
|
52
52
|
false
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
module State
|
58
|
+
def chmod(mode); File.chmod(mode, path) end
|
59
|
+
def lchmod(mode); File.lchmod(mode, path) end
|
60
|
+
def chown(uid, gid=nil); File.chown(uid, gid, path) end
|
61
|
+
def lchown(uid, gid=nil); File.lchown(uid, gid, path) end
|
62
|
+
def utime(atime, mtime); File.utime(atime, mtime, path) end
|
56
63
|
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|
@@ -11,12 +11,12 @@ a python like string format libraray.
|
|
11
11
|
use "#{var}" is easy and quick in many cases, but some times we need a more powerful format support.
|
12
12
|
|
13
13
|
"I like %s and %s" % %(apple, football)
|
14
|
-
"I like %{fruit} and %{sport}".format(
|
14
|
+
"I like %{fruit} and %{sport}".format('apple', 'football') # it has semantic meaning.
|
15
15
|
|
16
16
|
== Usage
|
17
17
|
|
18
18
|
require "tagen/core"
|
19
|
-
"it costs %{:.2f}
|
19
|
+
"it costs %{:.2f} dollars".format(1.123) #=> "it costs 1.12 dollars"
|
20
20
|
|
21
21
|
* support abritry-argument or hash-argument
|
22
22
|
"%{} %{}".format(1,2) #=> "1 2"
|
data/lib/tagen/erb.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
class ERB
|
4
|
+
alias original_result result
|
5
|
+
|
6
|
+
# add locals support
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# erb = Erb.new("<%=a%>")
|
10
|
+
# erb.result(nil, a: 1) #=> "1"
|
11
|
+
#
|
12
|
+
def result bind=nil, locals={}
|
13
|
+
bind ||= TOPLEVEL_BINDING
|
14
|
+
if locals.empty?
|
15
|
+
original_result bind
|
16
|
+
else
|
17
|
+
result_with_locals bind, locals
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def result_with_locals bind, locals
|
23
|
+
@locals = locals
|
24
|
+
evalstr = <<-EOF
|
25
|
+
def run_erb
|
26
|
+
#{locals.map{|k,v| "#{k} = @locals[:#{k}]"}.join(';')}
|
27
|
+
#{self.src}
|
28
|
+
_erbout
|
29
|
+
end
|
30
|
+
EOF
|
31
|
+
eval evalstr
|
32
|
+
run_erb
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|