simonc-AbsoluteRenamer 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/AbsoluteRenamer.gemspec +83 -0
- data/VERSION +1 -1
- data/conf/absrenamer/absrenamer.conf +34 -0
- data/lib/absolute_renamer.rb +122 -0
- data/lib/absolute_renamer/config.rb +40 -0
- data/lib/absolute_renamer/external.rb +56 -0
- data/lib/absolute_renamer/external/modules/core/case/module.rb +31 -0
- data/lib/absolute_renamer/external/modules/core/general/module.rb +126 -0
- data/lib/absolute_renamer/external/parsers/core/general/parser.rb +74 -0
- data/lib/absolute_renamer/external/parsers/interactive/parser.rb +20 -0
- data/lib/absolute_renamer/external/parsers/listing/parser.rb +9 -0
- data/lib/absolute_renamer/external/plugins/interactive/plugin.rb +35 -0
- data/lib/absolute_renamer/external/plugins/listing/plugin.rb +14 -0
- data/lib/absolute_renamer/file_info.rb +102 -0
- data/lib/absolute_renamer/imodule.rb +68 -0
- data/lib/absolute_renamer/iparser.rb +8 -0
- data/lib/absolute_renamer/iplugin.rb +11 -0
- data/lib/absolute_renamer/libs/file.rb +11 -0
- data/lib/absolute_renamer/libs/string.rb +27 -0
- data/lib/absolute_renamer/parser.rb +91 -0
- data/lib/absolute_renamer/use_config.rb +11 -0
- data/lib/absolute_renamer/with_children.rb +22 -0
- data/test/absolute_renamer_test.rb +2 -2
- data/test/config_test.rb +45 -0
- data/test/file_info_test.rb +71 -0
- data/test/file_test.rb +33 -0
- metadata +31 -2
@@ -0,0 +1,83 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{AbsoluteRenamer}
|
8
|
+
s.version = "0.9.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Simon COURTOIS"]
|
12
|
+
s.date = %q{2009-09-22}
|
13
|
+
s.default_executable = %q{absrenamer}
|
14
|
+
s.description = %q{Unlike many batch renaming tools, AbsoluteRenamer is able to rename folders.
|
15
|
+
AbsoluteRenamer is modular and can be extended to adapt itself to any kind of file
|
16
|
+
or to add new options and features.}
|
17
|
+
s.email = %q{happynoff@free.fr}
|
18
|
+
s.executables = ["absrenamer"]
|
19
|
+
s.extra_rdoc_files = [
|
20
|
+
"LICENSE",
|
21
|
+
"README.rdoc"
|
22
|
+
]
|
23
|
+
s.files = [
|
24
|
+
".document",
|
25
|
+
".gitignore",
|
26
|
+
"AbsoluteRenamer.gemspec",
|
27
|
+
"LICENSE",
|
28
|
+
"README.rdoc",
|
29
|
+
"Rakefile",
|
30
|
+
"VERSION",
|
31
|
+
"bin/absrenamer",
|
32
|
+
"conf/absrenamer/absrenamer.conf",
|
33
|
+
"lib/absolute_renamer.rb",
|
34
|
+
"lib/absolute_renamer/config.rb",
|
35
|
+
"lib/absolute_renamer/external.rb",
|
36
|
+
"lib/absolute_renamer/external/modules/core/case/module.rb",
|
37
|
+
"lib/absolute_renamer/external/modules/core/general/module.rb",
|
38
|
+
"lib/absolute_renamer/external/parsers/core/general/parser.rb",
|
39
|
+
"lib/absolute_renamer/external/parsers/interactive/parser.rb",
|
40
|
+
"lib/absolute_renamer/external/parsers/listing/parser.rb",
|
41
|
+
"lib/absolute_renamer/external/plugins/interactive/plugin.rb",
|
42
|
+
"lib/absolute_renamer/external/plugins/listing/plugin.rb",
|
43
|
+
"lib/absolute_renamer/file_info.rb",
|
44
|
+
"lib/absolute_renamer/imodule.rb",
|
45
|
+
"lib/absolute_renamer/iparser.rb",
|
46
|
+
"lib/absolute_renamer/iplugin.rb",
|
47
|
+
"lib/absolute_renamer/libs/file.rb",
|
48
|
+
"lib/absolute_renamer/libs/string.rb",
|
49
|
+
"lib/absolute_renamer/parser.rb",
|
50
|
+
"lib/absolute_renamer/use_config.rb",
|
51
|
+
"lib/absolute_renamer/with_children.rb",
|
52
|
+
"test/absolute_renamer_test.rb",
|
53
|
+
"test/config_test.rb",
|
54
|
+
"test/file_info_test.rb",
|
55
|
+
"test/file_test.rb",
|
56
|
+
"test/test_helper.rb"
|
57
|
+
]
|
58
|
+
s.homepage = %q{http://github.com/simonc/AbsoluteRenamer}
|
59
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
60
|
+
s.require_paths = ["lib"]
|
61
|
+
s.rubygems_version = %q{1.3.5}
|
62
|
+
s.summary = %q{AbsoluteRenamer is a very powerful tool that helps files and directories renaming using the Krename syntax.}
|
63
|
+
s.test_files = [
|
64
|
+
"test/absolute_renamer_test.rb",
|
65
|
+
"test/config_test.rb",
|
66
|
+
"test/file_info_test.rb",
|
67
|
+
"test/file_test.rb",
|
68
|
+
"test/test_helper.rb"
|
69
|
+
]
|
70
|
+
|
71
|
+
if s.respond_to? :specification_version then
|
72
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
73
|
+
s.specification_version = 3
|
74
|
+
|
75
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
76
|
+
s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
77
|
+
else
|
78
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
79
|
+
end
|
80
|
+
else
|
81
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
82
|
+
end
|
83
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.2
|
@@ -0,0 +1,34 @@
|
|
1
|
+
:debug: false
|
2
|
+
|
3
|
+
:options:
|
4
|
+
# Prompt :never, :once or :always before renaming
|
5
|
+
:interactive: :never
|
6
|
+
:format: '$'
|
7
|
+
:ext_format: '$'
|
8
|
+
|
9
|
+
# Renaming mode: :rename, :copy, :move, :link
|
10
|
+
:mode: :rename
|
11
|
+
:maxdepth: 0
|
12
|
+
|
13
|
+
# used when a value is not available (pdfAuthor for a PNG file, ...)
|
14
|
+
:default_string: '---'
|
15
|
+
|
16
|
+
# Word separator, regular expression statements can be used
|
17
|
+
# default: '\W_'
|
18
|
+
# This string will be used in AbsoluteRenamer just like this :
|
19
|
+
# [^WORD_SEPARATOR]
|
20
|
+
# Then, \W_ => [^\W_]
|
21
|
+
:word_separator: '\W_'
|
22
|
+
|
23
|
+
:path:
|
24
|
+
:modules: absolute_renamer/external/modules
|
25
|
+
:parsers: absolute_renamer/external/parsers
|
26
|
+
:plugins: absolute_renamer/external/plugins
|
27
|
+
|
28
|
+
:parsers:
|
29
|
+
- listing
|
30
|
+
- interactive
|
31
|
+
|
32
|
+
:plugins:
|
33
|
+
- listing
|
34
|
+
- interactive
|
@@ -0,0 +1,122 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'absolute_renamer/config'
|
5
|
+
require 'absolute_renamer/with_children'
|
6
|
+
require 'absolute_renamer/external'
|
7
|
+
require 'absolute_renamer/parser'
|
8
|
+
require 'absolute_renamer/file_info'
|
9
|
+
require 'absolute_renamer/libs/file'
|
10
|
+
require 'absolute_renamer/libs/string'
|
11
|
+
require 'absolute_renamer/use_config'
|
12
|
+
|
13
|
+
# top level module of AbsoluteRenamer.
|
14
|
+
module AbsoluteRenamer
|
15
|
+
VERSION = "0.9.1"
|
16
|
+
|
17
|
+
# The main class of AbsoluteRenamer.
|
18
|
+
#
|
19
|
+
# Organizes the files and directories renaming process.
|
20
|
+
class Processor
|
21
|
+
class << self
|
22
|
+
include AbsoluteRenamer::UseConfig
|
23
|
+
|
24
|
+
# Creates the new names for each file passed to AbsoluteRenamer.
|
25
|
+
#
|
26
|
+
# Asks to each module if he as something to replace
|
27
|
+
# in the name of each file.
|
28
|
+
#
|
29
|
+
# Calls the +before_names_generation+ entry point.
|
30
|
+
def create_names_list
|
31
|
+
call_entry_point(:before_names_generation)
|
32
|
+
return if conf[:files].empty?
|
33
|
+
mods = {}
|
34
|
+
conf[:files].each do |file|
|
35
|
+
name = conf[:options][:format].clone
|
36
|
+
ext = conf[:options][:ext_format].clone
|
37
|
+
do_replacements(file.name, :before)
|
38
|
+
AbsoluteRenamer::IModule.children.each do |mod|
|
39
|
+
mod_sym = mod.symbol
|
40
|
+
mods[mod_sym] ||= mod.new
|
41
|
+
name = mods[mod_sym].process(file, name)
|
42
|
+
ext = mods[mod_sym].process(file, ext, :ext) unless file.dir
|
43
|
+
end
|
44
|
+
do_replacements(name, :after)
|
45
|
+
file.new_name = name
|
46
|
+
file.new_name << '.' << ext unless (file.dir or file.ext.empty?)
|
47
|
+
end
|
48
|
+
if (conf[:options][:dir] and conf[:options][:rec])
|
49
|
+
conf[:files].sort! { |a, b| AbsoluteRenamer::FileInfo.compare_level(a, b) }
|
50
|
+
end
|
51
|
+
mods.clear
|
52
|
+
end
|
53
|
+
|
54
|
+
# For each file/dir replaces his name by his new name.
|
55
|
+
#
|
56
|
+
# Calls the following entry points :
|
57
|
+
# - before_batch_renaming ;
|
58
|
+
# - before_file_renaming ;
|
59
|
+
# - after_file_renaming ;
|
60
|
+
# - after_batch_renaming.
|
61
|
+
def do_renaming
|
62
|
+
if call_entry_point(:before_batch_renaming)
|
63
|
+
conf[:files].each do |file|
|
64
|
+
if call_entry_point(:before_file_renaming, :file => file)
|
65
|
+
if file.respond_to?(conf[:options][:mode])
|
66
|
+
file.send(conf[:options][:mode])
|
67
|
+
end
|
68
|
+
call_entry_point(:after_file_renaming, :file => file)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
call_entry_point(:after_batch_renaming)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Loads the plugins list in the @plugins variable.
|
76
|
+
def load_plugins
|
77
|
+
@plugins = {}
|
78
|
+
AbsoluteRenamer::IPlugin.children.each do |plugin|
|
79
|
+
@plugins[plugin.symbol] = plugin.new
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Calls the given entry point for each plugin available
|
84
|
+
#
|
85
|
+
# Ask to each plugin if it implements the entry point
|
86
|
+
# and calls it with params if it isn't null.
|
87
|
+
# It keeps going will all plugins return true.
|
88
|
+
#
|
89
|
+
# returns true if all plugins returned true
|
90
|
+
def call_entry_point(ep, params = nil)
|
91
|
+
puts "Plugin Entry Point: #{ep}" if conf[:debug]
|
92
|
+
keep_going = true
|
93
|
+
@plugins.each_value do |plugin|
|
94
|
+
if plugin.respond_to?(ep)
|
95
|
+
keep_going &= params.nil? ? plugin.send(ep) : plugin.send(ep, params)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
keep_going
|
99
|
+
end
|
100
|
+
|
101
|
+
# Applies replacements
|
102
|
+
#
|
103
|
+
# The replacements are stored in conf[options][replacements][moment]
|
104
|
+
# and are provided as command line paramters.
|
105
|
+
#
|
106
|
+
# format represents the string in which the replacements are done
|
107
|
+
# moment determines which replacements are done (on old or new name)
|
108
|
+
def do_replacements(format, moment)
|
109
|
+
begin
|
110
|
+
replacements = conf[:options][:replacements][moment]
|
111
|
+
rescue NoMethodError
|
112
|
+
replacements = nil
|
113
|
+
end
|
114
|
+
unless replacements.nil?
|
115
|
+
replacements.each do |repl|
|
116
|
+
format.gsub!(repl[:pattern], repl[:replace])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module AbsoluteRenamer
|
4
|
+
# Class handeling the configuration.
|
5
|
+
class Config
|
6
|
+
class << self
|
7
|
+
# Open and load a Yaml file into the +@conf+ variable.
|
8
|
+
# config_path: path of the file to load.
|
9
|
+
def load(config_path)
|
10
|
+
@conf = YAML::load_file(config_path)
|
11
|
+
|
12
|
+
@conf[:options] ||= {}
|
13
|
+
@conf[:options][:format] ||= '$'
|
14
|
+
@conf[:options][:ext_format] ||= '$'
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns a configuration value identified by +key+.
|
18
|
+
# If +key+ is ignored, returns the +@conf+ hash.
|
19
|
+
def get(key = nil)
|
20
|
+
return @conf[key] if @conf.has_key?(key)
|
21
|
+
return @conf
|
22
|
+
end
|
23
|
+
|
24
|
+
# Sets a configuration value in the +@conf+ variable.
|
25
|
+
def set(key, value = '')
|
26
|
+
@conf[key] = value
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a configuration value identified by +key+.
|
30
|
+
def [](key)
|
31
|
+
@conf[key]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Sets a configuration value in the +@conf+ variable.
|
35
|
+
def []=(key, value)
|
36
|
+
@conf[key] = value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'absolute_renamer/imodule'
|
2
|
+
require 'absolute_renamer/iplugin'
|
3
|
+
require 'absolute_renamer/use_config'
|
4
|
+
|
5
|
+
module AbsoluteRenamer
|
6
|
+
# Class in charge of loading +modules+ and +plugins+.
|
7
|
+
class External
|
8
|
+
class << self
|
9
|
+
include AbsoluteRenamer::UseConfig
|
10
|
+
|
11
|
+
# Loads the additional and core modules.
|
12
|
+
# The modules list is get from the conf[:modules] variable.
|
13
|
+
# The core modules are loaded after the additional ones.
|
14
|
+
#
|
15
|
+
# See also load
|
16
|
+
def load_modules
|
17
|
+
puts "[Loading modules]" if conf[:debug]
|
18
|
+
|
19
|
+
modules = conf[:modules]
|
20
|
+
load(modules, :modules, 'module.rb') unless modules.nil?
|
21
|
+
|
22
|
+
core_modules = ['case', 'general'].map! { |core_module| File.join('core', core_module) }
|
23
|
+
load(core_modules, :modules, 'module.rb')
|
24
|
+
end
|
25
|
+
|
26
|
+
# Loads the plugins.
|
27
|
+
# The plugins list is get from the conf[:plugins] variable.
|
28
|
+
#
|
29
|
+
# See also load
|
30
|
+
def load_plugins
|
31
|
+
puts "[Loading plugins]" if conf[:debug]
|
32
|
+
|
33
|
+
load(conf[:plugins], :plugins, 'plugin.rb')
|
34
|
+
end
|
35
|
+
|
36
|
+
# Loads an external list (+modules+ or +plugins+)
|
37
|
+
# externals: a list of +externals+ names to load.
|
38
|
+
# type: a symbol defining which type of external to load
|
39
|
+
# file: the filename to require to load the +externals+
|
40
|
+
def load(externals, type, file)
|
41
|
+
ext_dir = conf[:path][type]
|
42
|
+
|
43
|
+
externals.each do |external|
|
44
|
+
ext_to_load = File.join(ext_dir, external, file)
|
45
|
+
begin
|
46
|
+
if require ext_to_load
|
47
|
+
puts "Loaded: #{ext_to_load}" if conf[:debug]
|
48
|
+
end
|
49
|
+
rescue LoadError => e
|
50
|
+
STDERR.puts(e)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module AbsoluteRenamer
|
2
|
+
class CaseModule < AbsoluteRenamer::IModule
|
3
|
+
class << self
|
4
|
+
attr_reader :actions
|
5
|
+
|
6
|
+
def actions
|
7
|
+
@actions ||= {'*' => :camelize,
|
8
|
+
'&' => :upper,
|
9
|
+
'%' => :lower,
|
10
|
+
'$' => :original
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def camelize(str)
|
15
|
+
str.camelize
|
16
|
+
end
|
17
|
+
|
18
|
+
def original(str)
|
19
|
+
str
|
20
|
+
end
|
21
|
+
|
22
|
+
def lower(str)
|
23
|
+
str.downcase
|
24
|
+
end
|
25
|
+
|
26
|
+
def upper(str)
|
27
|
+
str.upcase
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module AbsoluteRenamer
|
2
|
+
class GeneralModule < AbsoluteRenamer::IModule
|
3
|
+
def initialize
|
4
|
+
@actions = {'*' => :file_camelize,
|
5
|
+
'$' => :file_original,
|
6
|
+
'%' => :file_downcase,
|
7
|
+
'&' => :file_upcase,
|
8
|
+
'\\' => :file_strip,
|
9
|
+
'#' => :count
|
10
|
+
}
|
11
|
+
|
12
|
+
@case_filters = ['(\\\\\*)', # \*
|
13
|
+
'(\\\\\$)', # \$
|
14
|
+
'(\\\%)', # \%
|
15
|
+
'(\\\&)', # \&
|
16
|
+
'(\\\\\\\)', # \\
|
17
|
+
'(\*)', # *
|
18
|
+
'(\$)', # $
|
19
|
+
'(%)', # %
|
20
|
+
'(&)', # &
|
21
|
+
'(\\\)' # \
|
22
|
+
]
|
23
|
+
|
24
|
+
# matches strings like [42-43] [42-] [*42-43] [42;43] etc...
|
25
|
+
@part_filters = ['(\[(.)?(\d+)(((-)(\d+)?)|((;)(\d+)))?\])']
|
26
|
+
|
27
|
+
# matches counters like # ### #{2} ##{2;42} or [length-42]
|
28
|
+
@misc_filters = ['(/)', '(#+(\{.*\})?)', '(\[length(--?\d+)?\])']
|
29
|
+
|
30
|
+
@filters = @case_filters + @part_filters + @misc_filters
|
31
|
+
end
|
32
|
+
|
33
|
+
def interpret(file, infos, type)
|
34
|
+
if (infos[0].length == 1)
|
35
|
+
self.method(@actions[infos[0][0].chr]).call(file, infos, type)
|
36
|
+
elsif (infos[0][1..6] == 'length')
|
37
|
+
self.length(file, infos, type)
|
38
|
+
elsif (infos[0][0].chr == '[')
|
39
|
+
self.file_part(file, infos, type)
|
40
|
+
elsif (infos[0][0].chr == '#')
|
41
|
+
self.count(file, infos, type)
|
42
|
+
else
|
43
|
+
infos[0][1].chr
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def file_camelize(file, infos, type)
|
48
|
+
file.send(type).camelize
|
49
|
+
end
|
50
|
+
|
51
|
+
def file_original(file, infos, type)
|
52
|
+
file.send(type)
|
53
|
+
end
|
54
|
+
|
55
|
+
def file_downcase(file, infos, type)
|
56
|
+
file.send(type).downcase
|
57
|
+
end
|
58
|
+
|
59
|
+
def file_upcase(file, infos, type)
|
60
|
+
file.send(type).upcase
|
61
|
+
end
|
62
|
+
|
63
|
+
def file_strip(file, infos, type)
|
64
|
+
file.send(type).strip
|
65
|
+
end
|
66
|
+
|
67
|
+
def file_part(file, infos, type)
|
68
|
+
matched = infos[0].match(/(\[([^\d])?(\d+)(((;)(\d+))|((-)(\d+)?))?\])/)
|
69
|
+
|
70
|
+
modifier = matched[2]
|
71
|
+
x = matched[3].to_i - 1
|
72
|
+
y = matched[7] || matched[10]
|
73
|
+
y = y.to_i unless y.nil?
|
74
|
+
action = matched[6] || matched[9]
|
75
|
+
|
76
|
+
str = file.send(type)
|
77
|
+
|
78
|
+
if (action == '-')
|
79
|
+
y -= 1 unless y.nil?
|
80
|
+
y ||= str.length
|
81
|
+
val = str[x..y]
|
82
|
+
elsif (action == ';')
|
83
|
+
val = str[x, y]
|
84
|
+
else
|
85
|
+
val = str[x].chr
|
86
|
+
end
|
87
|
+
|
88
|
+
unless modifier.nil?
|
89
|
+
mp = CaseModule.method(CaseModule.actions[modifier])
|
90
|
+
val = mp.call(val)
|
91
|
+
end
|
92
|
+
val
|
93
|
+
end
|
94
|
+
|
95
|
+
def count(file, infos, type)
|
96
|
+
matched = infos[0].match(/(#+)(\{((-?\d+)(;(-?\d+)?)?)?\})?/)
|
97
|
+
@counter ||= []
|
98
|
+
@last ||= nil
|
99
|
+
@current ||= 0
|
100
|
+
|
101
|
+
@current = 0 if @last != file
|
102
|
+
@current += 1 if @last == file
|
103
|
+
|
104
|
+
start = matched[4] || 1
|
105
|
+
step = matched[6] || 1
|
106
|
+
start = start.to_i
|
107
|
+
step = step.to_i
|
108
|
+
|
109
|
+
@counter[@current] ||= {:start => start,
|
110
|
+
:step => step,
|
111
|
+
:current => start - step
|
112
|
+
}
|
113
|
+
|
114
|
+
@counter[@current][:current] += @counter[@current][:step]
|
115
|
+
@last = file
|
116
|
+
val = @counter[@current][:current].to_s.rjust(matched[1].length, '0')
|
117
|
+
val.gsub!(/(0+)-/, '-\1')
|
118
|
+
val
|
119
|
+
end
|
120
|
+
|
121
|
+
def length(file, infos, type)
|
122
|
+
matched = infos[0].match(/\[length(-(-?\d+))?\]/)
|
123
|
+
file.name.length - matched[2].to_i
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# TODO ajouter une option pour la gestion du nombre de points avant l'extension
|
2
|
+
module AbsoluteRenamer
|
3
|
+
class GeneralParser < AbsoluteRenamer::IParser
|
4
|
+
def self.add_options(parser, options)
|
5
|
+
parser.banner << ' [file]...'
|
6
|
+
parser.on_tail('-h', '--help', 'Display this help screen') do
|
7
|
+
puts parser
|
8
|
+
exit 0
|
9
|
+
end
|
10
|
+
|
11
|
+
parser.on('-r', '--replace PATTERN,REPLACEMENT', Array,
|
12
|
+
'String replacement ex:"pattern,replacement" ') do |data|
|
13
|
+
self.add_replacement(data, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
parser.on('-e', '--regexp-replace PATTERN,REPLACEMENT', Array,
|
17
|
+
'String replacement using regexp') do |data|
|
18
|
+
self.add_replacement(data, options, true)
|
19
|
+
end
|
20
|
+
|
21
|
+
parser.on('-f', '--format FORMAT',
|
22
|
+
'Format string used as model') do |format|
|
23
|
+
options[:format] = format
|
24
|
+
@format_given = true
|
25
|
+
end
|
26
|
+
|
27
|
+
parser.on('-x', '--ext-format FORMAT',
|
28
|
+
'Format string used as model for the extension') do |format|
|
29
|
+
options[:ext_format] = format
|
30
|
+
end
|
31
|
+
|
32
|
+
parser.on('-R', '--recursive',
|
33
|
+
'Rename files in subdirectories recursively') do
|
34
|
+
options[:rec] = true
|
35
|
+
end
|
36
|
+
|
37
|
+
parser.on('--maxdepth N', Integer, 'Maximum recursion depth') do |depth|
|
38
|
+
options[:maxdepth] = depth
|
39
|
+
end
|
40
|
+
|
41
|
+
parser.on('-m', '--mode MODE', [:rename, :copy, :move, :link],
|
42
|
+
'Renaming mode. Can be used with --dest DEST.',
|
43
|
+
' rename: simply rename files',
|
44
|
+
' copy: make a copy of each file in DEST with its new name',
|
45
|
+
' move: move each file in DEST with its new name',
|
46
|
+
' link: create a symbolic link to each file in DEST' <<
|
47
|
+
' with its new name') do |mode|
|
48
|
+
options[:mode] = mode
|
49
|
+
end
|
50
|
+
|
51
|
+
parser.on('--dest DEST', 'Destination directory' <<
|
52
|
+
' for copy, move and link modes') do |dest|
|
53
|
+
options[:dest] = File.expand_path(dest)
|
54
|
+
end
|
55
|
+
|
56
|
+
parser.on('-d', '--directories', 'Directories handling') do
|
57
|
+
options[:dir] = true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.add_replacement(data, options, regexp = false)
|
62
|
+
pattern,replace = data[0..1]
|
63
|
+
replace ||= ''
|
64
|
+
pattern = Regexp.new(pattern) if regexp
|
65
|
+
moment = @format_given.nil? ? :before : :after
|
66
|
+
options[:replacements] ||= {}
|
67
|
+
options[:replacements][moment] ||= []
|
68
|
+
options[:replacements][moment] << {:type => pattern.class,
|
69
|
+
:pattern => pattern,
|
70
|
+
:replace => replace
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module AbsoluteRenamer
|
2
|
+
class InteractiveParser < AbsoluteRenamer::IParser
|
3
|
+
def self.add_options(parser, options)
|
4
|
+
parser.on('-i', 'Prompt before each renamming') do
|
5
|
+
options[:interactive] = :always
|
6
|
+
end
|
7
|
+
|
8
|
+
parser.on('-I', 'Prompt once before batch renamming') do
|
9
|
+
options[:interactive] = :once
|
10
|
+
end
|
11
|
+
|
12
|
+
parser.on('--interactive [WHEN]', [:always, :never, :once],
|
13
|
+
'Prompt according to WHEN: never, once (-I), or always (-i).',
|
14
|
+
'Without WHEN, prompt always') do |w|
|
15
|
+
w = :always if w.nil?
|
16
|
+
options[:interactive] = w
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module AbsoluteRenamer
|
2
|
+
class InteractivePlugin < AbsoluteRenamer::IPlugin
|
3
|
+
def before_batch_renaming
|
4
|
+
if conf[:options][:interactive] == :once
|
5
|
+
conf[:files].each do |file|
|
6
|
+
file.display_change
|
7
|
+
end
|
8
|
+
print "Do you want to rename this files ? [y/N] "
|
9
|
+
begin
|
10
|
+
resp = STDIN.readline.chomp.downcase
|
11
|
+
rescue Exception => e
|
12
|
+
puts "\nExiting renamer"
|
13
|
+
exit(0)
|
14
|
+
end
|
15
|
+
return resp == "y"
|
16
|
+
end
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def before_file_renaming(params)
|
21
|
+
if conf[:options][:interactive] == :always
|
22
|
+
params[:file].display_change
|
23
|
+
print "Do you want to rename this file ? [y/N] "
|
24
|
+
begin
|
25
|
+
resp = STDIN.readline.chomp.downcase
|
26
|
+
rescue Exception => e
|
27
|
+
puts "\nExiting renamer"
|
28
|
+
exit(0)
|
29
|
+
end
|
30
|
+
return resp == "y"
|
31
|
+
end
|
32
|
+
true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module AbsoluteRenamer
|
2
|
+
class ListingPlugin < AbsoluteRenamer::IPlugin
|
3
|
+
def before_batch_renaming
|
4
|
+
listing = conf[:options][:listing] || false
|
5
|
+
if listing
|
6
|
+
conf[:files].each do |file|
|
7
|
+
file.display_change
|
8
|
+
end
|
9
|
+
return false
|
10
|
+
end
|
11
|
+
true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'ftools'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'absolute_renamer/use_config'
|
4
|
+
require 'absolute_renamer/libs/file'
|
5
|
+
|
6
|
+
module AbsoluteRenamer
|
7
|
+
# Class that represents each file to be renamed.
|
8
|
+
# It contains all informations about a file and, in the end,
|
9
|
+
# processes to its renaming.
|
10
|
+
class FileInfo
|
11
|
+
include AbsoluteRenamer::UseConfig
|
12
|
+
|
13
|
+
attr_accessor :name, :new_name,
|
14
|
+
:path, :real_path,
|
15
|
+
:ext, :dir, :dir_path,
|
16
|
+
:level
|
17
|
+
|
18
|
+
# Initializes a FileInfo.
|
19
|
+
# path: the relative or absolute path of the file.
|
20
|
+
def initialize(path)
|
21
|
+
@path = path
|
22
|
+
@real_path = File.expand_path(@path)
|
23
|
+
@dir_path = File.dirname(@real_path)
|
24
|
+
@dir = File.directory?(@real_path)
|
25
|
+
@name = File.basename(@real_path)
|
26
|
+
unless @dir
|
27
|
+
# TODO utiliser une conf :dot
|
28
|
+
@ext = File.extname(@name)
|
29
|
+
@name.gsub!(Regexp.new('.' << @ext << '$'), '') unless @ext.empty?
|
30
|
+
@level = 0
|
31
|
+
else
|
32
|
+
@level = @real_path.split('/').size
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a description of a FileInfo
|
37
|
+
# some_fileinfo.inspect # => "File: hello_world pdf"
|
38
|
+
def inspect
|
39
|
+
"File: #{@name} #{@ext}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Displays the action that will be done on the file.
|
43
|
+
# some_fileinfo.display_change # => "rename a_file.txt --> A_File.TXT"
|
44
|
+
def display_change
|
45
|
+
puts "#{conf[:options][:mode]} #{@real_path.sub(Dir.pwd+'/', '')} --> #{new_path.sub(Dir.pwd+'/', '')}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the new path of the file.
|
49
|
+
def new_path
|
50
|
+
if conf[:options][:dest].nil? or conf[:options][:dest].empty?
|
51
|
+
File.join(@dir_path, @new_name)
|
52
|
+
else
|
53
|
+
File.join(conf[:options][:dest], @new_name)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Renames the file.
|
58
|
+
def rename
|
59
|
+
display_change
|
60
|
+
File.rename(@real_path, new_path)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Copies the file.
|
64
|
+
def copy
|
65
|
+
display_change
|
66
|
+
if @dir
|
67
|
+
if @real_path != conf[:options][:dest]
|
68
|
+
FileUtils.cp_r(@real_path, conf[:options][:dest])
|
69
|
+
else
|
70
|
+
puts "#{real_path} ignored"
|
71
|
+
end
|
72
|
+
else
|
73
|
+
File.copy(@real_path, new_path, false)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Moves a file. Moving to the same directories is just like renaming.
|
78
|
+
def move
|
79
|
+
display_change
|
80
|
+
File.move(@real_path, new_path, false)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Creates a symbolic link to the file.
|
84
|
+
def link
|
85
|
+
display_change
|
86
|
+
begin
|
87
|
+
File.symlink(@real_path, new_path)
|
88
|
+
rescue NotImplemented
|
89
|
+
# TODO trouver mieux
|
90
|
+
puts "Error: cannot create symlinks"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.compare_level(a, b)
|
95
|
+
if (a.level == b.level)
|
96
|
+
return (a.name <= b.name) ? -1 : 1
|
97
|
+
else
|
98
|
+
return (a.level < b.level) ? 1 : -1
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'absolute_renamer/with_children'
|
2
|
+
|
3
|
+
module AbsoluteRenamer
|
4
|
+
# Modules parent class.
|
5
|
+
# Modules must inherit of it.
|
6
|
+
class IModule < AbsoluteRenamer::WithChildren
|
7
|
+
def initialize
|
8
|
+
@filters = []
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns the classname symbol
|
12
|
+
def self.symbol
|
13
|
+
name.intern
|
14
|
+
end
|
15
|
+
|
16
|
+
# Process a +file+ by searching for a known pattern in its name
|
17
|
+
# and replacing it by the corresponding value.
|
18
|
+
# The pattern is a regular expression obtained by concatening
|
19
|
+
# the +@filters+ variable with "|".
|
20
|
+
#
|
21
|
+
# file: a FileInfo instance
|
22
|
+
# format: the format string used to rename the file
|
23
|
+
# type: the type of the renaming format (:name or :ext)
|
24
|
+
def process(file, format, type = :name)
|
25
|
+
return format if @filters.empty?
|
26
|
+
|
27
|
+
str = format
|
28
|
+
result = []
|
29
|
+
pattern = Regexp.new(@filters.join('|'))
|
30
|
+
|
31
|
+
idx = str.index(pattern)
|
32
|
+
while idx
|
33
|
+
matched = pattern.match(str).to_a.compact
|
34
|
+
part = str.partition(matched[0])
|
35
|
+
result.push(part[0])
|
36
|
+
val = self.interpret(file, matched, type)
|
37
|
+
result.push(val)
|
38
|
+
str = part[2]
|
39
|
+
idx = str.index(pattern)
|
40
|
+
end
|
41
|
+
result.push(str) unless str.empty?
|
42
|
+
format.replace(result.join)
|
43
|
+
format
|
44
|
+
end
|
45
|
+
|
46
|
+
# Interprets a matched pattern.
|
47
|
+
# Searchs for the corresponding callback
|
48
|
+
# in the current module and call it.
|
49
|
+
#
|
50
|
+
# file: a FileInfo instance
|
51
|
+
# infos: the matched values depending of the pattern
|
52
|
+
# type: the type of the renaming format (:name or :ext)
|
53
|
+
def interpret(file, infos, type)
|
54
|
+
modifier = infos[2]
|
55
|
+
action = infos[3]
|
56
|
+
|
57
|
+
return conf[:options][:default_string] unless self.respond_to?(action.intern)
|
58
|
+
|
59
|
+
ap = self.method(action.intern)
|
60
|
+
val = ap.call(file, infos, type)
|
61
|
+
unless modifier.empty?
|
62
|
+
mp = CaseModule.method(CaseModule.actions[modifier])
|
63
|
+
val = mp.call(val)
|
64
|
+
end
|
65
|
+
val.empty? ? conf[:options][:default_string] : val
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Extension of existing File class.
|
2
|
+
class << File
|
3
|
+
# Returns the extension of a file.
|
4
|
+
# path: the path of the file
|
5
|
+
# dot: starting from the end, number of dots to count before cuting extension.
|
6
|
+
def extname(path, dot = 1)
|
7
|
+
pattern = (0...dot).inject('') { |pat,x| pat << '\.[^\.]+' } << '$'
|
8
|
+
ext = File.basename(path).match(pattern).to_s
|
9
|
+
ext.empty? ? "" : ext[1..ext.length]
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Extension of existing String class
|
2
|
+
class String
|
3
|
+
# Returns a camelized version of a string
|
4
|
+
# word_separator: a regular expression used to separate words.
|
5
|
+
# str = "hello.THE world"
|
6
|
+
# str.camelize # => "Hello.The World"
|
7
|
+
# str.camelize(/[\.]/) # => "Hello.The world"
|
8
|
+
# str # => "hello.THE world"
|
9
|
+
def camelize(word_separators = /[\W_]/)
|
10
|
+
self.clone.camelize!(word_separators)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Camelizes a string and returns it.
|
14
|
+
# str = "Hello.THE World"
|
15
|
+
# str.camelize! # => "Hello.The World"
|
16
|
+
# str.camelize!(/[\.]/) # => "Hello.The World"
|
17
|
+
# str # => "Hello.The World"
|
18
|
+
def camelize!(word_separators = /[\W_]/)
|
19
|
+
self.downcase!
|
20
|
+
self.each_char.each_with_index do |c,i|
|
21
|
+
if self[i-1].chr =~ word_separators or i.zero?
|
22
|
+
self[i] = c.upcase if c =~ /[a-z]/
|
23
|
+
end
|
24
|
+
end
|
25
|
+
self
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'absolute_renamer/iparser'
|
3
|
+
require 'absolute_renamer/use_config'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
module AbsoluteRenamer
|
7
|
+
# Class in charge of the command line parsing.
|
8
|
+
class Parser
|
9
|
+
class << self
|
10
|
+
include AbsoluteRenamer::UseConfig
|
11
|
+
|
12
|
+
# Calls all registred parsers.
|
13
|
+
# The parsers are written in configuration files.
|
14
|
+
# The core parsers are automaticaly added.
|
15
|
+
def parse_cmd_line
|
16
|
+
parsers_dir = conf[:path][:parsers]
|
17
|
+
parsers = conf[:parsers]
|
18
|
+
|
19
|
+
core_parsers = ['general']
|
20
|
+
|
21
|
+
parsers += core_parsers.map! { |core_parser| File.join('core', core_parser) }
|
22
|
+
|
23
|
+
parsers.each do |parser|
|
24
|
+
parser_file = File.join(parsers_dir, parser, 'parser.rb')
|
25
|
+
begin
|
26
|
+
if require parser_file
|
27
|
+
puts "Loaded: #{parser_file}" if conf[:debug]
|
28
|
+
end
|
29
|
+
rescue LoadError => e
|
30
|
+
STDERR.puts(e)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
ARGV.options do |parser|
|
35
|
+
begin
|
36
|
+
list = AbsoluteRenamer::IParser.children
|
37
|
+
list.each do |class_name|
|
38
|
+
class_name.add_options(parser, conf[:options])
|
39
|
+
end
|
40
|
+
parser.parse!
|
41
|
+
rescue RuntimeError => ex
|
42
|
+
STDERR.puts(ex)
|
43
|
+
exit 1
|
44
|
+
end
|
45
|
+
conf[:files] = self.get_files(ARGV, 0) || []
|
46
|
+
conf[:options][:maxdepth] ||= 0
|
47
|
+
conf[:options][:interactive] ||= :never
|
48
|
+
conf[:options][:mode] ||= :rename
|
49
|
+
pp conf.get if conf[:debug]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Creates a list of all files and directories to rename.
|
54
|
+
# All options that have not been matched are considered as path.
|
55
|
+
# For directories, if the recursive otpion is set to true (conf[:rec] == true),
|
56
|
+
# files are searched in sub directories.
|
57
|
+
#
|
58
|
+
# list: a list of path to explore
|
59
|
+
# depth: maximum recursion depth
|
60
|
+
#
|
61
|
+
# Returns the files/directories list
|
62
|
+
def get_files(list, depth)
|
63
|
+
files = []
|
64
|
+
options = conf[:options]
|
65
|
+
|
66
|
+
list.each do |entry|
|
67
|
+
return files unless File.exists?(entry)
|
68
|
+
is_dir = File.directory?(entry)
|
69
|
+
mod_dir = options[:dir]
|
70
|
+
depth_ok = (depth < options[:maxdepth] or options[:maxdepth].zero?)
|
71
|
+
mod_rec = (options[:rec] and depth_ok)
|
72
|
+
|
73
|
+
add_dir = (is_dir and mod_dir)
|
74
|
+
add_file = (!is_dir and !mod_dir)
|
75
|
+
add_sub = (is_dir and (mod_rec or (!mod_dir and depth < 1)))
|
76
|
+
|
77
|
+
files << FileInfo.new(entry) if (add_dir or add_file)
|
78
|
+
files += self.get_files(self.get_subentries(entry), depth + 1) if (add_sub)
|
79
|
+
end
|
80
|
+
files
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns files and directories contained in +path+.
|
84
|
+
def get_subentries(path)
|
85
|
+
files = Dir.entries(path)
|
86
|
+
files.delete_if { |file| file[0,1] == '.' }
|
87
|
+
files.collect! { |file| path + '/' + file }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'absolute_renamer/use_config'
|
2
|
+
|
3
|
+
module AbsoluteRenamer
|
4
|
+
# Class allowing childs listing.
|
5
|
+
class WithChildren
|
6
|
+
include AbsoluteRenamer::UseConfig
|
7
|
+
|
8
|
+
@children = []
|
9
|
+
class << self
|
10
|
+
attr_reader :children
|
11
|
+
|
12
|
+
# Inheritance callback.
|
13
|
+
# When a class inherit from a WithChildren class, it is added to
|
14
|
+
# the childs list of this class.
|
15
|
+
# This list is available as the +children+ attribute.
|
16
|
+
def inherited(by)
|
17
|
+
@children << by
|
18
|
+
by.instance_variable_set(:@children, [])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class AbsoluterenamerTest < Test::Unit::TestCase
|
4
|
-
should "
|
5
|
-
|
4
|
+
should "be true" do
|
5
|
+
assert true
|
6
6
|
end
|
7
7
|
end
|
data/test/config_test.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ConfigTest < Test::Unit::TestCase
|
4
|
+
context "The Config instance" do
|
5
|
+
|
6
|
+
should "exist" do
|
7
|
+
assert_not_nil AbsoluteRenamer::Config
|
8
|
+
end
|
9
|
+
|
10
|
+
should "raise ENOENT if config file not found" do
|
11
|
+
assert_raise(Errno::ENOENT) do
|
12
|
+
AbsoluteRenamer::Config.load('a file that must not be found')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
should "not raise ENOENT if config file is found" do
|
17
|
+
assert_nothing_raised(Errno::ENOENT) do
|
18
|
+
AbsoluteRenamer::Config.load('conf/absrenamer/absrenamer.conf')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with a loaded config file" do
|
23
|
+
setup do
|
24
|
+
AbsoluteRenamer::Config.load('conf/absrenamer/absrenamer.conf')
|
25
|
+
end
|
26
|
+
|
27
|
+
should "be able to set and get config options" do
|
28
|
+
AbsoluteRenamer::Config.set(:test_key, :test_val)
|
29
|
+
assert_equal(:test_val, AbsoluteRenamer::Config.get(:test_key))
|
30
|
+
end
|
31
|
+
|
32
|
+
should "be able to set and get a config option with the nil key" do
|
33
|
+
AbsoluteRenamer::Config.set(nil, :test_val)
|
34
|
+
assert_equal(:test_val, AbsoluteRenamer::Config.get(nil))
|
35
|
+
end
|
36
|
+
|
37
|
+
should "be able to set config options using []" do
|
38
|
+
AbsoluteRenamer::Config[:test_key] = :test_val
|
39
|
+
assert_equal(:test_val, AbsoluteRenamer::Config[:test_key])
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class FileInfoTest < Test::Unit::TestCase
|
4
|
+
context "A FileInfo instance" do
|
5
|
+
context "loaded with some/path/to/a_file.txt" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@pwd = Dir.pwd
|
9
|
+
@fileinfo = AbsoluteRenamer::FileInfo.new('some/path/to/a_file.txt')
|
10
|
+
end
|
11
|
+
|
12
|
+
should "have as name : a_file" do
|
13
|
+
assert_equal('a_file', @fileinfo.name)
|
14
|
+
end
|
15
|
+
|
16
|
+
should "have as dir_path : pwd/some/path/to" do
|
17
|
+
assert_equal(@pwd + '/some/path/to', @fileinfo.dir_path)
|
18
|
+
end
|
19
|
+
|
20
|
+
should "have as path : some/path/to/a_file.txt" do
|
21
|
+
assert_equal('some/path/to/a_file.txt', @fileinfo.path)
|
22
|
+
end
|
23
|
+
|
24
|
+
should "have as real_path : pwd/some/path/to/a_file.txt" do
|
25
|
+
assert_equal(@pwd + '/some/path/to/a_file.txt', @fileinfo.real_path)
|
26
|
+
end
|
27
|
+
|
28
|
+
should "have as ext : txt" do
|
29
|
+
assert_equal('txt', @fileinfo.ext)
|
30
|
+
end
|
31
|
+
|
32
|
+
should "have as dir : false" do
|
33
|
+
assert_equal(false, @fileinfo.dir)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
context "loaded with lib/absolute_renamer" do
|
39
|
+
|
40
|
+
setup do
|
41
|
+
@pwd = Dir.pwd
|
42
|
+
@fileinfo = AbsoluteRenamer::FileInfo.new('lib/absolute_renamer')
|
43
|
+
end
|
44
|
+
|
45
|
+
should "have as name : absolute_renamer" do
|
46
|
+
assert_equal('absolute_renamer', @fileinfo.name)
|
47
|
+
end
|
48
|
+
|
49
|
+
should "have as dir_path : pwd/lib" do
|
50
|
+
assert_equal(@pwd + '/lib', @fileinfo.dir_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
should "have as path : lib/absolute_renamer" do
|
54
|
+
assert_equal('lib/absolute_renamer', @fileinfo.path)
|
55
|
+
end
|
56
|
+
|
57
|
+
should "have as real_path : pwd/lib/absolute_renamer" do
|
58
|
+
assert_equal(@pwd + '/lib/absolute_renamer', @fileinfo.real_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
should "have as ext : nil" do
|
62
|
+
assert_nil @fileinfo.ext
|
63
|
+
end
|
64
|
+
|
65
|
+
should "have as dir : true" do
|
66
|
+
assert_equal(true, @fileinfo.dir)
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/test/file_test.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Called LibFileTest instead of FileTest to avoid ruby errors
|
4
|
+
class LibFileTest < Test::Unit::TestCase
|
5
|
+
context "The File class" do
|
6
|
+
|
7
|
+
should "return txt for a_file.txt when calling extname" do
|
8
|
+
assert_equal("txt", File.extname('a_file.txt'))
|
9
|
+
end
|
10
|
+
|
11
|
+
should "return an empty string for a_file when calling extname" do
|
12
|
+
assert_equal("", File.extname('a_file'))
|
13
|
+
end
|
14
|
+
|
15
|
+
should "return tar.gz for archive.tar.gz when calling extname with 2 dots" do
|
16
|
+
assert_equal("tar.gz", File.extname('archive.tar.gz', 2))
|
17
|
+
end
|
18
|
+
|
19
|
+
should "return gz for archive.tar.gz when calling extname" do
|
20
|
+
assert_equal("gz", File.extname('archive.tar.gz'))
|
21
|
+
end
|
22
|
+
|
23
|
+
should "return an empty string for . and a_file. when calling extname" do
|
24
|
+
assert_equal("", File.extname('.'))
|
25
|
+
assert_equal("", File.extname('fichier.'))
|
26
|
+
end
|
27
|
+
|
28
|
+
should "return test for .test when calling extname" do
|
29
|
+
assert_equal("test", File.extname('.test'))
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simonc-AbsoluteRenamer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon COURTOIS
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-09-
|
12
|
+
date: 2009-09-22 00:00:00 -07:00
|
13
13
|
default_executable: absrenamer
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -34,10 +34,36 @@ extra_rdoc_files:
|
|
34
34
|
files:
|
35
35
|
- .document
|
36
36
|
- .gitignore
|
37
|
+
- AbsoluteRenamer.gemspec
|
37
38
|
- LICENSE
|
38
39
|
- README.rdoc
|
39
40
|
- Rakefile
|
40
41
|
- VERSION
|
42
|
+
- bin/absrenamer
|
43
|
+
- conf/absrenamer/absrenamer.conf
|
44
|
+
- lib/absolute_renamer.rb
|
45
|
+
- lib/absolute_renamer/config.rb
|
46
|
+
- lib/absolute_renamer/external.rb
|
47
|
+
- lib/absolute_renamer/external/modules/core/case/module.rb
|
48
|
+
- lib/absolute_renamer/external/modules/core/general/module.rb
|
49
|
+
- lib/absolute_renamer/external/parsers/core/general/parser.rb
|
50
|
+
- lib/absolute_renamer/external/parsers/interactive/parser.rb
|
51
|
+
- lib/absolute_renamer/external/parsers/listing/parser.rb
|
52
|
+
- lib/absolute_renamer/external/plugins/interactive/plugin.rb
|
53
|
+
- lib/absolute_renamer/external/plugins/listing/plugin.rb
|
54
|
+
- lib/absolute_renamer/file_info.rb
|
55
|
+
- lib/absolute_renamer/imodule.rb
|
56
|
+
- lib/absolute_renamer/iparser.rb
|
57
|
+
- lib/absolute_renamer/iplugin.rb
|
58
|
+
- lib/absolute_renamer/libs/file.rb
|
59
|
+
- lib/absolute_renamer/libs/string.rb
|
60
|
+
- lib/absolute_renamer/parser.rb
|
61
|
+
- lib/absolute_renamer/use_config.rb
|
62
|
+
- lib/absolute_renamer/with_children.rb
|
63
|
+
- test/absolute_renamer_test.rb
|
64
|
+
- test/config_test.rb
|
65
|
+
- test/file_info_test.rb
|
66
|
+
- test/file_test.rb
|
41
67
|
- test/test_helper.rb
|
42
68
|
has_rdoc: false
|
43
69
|
homepage: http://github.com/simonc/AbsoluteRenamer
|
@@ -68,4 +94,7 @@ specification_version: 3
|
|
68
94
|
summary: AbsoluteRenamer is a very powerful tool that helps files and directories renaming using the Krename syntax.
|
69
95
|
test_files:
|
70
96
|
- test/absolute_renamer_test.rb
|
97
|
+
- test/config_test.rb
|
98
|
+
- test/file_info_test.rb
|
99
|
+
- test/file_test.rb
|
71
100
|
- test/test_helper.rb
|