filter_rename 1.0.0

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.
@@ -0,0 +1,82 @@
1
+ require 'mp3info'
2
+
3
+ module FilterRename
4
+
5
+ class Mp3Filename < Filename
6
+
7
+ def self.has_writable_tags
8
+ true
9
+ end
10
+
11
+ def initialize(fname, cfg)
12
+ super fname, cfg
13
+
14
+ load_mp3_data(fname)
15
+ end
16
+
17
+ def ==(dest)
18
+ super &&
19
+ ([ @title, @artist, @album, @track, @comments, @year, @genre ] ==
20
+ [ dest.get_string(:title), dest.get_string(:artist), dest.get_string(:album), dest.get_string(:track),
21
+ dest.get_string(:comments), dest.get_string(:year), dest.get_string(:genre) ])
22
+ end
23
+
24
+ def rename!(dest)
25
+ old_data = super dest
26
+
27
+ Mp3Info.open(full_filename) do |mp3|
28
+ old_data.merge!({ title: mp3.tag.title, artist: mp3.tag.artist, album: mp3.tag.album,
29
+ tracknum: mp3.tag.tracknum, comments: mp3.tag.comments, year: mp3.tag.year,
30
+ genre_s: mp3.tag.genre_s })
31
+
32
+ mp3.tag.title = dest.get_string(:title)
33
+ mp3.tag.artist = dest.get_string(:artist)
34
+ mp3.tag.album = dest.get_string(:album)
35
+ mp3.tag.tracknum = dest.get_string(:track)
36
+ mp3.tag.comments = dest.get_string(:comments).to_s
37
+ mp3.tag.year = dest.get_string(:year)
38
+ mp3.tag.genre_s = dest.get_string(:genre)
39
+
40
+ end
41
+
42
+ load_mp3_data(full_filename)
43
+
44
+ old_data
45
+ end
46
+
47
+ def diff(dest)
48
+ super(dest) + "
49
+ Title: #{Differ.diff_by_word(dest.get_string(:title).to_s, @title.to_s)}
50
+ Artist: #{Differ.diff_by_word(dest.get_string(:artist).to_s, @artist.to_s)}
51
+ Album: #{Differ.diff_by_word(dest.get_string(:album).to_s, @album.to_s)}
52
+ Track: #{Differ.diff_by_word(dest.get_string(:track).to_s, @track.to_s)}
53
+ Comments: #{Differ.diff_by_word(dest.get_string(:comments).to_s, @comments.to_s)}
54
+ Year: #{Differ.diff_by_word(dest.get_string(:year).to_s, @year.to_s)}
55
+ Genre: #{Differ.diff_by_word(dest.get_string(:genre).to_s, @genre.to_s)}
56
+ "
57
+ end
58
+
59
+
60
+ private
61
+
62
+ def load_mp3_data(fname)
63
+ mp3info = Mp3Info.new(fname)
64
+ @title = mp3info.tag.title.to_s
65
+ @artist = mp3info.tag.artist.to_s
66
+ @album = mp3info.tag.album.to_s
67
+ @track = mp3info.tag.tracknum.to_i
68
+ @comments = mp3info.tag.comments.to_s
69
+ @year = mp3info.tag.year.to_i
70
+ @genre = mp3info.tag.genre_s.to_s
71
+
72
+ # read only stuff
73
+ @vbr = (mp3info.tag.vbr ? 'vbr' : '')
74
+ @samplerate = mp3info.samplerate.to_s
75
+ @bitrate = mp3info.bitrate.to_s
76
+
77
+ [@vbr, @samplerate, @bitrate].map(&:readonly!)
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -0,0 +1,24 @@
1
+ require 'pdf-reader'
2
+
3
+ module FilterRename
4
+
5
+ class PdfFilename < Filename
6
+
7
+ def initialize(fname, cfg)
8
+ super fname, cfg
9
+
10
+ if cfg.pdf_metadata
11
+
12
+ pdfinfo = PDF::Reader.new(fname)
13
+
14
+ @page_count = pdfinfo.page_count.to_s
15
+ @page_count.readonly!
16
+
17
+ pdfinfo.info.each do |key, value|
18
+ metatag_to_var!(key.to_s.gsub(/([A-Z])([^A-Z]+)/, '\1\2 ').strip, value, true)
19
+ end unless pdfinfo.info.nil?
20
+ end
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,191 @@
1
+ require 'delegate'
2
+
3
+ module FilterRename
4
+
5
+ # This is the class which handles the list
6
+ # of filters.
7
+ class FilterList
8
+ attr_reader :filters
9
+
10
+ def initialize(list)
11
+ @filters = list
12
+ end
13
+
14
+ def expand_macros!(macro)
15
+
16
+ @filters.each_with_index do |names , i|
17
+
18
+ if FilterRename::MacroConfig == names.keys[0]
19
+ z = 1
20
+ names.values.pop.each do |n|
21
+ macro.get_macro(n).each do |k, v|
22
+ if v.nil? # Array
23
+ @filters.insert(i + z, k.keys[0].to_s.to_filter => k[k.keys[0]])
24
+ else # Hash
25
+ @filters.insert(i + z, k.to_s.to_filter => v)
26
+ end
27
+ z += 1
28
+ end
29
+ @filters[i] = nil
30
+ end
31
+ end
32
+ end
33
+
34
+ @filters.delete_if(&:nil?)
35
+ end
36
+
37
+ end
38
+
39
+
40
+ class FilterBase < SimpleDelegator
41
+
42
+ def initialize(obj, options)
43
+ super obj
44
+ @dest = obj # useful for macros
45
+ @cfg = options[:cfg]
46
+ @words = options[:words]
47
+ end
48
+
49
+ def get_words(name, section, idx = nil)
50
+ @words.get_words name, section, idx
51
+ end
52
+
53
+ def set_config(name, value)
54
+ raise InvalidFilterSetting, name unless @cfg.instance_variables.include?("@#{name}".to_sym)
55
+
56
+ @cfg.instance_variable_set ('@' + name.to_s), value
57
+ end
58
+
59
+ def get_config(name)
60
+ raise InvalidFilterSetting, name unless @cfg.instance_variables.include?("@#{name}".to_sym)
61
+
62
+ @cfg.instance_variable_get '@' + name.to_s
63
+ end
64
+
65
+ def filter(value)
66
+ set_string value
67
+ end
68
+
69
+ def set_string(value, target = nil)
70
+ if target.nil?
71
+ super @cfg.target, value
72
+ else
73
+ super target, value
74
+ end
75
+ end
76
+
77
+ def get_string(target = nil)
78
+ if target.nil?
79
+ super @cfg.target
80
+ else
81
+ super target
82
+ end
83
+ end
84
+
85
+ def match?(mask)
86
+ get_string =~ Regexp.new(mask)
87
+ end
88
+
89
+ def wrap_regex(str)
90
+ str = "(#{str})" unless str =~ /\(.*\)/
91
+ str
92
+ end
93
+
94
+ end
95
+
96
+
97
+ module IndexedParams
98
+
99
+ def get_indexes(params, callback)
100
+ indexes = []
101
+ params_length = (indexed_params == 0) ? params.length : indexed_params
102
+
103
+ params[0..params_length.pred].each do |x|
104
+ if x =~ /\.\./
105
+ indexes = indexes + Range.new(*(x.split('..').map {|y| send(callback, y, get_string) })).map { |i| i }
106
+ else
107
+ indexes << send(callback, x, get_string)
108
+ end
109
+
110
+ end
111
+
112
+ indexes
113
+ end
114
+
115
+ def indexed_params
116
+ 1
117
+ end
118
+ end
119
+
120
+
121
+ class FilterWord < FilterBase
122
+ include IndexedParams
123
+
124
+ def filter(params)
125
+ super loop_words(get_string, get_indexes(params, :word_idx), params)
126
+ end
127
+
128
+
129
+ private
130
+
131
+ def ws
132
+ get_config(:word_separator)
133
+ end
134
+
135
+ def word_idx(idx, str)
136
+ if idx.to_i.positive?
137
+ idx = idx.to_i.pred
138
+ elsif idx.to_i.negative?
139
+ idx = idx.to_i + str.split(ws).length
140
+ end
141
+ idx.to_i
142
+ end
143
+
144
+ def loop_words(str, arr_index, params)
145
+ str = str.split(ws)
146
+
147
+ arr_index.each_with_index do |idx, param_num|
148
+ str[idx] = send :filtered_word, str[idx], params, param_num.next
149
+ end
150
+
151
+ str.delete_if(&:nil?).join(ws)
152
+ end
153
+
154
+ end
155
+
156
+ class FilterNumber < FilterBase
157
+
158
+ include IndexedParams
159
+
160
+ def filter(params)
161
+ super loop_numbers(get_string, get_indexes(params, :num_idx), params)
162
+ end
163
+
164
+
165
+ private
166
+
167
+ def num_idx(idx, str)
168
+ if idx.to_i < 0
169
+ idx = str.scan(/\d+/).length + idx.to_i
170
+ elsif idx.to_i > 0
171
+ idx = idx.to_i.pred
172
+ end
173
+ idx.to_i
174
+ end
175
+
176
+ def loop_numbers(str, arr_index, params)
177
+ arr_index.each_with_index do |idx, param_idx|
178
+ str = str.map_number_with_index do |num, i|
179
+ if idx == i
180
+ num = self.send :filtered_number, num, params, param_idx.next
181
+ end
182
+
183
+ num
184
+ end
185
+ end
186
+
187
+ str
188
+ end
189
+ end
190
+
191
+ end
@@ -0,0 +1,64 @@
1
+ module FilterRename
2
+
3
+ class FilterPipe
4
+ attr_reader :source, :dest
5
+
6
+ def initialize(fname, filters, cfg)
7
+ # Filter params have to be reset for each file
8
+ @cfg = cfg.filter.clone
9
+ @source = FilenameFactory.create(fname, cfg.global)
10
+ @dest = Marshal.load(Marshal.dump(@source))
11
+ @filters = (filters.class == Array) ? filters : filters.filters
12
+ @words = cfg.words
13
+ end
14
+
15
+ def changed?
16
+ ! unchanged?
17
+ end
18
+
19
+ def unchanged?
20
+ @source == @dest
21
+ end
22
+ alias_method :identical?, :unchanged?
23
+
24
+ def diff
25
+ @source.diff(@dest)
26
+ end
27
+
28
+ def apply
29
+
30
+ @filters.each_with_index do |f, i|
31
+
32
+ filter = f.keys.pop
33
+ params = f.values.pop
34
+
35
+ if [FilterRename::Filters::Config, FilterRename::Filters::Select].include? filter
36
+ filter.new(@dest, cfg: @cfg, words: @words).filter(params)
37
+ else
38
+ filter.new(@dest, cfg: @cfg, words: @words).filter(params) unless skip?
39
+ end
40
+
41
+ end
42
+
43
+ self
44
+ end
45
+
46
+ def rename!
47
+ @source.rename!(@dest)
48
+ end
49
+
50
+ private
51
+
52
+ def skip?
53
+ if [:full_filename, :full_path, :filename].include? @cfg.grep_target.to_sym
54
+ unmatched = instance_variable_get('@' + @cfg.grep_on.to_s).send(@cfg.grep_target.to_sym).match(Regexp.new(@cfg.grep)).nil?
55
+ else
56
+ unmatched = instance_variable_get('@' + @cfg.grep_on.to_s).get_string(@cfg.grep_target).match(Regexp.new(@cfg.grep)).nil?
57
+ end
58
+
59
+ @cfg.grep_exclude.to_s.to_boolean ? !unmatched : unmatched
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,660 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FilterRename
4
+
5
+ module Filters
6
+
7
+ class Select < FilterBase
8
+ def self.hint; 'Select the target where apply further transformations'; end
9
+ def self.params; 'name|ext|folder|...'; end
10
+
11
+ def filter(params)
12
+ raise InvalidTarget, params[0] unless has_target? params[0].to_sym
13
+ set_config :target, params[0].to_sym
14
+ end
15
+ end
16
+
17
+ class Config < FilterBase
18
+ def self.hint; 'Set config PARAM to VALUE'; end
19
+ def self.params; 'PARAM:VALUE[,PARAMS2:VALUE2,...]'; end
20
+
21
+ def filter(params)
22
+ params.each do |par|
23
+ set_config(par.split(':')[0], par.split(':')[1])
24
+ end
25
+ end
26
+ end
27
+
28
+ #------------------------
29
+
30
+
31
+ class AddNumber < FilterNumber
32
+ def self.hint; 'Add NUM to the NTH number'; end
33
+ def self.params; 'NTH,NUM'; end
34
+
35
+ def filtered_number(num, params, param_num)
36
+ num.to_i + params[1].to_i
37
+ end
38
+ end
39
+
40
+
41
+ class Append < FilterBase
42
+ def self.hint; 'Append the TEXT to the current target'; end
43
+ def self.params; 'TEXT'; end
44
+
45
+ def filter(params)
46
+ super "#{get_string}#{params[0]}"
47
+ end
48
+ end
49
+
50
+
51
+ class AppendFrom < FilterBase
52
+ def self.hint; 'Append the text from TARGET'; end
53
+ def self.params; 'TARGET'; end
54
+
55
+ def filter(params)
56
+ super "#{get_string}#{get_string(params[0])}"
57
+ end
58
+ end
59
+
60
+
61
+ class AppendAsWordTo < FilterBase
62
+ def self.hint; 'Append the TEXT to TARGET as a word'; end
63
+ def self.params; 'TEXT,TARGET'; end
64
+
65
+ def filter(params)
66
+ ws = get_config(:word_separator)
67
+ set_string(get_string(params[1]).to_s.split(ws).push(params[0]).join(ws), params[1])
68
+ super get_string
69
+ end
70
+ end
71
+
72
+
73
+ class AppendTo < FilterBase
74
+ def self.hint; 'Append the TEXT to TARGET'; end
75
+ def self.params; 'TEXT,TARGET'; end
76
+
77
+ def filter(params)
78
+ set_string(get_string(params[1]).to_s + params[0], params[1])
79
+ super get_string
80
+ end
81
+ end
82
+
83
+
84
+ class AppendNumberTo < FilterNumber
85
+ def self.hint; 'Append the NTH number to TARGET'; end
86
+ def self.params; 'NTH,TARGET'; end
87
+
88
+ def filtered_number(num, params, param_num)
89
+ str = get_string(params[1])
90
+ set_string("#{str}#{num}", params[1])
91
+ num
92
+ end
93
+ end
94
+
95
+
96
+ class AppendToNumber < FilterNumber
97
+ def self.hint; 'Append the TEXT to the NTH number'; end
98
+ def self.params; 'NTH,TEXT'; end
99
+
100
+ def filtered_number(num, params, param_num)
101
+ "#{num}#{params[1]}"
102
+ end
103
+ end
104
+
105
+
106
+ class AppendToWord < FilterWord
107
+ def self.hint; 'Append the TEXT to the NTH word'; end
108
+ def self.params; 'NTH,TEXT'; end
109
+
110
+ def filtered_word(word, params, param_num)
111
+ word + params[1]
112
+ end
113
+ end
114
+
115
+
116
+ class AppendWordFrom < FilterWord
117
+ def self.hint; 'Append the NTH word from TARGET'; end
118
+ def self.params; 'NTH,TARGET'; end
119
+
120
+ def filter(params)
121
+ word = get_string(params[1]).split(ws)
122
+ idx = word_idx(params[0], word)
123
+ set_string [get_string, word[idx]].join(ws)
124
+ end
125
+ end
126
+
127
+
128
+ class AppendWordTo < FilterWord
129
+ def self.hint; 'Append the NTH word to TARGET'; end
130
+ def self.params; 'NTH,TARGET'; end
131
+
132
+ def filtered_word(word, params, param_num)
133
+ set_string([get_string(params[1]), word].join(ws), params[1])
134
+ word
135
+ end
136
+ end
137
+
138
+
139
+ class Capitalize < FilterBase
140
+ def self.hint; 'Capitalize each word'; end
141
+ def self.params; nil; end
142
+
143
+ def filter(params)
144
+ ws = get_config(:word_separator)
145
+ super (get_string.split(ws).map(&:capitalize)).join(ws)
146
+ end
147
+ end
148
+
149
+
150
+ class CopyFrom < FilterBase
151
+ def self.hint; 'Copy the text from TARGET'; end
152
+ def self.params; 'TARGET'; end
153
+
154
+ def filter(params)
155
+ super get_string(params[0]).to_s
156
+ end
157
+ end
158
+
159
+
160
+ class CopyNumberTo < FilterNumber
161
+ def self.hint; 'Move the NTH number to TARGET'; end
162
+ def self.params; 'NTH,TARGET'; end
163
+
164
+ def filtered_number(num, params, param_num)
165
+ set_string(num, params[1])
166
+ num
167
+ end
168
+ end
169
+
170
+
171
+ class CopyTo < FilterBase
172
+ def self.hint; 'Copy the text selected by REGEX to TARGET'; end
173
+ def self.params; 'REGEX,TARGET'; end
174
+
175
+ def filter(params)
176
+ set_string(get_string.scan(Regexp.new(wrap_regex(params[0]), get_config(:ignore_case).to_boolean)).pop.to_a.pop, params[1])
177
+ super get_string
178
+ end
179
+ end
180
+
181
+
182
+ class CopyWord < FilterWord
183
+ def self.hint; 'Copy the NTH1 word to the NTH2 place'; end
184
+ def self.params; 'NTH1,NTH2'; end
185
+
186
+ def indexed_params; 2; end
187
+
188
+ def filtered_word(word, params, param_num)
189
+ case param_num
190
+ when 1
191
+ @word = word
192
+ when 2
193
+ word = @word + ws + word
194
+ end
195
+
196
+ word
197
+ end
198
+ end
199
+
200
+
201
+ class Delete < FilterBase
202
+ def self.hint; 'Remove the text matching REGEX'; end
203
+ def self.params; 'REGEX1[,REGEX2,...]'; end
204
+
205
+ def filter(params)
206
+ params.each do |par|
207
+ super get_string.gsub(Regexp.new(par, get_config(:ignore_case).to_boolean), '')
208
+ end
209
+ end
210
+ end
211
+
212
+
213
+ class DeleteNumber < FilterNumber
214
+ def self.hint; 'Remove the NTH number'; end
215
+ def self.params; 'NTH'; end
216
+
217
+ def filtered_number(num, params, param_num)
218
+ ''
219
+ end
220
+ end
221
+
222
+
223
+ class DeleteWord < FilterWord
224
+ def self.hint; 'Remove the NTH word'; end
225
+ def self.params; 'NTH'; end
226
+
227
+ def filtered_word(word, params, param_num)
228
+ nil
229
+ end
230
+ end
231
+
232
+
233
+ class FormatNumber < FilterNumber
234
+ def self.hint; 'Format the NTH number adding leading zeroes to have LENGTH'; end
235
+ def self.params; 'NTH,LENGTH'; end
236
+
237
+ def filtered_number(num, params, param_num)
238
+ num.to_i.to_s.rjust(params[1].to_i, '0')
239
+ end
240
+ end
241
+
242
+
243
+ class InsertAfterWord < FilterWord
244
+ def self.hint; 'Insert the WORD after the NTH word'; end
245
+ def self.params; 'NTH,WORD'; end
246
+
247
+ def filtered_word(word, params, param_num)
248
+ [word, params[1]].join(ws)
249
+ end
250
+ end
251
+
252
+
253
+ class InsertBeforeWord < FilterWord
254
+ def self.hint; 'Insert the WORD after the NTH word'; end
255
+ def self.params; 'NTH,WORD'; end
256
+
257
+ def filtered_word(word, params, param_num)
258
+ [params[1], word].join(ws)
259
+ end
260
+ end
261
+
262
+
263
+ class JoinWords < FilterWord
264
+ def self.hint; 'Join the words from NTH1 to NTH2'; end
265
+ def self.params; 'NTH1,NTH2'; end
266
+
267
+ def filter(params)
268
+ res = get_string.split(ws)
269
+ istart = word_idx(params[0], get_string)
270
+ iend = word_idx(params[1], get_string)
271
+
272
+ res = res.insert(istart, res[istart..iend].join)
273
+ set_string res.delete_if.with_index { |x, idx| ((istart.next)..(iend.next)).include?(idx) }.join(ws)
274
+ end
275
+ end
276
+
277
+
278
+ class LeftJustify < FilterBase
279
+ def self.hint; 'Add enough CHAR(s) to the right side to have a N-length string'; end
280
+ def self.params; 'N,CHAR'; end
281
+
282
+ def filter(params)
283
+ super get_string.ljust(params[0].to_i, params[1])
284
+ end
285
+ end
286
+
287
+
288
+ class Lowercase < FilterBase
289
+ def self.hint; 'Lowercase each word'; end
290
+ def self.params; nil; end
291
+
292
+ def filter(params)
293
+ super get_string.downcase
294
+ end
295
+ end
296
+
297
+
298
+ class MoveTo < FilterBase
299
+ def self.hint; 'Move the text selected by REGEX to TARGET'; end
300
+ def self.params; 'REGEX,TARGET'; end
301
+
302
+ def filter(params)
303
+ regex = Regexp.new(wrap_regex(params[0]), get_config(:ignore_case).to_boolean)
304
+ set_string(get_string.scan(regex).pop.to_a.pop, params[1])
305
+ str = get_string.gsub(regex, '')
306
+ super str
307
+ end
308
+ end
309
+
310
+
311
+ class MoveNumberTo < FilterNumber
312
+ def self.hint; 'Move the NTH number to TARGET'; end
313
+ def self.params; 'NTH,TARGET'; end
314
+
315
+ def filtered_number(num, params, param_num)
316
+ set_string(num, params[1])
317
+ ''
318
+ end
319
+ end
320
+
321
+
322
+ class MoveWord < FilterWord
323
+ def self.hint; 'Move the NTH1 word to the NTH2 place'; end
324
+ def self.params; 'NTH1,NTH2'; end
325
+
326
+ def indexed_params; 2; end
327
+
328
+ def filtered_word(word, params, param_num)
329
+ case param_num
330
+ when 1
331
+ @word = word
332
+ res = nil
333
+ when 2
334
+ res = [word, @word].join(ws)
335
+ end
336
+
337
+ res
338
+ end
339
+ end
340
+
341
+
342
+ class MoveWordTo < FilterWord
343
+ def self.hint; 'Move the NTH word to TARGET'; end
344
+ def self.params; 'NTH,TARGET'; end
345
+
346
+ def filtered_word(word, params, param_num)
347
+ set_string(word, params[1])
348
+ nil
349
+ end
350
+ end
351
+
352
+
353
+ class MultiplyNumber < FilterNumber
354
+ def self.hint; 'Multiply the NTH number with NUM'; end
355
+ def self.params; 'NTH,NUM'; end
356
+
357
+ def filtered_number(num, params, param_num)
358
+ num.to_i * params[1].to_i
359
+ end
360
+ end
361
+
362
+
363
+ class Prepend < FilterBase
364
+ def self.hint; 'Prepend the current target with TEXT'; end
365
+ def self.params; 'TEXT'; end
366
+
367
+ def filter(params)
368
+ super "#{params[0]}#{get_string}"
369
+ end
370
+ end
371
+
372
+
373
+ class PrependFrom < FilterBase
374
+ def self.hint; 'Prepend the current target with the text from TARGET'; end
375
+ def self.params; 'TARGET'; end
376
+
377
+ def filter(params)
378
+ super "#{get_string(params[0])}#{get_string}"
379
+ end
380
+ end
381
+
382
+
383
+ class PrependToNumber < FilterNumber
384
+ def self.hint; 'Prepend the TEXT to the NTH number'; end
385
+ def self.params; 'NTH,TEXT'; end
386
+
387
+ def filtered_number(num, params, param_num)
388
+ "#{params[1]}#{num}"
389
+ end
390
+ end
391
+
392
+
393
+ class PrependToWord < FilterWord
394
+ def self.hint; 'Prepend the TEXT to the NTH word'; end
395
+ def self.params; 'NTH,TEXT'; end
396
+
397
+ def filtered_word(word, params, param_num)
398
+ params[1] + word
399
+ end
400
+ end
401
+
402
+
403
+ class Replace < FilterBase
404
+ def self.hint; 'Replace the text matching REGEX with REPLACE'; end
405
+ def self.params; 'REGEX,REPLACE'; end
406
+
407
+ def filter(params)
408
+ regexp = Regexp.new(params[0], get_config(:ignore_case).to_boolean)
409
+ super get_string.gsub(regexp, params[1])
410
+ end
411
+ end
412
+
413
+
414
+ class ReplaceFrom < FilterBase
415
+ def self.hint; 'Replace the REGEX matching text with the TARGET content'; end
416
+ def self.params; 'REGEX,TARGET'; end
417
+
418
+ def filter(params)
419
+ regexp = Regexp.new(params[0], get_config(:ignore_case).to_boolean)
420
+ super get_string.gsub(regexp, get_string(params[1]).to_s)
421
+ end
422
+
423
+ end
424
+
425
+
426
+ class ReplaceNumber < FilterNumber
427
+ def self.hint; 'Replace the NTH number with NUMBER'; end
428
+ def self.params; 'NTH,NUMBER'; end
429
+
430
+ def filtered_number(num, params, param_num)
431
+ params[1]
432
+ end
433
+ end
434
+
435
+
436
+ class ReplaceWord < FilterWord
437
+ def self.hint; 'Replace the NTH word with TEXT'; end
438
+ def self.params; 'NTH,TEXT'; end
439
+
440
+ def filtered_word(word, params, param_num)
441
+ params[1]
442
+ end
443
+ end
444
+
445
+
446
+ class ReplaceDate < FilterBase
447
+ def self.hint; 'Replace a date from FORMATSRC to FORMATDEST (placeholders: <m>, <B>, <b>, <Y>, <d>)'; end
448
+ def self.params; 'FORMATSRC,FORMATDEST[,LANG]'; end
449
+
450
+ def filter(params)
451
+ params[2] ||= get_config(:lang)
452
+ super get_string.change_date_format(format_src: params[0], format_dest: params[1],
453
+ long_months: get_words(:long_months , params[2]),
454
+ short_months: get_words(:short_months , params[2]),
455
+ long_days: get_words(:long_days, params[2]),
456
+ short_days: get_words(:short_days, params[2]))
457
+ end
458
+ end
459
+
460
+
461
+ class Reverse < FilterBase
462
+ def self.hint; 'Reverse the string'; end
463
+ def self.params; nil; end
464
+
465
+ def filter(params)
466
+ super get_string.reverse
467
+ end
468
+ end
469
+
470
+
471
+ class RightJustify < FilterBase
472
+ def self.hint; 'Apply enough CHAR(s) to the left side to have a N-length string'; end
473
+ def self.params; 'N,CHAR'; end
474
+
475
+ def filter(params)
476
+ super get_string.rjust(params[0].to_i, params[1])
477
+ end
478
+ end
479
+
480
+
481
+ class Set < FilterBase
482
+ def self.hint; 'Set the current or an optional TARGET with TEXT'; end
483
+ def self.params; 'TEXT[,TARGET]'; end
484
+
485
+ def filter(params)
486
+ if params[1].nil?
487
+ str = params[0]
488
+ else
489
+ set_string(params[0], params[1].delete(':<>'))
490
+ str = get_string
491
+ end
492
+
493
+ super str
494
+ end
495
+ end
496
+
497
+
498
+ class SetWhen < FilterBase
499
+ def self.hint; 'Set the current or given TARGET to TEXT when REGEX is matched'; end
500
+ def self.params; 'REGEX,TEXT[,TARGET]'; end
501
+
502
+ def filter(params)
503
+ target = params[-1] if params.length.odd?
504
+ set_string(params[1], target) if get_string =~ Regexp.new(params[0], get_config(:ignore_case).to_boolean)
505
+ super get_string
506
+ end
507
+ end
508
+
509
+
510
+ class Spacify < FilterBase
511
+ def self.hint; 'Replace CHAR with a space'; end
512
+ def self.params; 'CHAR1,CHAR2,...'; end
513
+
514
+ def filter(params)
515
+ regexp = Regexp.new(params.join('|'), get_config(:ignore_case).to_boolean)
516
+ super get_string.gsub(regexp, ' ')
517
+ end
518
+ end
519
+
520
+
521
+ class SplitWord < FilterWord
522
+ def self.hint; 'Split the NTH word using a REGEX with capturing groups'; end
523
+ def self.params; 'NTH,REGEX'; end
524
+
525
+ def filtered_word(word, params, param_num)
526
+ word.scan(Regexp.new(wrap_regex(params[1]), get_config(:ignore_case))).pop.to_a.join(ws)
527
+ end
528
+ end
529
+
530
+
531
+ class Squeeze < FilterBase
532
+ def self.hint; 'Squeeze consecutive CHARS in only one'; end
533
+ def self.params; 'CHAR'; end
534
+
535
+ def filter(params)
536
+ super get_string.gsub Regexp.new("#{params[0]}{2,}", get_config(:ignore_case).to_boolean), params[0]
537
+ end
538
+ end
539
+
540
+
541
+ class SwapNumber < FilterNumber
542
+ def self.hint; 'Swap the NTH1 number with the NTH2'; end
543
+ def self.params; 'NTH1,NTH2'; end
544
+
545
+ def indexed_params; 2; end
546
+
547
+ def filtered_number(num, params, param_num)
548
+ case param_num
549
+ when 1
550
+ @number = num.clone
551
+ num = get_string.get_number(params[1].to_i.pred)
552
+ when 2
553
+ num = @number
554
+ end
555
+
556
+ num
557
+ end
558
+ end
559
+
560
+
561
+ class SwapWord < FilterWord
562
+ def self.hint; 'Swap the NTH1 word with the NTH2'; end
563
+ def self.params; 'NTH1,NTH2'; end
564
+
565
+ def indexed_words; 2; end
566
+
567
+ def filtered_word(word, params, param_num)
568
+ case param_num
569
+ when 1
570
+ @word = word.clone
571
+ word = get_string.split(ws)[params[1].to_i.pred]
572
+ when 2
573
+ word = @word
574
+ end
575
+
576
+ word
577
+ end
578
+ end
579
+
580
+
581
+ class Template < FilterBase
582
+ def self.hint; 'Replace the <placeholders> in TEMPLATE with the relative targets'; end
583
+ def self.params; 'TEMPLATE'; end
584
+
585
+ def filter(params)
586
+ super params[0].gsub(/<([a-z0-9\_]+)>/) { get_string(Regexp.last_match[1]) }
587
+ end
588
+ end
589
+
590
+
591
+ class TranslateWords < FilterBase
592
+ def self.hint; 'Replace words in GROUP from SUBGRPS to SUBGRPD'; end
593
+ def self.params; 'GROUP,SUBGRPS,SUBGRPD'; end
594
+
595
+ def filter(params)
596
+ str = get_string
597
+ group = params[0].to_sym
598
+ lang_src = params[1] ? params[1].to_sym : :none
599
+ lang_dest = params[2] ? params[2].to_sym : :none
600
+
601
+ get_words(group, lang_src).each_with_index do |x, i|
602
+ str = str.gsub(Regexp.new(x, get_config(:ignore_case)), get_words(group, lang_dest, i))
603
+ end
604
+
605
+ super str
606
+ end
607
+ end
608
+
609
+
610
+ class Trim < FilterBase
611
+ def self.hint; 'Remove trailing spaces'; end
612
+ def self.params; nil; end
613
+
614
+ def filter(params)
615
+ super get_string.strip
616
+ end
617
+ end
618
+
619
+
620
+ class Uppercase < FilterBase
621
+ def self.hint; 'Uppercase each word'; end
622
+ def self.params; nil; end
623
+
624
+ def filter(params)
625
+ super get_string.upcase
626
+ end
627
+ end
628
+
629
+
630
+ class Wrap < FilterBase
631
+ def self.hint; 'Wrap the text matching REGEX with SEPARATOR1 and SEPARATOR2'; end
632
+ def self.params; 'REGEX,SEPARATOR1,SEPARATOR2'; end
633
+
634
+ def filter(params)
635
+ params[0] = "(#{params[0]})" unless params[0] =~ /[()]+/
636
+ regexp = Regexp.new("(#{params[0]})", get_config(:ignore_case).to_boolean)
637
+ super get_string.gsub(regexp, "#{params[1]}\\1#{params[2]}")
638
+ end
639
+ end
640
+
641
+
642
+ class WrapWords < FilterWord
643
+ def self.hint; 'Wrap the words between the NTH1 and the NTH2 with SEPARATOR1 and SEPARATOR2'; end
644
+ def self.params; 'NTH1,NTH2,SEPARATOR1,SEPARATOR2'; end
645
+
646
+ def indexed_words; 2; end
647
+
648
+ def filtered_word(word, params, param_num)
649
+ case param_num
650
+ when 1
651
+ word = "#{params[2]}#{word}"
652
+ when 2
653
+ word = "#{word}#{params[3]}"
654
+ end
655
+ word
656
+ end
657
+ end
658
+ end
659
+
660
+ end