rant 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
data/NEWS CHANGED
@@ -1,6 +1,36 @@
1
1
 
2
2
  = Rant NEWS
3
3
 
4
+ == Rant 0.5.2
5
+
6
+ Incompatible changes:
7
+ * The two undocumented Array methods <tt>ary.arglist</tt> and
8
+ <tt>ary.shell_pathes</tt>, which are deprecated since release 0.4.8,
9
+ are removed with this release. Use <tt>sys.sp(ary)</tt>
10
+ in Rantfiles instead.
11
+ * The method +rac+ which is deprecated since release 0.4.6 is gone.
12
+ * Filelists no longer respond to all Array methods. To use the
13
+ filelist method +no_dir+, <tt>import "filelist/std"</tt> is required
14
+ now. See below for documentation links.
15
+
16
+ Fixes and minor improvements:
17
+ * A bug in the YAML library of Ruby 1.8.3/1.8.4-preview1 prevented
18
+ created gems to work with other ruby versions. Since this Rant
19
+ release gems created with a RubyPackage task and Ruby 1.8.3 will
20
+ work with all Ruby versions (with gem support, of course).
21
+ * Fixed bug where the method <tt>Rant::Sys.split_all</tt> would drop
22
+ a leading dot directory (e.g. as in "./foo/bar").
23
+ * New method <tt>Rant::Sys.regular_filename</tt> for filename
24
+ conversion.
25
+
26
+ New features:
27
+ * Major rework of filelist support. The Rant::FileList class is
28
+ available as "normal" Ruby library now. Read
29
+ doc/filelist.rdoc[link:files/doc/filelist_rdoc.html] for
30
+ Rant::FileList documentation and
31
+ doc/sys_filelist.rdoc[link:files/doc/sys_filelist_rdoc.html] for
32
+ instructions on how to use filelists in Rantfiles.
33
+
4
34
  == Rant 0.5.0
5
35
 
6
36
  Incompatible changes:
data/README CHANGED
@@ -42,7 +42,7 @@ Running rant in the directory of this file:
42
42
  will ensure that the "data" file in the "backup" directory is up to
43
43
  date.
44
44
 
45
- This document was written for version 0.5.0 of Rant. Most things
45
+ This document was written for version 0.5.2 of Rant. Most things
46
46
  described here will work for older/newer versions of Rant, but look at
47
47
  the README file in the Rant distribution you've installed for exact
48
48
  documentation of your Rant version.
@@ -96,6 +96,9 @@ Upgrading::
96
96
  read the NEWS[link:files/NEWS.html] for new features, not
97
97
  backwards compatible changes and other issues.
98
98
 
99
+ Using Rant libraries::
100
+ read doc/rubylib.rdoc[link:files/doc/rubylib_rdoc.html]
101
+
99
102
  == Copying
100
103
 
101
104
  Copyright (C) 2005 Stefan Lang
data/Rantfile CHANGED
@@ -4,12 +4,18 @@
4
4
  import "md5"
5
5
  import %w(rubytest rubydoc rubypackage autoclean win32/rubycmdwrapper sys/more)
6
6
 
7
+ ENV["RANT_DEV_LIB_DIR"] = sys.expand_path("lib")
8
+
7
9
  task :default => :test
8
10
 
9
- dist_files = sys["{bin,lib,test,doc,misc}/**/*"]
10
- dist_files.shun("html", "coverage")
11
- dist_files += sys["*"].no_dir.exclude("InstalledFiles", "Session.vim")
12
- dist_files.exclude("mk", "bench-*")
11
+ dist_files = sys.filelist [
12
+ "NEWS", "README", "INSTALL", "COPYING",
13
+ "Rantfile", "install.rb", "setup.rb",
14
+ "run_rant", "run_import"
15
+ ]
16
+ dist_files.glob_unix "{bin,lib,test,doc,misc}/**/*"
17
+ dist_files.exclude_name "html", "coverage"
18
+
13
19
  hp_files = sys["doc/homepage/*"]
14
20
  rdoc_files = sys["README", "NEWS", "INSTALL", "doc/*.rdoc"]
15
21
 
@@ -135,9 +141,23 @@ gen RubyTest, :tc do |t|
135
141
  end
136
142
 
137
143
  desc "Run all tests."
138
- gen RubyTest, :tall do |g|
139
- g.libs << "test"
140
- g.test_files = sys["test/**/test_*.rb"]
144
+ task :tall do
145
+ puts "Running build tool tests..."
146
+ make "trantfile"
147
+ puts "Build tool tests successful."
148
+ puts "Running library tests..."
149
+ make "tlib"
150
+ puts "All tests (build tool and library) successful."
151
+ end
152
+
153
+ gen RubyTest, :trantfile do |t|
154
+ t.libs << "test"
155
+ t.test_files = sys["test/**/test_*.rb"].exclude("test/lib/*")
156
+ end
157
+
158
+ gen RubyTest, :tlib do |t|
159
+ t.libs << "test"
160
+ t.test_files = sys["test/lib/**/test_*.rb"]
141
161
  end
142
162
 
143
163
  task :t180 do |t|
@@ -238,7 +258,7 @@ task "rb-stats" do
238
258
  puts " #{lines} total lines"
239
259
  puts " #{code_lines} LOC"
240
260
 
241
- files.exclude(%r{^lib/rant/archive})
261
+ files.exclude("lib/rant/archive*")
242
262
 
243
263
  lines = 0
244
264
  code_lines = 0
@@ -12,16 +12,16 @@ string or symbol. Symbols as variable names are converted to strings.
12
12
  Now you can access the "manifest" variable in every Rantfile of your
13
13
  project:
14
14
  file "MANIFEST" do |t|
15
- open(t.name, "w") { |f|
16
- var[:manifest].each { |str| f.puts(str) }
17
- }
15
+ open(t.name, "w") { |f|
16
+ var[:manifest].each { |str| f.puts(str) }
17
+ }
18
18
  end
19
19
 
20
20
  Arguments of the form VAR=VAL to the rant command are also available
21
21
  through +var+:
22
22
  % cat Rantfile
23
23
  task :show_test do
24
- puts var[:test]
24
+ puts var[:test]
25
25
  end
26
26
  % rant
27
27
  nil
@@ -34,57 +34,6 @@ subprocesses, like CC or CFLAGS:
34
34
  The variables CC and CFLAGS are available through +var+ as always and
