rfs 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +110 -0
- data/Rakefile.rb +7 -5
- data/bin/RenameFileSet.rbw +7 -9
- data/bin/rfs.rb +86 -49
- data/description.txt +1 -0
- data/lib/errors.rb +6 -0
- data/lib/gui.rb +21 -6
- data/lib/innate/array.rb +81 -72
- data/lib/innate/filelines.rb +1 -1
- data/lib/innate/regexp.rb +6 -2
- data/lib/innate/roman.rb +6 -5
- data/lib/innate/test/testarray.rb +71 -35
- data/lib/innate/test/testroman.rb +4 -0
- data/lib/options.rb +22 -23
- data/lib/providers.rb +60 -1
- data/lib/rename_functions.rb +18 -4
- data/lib/renamer.rb +9 -3
- data/lib/results.rb +17 -7
- data/profile.txt +226 -0
- data/tests/test_rename_functions.rb +10 -2
- metadata +8 -6
- data/lib/RenameFileSet.bak.rb +0 -372
- data/tests/test_helper.rb +0 -147
data/lib/innate/array.rb
CHANGED
@@ -10,76 +10,62 @@ class Array
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def rows(width = 80, spaces = 2, spacer = ' ')
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
13
|
+
results = row_col(width, spaces, spacer) do |array, cols, empty_element, max|
|
14
|
+
r = []
|
15
|
+
stat = :ok
|
16
|
+
begin
|
17
|
+
s = array.slice!(0, cols)
|
18
|
+
if max
|
19
|
+
break :fail if :fail == s.inject(0) do |a, b|
|
20
|
+
c = a + b
|
21
|
+
if c > max
|
22
|
+
stat = :fail
|
23
|
+
break :fail
|
24
|
+
else
|
25
|
+
c
|
26
|
+
end
|
27
|
+
end
|
28
28
|
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
bestcw = cw
|
29
|
+
r << s
|
30
|
+
end until array == []
|
31
|
+
next :fail if stat == :fail
|
32
|
+
l = r.last.length
|
33
|
+
if l == 0
|
34
|
+
r.pop
|
35
|
+
elsif l < cols
|
36
|
+
r.push(r.pop + [empty_element] * (cols - l))
|
38
37
|
end
|
38
|
+
[r, r.transpose]
|
39
39
|
end
|
40
|
-
|
41
|
-
best.collect {|row| format(fs, *row) }.join "\n"
|
40
|
+
row_col_format(spaces, spacer, *results)
|
42
41
|
end
|
43
|
-
|
42
|
+
|
44
43
|
def columns(width = 80, spaces = 2, spacer = ' ')
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
cw = [0] * columns
|
55
|
-
col_len = length / columns
|
56
|
-
col_len += 1 if length > (columns * col_len)
|
57
|
-
|
58
|
-
temp = nil
|
59
|
-
if length % col_len > 0
|
60
|
-
temp = sorted + ([''] * (col_len - length % col_len))
|
61
|
-
else
|
62
|
-
temp = sorted
|
63
|
-
end
|
64
|
-
|
65
|
-
columns.times do |c|
|
66
|
-
t = temp[(col_len * c)...(col_len * (c + 1))]
|
67
|
-
cols << t
|
44
|
+
results = row_col(width, spaces, spacer) do |array, cols, empty_element|
|
45
|
+
len = array.length
|
46
|
+
col_len = len / cols
|
47
|
+
if len > (cols * col_len)
|
48
|
+
col_len += 1
|
49
|
+
if col_len * cols - len >= col_len
|
50
|
+
fail = true
|
51
|
+
next :fail
|
52
|
+
end
|
68
53
|
end
|
69
|
-
|
70
|
-
|
71
|
-
cols = cols.transpose
|
72
|
-
result = cols.each do |row|
|
73
|
-
break :fail unless check_cols cw, rows, row, width, space, columns
|
54
|
+
if len % col_len > 0
|
55
|
+
array += ([empty_element] * (col_len - length % col_len))
|
74
56
|
end
|
75
|
-
|
76
|
-
|
77
|
-
|
57
|
+
col_data = []
|
58
|
+
cols.times do |c|
|
59
|
+
col_data << array.slice!(0, col_len)
|
78
60
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
61
|
+
#if col_data.last == [] # or col_data.last == nil
|
62
|
+
## shouldn't get here anymore...
|
63
|
+
#:fail
|
64
|
+
#else
|
65
|
+
[col_data.transpose, col_data]
|
66
|
+
#end
|
67
|
+
end
|
68
|
+
row_col_format(spaces, spacer, *results)
|
83
69
|
end
|
84
70
|
|
85
71
|
def pc(w = 130, s = 2, sr = ' ')
|
@@ -89,16 +75,39 @@ class Array
|
|
89
75
|
def pr(w = 130, s = 2, sr = ' ')
|
90
76
|
puts sort.rows(w, s, sr)
|
91
77
|
end
|
92
|
-
end
|
93
78
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
79
|
+
protected
|
80
|
+
def row_col(width, spaces, spacer)
|
81
|
+
return '', 1, [width] if length == 0
|
82
|
+
maxlen = 0
|
83
|
+
minlen = width
|
84
|
+
lengths = collect do |item|
|
85
|
+
len = item.to_s.length
|
86
|
+
maxlen = len if len > maxlen
|
87
|
+
minlen = len if len < minlen
|
88
|
+
len
|
89
|
+
end
|
90
|
+
return self, 1, [width] if maxlen > width or length == 1
|
91
|
+
best_col_count = nil
|
92
|
+
best_col_widths = nil
|
93
|
+
max_possible_cols = width / (spaces * spacer.length + minlen)
|
94
|
+
2.upto(max_possible_cols) do |column_count|
|
95
|
+
space = spacer.length * spaces * (column_count - 1)
|
96
|
+
row_data, column_data = result = yield(lengths.clone, column_count, 0, width - space)
|
97
|
+
next if result == :fail
|
98
|
+
col_widths = column_data.collect {|col| col.max }
|
99
|
+
total_width = col_widths.inject(0) {|a, b| a + b} + space
|
100
|
+
if total_width <= width
|
101
|
+
best_col_count = column_count
|
102
|
+
best_col_widths = col_widths
|
103
|
+
end
|
104
|
+
end
|
105
|
+
return yield(self.clone, best_col_count, '').first, best_col_count, best_col_widths
|
106
|
+
end
|
107
|
+
|
108
|
+
def row_col_format(spaces, spacer, row_data, col_count, col_widths)
|
109
|
+
fs = col_widths.collect {|w| "%#{w}-s" }.join(spacer * spaces)
|
110
|
+
row_data.collect {|row| format(fs, *row).rstrip }.join("\n")
|
103
111
|
end
|
112
|
+
|
104
113
|
end
|
data/lib/innate/filelines.rb
CHANGED
data/lib/innate/regexp.rb
CHANGED
@@ -70,11 +70,15 @@ class MatchData
|
|
70
70
|
# Interpolates %n to the corresponding capture.
|
71
71
|
def sub(repl, capture_num = 1)
|
72
72
|
cn = capture_num || 1
|
73
|
-
|
73
|
+
replace_capture self[cn] ? cn : 0, interpolate(repl)
|
74
|
+
end
|
75
|
+
|
76
|
+
def interpolate(s)
|
77
|
+
t = s.clone
|
74
78
|
to_a[1..-1].each_with_index do |m, i|
|
75
79
|
t.gsub!("%#{i + 1}", m ? m : '')
|
76
80
|
end
|
77
|
-
|
81
|
+
t
|
78
82
|
end
|
79
83
|
end
|
80
84
|
|
data/lib/innate/roman.rb
CHANGED
@@ -3,7 +3,7 @@ require 'innate/regexp'
|
|
3
3
|
class Regexp
|
4
4
|
# All groups are non-capturing!
|
5
5
|
def self.ROMAN_PATTERN
|
6
|
-
'(?:M{0,4})(?:C[DM]|D?C{0,3})(?:X[LC]|L?X{0,3})(?:I[VX]|V?I{0,3})'
|
6
|
+
'(?=[MCDLXVI])(?:M{0,4})(?:C[DM]|D?C{0,3})(?:X[LC]|L?X{0,3})(?:I[VX]|V?I{0,3})'
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.ROMAN
|
@@ -16,7 +16,8 @@ class Regexp
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
class RomanNumeralError < RuntimeError
|
20
|
+
end
|
20
21
|
|
21
22
|
class String
|
22
23
|
def roman_numeral?
|
@@ -32,7 +33,7 @@ class String
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def roman_to_i
|
35
|
-
raise "#{self} is not a valid roman numeral." unless roman_numeral?
|
36
|
+
raise RomanNumeralError.new("#{self} is not a valid roman numeral.") unless roman_numeral?
|
36
37
|
s = upcase
|
37
38
|
values = { ?M => 1000, ?D => 500, ?C => 100, ?L => 50, ?X => 10, ?V => 5, ?I => 1 }
|
38
39
|
value = result = 0
|
@@ -47,8 +48,8 @@ end
|
|
47
48
|
|
48
49
|
class Fixnum
|
49
50
|
def roman
|
50
|
-
raise 'There is no Roman representation for numbers below 1.' if self < 1
|
51
|
-
raise 'There is no Roman representation for numbers above 4999.' if self > 4999
|
51
|
+
raise RomanNumeralError.new('There is no Roman representation for numbers below 1.') if self < 1
|
52
|
+
raise RomanNumeralError.new('There is no Roman representation for numbers above 4999.') if self > 4999
|
52
53
|
elements = {1000 => 'M',500 => 'D',100 => 'C',50 => 'L',10 => 'X',5 => 'V',1 => 'I'}
|
53
54
|
values = [1000, 500, 100, 50, 10, 5, 1]
|
54
55
|
r = ''
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'test/unit'
|
2
2
|
require 'innate/array'
|
3
|
+
require 'cursor/indexed'
|
3
4
|
|
4
5
|
class TestArray < Test::Unit::TestCase
|
5
6
|
def test_match_string
|
@@ -35,26 +36,29 @@ class TestArray < Test::Unit::TestCase
|
|
35
36
|
to_r to_s to_sym truncate type untaint
|
36
37
|
upto zero? | ~}
|
37
38
|
|
38
|
-
s = "% & * ** +
|
39
|
-
"- -@ / < <<
|
40
|
-
"<=> == === =~ >
|
41
|
-
">> [] ^ __id__ __send__ abs
|
42
|
-
"between? ceil chr class clone coerce
|
43
|
-
"denominator display div divmod downto dup
|
44
|
-
"eql? equal? extend floor freeze frozen
|
45
|
-
"gcd gcd2 gcdlcm hash id id2name
|
46
|
-
"inspect instance_eval instance_of? instance_variable_get instance_variable_set instance_variables
|
47
|
-
"integer? is_a? kind_of? lcm method methods
|
48
|
-
"modulo next nil? nonzero? numerator object_id
|
49
|
-
"power! prec prec_f prec_i private_methods protected_methods
|
50
|
-
"public_methods quo rdiv remainder require require_gem
|
51
|
-
"require_gem_with_options respond_to? round rpower send singleton_method_added\n"
|
52
|
-
"singleton_methods size step succ taint tainted
|
53
|
-
"times to_a to_bn to_f to_i to_int
|
54
|
-
"to_r to_s to_sym truncate type untaint
|
55
|
-
"upto zero? | ~
|
39
|
+
s = ["% & * ** + +@\n",
|
40
|
+
"- -@ / < << <=\n",
|
41
|
+
"<=> == === =~ > >=\n",
|
42
|
+
">> [] ^ __id__ __send__ abs\n",
|
43
|
+
"between? ceil chr class clone coerce\n",
|
44
|
+
"denominator display div divmod downto dup\n",
|
45
|
+
"eql? equal? extend floor freeze frozen?\n",
|
46
|
+
"gcd gcd2 gcdlcm hash id id2name\n",
|
47
|
+
"inspect instance_eval instance_of? instance_variable_get instance_variable_set instance_variables\n",
|
48
|
+
"integer? is_a? kind_of? lcm method methods\n",
|
49
|
+
"modulo next nil? nonzero? numerator object_id\n",
|
50
|
+
"power! prec prec_f prec_i private_methods protected_methods\n",
|
51
|
+
"public_methods quo rdiv remainder require require_gem\n",
|
52
|
+
"require_gem_with_options respond_to? round rpower send singleton_method_added\n",
|
53
|
+
"singleton_methods size step succ taint tainted?\n",
|
54
|
+
"times to_a to_bn to_f to_i to_int\n",
|
55
|
+
"to_r to_s to_sym truncate type untaint\n",
|
56
|
+
"upto zero? | ~"].to_cursor
|
57
|
+
|
58
|
+
a.rows(130, 2, ' ').each_line do |l|
|
59
|
+
assert_equal s.read1next, l
|
60
|
+
end
|
56
61
|
|
57
|
-
assert_equal s, a.rows(130, 2, ' ')
|
58
62
|
end
|
59
63
|
|
60
64
|
def test_columns
|
@@ -77,22 +81,54 @@ class TestArray < Test::Unit::TestCase
|
|
77
81
|
to_r to_s to_sym truncate type untaint
|
78
82
|
upto zero? | ~}
|
79
83
|
|
80
|
-
s = "% === clone gcd kind_of? private_methods singleton_methods to_sym
|
81
|
-
"& =~ coerce gcd2 lcm protected_methods size truncate\n"
|
82
|
-
"* > denominator gcdlcm method public_methods step type
|
83
|
-
"** >= display hash methods quo succ untaint
|
84
|
-
"+ >> div id modulo rdiv taint upto
|
85
|
-
"+@ [] divmod id2name next remainder tainted? zero
|
86
|
-
"- ^ downto inspect nil? require times
|
87
|
-
"-@ __id__ dup instance_eval nonzero? require_gem to_a
|
88
|
-
"/ __send__ eql? instance_of? numerator require_gem_with_options to_bn
|
89
|
-
"< abs equal? instance_variable_get object_id respond_to? to_f
|
90
|
-
"<< between? extend instance_variable_set power! round to_i
|
91
|
-
"<= ceil floor instance_variables prec rpower to_int
|
92
|
-
"<=> chr freeze integer? prec_f send to_r
|
93
|
-
"== class frozen? is_a? prec_i singleton_method_added to_s
|
84
|
+
s = ["% === clone gcd kind_of? private_methods singleton_methods to_sym\n",
|
85
|
+
"& =~ coerce gcd2 lcm protected_methods size truncate\n",
|
86
|
+
"* > denominator gcdlcm method public_methods step type\n",
|
87
|
+
"** >= display hash methods quo succ untaint\n",
|
88
|
+
"+ >> div id modulo rdiv taint upto\n",
|
89
|
+
"+@ [] divmod id2name next remainder tainted? zero?\n",
|
90
|
+
"- ^ downto inspect nil? require times |\n",
|
91
|
+
"-@ __id__ dup instance_eval nonzero? require_gem to_a ~\n",
|
92
|
+
"/ __send__ eql? instance_of? numerator require_gem_with_options to_bn\n",
|
93
|
+
"< abs equal? instance_variable_get object_id respond_to? to_f\n",
|
94
|
+
"<< between? extend instance_variable_set power! round to_i\n",
|
95
|
+
"<= ceil floor instance_variables prec rpower to_int\n",
|
96
|
+
"<=> chr freeze integer? prec_f send to_r\n",
|
97
|
+
"== class frozen? is_a? prec_i singleton_method_added to_s"].to_cursor
|
98
|
+
|
99
|
+
a.columns(130, 2, ' ').each_line do |l|
|
100
|
+
assert_equal s.read1next, l
|
101
|
+
end
|
102
|
+
end
|
94
103
|
|
95
|
-
|
96
|
-
|
104
|
+
def test_empty_array
|
105
|
+
a = []
|
106
|
+
assert_equal '', a.columns(80, 2, ' ')
|
107
|
+
assert_equal '', a.rows(80, 2, ' ')
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_one_element
|
111
|
+
a = ['hello']
|
112
|
+
assert_equal 'hello', a.columns(80, 2, ' ')
|
113
|
+
assert_equal 'hello', a.rows(80, 2, ' ')
|
114
|
+
end
|
97
115
|
|
116
|
+
def test_long_element
|
117
|
+
a = ['hello', 'this is a rather long one']
|
118
|
+
assert_equal "hello\nthis is a rather long one", a.columns(15, 2, ' ')
|
119
|
+
assert_equal "hello\nthis is a rather long one", a.rows(15, 2, ' ')
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def test_nil_array
|
124
|
+
a = [nil]
|
125
|
+
assert_equal '', a.columns(80, 2, ' ')
|
126
|
+
assert_equal '', a.rows(80, 2, ' ')
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_array_with_nil
|
130
|
+
a = [1, nil, 3, nil]
|
131
|
+
assert_equal '1 3', a.columns(80, 2, ' ')
|
132
|
+
assert_equal '1 3', a.rows(80, 2, ' ')
|
133
|
+
end
|
98
134
|
end
|
@@ -50,5 +50,9 @@ class TestRoman < Test::Unit::TestCase
|
|
50
50
|
(/valiant(roman)soldier/i).interpolate_roman.to_s)
|
51
51
|
end
|
52
52
|
|
53
|
+
def test_roman_regexp
|
54
|
+
assert_equal('mcmxiv', Regexp.new("(#{Regexp.ROMAN_PATTERN})", Regexp::IGNORECASE).match('the war of mcmxiv.')[1])
|
55
|
+
end
|
56
|
+
|
53
57
|
end
|
54
58
|
|
data/lib/options.rb
CHANGED
@@ -28,37 +28,36 @@ module Options
|
|
28
28
|
def opt(sym, *types)
|
29
29
|
v = @options[sym]
|
30
30
|
if v
|
31
|
-
|
32
|
-
|
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
|
31
|
+
if !types.empty? and !types.find {|t| v.is_a? t}
|
32
|
+
raise BadOptionValueError.new(sym, v.class, types)
|
47
33
|
end
|
48
34
|
elsif !types.include? NilClass
|
49
35
|
raise MissingOptionError.new(sym)
|
50
36
|
end
|
37
|
+
if block_given?
|
38
|
+
yield v
|
39
|
+
else
|
40
|
+
v
|
41
|
+
end
|
51
42
|
end
|
52
43
|
|
53
44
|
def opt_if(sym, *types)
|
54
|
-
|
55
|
-
|
56
|
-
|
45
|
+
v = @options[sym]
|
46
|
+
r = if v
|
47
|
+
if types.empty?
|
48
|
+
:ok
|
49
|
+
elsif types.find {|t| v.is_a? t}
|
50
|
+
:ok
|
51
|
+
end
|
52
|
+
elsif types.include? NilClass
|
53
|
+
:ok
|
57
54
|
end
|
58
|
-
if
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
if r == :ok
|
56
|
+
if block_given?
|
57
|
+
yield v
|
58
|
+
else
|
59
|
+
v
|
60
|
+
end
|
62
61
|
end
|
63
62
|
end
|
64
63
|
end
|
data/lib/providers.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
|
2
1
|
module Provider
|
3
2
|
module Folder
|
4
3
|
class Tree
|
4
|
+
include Enumerable
|
5
|
+
|
5
6
|
def initialize(tree)
|
6
7
|
@tree = tree
|
7
8
|
end
|
@@ -25,6 +26,7 @@ module Provider
|
|
25
26
|
|
26
27
|
module File
|
27
28
|
class Base
|
29
|
+
attr_reader :folders
|
28
30
|
def initialize(folder_provider)
|
29
31
|
@folders = folder_provider
|
30
32
|
@iterator = :each
|
@@ -72,6 +74,7 @@ module Provider
|
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
77
|
+
|
75
78
|
class Array < Base
|
76
79
|
attr_accessor :files
|
77
80
|
|
@@ -87,6 +90,62 @@ module Provider
|
|
87
90
|
end
|
88
91
|
end
|
89
92
|
end
|
93
|
+
|
94
|
+
|
95
|
+
##I am decomissioning this code because
|
96
|
+
##it did not result in any performance
|
97
|
+
##improvement. Upon profiling the program
|
98
|
+
##it turns out (to my surprise) that
|
99
|
+
##retrieving file listings was not a
|
100
|
+
##bottleneck at all.
|
101
|
+
#class Cache < Base
|
102
|
+
#def initialize(file_provider)
|
103
|
+
#@fp = file_provider
|
104
|
+
#reset_cache
|
105
|
+
#end
|
106
|
+
|
107
|
+
#def reset_cache
|
108
|
+
#@fg = Generator.new(@fp)
|
109
|
+
#@cache = []
|
110
|
+
#@cache_complete = false
|
111
|
+
#end
|
112
|
+
|
113
|
+
#def each
|
114
|
+
#@cache.each do |a|
|
115
|
+
#yield a.first, a.last
|
116
|
+
#end
|
117
|
+
#unless @cache_complete
|
118
|
+
#while @fg.next?
|
119
|
+
#begin
|
120
|
+
#Thread.critical = true
|
121
|
+
#path, file = @fg.next
|
122
|
+
#@cache << [path, file]
|
123
|
+
#@cache_complete = true unless @fg.next?
|
124
|
+
#ensure
|
125
|
+
#Thread.critical = false
|
126
|
+
#end
|
127
|
+
#yield path, file
|
128
|
+
#end
|
129
|
+
#end
|
130
|
+
#end
|
131
|
+
#end
|
132
|
+
|
133
|
+
|
134
|
+
#class EnumerableFoldersCache < Cache
|
135
|
+
#def initialize(file_provider)
|
136
|
+
#@folders = []
|
137
|
+
#super
|
138
|
+
#end
|
139
|
+
|
140
|
+
#def each(&b)
|
141
|
+
#f = @fp.folders.collect
|
142
|
+
#unless f == @folders
|
143
|
+
#reset_cache
|
144
|
+
#@folders = f
|
145
|
+
#end
|
146
|
+
#super
|
147
|
+
#end
|
148
|
+
#end
|
90
149
|
end
|
91
150
|
end
|
92
151
|
|