rant 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -105,6 +105,12 @@
105
105
  before installing a newer version of Rant. It describes
106
106
  non-backwards compatible changes and new features.
107
107
  </p>
108
+ <h2>Rant libraries</h2>
109
+ <p>
110
+ You can reuse code written for the Rant build tool as
111
+ &quot;normal&quot; Ruby library. Read <a
112
+ href="files/doc/rubylib_rdoc.html">Rant libraries</a>
113
+ </p>
108
114
  <h2>Rant vs. Rake</h2>
109
115
  <p>
110
116
  <a href="files/doc/rant_vs_rake_rdoc.html">Read comparison</a>
@@ -118,8 +124,8 @@
118
124
  <a href="http://developer.berlios.de" title="BerliOS
119
125
  Developer"> <img
120
126
  src="http://developer.berlios.de/bslogo.php?group_id=5046"
121
- width="124px" height="32px" border="0" alt="BerliOS
122
- Developer Logo"></a>
127
+ width="124px" height="32px" alt="BerliOS
128
+ Developer Logo" /></a>
123
129
  </p>
124
130
 
125
131
  <!-- BlueRobot was here. -->
@@ -209,31 +209,11 @@ explain it a little bit. It can be used in three ways:
209
209
 
210
210
  file "program" => sys["*.o"]
211
211
 
212
- The task "program" depends on all files ending in ".o". Rant uses
213
- the Dir::glob method internally to resolve patterns, so you can
214
- read the ri docs to get an overview:
215
-
216
- ri Dir::glob
217
-
218
- From now on we'll call <tt>sys[...]</tt> the <em>glob
219
- operator</em>.
220
-
221
- You can give more patterns:
222
-
223
- c_files = sys["**/*.h", "**/*.c"]
224
-
225
- gives a list of all files ending in ".h" or ".c" in the current
226
- directory and all subdirectories.
227
-
228
- The object returned by the glob operator _behaves_ like an array of
229
- strings, so it is possible to pass it to methods expecting an array.
230
- If you're getting errors or experience strange behaviour convert
231
- the list explicetely to an array:
232
-
233
- # method foo_bar is hardcoded to check for an object of class
234
- # Array
235
- foo_bar(c_files.to_a)
236
-
212
+ The task "program" depends on all files ending in ".o".
213
+
214
+ For extensive documentation read
215
+ doc/sys_filelist.rdoc[link:files/doc/sys_filelist_rdoc.html].
216
+
237
217
  === Generators
238
218
 
239
219
  The *gen* function takes a generator which usually creates one or more
@@ -469,5 +449,7 @@ Packaging::
469
449
  doc/package.rdoc[link:files/doc/package_rdoc.html]
470
450
  Ruby project howto::
471
451
  doc/rubyproject.rdoc[link:files/doc/rubyproject_rdoc.html]
452
+ Using filelists in Rantfiles::
453
+ doc/sys_filelist.rdoc[link:files/doc/sys_filelist_rdoc.html]
472
454
  Rant Overview::
473
455
  README[link:files/README.html]
@@ -0,0 +1,27 @@
1
+
2
+ == Rant libraries
3
+
4
+ The Rant build tool contains much code that can be reused in other
5
+ Ruby applications or libraries. This document provides an overview of
6
+ what is "officially" supported.
7
+
8
+ As Rant matures, more classes will be provided to drive Rant
9
+ programmatically or just to allow reuse of library code.
10
+
11
+ === Rant::FileList class
12
+
13
+ This class provides an abstraction over the <tt>Dir.glob</tt> and
14
+ <tt>File.fnmatch</tt> methods. In many cases it can be used instead of
15
+ the +Find+ module in Ruby's standard library.
16
+
17
+ Read doc/filelist.rdoc[link:files/doc/filelist_rdoc.html] for full
18
+ documentation of the <tt>Rant::FileList</tt> class.
19
+
20
+ == See also
21
+
22
+ Rant Homepage::
23
+ http://make.ruby-co.de
24
+ Rant Overview::
25
+ README[link:files/README.html]
26
+ Rant::FileList documentation::
27
+ doc/filelist.rdoc[link:files/doc/filelist_rdoc.html]
@@ -536,13 +536,26 @@ standard output:
536
536
  # on windows: 'dmd "foo bar.d" util.d -offoo -I"/home/user/program files/d"'