35
35
  are mapped to environment variables.
36
36
 
37
- === The "ignore" variable
38
-
39
- The "ignore" variable is a list of files/regular expressions which are
40
- ignored when selecting files with the +sys+ command:
41
- var[:ignore] = ["CVS", /~$/]
42
- If you select files with <tt>sys[]</tt> now, the lists won't contain
43
- any directory/file named "CVS" or ending in ~. Examples would be:
44
- CVS
45
- src/CVS
46
- src/CVS/xy
47
- xy~
48
- src/util.c~
49
-
50
- === Selecting files with filelists
51
-
52
- The sys[] operator actually returns a _filelist_ object, which behaves
53
- similar to an array. There are many methods for filelist objects, here
54
- is a brief overview:
55
-
56
- # create a filelist containing all files in the current directory
57
- # and in the src directory
58
- fl = sys["*", "src/*"]
59
-
60
- # remove all files from the list which end in .bak
61
- fl.exclude "*.bak"
62
-
63
- # add all .rb files in directories lib and test
64
- fl.include "lib/*.rb", "test/*.rb"
65
-
66
- # remove all files from the list which contain the path element
67
- # "coverage" (e.g.: test/coverage/ lib/coverage/main.c)
68
- fl.exclude_all "coverage"
69
-
70
- # add a single file to the list
71
- fl << "doc/README"
72
-
73
- # get a new filelist containing only directories, fl isn't
74
- # modified:
75
- dirs = fl.select { |f| File.directory? f }
76
-
77
- # create a manifest file
78
- open("MANIFEST", "w") { |f| f.puts fl }
79
-
80
- sources = sys["*.c"]
81
- # substitute all filename extensions with .o
82
- objs = sources.sub_ext "o"
83
-
84
- Additionally, you can use all methods available for an array. Lookup
85
- docs with ri for array methods:
86
- % ri Array
87
-
88
37
  === Cleaning up generated files
89
38
 
90
39
  Use the +Clean+ generator in your Rantfiles:
@@ -127,7 +76,7 @@ any filetask (including those created by rules):
127
76
  var[:clean].include "**/*.bak"
128
77
 
129
78
  TAKE CARE:: AutoClean will recursively remove directories for which
130
- a task exists. Meaning:
79
+ a task exists. Meaning:
131
80
  gen Directory, "doc/html"
132
81
  AutoClean will recursively remove the doc directory!
133
82
 
@@ -147,7 +96,7 @@ This creates (amongst the other two tasks) a task for the "doc"
147
96
  directory, thus AutoClean will recursively unlink the "doc" directory.
148
97
 
149
98
  gen SubFile, "doc", "html/index.html" do |t|
150
- # do something
99
+ # do something
151
100
  end
152
101
  This doesn't create a task for the "doc" directory, thus AutoClean
153
102
  will only unlink the "doc/html" directory.
@@ -161,7 +110,7 @@ directory.
161
110
  import "directedrule"
162
111
 
163
112
  ro = gen DirectedRule, "obj" => sys["src_*"], :o => :c do |t|
164
- sys "cc -c -o #{t.name} #{t.source}"
113
+ sys "cc -c -o #{t.name} #{t.source}"
165
114
  end
166
115
 
167
116
  This rule produces a file task for targets in the obj/ directory
@@ -213,11 +162,11 @@ And now try to set the count variable from the commandline:
213
162
  5
214
163
  % rant count=-1
215
164
  rant: [ERROR] in file `/home/stefan/tmp/Rantfile', line 2:
216
- "-1" doesn't match constraint: integer 0..10
165
+ "-1" doesn't match constraint: integer 0..10
217
166
  rant aborted!
218
167
  % rant count=100
219
168
  rant: [ERROR] in file `/home/stefan/tmp/Rantfile', line 2:
220
- "100" doesn't match constraint: integer 0..10
169
+ "100" doesn't match constraint: integer 0..10
221
170
  rant aborted!
222
171
 
223
172
  Other available constraints:
@@ -241,8 +190,8 @@ duplicate it in a file called +version+, which contains just a line
241
190
  with the program version. One solution to automate the +version+ file
242
191
  creation would be to write a file task:
243
192
  file "version" => "config.h" do |t|
244
- puts "updating version file"
245
- open("w", t.name) { |f| f.puts(extract_config_version()) }
193
+ puts "updating version file"
194
+ open("w", t.name) { |f| f.puts(extract_config_version()) }
246
195
  end
247
196
  and make all other tasks that need this version dependent on it. But
248
197
  this can get very tedious if you have many tasks that need this
@@ -250,17 +199,17 @@ version file. Another solution is to just run the task every time the
250
199
  Rantfile is sourced. This can be achieved by replacing the +file+
251
200
  command with the +make+ command:
252
201
  make "version" => "config.h" do |t|
253
- puts "updating version file"
254
- open("w", t.name) { |f| f.puts(extract_config_version()) }
202
+ puts "updating version file"
203
+ open("w", t.name) { |f| f.puts(extract_config_version()) }
255
204
  end
256
205
  This creates a file task like before and tells rant to immediately
257
206
  invoke all tasks that are required to build the version file. But
258
207
  imagine your users just want to see the list of available tasks:
259
208
  % rant --tasks
260
209
  updating version file
261
- rant foo # build foo program
262
- rant lib # build libfoo.so
263
- rant clean # remove generated files
210
+ rant foo # build foo program
211
+ rant lib # build libfoo.so
212
+ rant clean # remove generated files
264
213
  Hmm, we really didn't need the version to show our users the available
265
214
  tasks. To avoid this, wrap such code in an Action:
266
215
  gen Action do
@@ -271,9 +220,9 @@ tasks. To avoid this, wrap such code in an Action:
271
220
  end
272
221
  And now on a clean source base:
273
222
  % rant --tasks
274
- rant foo # build foo program
275
- rant lib # build libfoo.so
276
- rant clean # remove generated files
223
+ rant foo # build foo program
224
+ rant lib # build libfoo.so
225
+ rant clean # remove generated files
277
226
  OK. Didn't confuse our users! Run any task:
278
227
  % rant foo
279
228
  updating version file
