rant 0.5.0 → 0.5.2

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