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.
Files changed (57) hide show
  1. data/MIT-LICENSE +7 -0
  2. data/Rakefile.rb +193 -0
  3. data/bin/RenameFileSet.rbw +14 -0
  4. data/bin/rfs.rb +214 -0
  5. data/bin/rfsd.rb +8 -0
  6. data/description.txt +24 -0
  7. data/lib/RenameFileSet.bak.rb +372 -0
  8. data/lib/errors.rb +15 -0
  9. data/lib/filters.rb +68 -0
  10. data/lib/gui.rb +216 -0
  11. data/lib/innate/array.rb +104 -0
  12. data/lib/innate/coverage.rb +315 -0
  13. data/lib/innate/debug.rb +12 -0
  14. data/lib/innate/debugger.rb +944 -0
  15. data/lib/innate/file.rb +5 -0
  16. data/lib/innate/filelines.rb +148 -0
  17. data/lib/innate/kernel.rb +41 -0
  18. data/lib/innate/metaid.rb +30 -0
  19. data/lib/innate/mkdirs.rb +12 -0
  20. data/lib/innate/regexp.rb +80 -0
  21. data/lib/innate/reload.rb +11 -0
  22. data/lib/innate/roman.rb +72 -0
  23. data/lib/innate/scriptlines.rb +60 -0
  24. data/lib/innate/string.rb +56 -0
  25. data/lib/innate/test/all_tests.rb +11 -0
  26. data/lib/innate/test/files/mkdirs_dummy.file +1 -0
  27. data/lib/innate/test/files/reloadtarget.rb +5 -0
  28. data/lib/innate/test/files/reloadtarget1.rb +5 -0
  29. data/lib/innate/test/files/reloadtarget2.rb +5 -0
  30. data/lib/innate/test/test_coverage.rb +13 -0
  31. data/lib/innate/test/testarray.rb +98 -0
  32. data/lib/innate/test/testfile.rb +15 -0
  33. data/lib/innate/test/testfilelines.rb +106 -0
  34. data/lib/innate/test/testkernel.rb +30 -0
  35. data/lib/innate/test/testmkdirs.rb +19 -0
  36. data/lib/innate/test/testregexp.rb +86 -0
  37. data/lib/innate/test/testreload.rb +61 -0
  38. data/lib/innate/test/testroman.rb +54 -0
  39. data/lib/innate/test/testscriptlines.rb +39 -0
  40. data/lib/innate/test/teststring.rb +52 -0
  41. data/lib/innate/test/testtitlecase.rb +20 -0
  42. data/lib/innate/titlecase.rb +64 -0
  43. data/lib/innate/tracerequire.rb +22 -0
  44. data/lib/namesource.rb +53 -0
  45. data/lib/options.rb +64 -0
  46. data/lib/providers.rb +93 -0
  47. data/lib/regexp.rb +56 -0
  48. data/lib/rename_functions.rb +142 -0
  49. data/lib/renamer.rb +210 -0
  50. data/lib/results.rb +83 -0
  51. data/lib/test/test_helper.rb +147 -0
  52. data/tests/dir/file1 +0 -0
  53. data/tests/dir/file2 +0 -0
  54. data/tests/dir/file3 +0 -0
  55. data/tests/test_helper.rb +147 -0
  56. data/tests/test_rename_functions.rb +605 -0
  57. 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
+