rrename 0.2.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.
- data/Makefile +33 -0
- data/README +11 -0
- data/TODO +8 -0
- data/rrename.gemspec +51 -0
- data/rrename.glade +1081 -0
- data/rrename.rb +897 -0
- metadata +46 -0
data/rrename.rb
ADDED
@@ -0,0 +1,897 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# RenameFiles in Ruby/GTK
|
4
|
+
#
|
5
|
+
# Copyright (c) 2005 Jens Lincke
|
6
|
+
#
|
7
|
+
# Last edited: 2005-06-27 23:52:15 by jens on wh11-618.st.uni-magdeburg.de
|
8
|
+
#
|
9
|
+
# This program is free software.
|
10
|
+
# You can distribute/modify this program under the terms of
|
11
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
12
|
+
#
|
13
|
+
|
14
|
+
require 'optparse'
|
15
|
+
require 'optparse/time'
|
16
|
+
require 'ostruct'
|
17
|
+
require 'pp'
|
18
|
+
|
19
|
+
require 'pango'
|
20
|
+
|
21
|
+
require 'gtk2'
|
22
|
+
require 'gnome2'
|
23
|
+
require 'libglade2'
|
24
|
+
|
25
|
+
require 'yaml'
|
26
|
+
require 'thread'
|
27
|
+
|
28
|
+
#
|
29
|
+
# standoff markup to inline marup
|
30
|
+
#
|
31
|
+
|
32
|
+
class Standoff
|
33
|
+
|
34
|
+
def initialize(text)
|
35
|
+
@index_tag= []
|
36
|
+
@text= text
|
37
|
+
end
|
38
|
+
|
39
|
+
def add(index, tag)
|
40
|
+
@index_tag << [index, tag]
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_tag(start_index, end_index, tag, attr="")
|
45
|
+
if attr.size == 0 then
|
46
|
+
add(start_index, "<"+tag +">")
|
47
|
+
else
|
48
|
+
add(start_index, "<"+tag +" "+attr + ">")
|
49
|
+
end
|
50
|
+
add(end_index, "</"+tag+">")
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def markup
|
55
|
+
@index_tag.sort!
|
56
|
+
offset= 0
|
57
|
+
markup= @text.clone
|
58
|
+
@index_tag.each { |index, tag|
|
59
|
+
markup.insert(index + offset, tag)
|
60
|
+
offset += tag.size
|
61
|
+
}
|
62
|
+
markup.gsub!("&", "&")
|
63
|
+
return markup
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
class CommandProcessor
|
69
|
+
attr_accessor :history
|
70
|
+
|
71
|
+
def initialize(renameFiles)
|
72
|
+
@renameFiles= renameFiles
|
73
|
+
@history= []
|
74
|
+
@redo_list= []
|
75
|
+
@log= renameFiles.log
|
76
|
+
@appbar= @renameFiles.appbar
|
77
|
+
@running= false
|
78
|
+
end
|
79
|
+
|
80
|
+
def exec(command_prototype)
|
81
|
+
if not @redo_list.empty? then
|
82
|
+
@redo_list= []
|
83
|
+
end
|
84
|
+
command= command_prototype.clone
|
85
|
+
@appbar.push(command.to_s)
|
86
|
+
command.exec
|
87
|
+
@history.push command
|
88
|
+
end
|
89
|
+
|
90
|
+
def undo
|
91
|
+
if not @history.empty? then
|
92
|
+
command= @history.pop
|
93
|
+
@appbar.push("undo " + command.to_s)
|
94
|
+
command.undo
|
95
|
+
@redo_list.push command
|
96
|
+
else
|
97
|
+
@log.p "nothing to undo"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def redo
|
102
|
+
if not @redo_list.empty? then
|
103
|
+
command= @redo_list.pop
|
104
|
+
@appbar.push("redo " + command.to_s)
|
105
|
+
command.redo
|
106
|
+
@history.push(command)
|
107
|
+
else
|
108
|
+
@log.p "nothing to redo"
|
109
|
+
@appbar.push("nothing to redo")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class RenameCommand
|
115
|
+
|
116
|
+
def initialize(renameFiles)
|
117
|
+
@renameFiles= renameFiles
|
118
|
+
@log= renameFiles.log
|
119
|
+
end
|
120
|
+
|
121
|
+
def exec
|
122
|
+
@fileset= @renameFiles.fileset
|
123
|
+
self.redo
|
124
|
+
end
|
125
|
+
|
126
|
+
def redo
|
127
|
+
@fileset.rename_changed()
|
128
|
+
end
|
129
|
+
|
130
|
+
def undo
|
131
|
+
@fileset.undo_rename()
|
132
|
+
end
|
133
|
+
|
134
|
+
def to_s
|
135
|
+
return "rename files"
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
class ReplaceCommand
|
141
|
+
|
142
|
+
def initialize(renameFiles)
|
143
|
+
@renameFiles= renameFiles
|
144
|
+
@log= renameFiles.log
|
145
|
+
end
|
146
|
+
|
147
|
+
def exec
|
148
|
+
@fileset= @renameFiles.fileset
|
149
|
+
@replaceSchema= @renameFiles.replaceschema
|
150
|
+
self.redo
|
151
|
+
end
|
152
|
+
|
153
|
+
def redo
|
154
|
+
@fileset.file_history_push
|
155
|
+
@log.p self.to_s
|
156
|
+
@fileset.replace(@replaceSchema)
|
157
|
+
end
|
158
|
+
|
159
|
+
def undo
|
160
|
+
@log.p "undo " + self.to_s
|
161
|
+
@fileset.file_history_pop
|
162
|
+
end
|
163
|
+
|
164
|
+
def to_s
|
165
|
+
"replace pattern in files"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
class EditCommand
|
171
|
+
|
172
|
+
def initialize(renameFiles, file, edit)
|
173
|
+
@renameFiles= renameFiles
|
174
|
+
@log= renameFiles.log
|
175
|
+
@file= file
|
176
|
+
@edit= edit
|
177
|
+
end
|
178
|
+
|
179
|
+
def exec
|
180
|
+
@undo_name= @file.name
|
181
|
+
self.redo
|
182
|
+
end
|
183
|
+
|
184
|
+
def redo
|
185
|
+
@log.p self.to_s
|
186
|
+
@file.name= @edit
|
187
|
+
end
|
188
|
+
|
189
|
+
def undo
|
190
|
+
@log.p "undo "+ self.to_s
|
191
|
+
@file.name= @undo_name
|
192
|
+
end
|
193
|
+
|
194
|
+
def to_s
|
195
|
+
"edit filename"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
class AddFilesCommand
|
201
|
+
|
202
|
+
def initialize(renameFiles, files)
|
203
|
+
@renameFiles= renameFiles
|
204
|
+
@log= renameFiles.log
|
205
|
+
@files= files
|
206
|
+
end
|
207
|
+
def exec
|
208
|
+
@files.each {|filename|
|
209
|
+
file= GLib.filename_to_utf8(filename)
|
210
|
+
@renameFiles.fileset.add(file)
|
211
|
+
}
|
212
|
+
end
|
213
|
+
|
214
|
+
def redo
|
215
|
+
end
|
216
|
+
|
217
|
+
def undo
|
218
|
+
end
|
219
|
+
|
220
|
+
def to_s
|
221
|
+
return "add files to list"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
class RemoveSelectedCommand
|
227
|
+
|
228
|
+
def initialize(renameFiles)
|
229
|
+
@renameFiles= renameFiles
|
230
|
+
@fileset= @renameFiles.fileset
|
231
|
+
@log= renameFiles.log
|
232
|
+
end
|
233
|
+
|
234
|
+
def exec
|
235
|
+
@removed= @fileset.remove_selected()
|
236
|
+
end
|
237
|
+
|
238
|
+
def undo
|
239
|
+
@log.p "undo remove files from list: "
|
240
|
+
@fileset.addEntries(@removed)
|
241
|
+
end
|
242
|
+
|
243
|
+
def redo
|
244
|
+
end
|
245
|
+
|
246
|
+
def to_s
|
247
|
+
return "remove files from list"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
class ReplaceSchema
|
252
|
+
attr_accessor :pattern # replace this regexp pattern
|
253
|
+
attr_accessor :substitute # with this
|
254
|
+
attr_accessor :initializeCode # eval this before iteration over file set
|
255
|
+
attr_accessor :iterationCode # eval this for each match
|
256
|
+
attr_accessor :name
|
257
|
+
|
258
|
+
def initialize(name, pattern, substitute, initializeCode, iterationCode)
|
259
|
+
@name = name
|
260
|
+
@pattern = pattern
|
261
|
+
@substitute = substitute
|
262
|
+
@initializeCode = initializeCode
|
263
|
+
@iterationCode = iterationCode
|
264
|
+
end
|
265
|
+
|
266
|
+
def file
|
267
|
+
@name.gsub(" ","_")+"_rs.yaml"
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
|
272
|
+
class FileSet
|
273
|
+
attr_accessor :regex
|
274
|
+
attr_accessor :renameFiles
|
275
|
+
attr_accessor :entries
|
276
|
+
attr_accessor :log
|
277
|
+
|
278
|
+
def initialize(renameFiles)
|
279
|
+
@renameFiles= renameFiles
|
280
|
+
@log= renameFiles.log
|
281
|
+
@entries= Hash.new
|
282
|
+
end
|
283
|
+
|
284
|
+
def markup(regex_str)
|
285
|
+
@regex= Regexp.new(regex_str)
|
286
|
+
@renameFiles.treestore.each do |model,path,iter|
|
287
|
+
model.signal_emit("row-changed", path, iter)
|
288
|
+
end
|
289
|
+
rescue RegexpError
|
290
|
+
@log.p "RegexpError: " + regex_str
|
291
|
+
end
|
292
|
+
|
293
|
+
def add(file)
|
294
|
+
addToNode(file, nil)
|
295
|
+
end
|
296
|
+
|
297
|
+
def addToNode(file, node)
|
298
|
+
filename= GLib.filename_from_utf8(file)
|
299
|
+
fileStat= File.stat(filename)
|
300
|
+
filename= GLib.filename_from_utf8(file)
|
301
|
+
if File.exist?(filename) then
|
302
|
+
@log.p "added #{file}"
|
303
|
+
|
304
|
+
if node then
|
305
|
+
addEntry(FileEntry.new(file, self), node)
|
306
|
+
else
|
307
|
+
addEntry(FileEntry.new(file, self))
|
308
|
+
end
|
309
|
+
|
310
|
+
else
|
311
|
+
@log.p file + " don't exist"
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def addEntryToNode(entry, parent)
|
316
|
+
if(parent) then
|
317
|
+
entry.parent= parent
|
318
|
+
end
|
319
|
+
entry.iter= @renameFiles.treestore.append((parent ? parent.iter : nil))
|
320
|
+
entry.iter[0]= entry
|
321
|
+
end
|
322
|
+
|
323
|
+
def includes?(entry)
|
324
|
+
return @entries[entry.expand_path]
|
325
|
+
end
|
326
|
+
|
327
|
+
def addEntry(entry)
|
328
|
+
if not includes?(entry) then
|
329
|
+
@entries[entry.expand_path]=entry
|
330
|
+
parent= @entries[File.expand_path(entry.path)]
|
331
|
+
addEntryToNode(entry, parent)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
def save_eval(aString, aBinding)
|
336
|
+
begin
|
337
|
+
return eval(aString, aBinding)
|
338
|
+
rescue SyntaxError, NameError
|
339
|
+
@log.p "error in eval: " + aString
|
340
|
+
return nil
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
def replace(replaceSchema)
|
345
|
+
file=nil
|
346
|
+
aBinding= binding
|
347
|
+
save_eval(replaceSchema.initializeCode, aBinding)
|
348
|
+
@regex= Regexp.new(replaceSchema.pattern)
|
349
|
+
@renameFiles.treestore.each do |model,path,iter|
|
350
|
+
file= iter[0]
|
351
|
+
if file.match(@regex) then
|
352
|
+
save_eval(replaceSchema.iterationCode, aBinding)
|
353
|
+
substitute= save_eval('"'+replaceSchema.substitute+'"', aBinding)
|
354
|
+
file.replace(@regex,substitute) if substitute
|
355
|
+
model.signal_emit("row-changed", path, iter)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
def file_history_pop
|
361
|
+
@renameFiles.treestore.each do |model,path,iter|
|
362
|
+
file= iter[0]
|
363
|
+
oldname= file.name
|
364
|
+
file.pop_name
|
365
|
+
model.signal_emit("row-changed", path, iter)
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def file_history_push
|
370
|
+
@renameFiles.treestore.each do |model,path,iter|
|
371
|
+
file= iter[0]
|
372
|
+
file.push_name
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def remove_selected()
|
377
|
+
remove_list= []
|
378
|
+
# iter k�nnen nicht direkt entfernt werden
|
379
|
+
removed= []
|
380
|
+
@renameFiles.treeview.selection.selected_each {|model, path, iter|
|
381
|
+
remove_list << iter
|
382
|
+
removed << iter[0]
|
383
|
+
}
|
384
|
+
remove_list.each { |iter|
|
385
|
+
remove_iter(iter)
|
386
|
+
}
|
387
|
+
return removed
|
388
|
+
end
|
389
|
+
|
390
|
+
def remove_iter(iter)
|
391
|
+
if @renameFiles.treestore.iter_is_valid? iter then
|
392
|
+
@log.p "remove #{iter[0].name} from list"
|
393
|
+
@entries.delete iter[0].expand_path
|
394
|
+
|
395
|
+
@renameFiles.treestore.remove(iter)
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
def addEntries(entries)
|
400
|
+
entries.each { |entry| addEntry(entry) }
|
401
|
+
end
|
402
|
+
|
403
|
+
def undo_rename
|
404
|
+
@renameFiles.treestore.each { |model,path,iter|
|
405
|
+
file= iter[0]
|
406
|
+
if file.undo_rename then
|
407
|
+
model.signal_emit("row-changed", path, iter)
|
408
|
+
end
|
409
|
+
}
|
410
|
+
end
|
411
|
+
|
412
|
+
def rename_changed
|
413
|
+
@renameFiles.treestore.each { |model,path,iter|
|
414
|
+
file= iter[0]
|
415
|
+
if file.changed? then
|
416
|
+
file.rename
|
417
|
+
model.signal_emit("row-changed", path, iter)
|
418
|
+
else
|
419
|
+
file.fake_rename
|
420
|
+
end
|
421
|
+
}
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
class FileEntry
|
426
|
+
attr_accessor :name
|
427
|
+
attr_accessor :parent
|
428
|
+
attr_accessor :iter
|
429
|
+
|
430
|
+
def initialize(filename, fileset, parent=nil)
|
431
|
+
@path= File.dirname(filename)
|
432
|
+
@name= File.basename(filename)
|
433
|
+
@old_name= @name.clone
|
434
|
+
@colors= ["red", "green", "blue", "orange"]
|
435
|
+
@fileset= fileset
|
436
|
+
@name_history= []
|
437
|
+
@rename_history= []
|
438
|
+
@parent= parent
|
439
|
+
@log= @fileset.log
|
440
|
+
end
|
441
|
+
|
442
|
+
def mark_color(string, color)
|
443
|
+
'<span foreground=\""'+ color + '\"">'+ string + '</span>'
|
444
|
+
end
|
445
|
+
|
446
|
+
def changed?()
|
447
|
+
return @name != @old_name
|
448
|
+
end
|
449
|
+
|
450
|
+
def full_path
|
451
|
+
path + "/" + @name
|
452
|
+
end
|
453
|
+
|
454
|
+
def expand_path
|
455
|
+
File.expand_path(full_path)
|
456
|
+
end
|
457
|
+
|
458
|
+
def path
|
459
|
+
if @parent then
|
460
|
+
return @parent.full_path
|
461
|
+
else
|
462
|
+
return @path
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
def colorize(regex)
|
467
|
+
standoff= Standoff.new(@name)
|
468
|
+
@name.scan(regex) { |m|
|
469
|
+
match= Regexp.last_match
|
470
|
+
(0...(match.length)).each {|i|
|
471
|
+
color= @colors[ i % @colors.size]
|
472
|
+
if(match.begin(i) != match.end(i)) then
|
473
|
+
standoff.add_tag(match.begin(i), match.end(i),
|
474
|
+
"span","foreground=\""+ color + "\"")
|
475
|
+
end
|
476
|
+
}
|
477
|
+
}
|
478
|
+
standoff.markup
|
479
|
+
end
|
480
|
+
|
481
|
+
def markup()
|
482
|
+
if @fileset.regex then
|
483
|
+
colorize(@fileset.regex);
|
484
|
+
else
|
485
|
+
Standoff.new(@name).markup
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
def undo_rename
|
490
|
+
old_name_name= @rename_history.pop
|
491
|
+
if old_name_name then
|
492
|
+
old_name_name
|
493
|
+
@old_name= old_name_name[0]
|
494
|
+
@name= old_name_name[1]
|
495
|
+
from= GLib.filename_from_utf8(@path + "/" + @old_name)
|
496
|
+
to= GLib.filename_from_utf8(@path + "/" + @name)
|
497
|
+
|
498
|
+
if not File.exists?(from) or not File.exists?(to) then
|
499
|
+
@log.p "rename #{to} to #{from} back"
|
500
|
+
begin
|
501
|
+
File.rename(to, from)
|
502
|
+
rescue
|
503
|
+
@log.p "error: couldn't undo rename #{to} to #{from}"
|
504
|
+
end
|
505
|
+
else
|
506
|
+
@log.p "couldn't undo rename #{to} to #{from}"
|
507
|
+
end
|
508
|
+
@log.p "undo rename #{from} to #{to}"
|
509
|
+
return true
|
510
|
+
else
|
511
|
+
return false
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
def fake_rename
|
516
|
+
@rename_history.push(nil)
|
517
|
+
end
|
518
|
+
|
519
|
+
def rename
|
520
|
+
from= GLib.filename_from_utf8(path + "/" + @old_name)
|
521
|
+
to= GLib.filename_from_utf8(path + "/" + @name)
|
522
|
+
if File.exists?(from) and not File.exists?(to) then
|
523
|
+
begin
|
524
|
+
@rename_history.push([@old_name, @name])
|
525
|
+
File.rename(from, to)
|
526
|
+
@log.p "rename #{from} to #{to}"
|
527
|
+
rescue
|
528
|
+
@log.p "couldn't rename #{from} to #{to}"
|
529
|
+
return
|
530
|
+
end
|
531
|
+
@old_name= @name.clone
|
532
|
+
else
|
533
|
+
@log.p "couldn't rename #{from} to #{to}"
|
534
|
+
@rename_history.push(nil)
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
def replace(regex, string)
|
539
|
+
if regex.match(@name) then
|
540
|
+
@name.gsub!(regex, string)
|
541
|
+
return true
|
542
|
+
else
|
543
|
+
return false
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
def match(regex)
|
548
|
+
return regex.match(@name)
|
549
|
+
end
|
550
|
+
|
551
|
+
|
552
|
+
def push_name
|
553
|
+
@name_history.push(name.clone)
|
554
|
+
end
|
555
|
+
|
556
|
+
def pop_name
|
557
|
+
if @name_history.empty? then
|
558
|
+
return false
|
559
|
+
else
|
560
|
+
@name= @name_history.pop()
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
end
|
565
|
+
|
566
|
+
class Log
|
567
|
+
|
568
|
+
def initialize(buffer, bar)
|
569
|
+
@buffer=buffer
|
570
|
+
@bar=bar
|
571
|
+
end
|
572
|
+
|
573
|
+
def p(line)
|
574
|
+
line
|
575
|
+
@buffer.insert_at_cursor(line +"\n")
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
class RenameFiles
|
580
|
+
TITLE= "Ruby Rename Files"
|
581
|
+
NAME= "Rename Files"
|
582
|
+
VERSION= "0.2.0"
|
583
|
+
CONFDIR= ".rrename"
|
584
|
+
REPLACESCHEMAS= "replaceschemas.yaml"
|
585
|
+
|
586
|
+
attr_accessor :fileset
|
587
|
+
attr_accessor :entry_replace_this
|
588
|
+
attr_accessor :entry_replace_with
|
589
|
+
attr_accessor :treestore
|
590
|
+
attr_accessor :treeview
|
591
|
+
attr_accessor :options
|
592
|
+
attr_accessor :progressBar
|
593
|
+
attr_accessor :comandProcessor
|
594
|
+
attr_accessor :log
|
595
|
+
attr_accessor :appbar
|
596
|
+
attr_accessor :textview_eval_initialize
|
597
|
+
attr_accessor :textview_eval_iteration
|
598
|
+
attr_accessor :replace_schemas
|
599
|
+
|
600
|
+
def initialize()
|
601
|
+
Gnome::Program.new(RenameFiles::NAME, RenameFiles::VERSION)
|
602
|
+
|
603
|
+
glade_file= find_in_load_path("/RenameFiles/rrename.glade")
|
604
|
+
glade_file= find_in_load_path("/rrename.glade") if not glade_file
|
605
|
+
glade_file= File.dirname($0) + "/rrename.glade" if not glade_file
|
606
|
+
@glade= GladeXML.new(glade_file, nil, "rrename"){|handler| method(handler)}
|
607
|
+
|
608
|
+
# get widgets from glade
|
609
|
+
@window= @glade.get_widget("appwindow")
|
610
|
+
@appbar= @glade.get_widget("appbar")
|
611
|
+
@treeview= @glade.get_widget("files_treeview")
|
612
|
+
@filechooser= @glade.get_widget("filechooser")
|
613
|
+
@entry_replace_this= @glade.get_widget("pattern_entry")
|
614
|
+
@entry_replace_with= @glade.get_widget("replace_entry")
|
615
|
+
@log_view= @glade.get_widget("log_textview")
|
616
|
+
@textview_eval_initialize= @glade.get_widget("textview_eval_initialize")
|
617
|
+
@textview_eval_iteration= @glade.get_widget("textview_eval_eachmatch")
|
618
|
+
@settings_menu= @glade.get_widget("settings1_menu")
|
619
|
+
@replace_schema_name= @glade.get_widget("replace_schema_name")
|
620
|
+
|
621
|
+
# initialize
|
622
|
+
@replace_schemas= Hash.new
|
623
|
+
add_replace_schema(replaceschema)
|
624
|
+
|
625
|
+
@logbuffer= @log_view.buffer
|
626
|
+
@log= Log.new(@logbuffer, @appbar)
|
627
|
+
@comandProcessor= CommandProcessor.new(self)
|
628
|
+
@fileset= FileSet.new(self)
|
629
|
+
|
630
|
+
# initialize commands
|
631
|
+
@renameCommand= RenameCommand.new(self)
|
632
|
+
@replaceCommand= ReplaceCommand.new(self)
|
633
|
+
|
634
|
+
# customize
|
635
|
+
@filechooser.select_multiple= true
|
636
|
+
parse_options(ARGV)
|
637
|
+
|
638
|
+
# setup treeview
|
639
|
+
@treestore= Gtk::TreeStore.new(Object)
|
640
|
+
@treeview.model= @treestore
|
641
|
+
@treeview.selection.mode= Gtk::SELECTION_MULTIPLE
|
642
|
+
|
643
|
+
renderer= Gtk::CellRendererText.new
|
644
|
+
renderer.editable= true
|
645
|
+
renderer.editable_set= true
|
646
|
+
renderer.mode= Gtk::CellRenderer::MODE_EDITABLE
|
647
|
+
|
648
|
+
renderer.signal_connect("edited") do |cell, arg1, arg2|
|
649
|
+
file= @treestore.get_iter(arg1)[0]
|
650
|
+
@comandProcessor.exec(EditCommand.new(self, file,arg2))
|
651
|
+
end
|
652
|
+
|
653
|
+
col= Gtk::TreeViewColumn.new("name", renderer)
|
654
|
+
@treeview.append_column(col)
|
655
|
+
col.set_cell_data_func(renderer) do |col, renderer, model, iter|
|
656
|
+
file= iter[0]
|
657
|
+
renderer.text= file.name
|
658
|
+
renderer.markup= file.markup
|
659
|
+
renderer.background= file.changed? ? "green" : "white"
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
def show_filechooser
|
664
|
+
@filechooser.set_current_folder(Dir.pwd + "/")
|
665
|
+
ret= @filechooser.run
|
666
|
+
if ret == Gtk::Dialog::RESPONSE_CANCEL
|
667
|
+
@filechooser.hide
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
def add_files(recursive=false)
|
672
|
+
if not @filechooser.filenames then
|
673
|
+
files= [ @filechooser.filename ]
|
674
|
+
else
|
675
|
+
files= @filechooser.filenames
|
676
|
+
end
|
677
|
+
files= expand_filelist_recursive(files, []).sort if recursive
|
678
|
+
@comandProcessor.exec(AddFilesCommand.new(self,files))
|
679
|
+
@treeview.expand_all
|
680
|
+
@filechooser.hide
|
681
|
+
end
|
682
|
+
|
683
|
+
def add_replace_schema(replaceSchema)
|
684
|
+
@replace_schemas[replaceSchema.name]= replaceSchema
|
685
|
+
update_setting_menu
|
686
|
+
end
|
687
|
+
|
688
|
+
def replaceschema
|
689
|
+
return ReplaceSchema.new(@replace_schema_name.gtk_entry.text,
|
690
|
+
@entry_replace_this.text,
|
691
|
+
@entry_replace_with.text,
|
692
|
+
@textview_eval_initialize.buffer.text,
|
693
|
+
@textview_eval_iteration.buffer.text)
|
694
|
+
end
|
695
|
+
|
696
|
+
def set_replaceschema(replaceschema)
|
697
|
+
return nil if not replaceschema
|
698
|
+
@replace_schema_name.gtk_entry.text = replaceschema.name
|
699
|
+
@entry_replace_this.text = replaceschema.pattern
|
700
|
+
@entry_replace_with.text = replaceschema.substitute
|
701
|
+
@textview_eval_initialize.buffer.text = replaceschema.initializeCode
|
702
|
+
@textview_eval_iteration.buffer.text = replaceschema.iterationCode
|
703
|
+
end
|
704
|
+
|
705
|
+
def confpath
|
706
|
+
GLib.home_dir+"/"+CONFDIR+"/"
|
707
|
+
end
|
708
|
+
|
709
|
+
def save_last_replace_schema
|
710
|
+
save_replace_schema(replaceschema)
|
711
|
+
end
|
712
|
+
|
713
|
+
def save_replace_schemas
|
714
|
+
file= confpath+REPLACESCHEMAS
|
715
|
+
begin
|
716
|
+
Dir.mkdir(confpath) if not File.exist? confpath
|
717
|
+
file = File.new(file, 'w')
|
718
|
+
file.write(@replace_schemas.to_yaml)
|
719
|
+
rescue
|
720
|
+
@log.p "can not save "+file
|
721
|
+
end
|
722
|
+
end
|
723
|
+
|
724
|
+
def load_replace_schemas
|
725
|
+
file= confpath+REPLACESCHEMAS
|
726
|
+
begin
|
727
|
+
@replace_schemas= YAML::load(File.open(file))
|
728
|
+
set_replaceschema= @replace_schemas[0]
|
729
|
+
rescue
|
730
|
+
@log.p "can not open "+file
|
731
|
+
end
|
732
|
+
update_setting_menu
|
733
|
+
end
|
734
|
+
|
735
|
+
def update_setting_menu
|
736
|
+
@settings_menu.each { |each|
|
737
|
+
@settings_menu.remove each
|
738
|
+
}
|
739
|
+
@replace_schemas.sort.each { |name, replaceSchema|
|
740
|
+
item= Gtk::MenuItem.new(replaceSchema.name)
|
741
|
+
@settings_menu.append(item)
|
742
|
+
item.signal_connect( "activate" ) {
|
743
|
+
set_replaceschema replaceSchema
|
744
|
+
@comandProcessor.exec(@replaceCommand)
|
745
|
+
}
|
746
|
+
}
|
747
|
+
@settings_menu.show_all
|
748
|
+
|
749
|
+
@replace_schemas.sort.each { |name, replaceSchema|
|
750
|
+
@replace_schema_name.append_history(0,name)
|
751
|
+
}
|
752
|
+
end
|
753
|
+
|
754
|
+
#
|
755
|
+
# Event Handler
|
756
|
+
#
|
757
|
+
def on_addfiles(widget)
|
758
|
+
show_filechooser
|
759
|
+
end
|
760
|
+
|
761
|
+
def on_filechooser_addfiles(widget)
|
762
|
+
add_files
|
763
|
+
end
|
764
|
+
|
765
|
+
def on_filechooser_addfiles_recursive(widget)
|
766
|
+
add_files(true)
|
767
|
+
end
|
768
|
+
|
769
|
+
def on_removefiles
|
770
|
+
@comandProcessor.exec(RemoveSelectedCommand.new(self))
|
771
|
+
end
|
772
|
+
|
773
|
+
def on_renamefiles
|
774
|
+
@comandProcessor.exec(@renameCommand)
|
775
|
+
end
|
776
|
+
|
777
|
+
def on_select_all(widget)
|
778
|
+
@treeview.select_all
|
779
|
+
end
|
780
|
+
|
781
|
+
def on_unselect_all(widget)
|
782
|
+
@treeview.unselect_all
|
783
|
+
end
|
784
|
+
|
785
|
+
def on_undo
|
786
|
+
@comandProcessor.undo
|
787
|
+
end
|
788
|
+
|
789
|
+
def on_redo
|
790
|
+
@comandProcessor.redo
|
791
|
+
end
|
792
|
+
|
793
|
+
def on_pattern_gnome_entry_changed
|
794
|
+
Thread.new {
|
795
|
+
@fileset.markup(@entry_replace_this.text)
|
796
|
+
}
|
797
|
+
end
|
798
|
+
|
799
|
+
def on_replacepattern
|
800
|
+
@comandProcessor.exec(@replaceCommand)
|
801
|
+
end
|
802
|
+
|
803
|
+
def on_replace_schema_save
|
804
|
+
add_replace_schema(replaceschema)
|
805
|
+
end
|
806
|
+
|
807
|
+
def on_replace_schema_delete
|
808
|
+
@replace_schemas.delete(replaceschema.name)
|
809
|
+
update_setting_menu
|
810
|
+
end
|
811
|
+
|
812
|
+
def on_replace_schema_name_changed
|
813
|
+
set_replaceschema @replace_schemas[@replace_schema_name.gtk_entry.text]
|
814
|
+
end
|
815
|
+
|
816
|
+
def on_quit(*widget)
|
817
|
+
save_replace_schemas
|
818
|
+
Gtk.main_quit
|
819
|
+
end
|
820
|
+
|
821
|
+
def on_about(widget)
|
822
|
+
Gnome::About.new(TITLE, VERSION ,
|
823
|
+
"Copyright (C) 2005 Jens Lincke",
|
824
|
+
"RRename - A Rename Files Tool in Ruby",
|
825
|
+
["Jens Lincke"], ["Jens Lincke"], nil).show
|
826
|
+
end
|
827
|
+
|
828
|
+
#
|
829
|
+
# private
|
830
|
+
#
|
831
|
+
def expand_filelist_recursive(fileList, result)
|
832
|
+
fileList.each{ |file|
|
833
|
+
result << file
|
834
|
+
if File.directory?(file) then
|
835
|
+
expand_filelist_recursive(Dir[file+"/*"].sort, result)
|
836
|
+
end
|
837
|
+
}
|
838
|
+
return result
|
839
|
+
end
|
840
|
+
|
841
|
+
def afterStart
|
842
|
+
load_replace_schemas
|
843
|
+
set_replaceschema @replace_schemas["default"]
|
844
|
+
if @options.recursive then
|
845
|
+
@commandArgFiles= expand_filelist_recursive(@commandArgFiles, [])
|
846
|
+
end
|
847
|
+
@comandProcessor.exec(AddFilesCommand.new(self,@commandArgFiles))
|
848
|
+
@treeview.expand_all
|
849
|
+
end
|
850
|
+
|
851
|
+
def parse_options(args)
|
852
|
+
@options= OpenStruct.new
|
853
|
+
@options.verbose= false
|
854
|
+
@options.print= true
|
855
|
+
@options.recursive= false
|
856
|
+
@file_list= []
|
857
|
+
|
858
|
+
|
859
|
+
opts= OptionParser.new do |opts|
|
860
|
+
opts.banner= "Usage: refactorhtml.rb [options] [files]"
|
861
|
+
opts.separator ""
|
862
|
+
opts.separator "Specific options:"
|
863
|
+
|
864
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
865
|
+
STDERR.puts opts
|
866
|
+
exit
|
867
|
+
end
|
868
|
+
opts.on_tail("-R", "--recursive", "add directories recursively") do
|
869
|
+
@options.recursive= true
|
870
|
+
end
|
871
|
+
end
|
872
|
+
|
873
|
+
opts.parse!(args)
|
874
|
+
|
875
|
+
@commandArgFiles= []
|
876
|
+
ARGV.each { |f|
|
877
|
+
@commandArgFiles.push(f)
|
878
|
+
}
|
879
|
+
end
|
880
|
+
|
881
|
+
def find_in_load_path( file )
|
882
|
+
$:.each { |path|
|
883
|
+
abs_file= path + file
|
884
|
+
return abs_file if File.exist? abs_file
|
885
|
+
}
|
886
|
+
return nil
|
887
|
+
end
|
888
|
+
end
|
889
|
+
|
890
|
+
@app= RenameFiles.new
|
891
|
+
Thread.new {
|
892
|
+
@app.afterStart
|
893
|
+
}
|
894
|
+
Gtk.main
|
895
|
+
|
896
|
+
|
897
|
+
|