@@ -0,0 +1,963 @@
1
+
2
+ == Rant::FileList
3
+
4
+ A +FileList+ object is in essence a list of path names. It behaves
5
+ similar to an array of strings, but provides useful methods to include
6
+ files based on so called "glob" patterns, i.e. strings containing
7
+ wildcards and similar special characters.
8
+
9
+ The examples in this document show how to use the +FileList+ class as
10
+ library from other ruby applications/libraries.
11
+
12
+ To use the <tt>Rant::FileList</tt> class, you must <tt>require
13
+ "rant/filelist"</tt> first. This will define the following constants:
14
+
15
+ Rant:: Module, used as namespace for all Rant code.
16
+ Rant::VERSION:: The Rant version in use, e.g. <tt>"0.5.2"</tt>.
17
+ Rant::FileList:: The filelist class.
18
+ Rant::Sys:: With method +regular_filename+.
19
+
20
+ It is recommended to *not* <tt>include Rant</tt> at the toplevel for
21
+ use in libraries or bigger applications. A better technique is to
22
+ assign often used constants to shorter names, e.g.:
23
+
24
+ FileList = Rant::FileList
25
+
26
+ Some method documentations contain an <em>Implementation Note</em>.
27
+ These notes are provided for better understanding. The actual
28
+ implementation might change.
29
+
30
+ === Creating a Rant::FileList
31
+
32
+ There a five ways to obtain a +FileList+ object:
33
+
34
+ * <b>Rant::FileList.new</b>
35
+
36
+ Creates an empty filelist.
37
+
38
+ Examples:
39
+
40
+ require 'rant/filelist'
41
+
42
+ fl = Rant::FileList.new
43
+ fl.entries # => []
44
+
45
+ fl.include("*README*")
46
+ fl.entries # => ["README", ".README.swp"]
47
+
48
+
49
+ * <b>Rant::FileList[*patterns]</b>
50
+
51
+ Create a filelist which contains all file names matching one of
52
+ +patterns+. Each of +patterns+ is a glob pattern as described under
53
+ <em>Glob pattern syntax</em>.
54
+
55
+ Per default, all files/directories starting with a dot are ignored,
56
+ unless a pattern explicitely matches names starting with a dot.
57
+
58
+ Examples:
59
+
60
+ require 'rant/filelist'
61
+
62
+ # Create a filelist containing all file names ending in ".c" from
63
+ # the current directory
64
+ fl = Rant::FileList["*.c"]
65
+ fl.entries # => ["main.c", "util.c"]
66
+
67
+ # Create a filelist containing the "README" file from the current
68
+ # directory (if it exists) and all files ending in ".rdoc" under
69
+ # the "doc" directory and its subdirectories.
70
+ fl = Rant::FileList["README", "doc/**/*.rdoc"]
71
+ fl.entries # => ["README", "doc/foo.rdoc", "doc/html/emit.rdoc", "doc/tutorials/html/creating.rdoc"]
72
+
73
+ # Create a filelist containing all files starting with a dot and
74
+ # ending in ".rdoc" under the "doc" directory.
75
+ fl = Rant::FileList["doc/.*.rdoc"]
76
+ fl.entries # => ["doc/.bar.rdoc"]
77
+
78
+ Note:: The order of the file names in the filelist
79
+ and in the array returned by the +entries+
80
+ method is unspecified.
81
+
82
+ Implementation Note:: Equivalent to
83
+ <code>Rant::FileList.new.hide_dotfiles.include(*patterns)</code>
84
+
85
+ * <b>Rant::FileList.glob(*patterns) { |filelist| ... }</b>
86
+
87
+ The same as <tt>Rant::FileList[*patterns]</tt> but yields the
88
+ new filelist to the block if a block is given. Additionally, it
89
+ won't include the "." (current) and ".." (parent) directory entries.
90
+
91
+ If a block is given, returns the return value of the block,
92
+ otherwise the new filelist.
93
+
94
+ Examples:
95
+
96
+ require 'rant/filelist'
97
+
98
+ Rant::FileList.glob("*.*) do |fl|
99
+ fl.exclude "*.bak", "*~"
100
+ fl.entries
101
+ end # => ["README.txt", "setup.rb"]
102
+
103
+ fl = Rant::FileList.glob(".*")
104
+ fl.entries # => [".svn", ".README.txt.swp"]
105
+
106
+ # compare the last example with the result of using
107
+ # Rant::FileList.new:
108
+ fl = Rant::FileList.new(".*")
109
+ fl.entries # => [".", "..", ".svn", ".README.txt.swp"]
110
+
111
+ Implementation Note:: Before the given block is called, the filelist
112
+ is created and initialized with
113
+ <code>Rant::FileList.new.hide_dotfiles.ignore(".",
114
+ "..").include(*patterns)</code>
115
+
116
+ * <b>Rant::FileList.glob_all(*patterns) { |filelist| ... }</b>
117
+
118
+ The same as <tt>Rant::FileList.glob(*patterns)</tt> but also
119
+ includes files starting with a dot.
120
+
121
+ Examples:
122
+
123
+ require 'rant/filelist'
124
+
125
+ Rant::FileList.glob_all("*.*) do |fl|
126
+ fl.exclude "*.bak", "*~"
127
+ fl.entries
128
+ end # => ["README.txt", "setup.rb", ".README.txt.swp"]
129
+
130
+ Implementation Note:: Before the given block is called, the filelist
131
+ is created and initialized with
132
+ <code>Rant::FileList.new.ignore(".",
133
+ "..").include(*patterns)</code>
134
+
135
+ * <b>Rant::FileList(arg)</b>
136
+
137
+ Tries to convert +arg+ to an Rant::FileList object.
138
+
139
+ If +arg+ responds to +to_rant_filelist+, the result of
140
+ <tt>arg.to_rant_filelist</tt> is returned.
141
+
142
+ If +arg+ responds to +to_ary+, a new filelist object containing the
143
+ entries of <tt>arg.to_ary</tt> is returned.
144
+
145
+ Note that changes to the returned filelist might cause changes to
146
+ +arg+.
147
+
148
+ Examples:
149
+
150
+ require 'rant/filelist'
151
+
152
+ fl = Rant::FileList.new
153
+ Rant::FileList(fl) # => fl
154
+
155
+ # convert array to filelist
156
+ a = ["foo", "bar"]
157
+ fl = Rant::FileList(a) # => new Rant::FileList
158
+ fl.entries # => ["foo", "bar"]
159
+
160
+ # obj doesn't respond to one of to_rant_filelist, to_ary
161
+ obj = Object.new
162
+ fl = Rant::FileList(obj) # => raises TypeError
163
+
164
+ === Rant::FileList instance methods
165
+
166
+ The <tt>Rant::FileList</tt> class includes the +Enumerable+ module.
167
+ Thus you can call all methods provided by the +Enumerable+ module on
168
+ +FileList+ instances. You can read the +ri+ documentation for those
169
+ methods:
170
+
171
+ % ri Enumerable
172
+
173
+ Note that the methods +map+ (alias +collect+) and +select+ (alias
174
+ +find_all+) have slightly different semantics as documented by
175
+ +Enumerable+. Read below for documentation.
176
+
177
+ Most <tt>Rant::FileList</tt> instance methods are _lazy_. This means
178
+ that the actual work (e.g. glob pattern expansion) isn't done unless
179
+ the filelists entries are being read.
180
+
181
+ Following is a list of <tt>Rant::FileList</tt> instance methods. All
182
+ lazy methods are marked with <em>-lazy-</em>. All methods that force
183
+ evaluation of previously specified lazy operations, are marked with
184
+ <em>-eager-</em>. Note that not all methods marked with
185
+ <em>-eager-</em> are guaranteed to hold this predicate in future
186
+ versions. The <em>-eager-</em> marker is just intended as additional
187
+ information. To force execution of all previously lazy operations,
188
+ call the +resolve+ method.
189
+
190
+ rb_names = Rant::FileList["**/*.rb"].map { |fn| File.basename(fn) }
191
+
192
+ # force expansion of the glob pattern "**/*.rb" and execution of
193
+ # the map operation
194
+ rb_names.resolve
195
+
196
+ Note that you need to call +resolve+ only if the actual point in time
197
+ of execution is important, e.g. this could be if a map operation has
198
+ side effects like printing to standard output.
199
+
200
+ * <b>glob_unix(*patterns)</b> <em>-lazy-</em>
201
+
202
+ Include the file names specified by the glob patterns +patterns+.
203
+ For exact glob pattern syntax read the section <em>Glob pattern
204
+ syntax</em> below.
205
+
206
+ Filenames starting with a dot ignored, unless explicitely matched
207
+ by a pattern (e.g. ".*").
208
+
209
+ Returns +self+.
210
+
211
+ Examples:
212
+
213
+ require 'rant/filelist'
214
+ fl = Rant::FileList.new
215
+ fl.include "**/*.{c,h}", "main.cpp"
216
+ fl.entries # => ["lib/util.c", "include/util.h", "config.h", "main.cpp"]
217
+
218
+ Note:: No specific order of entries included with this method is
219
+ guaranteed.
220
+
221
+ * <b>glob_all(*patterns)</b> <em>-lazy-</em>
222
+
223
+ Same as <tt>glob_unix(*patterns)</tt> but no special handling of
224
+ filenames starting with a dot.
225
+
226
+ Examples:
227
+
228
+ require 'rant/filelist'
229
+ fl = Rant::FileList.new
230
+ fl.include "**/*.{c,h}", "main.cpp"
231
+ fl.entries # => ["lib/.util.c", "lib/util.c", "include/util.h", "config.h", "main.cpp"]
232
+
233
+ * <b>include(*patterns)</b> <em>-lazy-</em>
234
+
235
+ <b>glob(*patterns)</b>
236
+
237
+ Include the file names specified by the glob patterns +patterns+.
238
+ For exact glob pattern syntax read the section <em>Glob pattern
239
+ syntax</em> below.
240
+
241
+ Each filelist has a flag that indicates wheter a glob operation
242
+ should hide dotfiles or not. It can be read with the method
243
+ <tt>glob_dotfiles?</tt>, and set with the method
244
+ <tt>glob_dotfiles=</tt> to either +true+ or +false+. For filelists
245
+ created with <tt>Rant::FileList.new</tt> or
246
+ <tt>Rant::FileList.glob_all()</tt> this flag is +true+ per default.
247
+ For filelists created with <tt>Rant::FileList[]</tt> or
248
+ <tt>Rant::FileList.glob()</tt> this flag is +false+ per default.
249
+ If this flag is true, the +glob+ (alias +include+) method calls
250
+ <tt>glob_all(*patterns)</tt>, otherwise it calls
251
+ <tt>glob_unix(*patterns)</tt>.
252
+
253
+ Returns +self+.
254
+
255
+ Examples:
256
+
257
+ require 'rant/filelist'
258
+ fl = Rant::FileList.new
259
+ fl.include "**/*.{c,h}", "main.cpp"
260
+ fl.entries # => ["lib/.util.c", "lib/util.c", "include/util.h", "config.h", "main.cpp"]
261
+
262
+ fl = Rant::FileList.new
263
+ fl.glob_dotfiles = false
264
+ fl.include "**/*.{c,h}", "main.cpp"
265
+ fl.entries # => ["lib/util.c", "include/util.h", "config.h", "main.cpp"]
266
+
267
+ Note:: No specific order of entries included with this method is
268
+ guaranteed.
269
+
270
+ * <b>exclude(*patterns)</b> <em>-lazy-</em>
271
+
272
+ Remove all entries matching one of +patterns+. Each of +patterns+ is
273
+ either a regular expression or a glob pattern as described under the
274
+ section <em>Glob pattern syntax</em>, *except* that *currently* the
275
+ characters <tt>{</tt> and <tt>}</tt> (curly braces) are not treated
276
+ special.
277
+
278
+ A call to +exclude+ does not effect entries added later to the
279
+ filelist.
280
+
281
+ Returns +self+.
282
+
283
+ Examples:
284
+
285
+ require 'rant/filelist'
286
+ fl = Rant::FileList["*.c"]
287
+ fl.entries # => ["main.c", "main.c~"]
288
+ fl.exclude("*~")
289
+ fl.entries # => ["main.c"]
290
+ fl.include("*.h")
291
+ fl.entries # => ["main.c", "main.h", "main.h~"]
292
+ fl.exclude(/~$/)
293
+ fl.entries # => ["main.c", "main.h"]
294
+
295
+ * <b>exclude_path(*patterns)</b> <em>-lazy-</em>
296
+
297
+ Like <tt>exclude(*patterns)</tt>, but doesn't accept regular
298
+ expressions and the metacharacters in the patterns are treated more
299
+ restrictive. Wildcards ("*") and "?" won't match filename
300
+ separators.
301
+
302
+ Returns +self+.
303
+
304
+ Examples:
305
+
306
+ # exclude vs. exclude_path
307
+ fl1 = Rant::FileList["**/*.rb"]
308
+ fl1.entries # => ["setup.rb", "lib/foo.rb"]
309
+
310
+ fl2 = fl1.dup
311
+ fl2.entries # => ["setup.rb", "lib/foo.rb"]
312
+
313
+ fl1.exclude "*.rb"
314
+ fl2.exclude_path "*.rb"
315
+
316
+ fl1.entries # => []
317
+ fl2.entries # => ["lib/foo.rb"]
318
+
319
+ # another one
320
+ fl = Rant::FileList(["a.rb", "lib/b.rb", "lib/foo/c.rb"])
321
+ fl.exclude_path "lib/*.rb"
322
+ fl.entries # => ["a.rb", "lib/foo/c.rb"]
323
+
324
+ Note:: The method +exclude_path+ provides an
325
+ abstraction over the
326
+ <tt>File::FNM_PATHNAME</tt> flag for the
327
+ <tt>File.fnmatch</tt> method.
328
+
329
+ * <b>exclude_name(*names)</b> <em>-lazy-</em>
330
+
331
+ <b>shun(*names)</b>
332
+
333
+ Remove all entries whose base name or one of its parent directory
334
+ names is in +names+.
335
+
336
+ A call to +exclude_name+ (or +shun+) does not effect entries added
337
+ later to the filelist.
338
+
339
+ Returns +self+.
340
+
341
+ Examples:
342
+
343
+ require 'rant/filelist'
344
+ fl = Rant::FileList["**/*"]
345
+ fl.entries # => ["CVS", "README", "README.CVS", "sub/CVS", "sub/README", "sub/CVS/foo", "sub/foo/bar"]
346
+ fl.exclude_name("CVS")
347
+ fl.entries # => ["README", "README.CVS", "sub/README", "sub/foo/bar"]
348
+
349
+ * <b>ignore(*patterns)</b> <em>-lazy-</em>
350
+
351
+ This filelist will never contain an entry matching one of
352
+ +patterns+. Each element of +patterns+ is either a regular
353
+ expression or a string. If the pattern is a string it matches all
354
+ entries which have the string as base name or parent directory name
355
+ (like +exclude_name+).
356
+
357
+ This method applies to all previously added entries and to all
358
+ entries that will be added in the future.
359
+
360
+ Returns +self+.
361
+
362
+ Examples:
363
+
364
+ fl = Rant::FileList["**/*"]
365
+ fl.entries # => ["CVS", "README", "README.CVS", "sub/CVS", "sub/README", "sub/CVS/foo", "sub/foo/bar"]
366
+
367
+ fl.ignore("CVS")
368
+ fl.entries # => ["README", "README.CVS", "sub/README", "sub/foo/bar"]
369
+
370
+ fl.concat("dir/CVS", "dir")
371
+ # note that fl doesn't contain "dir/CVS"
372
+ fl.entries # => ["README", "README.CVS", "sub/README", "sub/foo/bar", "dir"]
373
+
374
+ * <b>files</b> <em>-lazy-</em>
375
+
376
+ Get a new filelist containing only the existing files from +self+.
377
+
378
+ Examples:
379
+
380
+ fl = Rant::FileList["**/*"]
381
+ fl.concat ["does_not_exist"]
382
+ fl.entries # => ["README", "sub", "sub/README", "does_not_exist"]
383
+
384
+ files = fl.files
385
+ files.entries # => ["README", "sub/README"]
386
+
387
+ Rantfile Note::
388
+ In Rantfiles, this method is not loaded per default. You
389
+ have to <code>import "filelist/std"</code> first.
390
+
391
+ * <b>dirs</b> <em>-lazy-</em>
392
+
393
+ Get a new filelist containing only the existing directories from
394
+ +self+.
395
+
396
+ Examples:
397
+
398
+ fl = Rant::FileList["**/*"]
399
+ fl.concat ["does_not_exist"]
400
+ fl.entries # => ["README", "sub", "sub/README", "does_not_exist"]
401
+
402
+ dirs = fl.dirs
403
+ dirs.entries # => ["sub"]
404
+
405
+ Rantfile Note::
406
+ In Rantfiles, this method is not loaded per default. You
407
+ have to <code>import "filelist/std"</code> first.
408
+
409
+ * <b>no_dir</b> <em>-lazy-</em>
410
+
411
+ Remove all existing directories.
412
+
413
+ A call to +no_dir+ does not effect entries added later to the
414
+ filelist.
415
+
416
+ Returns +self+.
417
+
418
+ Examples:
419
+
420
+ require 'rant/filelist'
421
+ # create a filelist including all files in the current directory
422
+ # and its subdirectories (recursive).
423
+ fl = Rant::FileList["**/*"]
424
+ fl.entries => ["README", "lib", "bin", "bin/rant", "lib/rant.rb"]
425
+ fl.no_dir
426
+ # now fl doesn't contain directory entries
427
+ fl.entries => ["README", "bin/rant", "lib/rant.rb"]
428
+
429
+ Rantfile Note::
430
+ In Rantfiles, this method is not loaded per default. You
431
+ have to <code>import "filelist/std"</code> first.
432
+
433
+ * <b>no_dir(dir)</b> <em>-lazy-</em>
434
+
435
+ Remove all entries with a parent directory with the name +dir+ and
436
+ all directories with a base name of +dir+.
437
+
438
+ A call to this method does not effect entries added later to the
439
+ filelist.
440
+
441
+ Returns +self+.
442
+
443
+ Examples:
444
+
445
+ fl = Rant::FileList["**/*"]
446
+ fl.entries # => ["README", "coverage", "coverage/index.html", "bin/coverage", "test/coverage", "test/coverage/index.html", "test/test_foo.rb"]
447
+ fl.no_dir("coverage")
448
+ # assumin "bin/coverage" is not a directory
449
+ fl.entries # => ["README", "bin/coverage", "test/test_foo.rb"]
450
+
451
+ Rantfile Note::
452
+ In Rantfiles, this method is not loaded per default. You
453
+ have to <code>import "filelist/std"</code> first.
454
+
455
+ * <b>select { |fn| ... }</b> <em>-lazy-</em>
456
+
457
+ <b>find_all { |fn| ... }</b>
458
+
459
+ Returns a copy of this filelist which contains only the elements for
460
+ which the given block returns true. The calling filelist object
461
+ isn't modified.
462
+
463
+ Examples:
464
+
465
+ # create a list of all files in the current directory and its
466
+ # subdirectories
467
+ all_files = Rant::FileList["**/*"].no_dir
468
+
469
+ # create a list which contains the file names of all empty files
470
+ empty_files = all_files.select { |fn| File.size(fn) == 0 }
471
+
472
+ puts "The following files are empty:"
473
+ # print the file names, one per line
474
+ puts empty_files
475
+
476
+ * <b>map { |fn| ... }</b> <em>-lazy-</em>
477
+
478
+ <b>collect { |fn| ... }</b>
479
+
480
+ Each entry of this filelist is passed in turn to the given block.
481
+ The method returns a copy of this filelist with all entries replaced
482
+ by the return value of block execution.
483
+
484
+ The calling filelist object is not modified.
485
+
486
+ Examples:
487
+
488
+ names = Rant::FileList["**/*"]
489
+
490
+ # create a filelist containing only absolute pathes
491
+ abs_pathes = names.map { |fn| File.expand_path(fn) }
492
+
493
+ * <b>ext(ext_str)</b> <em>-lazy-</em>
494
+
495
+ Returns a new filelist containing the same entries as this list, but
496
+ all entries have the extension +ext_str+.
497
+
498
+ The calling filelist object is not modified.
499
+
500
+ Examples:
501
+
502
+ c_files = Rant::FileList["*.c"]
503
+ c_files.entries # => ["a.c", "b.c"]
504
+ obj_files = c_files.ext("o")
505
+ obj_files.entries # => ["a.o", "b.o"]
506
+
507
+ files = Rant::FileList(["a.c", "b", "c.en.doc", "d.txt"])
508
+ txt_files = file.ext("txt")
509
+ txt_files.entries # => ["a.txt", "b.txt", "c.en.txt", "d.txt"]
510
+
511
+ * <b>uniq!</b> <em>-lazy-</em>
512
+
513
+ Removes duplicate entries.
514
+
515
+ Returns +self+.
516
+
517
+ Examples:
518
+
519
+ files = Rant::FileList(["a", "b", "a", "a"])
520
+ files.uniq!
521
+ files.entries # => ["a", "b"]
522
+
523
+ * <b>sort!</b> <em>-lazy-</em>
524
+
525
+ Sort the entries in this list in alphabetical order.
526
+
527
+ Returns +self+.
528
+
529
+ Examples:
530
+
531
+ fl = Rant::FileList(["b", "a", "c"])
532
+ fl.sort!
533
+ fl.entries # => ["a", "b", "c"]
534
+
535
+ * <b>map! { |fn| ... }</b> <em>-lazy-</em>
536
+
537
+ Pass each entry to the given block and replace it by the return
538
+ value of the block.
539
+
540
+ Returns +self+.
541
+
542
+ Examples:
543
+
544
+ # get a list of directories containing C source files
545
+ src_dirs =
546
+ Rant::FileList.glob "**/*.{c,h}" do |fl|
547
+ fl.map! { |fn| File.dirname(fn) }
548
+ fl.uniq!
549
+ end
550
+
551
+ * <b>reject! { |fn| ... }</b> <em>-lazy-</em>
552
+
553
+ Pass each entry to the given block and remove those entries for
554
+ which the block returns a true value.
555
+
556
+ Returns +self+.
557
+
558
+ Examples:
559
+
560
+ non_empty_files = Rant::FileList["**/*"].reject! { |fn|
561
+ stat = File.stat(fn)
562
+ !stat.file? or stat.zero?
563
+ }
564
+
565
+ * <b>resolve</b> <em>-eager-</em>
566
+
567
+ Execute all lazy operations.
568
+
569
+ Returns +self+.
570
+
571
+ * <b>to_s</b> <em>-eager-</em>
572
+
573
+ Joins all entries with a single space as separator. Spaces in
574
+ entries are escaped for the shell used on the current platform.
575
+
576
+ Examples:
577
+
578
+ txt_files = Rant::FileList["*.txt"]
579
+ txt_files.entries # => ["User Manual.txt", "README.txt"]
580
+ txt_files.to_s
581
+ # on windows: '"User Manual.txt" README.txt'
582
+ # unix/linux: 'User\ Manual.txt README.txt'
583
+
584
+ # start the vim editor to edit all text files
585
+ system "vim #{txt_files}"
586
+
587
+ Note:: Might escape more special shell characters in the future.
588
+
589
+ * <b>entries</b> <em>-eager-</em>
590
+
591
+ <b>to_a</b>
592
+
593
+ <b>to_ary</b>
594
+
595
+ Convert this filelist to an array.
596
+
597
+ Examples:
598
+
599
+ fl = Rant::FileList["*.c"]
600
+ fl.entries # => ["main.c", "util.c"]
601
+
602
+ Especially the definition of the +to_ary+ method has much impact on
603
+ how a filelist object is treated by Ruby libraries. Per convention,
604
+ an object that responds to +to_ary+ can be passed to most methods
605
+ that expect an actual array. So, in most cases you can use a
606
+ filelist object where an array is expected.
607
+
608
+ Examples:
609
+
610
+ a = ["foo", "bar"]
611
+ a.concat Rant::FileList["*.c"]
612
+ a # => ["foo", "bar", "main.c", "util.c"]
613
+
614
+ # remove all object files
615
+ require 'fileutils'
616
+ FileUtils.rm_f Rant::FileList["**/*.o"]
617
+
618
+ # flattening an array (a somewhat artifical example ;)
619
+ a = ["foo"]
620
+ a << Rant::FileList["*.c"].ext("o")
621
+ a.flatten # => ["foo", "main.o", "util.o"]
622
+
623
+ It is not guaranteed that this method always returns the same
624
+ object. It is guaranteed that the returned object is an instance of
625
+ the +Array+ class. Note that changes to the returned array might
626
+ affect the filelist and cause an undefined filelist state.
627
+
628
+ * <b>+(other)</b> <em>-lazy-</em>
629
+
630
+ Returns a new filelist containing the entries of +self+ and +other+.
631
+ +other+ has to respond to +to_rant_filelist+ or to +to_ary+,
632
+ otherwise a +TypeError+ is risen.
633
+
634
+ Examples:
635
+
636
+ c_files = Rant::FileList["*.c"]
637
+ h_files = Rant::FileList["*.h"]
638
+ src_files = c_files + h_files
639
+
640
+ c_files.entries # => ["main.c", "util.c"]
641
+ h_files.entries # => ["main.h", "util.h"]
642
+ src_files.entries # => ["main.c", "util.c", "main.h", "util.h"]
643
+
644
+ * <b>size</b> <em>-eager-</em>
645
+
646
+ Returns the number of entries in this filelist.
647
+
648
+ Examples:
649
+
650
+ fl = Rant::FileList["*.c"]
651
+ fl.entries # => ["main.c", "util.c"]
652
+ fl.size # => 2
653
+
654
+ * <b>empty?</b> <em>-eager-</em>
655
+
656
+ Returns true if this filelist doesn't contain any entry.
657
+
658
+ Examples:
659
+
660
+ fl = Rant::FileList([])
661
+ fl.empty? # => true
662
+
663
+ fl = Rant::FileList["*.c"]
664
+ fl.entries # => ["main.c", "util.c"]
665
+ fl.empty? # => false
666
+
667
+ * <b>join(sep = ' ')</b> <em>-eager-</em>
668
+
669
+ Join the entries together to form a single string. Entries are
670
+ seperated with the given separator string +sep+ or a single space if
671
+ +sep+ is not given.
672
+
673
+ Examples:
674
+
675
+ fl = Rant::FileList(["a", "b"])
676
+ fl.join # => "a b"
677
+ fl.join("\n") # => "a\nb"
678
+
679
+ * <b>pop</b> <em>-eager-</em>
680
+
681
+ Removes the last element and returns it, or +nil+ if this filelist
682
+ is empty.
683
+
684
+ Examples:
685
+
686
+ fl = Rant::FileList["*.c"]
687
+ fl.entries # => ["main.c", "util.c"]
688
+ fl.pop # => "util.c"
689
+ fl.entries # => ["main.c"]
690
+
691
+ * <b>push(entry)</b> <em>-eager-</em>
692
+
693
+ Append +entry+ to this filelist.
694
+
695
+ Returns +self+.
696
+
697
+ Examples:
698
+
699
+ fl = Rant::FileList["*.c"]
700
+ fl.push("foo")
701
+ fl.entries # => ["main.c", "util.c", "foo"]
702
+
703
+ * <b>shift</b> <em>-eager-</em>
704
+
705
+ Removes the first entry and returns it. Returns +nil+ if the
706
+ filelist is empty.
707
+
708
+ Examples:
709
+
710
+ fl = Rant::FileList["*.c"]
711
+ fl.entries # => ["main.c", "util.c"]
712
+ fl.shift # => "main.c"
713
+ fl.entries # => ["util.c"]
714
+
715
+ * <b>unshift(entry)</b> <em>-eager-</em>
716
+
717
+ Insert +entry+ at the first position.
718
+
719
+ Returns +self+.
720
+
721
+ Examples:
722
+
723
+ fl = Rant::FileList["*.c"]
724
+ fl.entries # => ["main.c", "util.c"]
725
+ fl.unshift("foo")
726
+ fl.entries # => ["foo", "main.c", "util.c"]
727
+
728
+ * <b>keep(entry)</b>
729
+
730
+ Add +entry+ to this filelist. +entry+ will stay in this list, even
731
+ if it matches a pattern given to +exclude+ or +ignore+. The position
732
+ of +entry+ in this list is unspecified.
733
+
734
+ Examples:
735
+
736
+ fl = Rant::FileList.new
737
+ fl.include "README.txt", "README.txt~"
738
+ fl.keep "NEWS.txt"
739
+ fl.keep "NEWS.txt~"
740
+ fl.exclude "*~"
741
+ fl.uniq!
742
+ # Note that "README.txt~" was excluded, but "NEWS.txt~" not.
743
+ fl.entries # => ["README.txt", "NEWS.txt", "NEWS.txt~"]
744
+
745
+ * <b>concat(ary)</b>
746
+
747
+ +ary+ has to respond to +to_ary+ (+ary+ could be an Array or other
748
+ filelist). Appends the entries of +ary+ to this filelist.
749
+
750
+ Returns +self+.
751
+
752
+ Examples:
753
+
754
+ fl = Rant::FileList(["a"])
755
+ fl.concat ["b", "c"]
756
+ fl.entries # => ["a", "b", "c"]
757
+
758
+ fl = Rant::FileList.new
759
+ fl.include "*.c"
760
+ fl.concat ["foo", "bar"]
761
+ fl.entries # => ["main.c", "util.c", "foo", "bar"]
762
+
763
+ * <b>each { |entry| ... }</b>
764
+
765
+ Iterate over the filelist entries.
766
+
767
+ Examples:
768
+
769
+ # cat.rb - A simple cat program using Ruby glob patterns.
770
+ require 'rant/filelist'
771
+ Rant::FileList[*ARGV].no_dir.each { |file| print File.read(file) }
772
+
773
+ # example usage: print contents of all Ruby files under lib
774
+ % cat.rb "lib/**/*.rb"
775
+
776
+ * <b>to_rant_filelist</b>
777
+
778
+ Returns +self+.
779
+
780
+ * <b>dup</b>
781
+
782
+ Returns a copy of +self+. Thus after calling this method, there are
783
+ two equal filelist objects. It is guaranteed that modifications of
784
+ one filelist do not affect the other filelist, as long as the entry
785
+ strings aren't modified.
786
+
787
+ Examples:
788
+
789
+ a = Rant::FileList["*.c"]
790
+ a.entries # => ["main.c", "util.c"]
791
+
792
+ b = a.dup
793
+ b.entries # => ["main.c", "util.c"]
794
+
795
+ a.include("*.h")
796
+ a.entries # => ["main.c", "util.c", "main.h", "util.h"]
797
+ # b not affected
798
+ b.entries # => ["main.c", "util.c"]
799
+
800
+ # Note: the original entry strings aren't modified.
801
+ # a not affected
802
+ b.map! { |entry| entry.capitalize }
803
+ b.entries # => ["Main.c", "Util.c"]
804
+ a.entries # => ["main.c", "util.c", "main.h", "util.h"]
805
+
806
+ c = a.dup
807
+ # DON'T DO THAT. Look at the previous example on how to accomplish
808
+ # the same.
809
+ c.each { |entry| entry.capitalize! }
810
+ c.entries # => ["Main.c", "Util.c", "Main.h", "Util.h"]
811
+ # Now the state of a is unspecified: The individual entries may be
812
+ # capitalized or not!
813
+
814
+ * <b>copy</b>
815
+
816
+ Returns a deep copy of +self+. Thus after calling this method, there
817
+ are two equal filelist objects. It is guaranteed that modification
818
+ of one filelist (or its entries) has no impact on the other
819
+ filelist.
820
+
821
+ Examples:
822
+
823
+ a = Rant::FileList["*.c"]
824
+ a.entries # => ["main.c", "util.c"]
825
+
826
+ b = a.copy
827
+ b.entries # => ["main.c", "util.c"]
828
+
829
+ b.each { |entry| entry.capitalize! }
830
+ b.entries # => ["Main.c", "Util.c"]
831
+
832
+ a.entries # => ["main.c", "util.c"]
833
+
834
+ * <b>glob_dotfiles</b>
835
+
836
+ Convinience method for <code>glob_dotfiles = true</code>. The
837
+ following calls to +glob+ (alias +include+) won't treat filenames
838
+ starting with a dot special.
839
+
840
+ Returns +self+.
841
+
842
+ * <b>hide_dotfiles</b>
843
+
844
+ Convinience method for <code>glob_dotfiles = false</code>. The
845
+ following calls to +glob+ (alias +include+) won't include filenames
846
+ starting with a dot.
847
+
848
+ Returns +self+.
849
+
850
+ * <b>inspect</b>
851
+
852
+ Overrides <tt>Object#inspect</tt>. Defined mainly for use in +irb+.
853
+ The +inspect+ method as defined by the +Object+ class is still
854
+ available under the name +object_inspect+.
855
+
856
+ Examples:
857
+
858
+ # irb session
859
+ # Remember that irb uses the inspect method to show results (lines
860
+ # starting with `=>').
861
+
862
+ % irb
863
+ irb(main):001:0> require 'rant/filelist'
864
+ => true
865
+ irb(main):002:0> fl = Rant::FileList["*.rb"]
866
+ => #<Rant::FileList:0x402e46e0 glob:unix res:1 entries:0>
867
+ irb(main):003:0> fl.resolve
868
+ => #<Rant::FileList:0x402e46e0 glob:unix entries:2["install.rb", "setup.rb"]>
869
+ irb(main):004:0>
870
+
871
+ Note::
872
+ Don't rely on the exact format of the string produced by
873
+ +inspect+.
874
+ Rantfile Note::
875
+ To get this +inspect+ method in Rantfiles, you have to
876
+ <code>import "filelist/std"</code> first.
877
+
878
+ * <b>object_inspect</b>
879
+
880
+ Ruby's default +inspect+ method.
881
+
882
+ === Glob pattern syntax
883
+
884
+ The syntax used for filelist glob patterns is the same as for the
885
+ <tt>Dir.glob</tt> Ruby core method.
886
+
887
+ Basically, a glob pattern is a string where a few characters are
888
+ treated special. Unless otherwise mentioned, a pattern is matched
889
+ against the file/directory entries in the current directory. The
890
+ following is a list of characters (the so called "metacharacters")
891
+ that get special treatment:
892
+
893
+ (Parts of this documentation are taken from the output of <tt>% ri
894
+ Dir.glob</tt>, Ruby 1.8.4).
895
+
896
+ <tt>*</tt>:: Match any file/directory. Can be restricted, e.g.
897
+ "*.txt" matches all files/directories ending in
898
+ ".txt". The pattern "\*a\*" matches any entry
899
+ containing the character "a". The pattern "bar*"
900
+ matches any entry starting with "bar". The pattern
901
+ "lib/*.rb" matches any entry under the "lib" directory
902
+ that ends in ".rb".
903
+
904
+ <tt>**</tt>:: Matches directories recursively. E.g. the pattern
905
+ "**/*.rb" matches all entries in the current directory
906
+ and all its subdirectories (recursively) that end in
907
+ ".rb".
908
+
909
+ <tt>?</tt>:: Matches any one character.
910
+
911
+ <tt>[set]</tt>:: Matches any one character in +set+. E.g. the pattern
912
+ "ca[rt]s" matches the entries "cars" and "cats".
913
+
914
+ <tt>{p,q}</tt>:: Matches either literal +p+ or literal +q+.
915
+ Matching literals may be more than one character in
916
+ length. More than two literals may be specified.
917
+
918
+ <tt>\\</tt>:: Escapes the following metacharacter. E.g. while
919
+ pattern "a*b" would match any entry starting with "a"
920
+ and ending with "b", the pattern "a\\*b" literally
921
+ matches the entry "a*b".
922
+
923
+ Some Ruby programmers use the <tt>File.join(dir, filename)</tt> method
924
+ to construct patterns for <tt>Dir.glob</tt> (or <tt>Dir[]</tt>). The
925
+ <tt>Rant::FileList</tt> class guarantees support for either directly
926
+ using a slash ("/") as filename separator, which is recommended, or
927
+ using <tt>File.join</tt>.
928
+
929
+ Examples:
930
+
931
+ # Using a slash as filename separator, supported and preferred
932
+ fl = Rant::FileList["lib/*.c"]
933
+
934
+ # Using File.join, supported
935
+ pattern = File.join("lib", "*.c")
936
+ fl = Rant::FileList[pattern]
937
+
938
+ Note that the Rant::FileList class only supports a slash as filename
939
+ separator. To convert a filename into Rant's internal filename format,
940
+ use the <tt>Rant::Sys.regular_filename</tt> method.
941
+
942
+ Example script, filename.rb:
943
+
944
+ require 'rant/filelist'
945
+
946
+ print "Rant internal filename: "
947
+ puts Rant::Sys.regular_filename(ARGV[0])
948
+
949
+ Executing this on windows:
950
+
951
+ % ruby filename.rb foo\bar
952
+ Rant internal filename: foo/bar
953
+
954
+ == See also
955
+
956
+ Rant Overview::
957
+ README[link:files/README.html]
958
+ Using filelists in Rantfiles::
959
+ doc/sys_filelist.rdoc[link:files/doc/sys_filelist_rdoc.html]
960
+ Rant libraries::
961
+ doc/rubylib.rdoc[link:files/doc/rubylib_rdoc.html]
962
+ Rantfile basics::
963
+ doc/rantfile.rdoc[link:files/doc/rantfile_rdoc.html]