Class: FileList

Inherits:
Object
  • Object
show all
Includes:
Cloneable
Defined in:
lib/filelist.rb

Constant Summary collapse

ARRAY_METHODS =

List of array methods (that are not in Object) that need to be delegated.

(Array.instance_methods - Object.instance_methods).map { |n| n.to_s }
MUST_DEFINE =

List of additional methods that must be delegated.

%w[to_a inspect]
MUST_NOT_DEFINE =

List of methods that should not be delegated here (we define special versions of them explicitly below).

%w[to_a to_ary partition *]
SPECIAL_RETURN =

List of delegated methods that return new array values which need wrapping.

%w[
  map collect sort sort_by select find_all reject grep
  compact flatten uniq values_at
  + - & |
]
DELEGATING_METHODS =
(ARRAY_METHODS + MUST_DEFINE - MUST_NOT_DEFINE).collect{ |s| s.to_s }.sort.uniq
DEFAULT_IGNORE_PATTERNS =
[
  /(^|[\/\\])CVS([\/\\]|$)/,
  /(^|[\/\\])\.svn([\/\\]|$)/,
  /\.bak$/,
  /~$/
]
DEFAULT_IGNORE_PROCS =
[
  proc { |fn| fn =~ /(^|[\/\\])core$/ && ! File.directory?(fn) }
]

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Cloneable

#clone, #dup

Constructor Details

#initialize(*patterns) {|_self| ... } ⇒ FileList

Create a file list from the globbable patterns given. If you wish to perform multiple includes or excludes at object build time, use the “yield self” pattern.

Example:

file_list = FileList.new('lib/**/*.rb', 'test/test*.rb')

pkg_files = FileList.new('lib/**/*') do |fl|
  fl.exclude(/\bCVS\b/)
end

Yields:

  • (_self)

Yield Parameters:

  • _self (FileList)

    the object that the method was called on



98
99
100
101
102
103
104
105
106
107
# File 'lib/filelist.rb', line 98

def initialize(*patterns)
  @pending_add = []
  @pending = false
  @exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup
  @exclude_procs = DEFAULT_IGNORE_PROCS.dup
  @exclude_re = nil
  @items = []
  patterns.each { |pattern| include(pattern) }
  yield self if block_given?
end

Class Method Details

.[](*args) ⇒ Object

Create a new file list including the files listed. Similar to:

FileList.new(*args)


392
393
394
# File 'lib/filelist.rb', line 392

def [](*args)
  new(*args)
end

Instance Method Details

#*(other) ⇒ Object

Redefine * to return either a string or a new file list.



193
194
195
196
197
198
199
200
201
# File 'lib/filelist.rb', line 193

def *(other)
  result = @items * other
  case result
  when Array
    FileList.new.import(result)
  else
    result
  end
end

#==(array) ⇒ Object

Define equality.



171
172
173
# File 'lib/filelist.rb', line 171

def ==(array)
  to_ary == array
end

#calculate_exclude_regexpObject



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/filelist.rb', line 214

def calculate_exclude_regexp
  ignores = []
  @exclude_patterns.each do |pat|
    case pat
    when Regexp
      ignores << pat
    when /[*?]/
      Dir[pat].each do |p| ignores << p end
    else
      ignores << Regexp.quote(pat)
    end
  end
  if ignores.empty?
    @exclude_re = /^$/
  else
    re_str = ignores.collect { |p| "(" + p.to_s + ")" }.join("|")
    @exclude_re = Regexp.new(re_str)
  end
end

#clear_excludeObject

Clear all the exclude patterns so that we exclude nothing.



163
164
165
166
167
168
# File 'lib/filelist.rb', line 163

def clear_exclude
  @exclude_patterns = []
  @exclude_procs = []
  calculate_exclude_regexp if ! @pending
  self
end

#egrep(pattern) ⇒ Object

Grep each of the files in the filelist using the given pattern. If a block is given, call the block on each matching line, passing the file name, line number, and the matching line of text. If no block is given, a standard emac style file:linenumber:line message will be printed to standard out.



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'lib/filelist.rb', line 309

def egrep(pattern)
  each do |fn|
    open(fn) do |inf|
      count = 0
      inf.each do |line|
        count += 1
        if pattern.match(line)
          if block_given?
            yield fn, count, line
          else
            puts "#{fn}:#{count}:#{line}"
          end
        end
      end
    end
  end
end

#exclude(*patterns, &block) ⇒ Object

Register a list of file name patterns that should be excluded from the list. Patterns may be regular expressions, glob patterns or regular strings. In addition, a block given to exclude will remove entries that return true when given to the block.

Note that glob patterns are expanded against the file system. If a file is explicitly added to a file list, but does not exist in the file system, then an glob pattern in the exclude list will not exclude the file.

Examples:

FileList['a.c', 'b.c'].exclude("a.c") => ['b.c']
FileList['a.c', 'b.c'].exclude(/^a/)  => ['b.c']

If “a.c” is a file, then …

FileList['a.c', 'b.c'].exclude("a.*") => ['b.c']

If “a.c” is not a file, then …

FileList['a.c', 'b.c'].exclude("a.*") => ['a.c', 'b.c']


150
151
152
153
154
155
156
157
158
159
# File 'lib/filelist.rb', line 150