537
537
  # other systems: 'dmd foo\ bar.d util.d -offoo -I/home/user/program\ files/d'
538
538
 
539
+ * <b>regular_filename(path)</b>
540
+
541
+ Replaces all platform dependent filename separators with a slash,
542
+ thus returning a platform independent filename.
543
+
544
+ Examples:
545
+
546
+ # on windows:
547
+ sys.regular_filename('foo\bar') # "foo/bar"
548
+
549
+ # on all platforms:
550
+ sys.regular_filename('foo//bar') # "foo/bar"
551
+
539
552
  * <b>glob(pattern1, pattern2, ...)</b>
540
553
 
541
554
  <b>[pattern1, pattern2, ...]</b>
542
555
 
543
556
  Returns a filelist including the given patterns. For a discussion of
544
- filelists, read <em>Selecting files with filelists</em> in
545
- doc/advanced.rdoc[link:files/doc/advanced_rdoc.html].
557
+ filelists, read
558
+ doc/sys_filelist.rdoc[link:files/doc/sys_filelist_rdoc.html].
546
559
 
547
560
  Examples:
548
561
 
@@ -0,0 +1,118 @@
1
+
2
+ == Using filelists in Rantfiles
3
+
4
+ You can find documentation for Rant's +FileList+ class in the file
5
+ doc/filelist.rdoc[link:files/doc/filelist_rdoc.html]. This document
6
+ describes how you can use filelists in your Rant build scripts
7
+ (Rantfiles).
8
+
9
+ First of all, you don't need to <tt>require</tt> or <tt>import</tt>
10
+ anything to use filelists in Rantfiles. Additionally the
11
+ <tt>Rant::FileList</tt> class is directly available as +FileList+.
12
+ Thus, for example, instead of typing:
13
+
14
+ c_files = Rant::FileList["*.c"]
15
+
16
+ you can type:
17
+
18
+ c_files = FileList["*.c"]
19
+
20
+ Again, you don't need to <tt>require "rant/filelist"</tt>. But if you
21
+ want to use one of the methods +no_dir+, +files+ or +dirs+ <tt>import
22
+ "filelist/std"</tt> is required.
23
+
24
+ Often there are files/directories you want to always ignore when using
25
+ filelists. This could be the "CVS" directories if you are using the
26
+ CVS version control system or simply all backup files.
27
+
28
+ Rant allows you to specify a set of patterns once for your project
29
+ with the <tt>sys.ignore</tt> method.
30
+
31
+ E.g. place the following line of code in your Rantfile:
32
+
33
+ sys.ignore "CVS", /~$/
34
+
35
+ In the Rant::FileList documentation there are five ways to create a
36
+ filelist documented. In Rantfiles:
37
+
38
+ instead of | use
39
+ -----------------------------------------------------------------
40
+ Rant::FileList.new | sys.filelist
41
+ Rant::FileList[*patterns] | sys[*patterns]
42
+ Rant::FileList.glob(*patterns) | sys.glob(*patterns)
43
+ Rant::FileList.glob_all(*patterns) | sys.glob_all(*patterns)
44
+ Rant::FileList(list) | sys.filelist(list)
45
+
46
+ The <tt>sys</tt> variants of filelist creation all honour the project
47
+ wide ignore patterns set by <tt>sys.ignore</tt>.
48
+
49
+ Let's look at an example. First an Rantfile using the "normal"
50
+ filelist constructors:
51
+
52
+ all_files = FileList["**/*"].ignore("CVS", /~$/)
53
+ lib_files = FileList["lib/**/*.rb"].ignore("CVS")
54
+ pkg_files = FileList["bin/*", "lib/**/*.rb", "test/**/*"].ignore("CVS", /~$/)
55
+ backup_files = FileList["**/*~"]
56
+
57
+ # define tasks
58
+
59
+ I admit that the example is a bit exaggerated, but in essence you
60
+ always have to care that you don't accidently include a backup file or
61
+ some file living under a "CVS" directory. Now look at the equivalent
62
+ Rantfile using <tt>sys</tt> to create filelists.
63
+
64
+ sys.ignore "CVS", /~$/
65
+ all_files = sys["**/*"]
66
+ lib_files = sys["lib/**/*.rb"]
67
+ pkg_files = sys["bin/*", "lib/**/*.rb", "test/**/*"]
68
+ backup_files = FileList["**/*~"]
69
+
70
+ # define tasks
71
+
72
+ Now, per default CVS directories and backup files won't appear in
73
+ filelists. We use a "stateless" filelist for +backup_files+, since all
74
+ backup files would be ignored otherwise.
75
+
76
+ == Where to use filelists?
77
+
78
+ Basically, you can use a filelist wherever you can use an array. The
79
+ following is a list of use cases where filelists are handy.
80
+
81
+ * As prerequisite list for a task. Example:
82
+
83
+ # get a list of all c files
84
+ c_files = sys["**/*.c"]
85
+ # get a list of all resulting object files
86
+ obj_files = c_files.ext("o")
87
+
88
+ # static library "foo" depends on all object files
89
+ file "libfoo.a" => obj_files do |t|
90
+ # build t.name from t.prerequisites (obj_files)
91
+ end
92
+
93
+ * As argument to file system operations. Example:
94
+
95
+ task :clean do
96
+ # remove all backup files
97
+ sys.rm_f FileList["**/*~"]
98
+ end
99
+
100
+ * If you want to apply an operation to a list of files, e.g.
101
+ substituting a variable in text files. Example:
102
+
103
+ # Do something with all files in the project
104
+ import "filelist/std"
105
+ sys["**/*"].files.each { |filename|
106
+ # do something with the file "filename"
107
+ }
108
+
109
+ == See also
110
+
111
+ Rant Overview::
112
+ README[link:files/README.html]
113
+ Rant::FileList documentation::
114
+ doc/filelist.rdoc[link:files/doc/filelist_rdoc.html]
115
+ Rantfile basics::
116
+ doc/rantfile.rdoc[link:files/doc/rantfile_rdoc.html]
117
+ Advanced Rantfiles::
118
+ doc/advanced.rdoc[link:files/doc/advanced_rdoc.html]
@@ -13,7 +13,7 @@ module Rant
13
13
  def inspect
