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.
@@ -12,7 +12,7 @@
12
12
  each(".").with_index(2){|pa,i| ... }
13
13
  =end
14
14
  class Pa
15
- module Directory
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 return if not a directory.
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 (nil) include dot file
73
- # @option o [Boolean] :nobackup (nil) include backup file
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) if not blk
84
+ return Pa.to_enum(:each, *args) unless blk
80
85
 
81
86
  (path,), o = args.extract_options
82
- pa = Pa(path || ".")
83
- return if not pa.directory?
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
- 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=~/~$/
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
- blk.call pa.p=="." ? Pa(name) : pa.join(name)
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
- # @yield [pa,err]
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(Pa(path), "", o, &blk)
131
+ _each_r(path, "", o, &blk)
113
132
  end
114
133
 
115
- def _each_r pa, relative, o, &blk
116
- each(pa, o) do |pa1|
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
- blk.call pa1, relative1
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
 
@@ -1,37 +1,47 @@
1
1
  class Pa
2
- module Path
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,Pa] obj
37
+ # @param [String,#path] obj
28
38
  # @return [String,nil] path
29
39
  def get obj
30
- return obj if String === obj
31
-
32
- begin
40
+ if obj.respond_to?(:path)
33
41
  obj.path
34
- rescue NoMethodError
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) absolute(path) == get(path) end
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
- # @param [String] name
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,String>] \[name, ext] if o[:ext] is true
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
- _, name, ext = name.match(/^(.+?)(\.[^.]+)?$/).to_a
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
- join(get(path), "..")
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 = Pa(dest)
179
+ dest = get(dest)
161
180
  glob(*Array.wrap(src_s)) {|src|
162
- dest = dest.join(src.b) if dest.directory?
163
- rm_r(dest) if o[:force] and dest.exists?
164
- method.call(src.p, dest.p)
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
+
@@ -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 = path.lstat
49
- stat2 = path.parent.lstat
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(%w(apple football)) # it has semantic meaning.
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} dollar".format(1.123) #=> "it costs 1.12 dollar"
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"
@@ -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