rfs 0.1 → 0.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.
- 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
|
|