14
14
  # what's the right encoding for object_id ?
15
15
  s = "#<#{self.class}:0x#{"%x" % object_id} "
16
- s << "#{@actions.size} actions, #{@files.size} files"
16
+ s << "#{@actions.size} actions, #{@items.size} entries"
17
17
  if @ignore_rx
18
18
  is = @ignore_rx.inspect.gsub(/\n|\t/, ' ')
19
19
  s << ", ignore#{is.squeeze ' '}"
@@ -1,5 +1,5 @@
1
1
 
2
- require 'rant/rantenv'
2
+ require 'rant/init'
3
3
 
4
4
  module Rant
5
5
  # An object extending this module acts as an
@@ -277,7 +277,7 @@ module Rant
277
277
  resources.each { |p|
278
278
  cc_args << " -fresources=#{Env.shell_path(p)}"
279
279
  }
280
- cc_args << " " << sources.arglist if sources
280
+ cc_args << " " << Rant::Sys.sp(sources) if sources
281
281
  cc_args
282
282
  end
283
283
 
@@ -302,7 +302,7 @@ module Rant
302
302
  resources.each { |p|
303
303
  cc_args << " /res:#{Env.shell_path(p)}"
304
304
  }
305
- cc_args << " " << sources.arglist if sources
305
+ cc_args << " " << Rant::Sys.sp(sources) if sources
306
306
  cc_args
307
307
  end
308
308
 
@@ -328,7 +328,7 @@ module Rant
328
328
  resources.each { |p|
329
329
  cc_args << " -resource:#{Env.shell_path(p)}"
330
330
  }
331
- cc_args << " " << sources.arglist if sources
331
+ cc_args << " " << Rant::Sys.sp(sources) if sources
332
332
  cc_args
333
333
  end
334
334
 
@@ -0,0 +1,8 @@
1
+
2
+ # filelist.rb - Define Rant::FileList class.
3
+ #
4
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
5
+
6
+ require 'rant/init'
7
+ require 'rant/import/filelist/core'
8
+ require 'rant/import/filelist/std'
@@ -154,16 +154,16 @@ module Rant::Generators::Archive
154
154
  fl = @files ? @files.dup : []