def exclude(*patterns, &block)
  patterns.each do |pat|
    @exclude_patterns << pat
  end
  if block_given?
    @exclude_procs << block
  end
  resolve_exclude if ! @pending
  self
end

#exclude?(fn) ⇒ Boolean

Should the given file name be excluded?

Returns:

  • (Boolean)


367
368
369
370
# File 'lib/filelist.rb', line 367

def exclude?(fn)
  calculate_exclude_regexp unless @exclude_re
  fn =~ @exclude_re || @exclude_procs.any? { |p| p.call(fn) }
end

#existingObject

Return a new file list that only contains file names from the current file list that exist on the file system.



329
330
331
# File 'lib/filelist.rb', line 329

def existing
  select { |fn| File.exist?(fn) }
end

#existing!Object

Modify the current file list so that it contains only file name that exist on the file system.



335
336
337
338
339
# File 'lib/filelist.rb', line 335

def existing!
  resolve
  @items = @items.select { |fn| File.exist?(fn) }
  self
end

#ext(newext = '') ⇒ Object

Return a new array with String#ext method applied to each member of the array.

This method is a shortcut for:

array.collect { |item| item.ext(newext) }

ext is a user added method for the Array class.



299
300
301
# File 'lib/filelist.rb', line 299

def ext(newext='')
  collect { |fn| fn.ext(newext) }
end

#gsub(pat, rep) ⇒ Object

Return a new FileList with the results of running gsub against each element of the original list.

Example:

FileList['lib/test/file', 'x/y'].gsub(/\//, "\\")
   => ['lib\\test\\file', 'x\\y']


268
269
270
# File 'lib/filelist.rb', line 268

def gsub(pat, rep)
  inject(FileList.new) { |res, fn| res << fn.gsub(pat,rep) }
end

#gsub!(pat, rep) ⇒ Object

Same as gsub except that the original file list is modified.



279
280
281
282
# File 'lib/filelist.rb', line 279

def gsub!(pat, rep)
  each_with_index { |fn, i| self[i] = fn.gsub(pat,rep) }
  self
end

#import(array) ⇒ Object

@exclude_patterns = DEFAULT_IGNORE_PATTERNS.dup



383
384
385
386
# File 'lib/filelist.rb', line 383

def import(array)
  @items = array
  self
end

#include(*filenames) ⇒ Object Also known as: add

Add file names defined by glob patterns to the file list. If an array is given, add each element of the array.

Example:

file_list.include("*.java", "*.cfg")
file_list.include %w( math.c lib.h *.o )


116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/filelist.rb', line 116

def include(*filenames)
  # TODO: check for pending
  filenames.each do |fn|
    if fn.respond_to? :to_ary
      include(*fn.to_ary)
    else
      @pending_add << fn
    end
  end
  @pending = true
  self
end

#is_a?(klass) ⇒ Boolean Also known as: kind_of?

Lie about our class.

Returns:

  • (Boolean)


187
188
189
# File 'lib/filelist.rb', line 187

def is_a?(klass)
  klass == Array || super(klass)
end

#partition(&block) ⇒ Object

FileList version of partition. Needed because the nested arrays should be FileLists in this version.



343
344
345
346
347
348
349
350
# File 'lib/filelist.rb', line 343

def partition(&block)       # :nodoc:
  resolve
  result = @items.partition(&block)
  [
    FileList.new.import(result[0]),
    FileList.new.import(result[1]),
  ]
end

#pathmap(spec = nil) ⇒ Object

Apply the pathmap spec to each of the included file names, returning a new file list with the modified paths. (See String#pathmap for details.)



287
288
289
# File 'lib/filelist.rb', line 287

def pathmap(spec=nil)
  collect { |fn| fn.pathmap(spec) }
end

#resolveObject

Resolve all the pending adds now.



204
205
206
207
208
209
210
211
212
# File 'lib/filelist.rb', line 204

def resolve
  if @pending
    @pending = false
    @pending_add.each do |fn| resolve_add(fn) end
    @pending_add = []
    resolve_exclude
  end
  self
end

#sub(pat, rep) ⇒ Object

Return a new FileList with the results of running sub against each element of the oringal list.

Example:

FileList['a.c', 'b.c'].sub(/\.c$/, '.o')  => ['a.o', 'b.o']


257
258
259
# File 'lib/filelist.rb', line 257

def sub(pat, rep)
  inject(FileList.new) { |res, fn| res << fn.sub(pat,rep) }
end

#sub!(pat, rep) ⇒ Object

Same as sub except that the oringal file list is modified.



273
274
275
276
# File 'lib/filelist.rb', line 273

def sub!(pat, rep)
  each_with_index { |fn, i| self[i] = fn.sub(pat,rep) }
  self
end

#to_aObject

Return the internal array object.



176
177
178
179
# File 'lib/filelist.rb', line 176

def to_a
  resolve
  @items
end

#to_aryObject

Return the internal array object.



182
183
184
# File 'lib/filelist.rb', line 182

def to_ary
  to_a
end

#to_sObject

Convert a FileList to a string by joining all elements with a space.



353
354
355
356
# File 'lib/filelist.rb', line 353

def to_s
  resolve
  self.join(' ')
end