rfs 0.1
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.
- data/MIT-LICENSE +7 -0
- data/Rakefile.rb +193 -0
- data/bin/RenameFileSet.rbw +14 -0
- data/bin/rfs.rb +214 -0
- data/bin/rfsd.rb +8 -0
- data/description.txt +24 -0
- data/lib/RenameFileSet.bak.rb +372 -0
- data/lib/errors.rb +15 -0
- data/lib/filters.rb +68 -0
- data/lib/gui.rb +216 -0
- data/lib/innate/array.rb +104 -0
- data/lib/innate/coverage.rb +315 -0
- data/lib/innate/debug.rb +12 -0
- data/lib/innate/debugger.rb +944 -0
- data/lib/innate/file.rb +5 -0
- data/lib/innate/filelines.rb +148 -0
- data/lib/innate/kernel.rb +41 -0
- data/lib/innate/metaid.rb +30 -0
- data/lib/innate/mkdirs.rb +12 -0
- data/lib/innate/regexp.rb +80 -0
- data/lib/innate/reload.rb +11 -0
- data/lib/innate/roman.rb +72 -0
- data/lib/innate/scriptlines.rb +60 -0
- data/lib/innate/string.rb +56 -0
- data/lib/innate/test/all_tests.rb +11 -0
- data/lib/innate/test/files/mkdirs_dummy.file +1 -0
- data/lib/innate/test/files/reloadtarget.rb +5 -0
- data/lib/innate/test/files/reloadtarget1.rb +5 -0
- data/lib/innate/test/files/reloadtarget2.rb +5 -0
- data/lib/innate/test/test_coverage.rb +13 -0
- data/lib/innate/test/testarray.rb +98 -0
- data/lib/innate/test/testfile.rb +15 -0
- data/lib/innate/test/testfilelines.rb +106 -0
- data/lib/innate/test/testkernel.rb +30 -0
- data/lib/innate/test/testmkdirs.rb +19 -0
- data/lib/innate/test/testregexp.rb +86 -0
- data/lib/innate/test/testreload.rb +61 -0
- data/lib/innate/test/testroman.rb +54 -0
- data/lib/innate/test/testscriptlines.rb +39 -0
- data/lib/innate/test/teststring.rb +52 -0
- data/lib/innate/test/testtitlecase.rb +20 -0
- data/lib/innate/titlecase.rb +64 -0
- data/lib/innate/tracerequire.rb +22 -0
- data/lib/namesource.rb +53 -0
- data/lib/options.rb +64 -0
- data/lib/providers.rb +93 -0
- data/lib/regexp.rb +56 -0
- data/lib/rename_functions.rb +142 -0
- data/lib/renamer.rb +210 -0
- data/lib/results.rb +83 -0
- data/lib/test/test_helper.rb +147 -0
- data/tests/dir/file1 +0 -0
- data/tests/dir/file2 +0 -0
- data/tests/dir/file3 +0 -0
- data/tests/test_helper.rb +147 -0
- data/tests/test_rename_functions.rb +605 -0
- metadata +105 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
def copy(a, b)
|
2
|
+
File.open(b, 'w') do |f|
|
3
|
+
f.write File.read(a)
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'test/unit'
|
8
|
+
require 'innate/reload'
|
9
|
+
require 'innate/scriptlines'
|
10
|
+
|
11
|
+
class TestReload < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def t
|
14
|
+
begin
|
15
|
+
copy 'files/reloadtarget1.rb', 'files/reloadtarget.rb'
|
16
|
+
require 'files/reloadtarget'
|
17
|
+
yield :original
|
18
|
+
copy 'files/reloadtarget2.rb', 'files/reloadtarget.rb'
|
19
|
+
reload 'files/reloadtarget'
|
20
|
+
yield :reloaded
|
21
|
+
ensure
|
22
|
+
# I don't delete anymore because it messes up the tests
|
23
|
+
# for scriptlines
|
24
|
+
#File.delete 'files/reloadtarget.rb' rescue nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
#targetfn sleeps for 2 seconds.. more than enough time to have an overlap
|
30
|
+
def test_reload
|
31
|
+
thread = nil
|
32
|
+
t do |step|
|
33
|
+
if step == :original
|
34
|
+
thread = Thread.new do
|
35
|
+
assert_equal 'function1', targetfn {|v| assert_equal 'start 1', v }
|
36
|
+
end
|
37
|
+
elsif step == :reloaded
|
38
|
+
assert_equal 'function2', targetfn {|v| assert_equal 'start 2', v }
|
39
|
+
thread.join
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_reload_scriptlines
|
45
|
+
orig = nil
|
46
|
+
fn = nil
|
47
|
+
t do |step|
|
48
|
+
if step == :original
|
49
|
+
fn = find_in_path 'files/reloadtarget'
|
50
|
+
orig = SCRIPT_LINES__[fn].collect
|
51
|
+
elsif step == :reloaded
|
52
|
+
r = SCRIPT_LINES__[fn]
|
53
|
+
assert_not_nil orig.first
|
54
|
+
assert_equal orig.first, r.first
|
55
|
+
assert_equal orig.last, r.last
|
56
|
+
assert_equal orig[1..-2].collect {|l| l.tr('12', '21') }, r[1..-2]
|
57
|
+
assert_equal orig.collect {|l| l.tr('12', '21') }, r.collect
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'innate/roman'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class TestRoman < Test::Unit::TestCase
|
5
|
+
# Since it works already I don't really need more
|
6
|
+
# detailed tests. If it breaks, break this down.
|
7
|
+
def test_full_range
|
8
|
+
r = (1..4999).inject(['']) { |lon, v|
|
9
|
+
lon.unshift v.roman if v.roman.length > lon.first.length
|
10
|
+
lon
|
11
|
+
}.delete_if {|v| v == ''}.reverse.collect {|v| [v, v.roman_to_i] }
|
12
|
+
assert_equal([["I", 1],
|
13
|
+
["II", 2],
|
14
|
+
["III", 3],
|
15
|
+
["VIII", 8],
|
16
|
+
["XVIII", 18],
|
17
|
+
["XXVIII", 28],
|
18
|
+
["XXXVIII", 38],
|
19
|
+
["LXXXVIII", 88],
|
20
|
+
["CLXXXVIII", 188],
|
21
|
+
["CCLXXXVIII", 288],
|
22
|
+
["CCCLXXXVIII", 388],
|
23
|
+
["DCCCLXXXVIII", 888],
|
24
|
+
["MDCCCLXXXVIII", 1888],
|
25
|
+
["MMDCCCLXXXVIII", 2888],
|
26
|
+
["MMMDCCCLXXXVIII", 3888],
|
27
|
+
["MMMMDCCCLXXXVIII", 4888]],
|
28
|
+
r)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_lower_case
|
32
|
+
assert_equal 1914, 'mcmxiv'.roman_to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_toggle1
|
36
|
+
assert_equal '1914', '1914'.toggle_roman.toggle_roman
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_toggle2
|
40
|
+
assert_equal 'MCMXLIV', 'mcmxliv'.toggle_roman.toggle_roman
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_interpolate_regexp
|
44
|
+
assert_equal('(?-mix:valiant(' + Regexp.ROMAN_PATTERN + ')soldier)',
|
45
|
+
(/valiant(roman)soldier/).interpolate_roman.to_s)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_interpolate_regexp2
|
49
|
+
assert_equal('(?i-mx:valiant(' + Regexp.ROMAN_PATTERN + ')soldier)',
|
50
|
+
(/valiant(roman)soldier/i).interpolate_roman.to_s)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'innate/scriptlines'
|
3
|
+
require 'cursor/indexed'
|
4
|
+
require 'timeout'
|
5
|
+
|
6
|
+
class TestScriptLines < Test::Unit::TestCase
|
7
|
+
def test_defined
|
8
|
+
assert defined?(SCRIPT_LINES__)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_types
|
12
|
+
assert SCRIPT_LINES__.length > 0
|
13
|
+
SCRIPT_LINES__.each do |name, file|
|
14
|
+
assert File.exists?(name)
|
15
|
+
assert_kind_of FileLines, file
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_contents
|
20
|
+
locked = 0
|
21
|
+
begin
|
22
|
+
Timeout::timeout(30) do
|
23
|
+
SCRIPT_LINES__.each do |name, file|
|
24
|
+
begin
|
25
|
+
lines = File.open(name) {|f| f.readlines }.to_cursor
|
26
|
+
file.each do |line|
|
27
|
+
assert_equal lines.read1next, line
|
28
|
+
end
|
29
|
+
rescue Errno::EACCES
|
30
|
+
locked += 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
assert locked <= 3, 'too many locked files...??'
|
34
|
+
end
|
35
|
+
rescue Timeout::Error
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'innate/string'
|
3
|
+
require 'cursor/indexed'
|
4
|
+
|
5
|
+
class TestString < Test::Unit::TestCase
|
6
|
+
def test_starts_with?
|
7
|
+
assert_nil 'o\'hare'.starts_with?('Mc', 'Mac', 'O\'')
|
8
|
+
assert_equal 'O\'', 'O\'hare'.starts_with?('Mc', 'Mac', 'O\'')
|
9
|
+
assert_nil 'mcdonald'.starts_with?('Mc', 'Mac', 'O\'')
|
10
|
+
assert_equal 'Mc', 'Mcdonald'.starts_with?('Mc', 'Mac', 'O\'')
|
11
|
+
assert_nil 'normal'.starts_with?('Mc', 'Mac', 'O\'')
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_starts_with_i?
|
15
|
+
assert_equal 'O\'', 'o\'hare'.starts_with_i?('Mc', 'Mac', 'O\'')
|
16
|
+
assert_equal 'O\'', 'O\'hare'.starts_with_i?('Mc', 'Mac', 'O\'')
|
17
|
+
assert_equal 'Mc', 'mcdonald'.starts_with_i?('Mc', 'Mac', 'O\'')
|
18
|
+
assert_nil 'normal'.starts_with_i?('Mc', 'Mac', 'O\'')
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_prefix_to?
|
22
|
+
assert_equal 'spud', 's'.prefix_to?('blog', 'roil', 'spud', 'star')
|
23
|
+
assert_equal 'star', 'st'.prefix_to?('blog', 'roil', 'spud', 'star')
|
24
|
+
assert_nil 'S'.prefix_to?('blog', 'roil', 'spud', 'star')
|
25
|
+
assert_nil 'xz'.prefix_to?('blog', 'roil', 'spud', 'star')
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_prefix_to?
|
29
|
+
assert_equal 'Spud', 's'.prefix_to_i?('Blog', 'Roil', 'Spud', 'star')
|
30
|
+
assert_equal 'star', 'St'.prefix_to_i?('blog', 'roil', 'spud', 'star')
|
31
|
+
assert_nil 'xz'.prefix_to_i?('blog', 'roil', 'spud', 'star')
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_split_with_separator
|
35
|
+
assert_equal([[nil, 'hello'], [', ', 'is darrick there'], ['? ', 'no'], ['.', '']],
|
36
|
+
'hello, is darrick there? no.'.split_with_separator(/[.,?]\s*/))
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_split_with_separator2
|
40
|
+
count = 0
|
41
|
+
c = [[nil, 'hello'], [', ', 'is darrick there'], ['? ', 'no'], ['.', '']].to_cursor
|
42
|
+
'hello, is darrick there? no.'.split_with_separator(/[.,?]\s*/) do |s, text|
|
43
|
+
cs, ctext = c.read1next
|
44
|
+
assert_equal cs, s
|
45
|
+
assert_equal ctext, text
|
46
|
+
count += 1
|
47
|
+
end
|
48
|
+
assert_equal 4, count
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'innate/titlecase'
|
3
|
+
require 'cursor/indexed'
|
4
|
+
|
5
|
+
class TestTitleCase < Test::Unit::TestCase
|
6
|
+
def test_s
|
7
|
+
s = ['this sentence should be capitalized',
|
8
|
+
'here is another one. the best is to see what will happen! is it good?',
|
9
|
+
'how many more do i need here? a few.',
|
10
|
+
"i'll have to get this done soon, it may get boring..."]
|
11
|
+
t = ['This Sentence Should Be Capitalized',
|
12
|
+
'Here is Another One. The Best is to See What Will Happen! Is it Good?',
|
13
|
+
'How Many More Do I Need Here? A Few.',
|
14
|
+
"I'll Have to Get This Done Soon, it May Get Boring..."].to_cursor
|
15
|
+
s.each do |string|
|
16
|
+
assert_equal t.read1next, string.title_case
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'innate/roman'
|
2
|
+
require 'innate/string'
|
3
|
+
require 'innate/array'
|
4
|
+
|
5
|
+
class String
|
6
|
+
# lower even if it occurs after punctuation.
|
7
|
+
def self.ALWAYS_LOWER
|
8
|
+
[]
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.LOWER
|
12
|
+
%w{ as of in the and at or a to it is on by for with an from }
|
13
|
+
end
|
14
|
+
|
15
|
+
# good for names with a second capital.
|
16
|
+
# this is prefixes rather than words, so it
|
17
|
+
# doesn't use +Array#match?+
|
18
|
+
def self.DOUBLE_CAP
|
19
|
+
%w{ mac mc o' d' }
|
20
|
+
end
|
21
|
+
|
22
|
+
# which punctuation causes :lower words to be capitalized after all
|
23
|
+
def self.CAP_AFTER
|
24
|
+
%w{ . ! ? ( � : ; } << ' - '
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.SPLIT_PATTERN
|
28
|
+
/('?[ .!?:;""()\-\n\r\t�_]'?)+/
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.UPPER
|
32
|
+
[Regexp.ROMAN]
|
33
|
+
end
|
34
|
+
|
35
|
+
def title_case(opts = {})
|
36
|
+
opts[:always_lower] ||= String.ALWAYS_LOWER
|
37
|
+
opts[:lower] ||= String.LOWER
|
38
|
+
opts[:double_cap] ||= String.DOUBLE_CAP
|
39
|
+
opts[:cap_after] ||= String.CAP_AFTER
|
40
|
+
opts[:split_pattern] ||= String.SPLIT_PATTERN
|
41
|
+
opts[:upper] ||= String.UPPER
|
42
|
+
|
43
|
+
res = split_with_separator(opts[:split_pattern]) do |s, w|
|
44
|
+
w.downcase!
|
45
|
+
s.to_s + if opts[:always_lower].match? w
|
46
|
+
w
|
47
|
+
elsif opts[:lower].match? w
|
48
|
+
if !s or opts[:cap_after].match?(s.rstrip[-1, 1]) or opts[:cap_after].match?(s)
|
49
|
+
w.capitalize
|
50
|
+
else
|
51
|
+
w
|
52
|
+
end
|
53
|
+
elsif opts[:upper].match? w
|
54
|
+
w.upcase
|
55
|
+
elsif (t = w.starts_with?(opts[:double_cap]))
|
56
|
+
t.capitalize + w[t.length...w.length].capitalize
|
57
|
+
else
|
58
|
+
w.capitalize
|
59
|
+
end
|
60
|
+
end
|
61
|
+
res.join
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Object
|
2
|
+
alias :require_before_tracerequire :require unless respond_to? :require_before_tracerequire
|
3
|
+
@@__require_depth = 0
|
4
|
+
@@__require_count = 0
|
5
|
+
|
6
|
+
def require(s)
|
7
|
+
@@__require_count += 1
|
8
|
+
rc = @@__require_count
|
9
|
+
print "\n#{' ' * @@__require_depth}require '#{s}'"
|
10
|
+
@@__require_depth += 1
|
11
|
+
r = require_before_tracerequire(s)
|
12
|
+
@@__require_depth -= 1
|
13
|
+
s = "=> #{r.to_s}"
|
14
|
+
if rc == @@__require_count
|
15
|
+
print " " + s
|
16
|
+
else
|
17
|
+
print "\n#{' ' * @@__require_depth}" + s
|
18
|
+
end
|
19
|
+
puts if @@__require_depth == 0
|
20
|
+
return r
|
21
|
+
end
|
22
|
+
end
|
data/lib/namesource.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
class NameSource
|
2
|
+
def name(file, md, path)
|
3
|
+
file
|
4
|
+
end
|
5
|
+
|
6
|
+
def close
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
class NameStreamSource < NameSource
|
12
|
+
def initialize(stream)
|
13
|
+
@stream = stream
|
14
|
+
end
|
15
|
+
|
16
|
+
def name(file, md, path)
|
17
|
+
@stream.readline.chomp
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
class NameFileSource < NameSource
|
23
|
+
def initialize(file_name)
|
24
|
+
@file_name = file_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def name(file, md, path)
|
28
|
+
unless @file and @path == path
|
29
|
+
@file.close if @file
|
30
|
+
@path = path
|
31
|
+
fn = File.join(path, @file_name)
|
32
|
+
if File.exists? fn
|
33
|
+
@file = File.open(fn)
|
34
|
+
else
|
35
|
+
@file = File.open(@file_name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
@file.readline.chomp
|
39
|
+
end
|
40
|
+
|
41
|
+
def close
|
42
|
+
@file.close if @file
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
class NamePromptSource < NameSource
|
48
|
+
def name(file, md, path)
|
49
|
+
print "Rename #{File.join(path, file)}\n#[captures: #{md.display} ] to:\n>>> "
|
50
|
+
STDIN.gets.chomp
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
data/lib/options.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
class OptionError < RenamerError
|
2
|
+
end
|
3
|
+
|
4
|
+
class MissingOptionError < OptionError
|
5
|
+
attr_reader :missing_opt
|
6
|
+
def initialize missing_opt
|
7
|
+
@missing_opt = missing_opt
|
8
|
+
super "The required option #{missing_opt} was not present."
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class BadOptionValueError < OptionError
|
13
|
+
attr_reader :opt, :klass, :klass_expected
|
14
|
+
def initialize opt, klass, klass_expected
|
15
|
+
@opt = opt
|
16
|
+
@klass = klass
|
17
|
+
@klass_expected = klass_expected
|
18
|
+
super "#{opt} was expected to be one of #{klass_expected.to_a.flatten.join ', '} but was #{klass}."
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
module Options
|
24
|
+
|
25
|
+
|
26
|
+
attr_accessor :options
|
27
|
+
|
28
|
+
def opt(sym, *types)
|
29
|
+
v = @options[sym]
|
30
|
+
if v
|
31
|
+
unless types.empty?
|
32
|
+
if types.find {|t| v.is_a? t}
|
33
|
+
if block_given?
|
34
|
+
yield v
|
35
|
+
else
|
36
|
+
v
|
37
|
+
end
|
38
|
+
else
|
39
|
+
raise BadOptionValueError.new(sym, v.class, types)
|
40
|
+
end
|
41
|
+
else
|
42
|
+
if block_given?
|
43
|
+
yield v
|
44
|
+
else
|
45
|
+
v
|
46
|
+
end
|
47
|
+
end
|
48
|
+
elsif !types.include? NilClass
|
49
|
+
raise MissingOptionError.new(sym)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def opt_if(sym, *types)
|
54
|
+
begin
|
55
|
+
v = opt sym, *types
|
56
|
+
rescue OptionError
|
57
|
+
end
|
58
|
+
if block_given?
|
59
|
+
yield v if v
|
60
|
+
else
|
61
|
+
v
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/providers.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
|
2
|
+
module Provider
|
3
|
+
module Folder
|
4
|
+
class Tree
|
5
|
+
def initialize(tree)
|
6
|
+
@tree = tree
|
7
|
+
end
|
8
|
+
|
9
|
+
def each(&block)
|
10
|
+
traverse_list @tree, nil, &block
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
def traverse_list branch, path, &block
|
15
|
+
branch.each do |i|
|
16
|
+
if i.selected?
|
17
|
+
yield @tree.itemPathname(i)
|
18
|
+
end
|
19
|
+
traverse_list(i, p, &block) if i.expanded?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
module File
|
27
|
+
class Base
|
28
|
+
def initialize(folder_provider)
|
29
|
+
@folders = folder_provider
|
30
|
+
@iterator = :each
|
31
|
+
end
|
32
|
+
|
33
|
+
def reverse
|
34
|
+
@iterator = :reverse_each
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
class NonRecursive < Base
|
40
|
+
def each
|
41
|
+
@folders.each do |folder|
|
42
|
+
dir = Dir.new(folder)
|
43
|
+
dir.collect.send(@iterator) do |file|
|
44
|
+
unless file =~ /^\.+$/
|
45
|
+
yield folder, file
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
class Recursive < Base
|
54
|
+
def each(&block)
|
55
|
+
@folders.each do |folder|
|
56
|
+
recursive_each(folder, &block)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def recursive_each(folder, &block)
|
62
|
+
dir = Dir.new(folder) rescue return
|
63
|
+
dir.collect.send(@iterator) do |file|
|
64
|
+
j = ::File.join(folder, file)
|
65
|
+
unless file =~ /^\.+$/
|
66
|
+
if ::File.directory? j
|
67
|
+
recursive_each j, &block
|
68
|
+
end
|
69
|
+
yield folder, file
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Array < Base
|
76
|
+
attr_accessor :files
|
77
|
+
|
78
|
+
def initialize(files)
|
79
|
+
super nil
|
80
|
+
@files = files
|
81
|
+
end
|
82
|
+
|
83
|
+
def each
|
84
|
+
@files.send(@iterator) do |file|
|
85
|
+
p, f = ::File.split file
|
86
|
+
yield p, f
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|