155
155
  if @manifest
156
156
  fl = read_manifest unless @files
157
- fl = Rant::RacFileList.filelist(@rac, fl)
158
- fl << @manifest
157
+ fl = Rant::FileList(fl)
158
+ fl.keep(@manifest)
159
159
  elsif @files_only
160
- fl = Rant::RacFileList.filelist(@rac, fl)
160
+ fl = Rant::FileList(fl)
161
161
  fl.no_dirs
162
162
  else
163
- fl = Rant::RacFileList.filelist(@rac, fl)
163
+ fl = Rant::FileList(fl)
164
164
  end
165
165
  # remove leading `./' relicts
166
- @res_files = fl.lazy_map! { |fn| fn.sub(/^\.\/(?=.)/,'') }
166
+ @res_files = fl.map! { |fn| fn.sub(/^\.\/(?=.)/,'') }
167
167
  if defined?(@dist_path) && @dist_path
168
168
  # Remove entries from the dist_path directory, which
169
169
  # would create some sort of weird recursion.
@@ -172,7 +172,7 @@ module Rant::Generators::Archive
172
172
  # but since I tapped into this trap frequently now...
173
173
  @res_files.exclude(/^#{Regexp.escape @dist_path}/)
174
174
  end
175
- @res_files.lazy_uniq!.lazy_sort!
175
+ @res_files.uniq!.sort!
176
176
  end
177
177
 
178
178
  # Creates an (eventually) temporary manifest file and yields
@@ -0,0 +1,429 @@
1
+
2
+ # core.rb - Core functionality for the Rant::FileList class.
3
+ #
4
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
5
+
6
+ module Rant
7
+ def FileList(arg)
8
+ if arg.respond_to?(:to_rant_filelist)
9
+ arg.to_rant_filelist
10
+ elsif arg.respond_to?(:to_ary)
11
+ FileList.new(arg.to_ary)
12
+ # or?
13
+ #FileList.new.concat(arg.to_ary)
14
+ else
15
+ raise TypeError,
16
+ "cannot convert #{arg.class} into Rant::FileList"
17
+ end
18
+ end
19
+ module_function :FileList
20
+ class FileList
21
+ include Enumerable
22
+
23
+ ESC_SEPARATOR = Regexp.escape(File::SEPARATOR)
24
+ ESC_ALT_SEPARATOR = File::ALT_SEPARATOR ?
25
+ Regexp.escape(File::ALT_SEPARATOR) : nil
26
+
27
+ class << self
28
+ def [](*patterns)
29
+ new.hide_dotfiles.include(*patterns)
30
+ end
31
+ def glob(*patterns)
32
+ fl = new.hide_dotfiles.ignore(".", "..").include(*patterns)
33
+ if block_given? then yield fl else fl end
34
+ end
35
+ def glob_all(*patterns)
36
+ fl = new.ignore(".", "..").include(*patterns)
37
+ if block_given? then yield fl else fl end
38
+ end
39
+ end
40
+
41
+ def initialize(store = [])
42
+ @pending = false
43
+ @def_glob_dotfiles = true
44
+ @items = store
45
+ @ignore_rx = nil
46
+ @keep = {}
47
+ @actions = []
48
+ end
49
+ alias _object_dup dup
50
+ private :_object_dup
51
+ def dup
52
+ c = _object_dup
53
+ c.items = @items.dup
54
+ c.actions = @actions.dup
55
+ c.ignore_rx = @ignore_rx.dup if @ignore_rx
56
+ c.instance_variable_set(:@keep, @keep.dup)
57
+ c
58
+ end
59
+ def copy
60
+ c = _object_dup
61
+ c.items = @items.map { |entry| entry.dup }
62
+ c.actions = @actions.dup
63
+ c.ignore_rx = @ignore_rx.dup if @ignore_rx
64
+ # alternative approach: copy & freeze "keep" entries on
65
+ # inclusion in the keep hash
66
+ h_keep = {}
67
+ @keep.each_key { |entry| h_keep[entry] = true }
68
+ c.instance_variable_set(:@keep, h_keep)
69
+ c
70
+ end
71
+ # Currently for Rant internal use only. Might go in future
72
+ # releases.
73
+ def glob_dotfiles?
74
+ @def_glob_dotfiles
75
+ end
76
+ # Currently for Rant internal use only. Might go in future
77
+ # releases.
78
+ def glob_dotfiles=(flag)
79
+ @def_glob_dotfiles = flag ? true : false
80
+ end
81
+ # Has the same effect as <tt>glob_dotfiles = false</tt>.
82
+ #
83
+ # Returns self.
84
+ #
85
+ # Currently for Rant internal use only. Might go in future
86
+ # releases.
87
+ def hide_dotfiles
88
+ @def_glob_dotfiles = false
89
+ self
90
+ end
91
+ # Has the same effect as <tt>glob_dotfiles = true</tt>.
92
+ #
93
+ # Returns self.
94
+ #
95
+ # Currently for Rant internal use only. Might go in future
96
+ # releases.
97
+ def glob_dotfiles
98
+ @def_glob_dotfiles = true
99
+ self
100
+ end
101
+
102
+ protected
103
+ attr_accessor :actions, :items
104
+ attr_accessor :pending
105
+ attr_accessor :ignore_rx
106
+
107
+ public
108
+ def each(&block)
109
+ resolve if @pending
110
+ @items.each(&block)
111
+ self
112
+ end
113
+ def to_ary
114
+ resolve if @pending
115
+ @items
116
+ end
117
+ alias to_a to_ary
118
+ alias entries to_ary # entries: defined in Enumerable
119
+ def to_rant_filelist
120
+ self
121
+ end
122
+ def +(other)
123
+ if other.respond_to? :to_rant_filelist
124
+ c = other.to_rant_filelist.dup
125
+ c.actions.concat(@actions)
126
+ c.items.concat(@items)
127
+ c.pending = !c.actions.empty?
128
+ c
129
+ elsif other.respond_to? :to_ary
130
+ c = dup
131
+ c.actions <<
132
+ [:apply_ary_method_1, :concat, other.to_ary.dup]
133
+ c.pending = true
134
+ c
135
+ else
136
+ raise TypeError,
137
+ "cannot add #{other.class} to Rant::FileList"
138
+ end
139
+ end
140
+ # Use this method to append +file+ to this list. +file+ will
141
+ # stay in this list even if it matches an exclude or ignore
142
+ # pattern.
143
+ #
144
+ # Returns self.
145
+ def <<(file)
146
+ @actions << [:apply_ary_method_1, :push, file]
147
+ @keep[file] = true
148
+ @pending = true
149
+ self
150
+ end
151
+ # Add +entry+ to this filelist. Position of +entry+ in this
152
+ # list is undefined. More efficient than #<<. +entry+ will
153
+ # stay in this list even if it matches an exclude or ignore
154
+ # pattern.
155
+ #
156
+ # Returns self.
157
+ def keep(entry)
158
+ @keep[entry] = true
159
+ @items << entry
160
+ self
161
+ end
162
+ # Append the entries of +ary+ (an array like object) to
163
+ # this list.
164
+ def concat(ary)
165
+ if @pending
166
+ ary = ary.to_ary.dup
167
+ @actions << [:apply_ary_method_1, :concat, ary]
168
+ else
169
+ ix = ignore_rx and ary = ary.to_ary.reject { |f| f =~ ix }
170
+ @items.concat(ary)
171
+ end
172
+ self
173
+ end
174
+ # Number of entries in this filelist.
175
+ def size
176
+ resolve if @pending
177
+ @items.size
178
+ end
179
+ alias length size
180
+ def empty?
181
+ resolve if @pending
182
+ @items.empty?
183
+ end
184
+ def join(sep = ' ')
185
+ resolve if @pending
186
+ @items.join(sep)
187
+ end
188
+ def pop
189
+ resolve if @pending
190
+ @items.pop
191
+ end
192
+ def push(entry)
193
+ resolve if @pending
194
+ @items.push(entry) if entry !~ ignore_rx
195
+ self
196
+ end
197
+ def shift
198
+ resolve if @pending
199
+ @items.shift
200
+ end
201
+ def unshift(entry)
202
+ resolve if @pending
203
+ @items.unshift(entry) if entry !~ ignore_rx
204
+ self
205
+ end
206
+ if Object.method_defined?(:fcall) || Object.method_defined?(:funcall) # in Ruby 1.9 like __send__
207
+ @@__send_private__ = Object.method_defined?(:fcall) ? :fcall : :funcall
208
+ def resolve
209
+ @pending = false
210
+ @actions.each{ |action| self.__send__(@@__send_private__, *action) }.clear
211
+ ix = ignore_rx
212
+ if ix
213
+ @items.reject! { |f| f =~ ix && !@keep[f] }
214
+ end
215
+ self
216
+ end
217
+ else
218
+ # Force evaluation of all patterns.
219
+ def resolve
220
+ @pending = false
221
+ @actions.each{ |action| self.__send__(*action) }.clear
222
+ ix = ignore_rx
223
+ if ix
224
+ @items.reject! { |f| f =~ ix && !@keep[f] }
225
+ end
226
+ self
227
+ end
228
+ end
229
+ # Include entries matching one of +patterns+ in this filelist.
230
+ def include(*pats)
231
+ @def_glob_dotfiles ? glob_all(*pats) : glob_unix(*pats)
232
+ end
233
+ alias glob include
234
+ # Unix style glob: hide files starting with a dot
235
+ def glob_unix(*patterns)
236
+ patterns.flatten.each { |pat|
237
+ @actions << [:apply_glob_unix, pat]
238
+ }
239
+ @pending = true
240
+ self
241
+ end
242
+ def glob_all(*patterns)
243
+ patterns.flatten.each { |pat|
244
+ @actions << [:apply_glob_all, pat]
245
+ }
246
+ @pending = true
247
+ self
248
+ end
249
+ if RUBY_VERSION < "1.8.2"
250
+ # Dir.glob of Ruby releases before 1.8.2 returned dotfiles
251
+ # even if File::FNM_DOTMATCH was not set.
252
+ FN_DOTFILE_RX_ = ESC_ALT_SEPARATOR ?
253
+ /(^|(#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+)\..*
254
+ ((#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+|$)/x :
255
+ /(^|#{ESC_SEPARATOR}+)\..* (#{ESC_SEPARATOR}+|$)/x
256
+ def apply_glob_unix(pattern)
257
+ inc_files = Dir.glob(pattern)
258
+ # it's not 100% correct, but it works for most use
259
+ # cases
260
+ unless pattern =~ /(^|\/)\./
261
+ inc_files.reject! { |fn| fn =~ FN_DOTFILE_RX_ }
262
+ end
263
+ @items.concat(inc_files)
264
+ end
265
+ else
266
+ def apply_glob_unix(pattern)
267
+ @items.concat(Dir.glob(pattern))
268
+ end
269
+ end
270
+ private :apply_glob_unix
271
+ def apply_glob_all(pattern)
272
+ @items.concat(Dir.glob(pattern, File::FNM_DOTMATCH))
273
+ end
274
+ private :apply_glob_all
275
+ # Exclude all entries matching one of +patterns+ from this
276
+ # filelist.
277
+ #
278
+ # Note: Only applies to entries previousely included.
279
+ def exclude(*patterns)
280
+ patterns.each { |pat|
281
+ if Regexp === pat
282
+ @actions << [:apply_exclude_rx, pat]
283
+ else
284
+ @actions << [:apply_exclude, pat]
285
+ end
286
+ }
287
+ @pending = true
288
+ self
289
+ end
290
+ def ignore(*patterns)
291
+ patterns.each { |pat|
292
+ add_ignore_rx(Regexp === pat ? pat : mk_all_rx(pat))
293
+ }
294
+ @pending = true
295
+ self
296
+ end
297
+ def add_ignore_rx(rx)
298
+ @ignore_rx =
299
+ if @ignore_rx
300
+ Regexp.union(@ignore_rx, rx)
301
+ else
302
+ rx
303
+ end
304
+ end
305
+ private :add_ignore_rx
306
+ def apply_exclude(pattern)
307
+ @items.reject! { |elem|
308
+ File.fnmatch?(pattern, elem, File::FNM_DOTMATCH) && !@keep[elem]
309
+ }
310
+ end
311
+ private :apply_exclude
312
+ def apply_exclude_rx(rx)
313
+ @items.reject! { |elem|
314
+ elem =~ rx && !@keep[elem]
315
+ }
316
+ end
317
+ private :apply_exclude_rx
318
+ def exclude_name(*names)
319
+ names.each { |name|
320
+ @actions << [:apply_exclude_rx, mk_all_rx(name)]
321
+ }
322
+ @pending = true
323
+ self
324
+ end
325
+ alias shun exclude_name
326
+ if File::ALT_SEPARATOR
327
+ # TODO: check for FS case sensitivity?
328
+ def mk_all_rx(file)
329
+ /(^|(#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+)#{Regexp.escape(file)}
330
+ ((#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+|$)/x
331
+ end
332
+ else
333
+ def mk_all_rx(file)
334
+ /(^|#{ESC_SEPARATOR}+)#{Regexp.escape(file)}
335
+ (#{ESC_SEPARATOR}+|$)/x
336
+ end
337
+ end
338
+ private :mk_all_rx
339
+ def exclude_path(*patterns)
340
+ patterns.each { |pat|
341
+ @actions << [:apply_exclude_path, pat]
342
+ }
343
+ @pending = true
344
+ self
345
+ end
346
+ def apply_exclude_path(pattern)
347
+ flags = File::FNM_DOTMATCH|File::FNM_PATHNAME
348
+ @items.reject! { |elem|
349
+ File.fnmatch?(pattern, elem, flags) && !@keep[elem]
350
+ }
351
+ end
352
+ private :apply_exclude
353
+ def select(&block)
354
+ d = dup
355
+ d.actions << [:apply_select, block]
356
+ d.pending = true
357
+ d
358
+ end
359
+ alias find_all select
360
+ def apply_select blk
361
+ @items = @items.select(&blk)
362
+ end
363
+ private :apply_select
364
+ def map(&block)
365
+ d = dup
366
+ d.actions << [:apply_ary_method, :map!, block]
367
+ d.pending = true
368
+ d
369
+ end
370
+ alias collect map
371
+ def sub_ext(ext, new_ext=nil)
372
+ map { |f| f._rant_sub_ext ext, new_ext }
373
+ end
374
+ def ext(ext_str)
375
+ sub_ext(ext_str)
376
+ end
377
+ # Get a string with all entries. This is very usefull
378
+ # if you invoke a shell:
379
+ # files # => ["foo/bar", "with space"]
380
+ # sh "rdoc #{files.arglist}"
381
+ # will result on windows:
382
+ # rdoc foo\bar "with space"
383
+ # on other systems:
384
+ # rdoc foo/bar with\ space
385
+ def arglist
386
+ Rant::Sys.sp to_ary
387
+ end
388
+ alias to_s arglist
389
+ alias object_inspect inspect
390
+ # Same as #uniq! but evaluation is delayed until the next read
391
+ # access (e.g. by calling #each). Always returns self.
392
+ def uniq!
393
+ @actions << [:apply_ary_method, :uniq!]
394
+ @pending = true
395
+ self
396
+ end
397
+ # Same as #sort! but evaluation is delayed until the next read
398
+ # access (e.g. by calling #each). Always returns self.
399
+ def sort!
400
+ @actions << [:apply_ary_method, :sort!]
401
+ @pending = true
402
+ self
403
+ end
404
+ # Same as #map! but evaluation is delayed until the next read
405
+ # access (e.g. by calling #each). Always returns self.
406
+ def map!(&block)
407
+ @actions << [:apply_ary_method, :map!, block]
408
+ @pending = true
409
+ self
410
+ end
411
+ def reject!(&block)
412
+ @actions << [:apply_ary_method, :reject!, block]
413
+ @pending = true
414
+ self
415
+ end
416
+ private
417
+ def apply_ary_method(meth, block=nil)
418
+ @items.send meth, &block
419
+ end
420
+ def apply_ary_method_1(meth, arg1, block=nil)
421
+ @items.send meth, arg1, &block
422
+ end
423
+ =begin
424
+ def apply_lazy_operation(meth, args, block)
425
+ @items.send(meth, *args, &block)
426
+ end
427
+ =end
428
+ end # class FileList
429
+ end # module Rant