vimamsa 0.1.13 → 0.1.14
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.
- checksums.yaml +4 -4
- data/custom_example.rb +5 -0
- data/lib/vimamsa/ack.rb +3 -4
- data/lib/vimamsa/audio.rb +25 -1
- data/lib/vimamsa/buffer.rb +43 -566
- data/lib/vimamsa/buffer_changetext.rb +255 -0
- data/lib/vimamsa/buffer_cursor.rb +303 -0
- data/lib/vimamsa/buffer_list.rb +26 -9
- data/lib/vimamsa/buffer_manager.rb +4 -2
- data/lib/vimamsa/clipboard.rb +35 -0
- data/lib/vimamsa/conf.rb +130 -5
- data/lib/vimamsa/debug.rb +4 -8
- data/lib/vimamsa/editor.rb +41 -78
- data/lib/vimamsa/encrypt.rb +6 -11
- data/lib/vimamsa/file_manager.rb +138 -9
- data/lib/vimamsa/gui.rb +3 -32
- data/lib/vimamsa/gui_dialog.rb +113 -0
- data/lib/vimamsa/gui_sourceview.rb +10 -14
- data/lib/vimamsa/gui_text.rb +19 -0
- data/lib/vimamsa/hyper_plain_text.rb +8 -5
- data/lib/vimamsa/key_actions.rb +17 -197
- data/lib/vimamsa/key_binding_tree.rb +49 -31
- data/lib/vimamsa/key_bindings_vimlike.rb +30 -30
- data/lib/vimamsa/macro.rb +35 -25
- data/lib/vimamsa/main.rb +3 -10
- data/lib/vimamsa/rbvma.rb +11 -11
- data/lib/vimamsa/search.rb +1 -1
- data/lib/vimamsa/search_replace.rb +89 -151
- data/lib/vimamsa/terminal.rb +22 -0
- data/lib/vimamsa/tests.rb +122 -0
- data/lib/vimamsa/util.rb +33 -3
- data/lib/vimamsa/version.rb +1 -1
- data/vimamsa.gemspec +3 -1
- metadata +56 -7
- /data/lib/vimamsa/{form_generator.rb → gui_form_generator.rb} +0 -0
data/lib/vimamsa/conf.rb
CHANGED
@@ -13,18 +13,143 @@ def setcnf(id, val)
|
|
13
13
|
end
|
14
14
|
|
15
15
|
setcnf :custom_lsp, {}
|
16
|
-
conf(:custom_lsp)[:ruby] = {name: "solargraph", command:"solargraph stdio", type: "stdio"}
|
17
|
-
conf(:custom_lsp)[:cpp] = {name: "clangd", command:"clangd-12 --offset-encoding=utf-8", type: "stdio"}
|
18
|
-
conf(:custom_lsp)[:python] = {name: "pyright", command:"pyright-langserver --stdio --verbose", type: "stdio"}
|
19
16
|
|
20
17
|
setcnf :indent_based_on_last_line, true
|
21
18
|
setcnf :extensions_to_open, [".txt", ".h", ".c", ".cpp", ".hpp", ".rb", ".inc", ".php", ".sh", ".m", ".gd", ".js", ".py"]
|
22
19
|
setcnf :default_search_extensions, ["txt", "rb"]
|
23
20
|
|
24
|
-
|
25
21
|
setcnf "log.verbose", 1
|
26
|
-
setcnf :tab_width, 4
|
27
22
|
setcnf :enable_lsp, false
|
28
23
|
|
24
|
+
setcnf :tab_width, 2
|
25
|
+
setcnf :tab_to_spaces_default, false
|
26
|
+
setcnf :tab_to_spaces_languages, ["c", "java", "ruby", "hyperplaintext", "php"]
|
27
|
+
setcnf :tab_to_spaces_not_languages, ["makefile"]
|
28
|
+
|
29
29
|
setcnf :workspace_folders, []
|
30
30
|
|
31
|
+
|
32
|
+
# New way to configure:
|
33
|
+
# To set conf value:
|
34
|
+
# cnf.foo.bar.baz = 3
|
35
|
+
|
36
|
+
#To get conf value:
|
37
|
+
# cnf.foo.bar.baz?
|
38
|
+
# cnf.foo.bar.baz!
|
39
|
+
# get(cnf.foo.bar.baz)
|
40
|
+
# (All get the same result)
|
41
|
+
|
42
|
+
class ConfId
|
43
|
+
def initialize(first)
|
44
|
+
@id = [first]
|
45
|
+
end
|
46
|
+
|
47
|
+
def method_missing(method_name, *args)
|
48
|
+
# pp "asize:#{args.size}"
|
49
|
+
if m = method_name.match(/(.*)=$/)
|
50
|
+
@id << m[1].to_sym
|
51
|
+
# pp [@id, args[0]]
|
52
|
+
set(self, args[0])
|
53
|
+
return args[0]
|
54
|
+
elsif m = method_name.match(/(.*)[\!\?]$/)
|
55
|
+
@id << m[1].to_sym
|
56
|
+
r = get(self)
|
57
|
+
|
58
|
+
if r.class == Hash and r.empty?
|
59
|
+
# The accessed key was not defined
|
60
|
+
return nil
|
61
|
+
else
|
62
|
+
return r
|
63
|
+
end
|
64
|
+
else
|
65
|
+
@id << method_name
|
66
|
+
end
|
67
|
+
|
68
|
+
return self
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_s
|
72
|
+
@id.join(".")
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_a
|
76
|
+
return @id
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class Conf
|
81
|
+
attr_reader :confh
|
82
|
+
|
83
|
+
def initialize()
|
84
|
+
@id = []
|
85
|
+
@confh = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
|
86
|
+
end
|
87
|
+
|
88
|
+
def method_missing(method_name, *args)
|
89
|
+
c = ConfId.new(method_name)
|
90
|
+
|
91
|
+
#TODO: improve
|
92
|
+
if m = method_name.match(/(.*)[\!\?]$/)
|
93
|
+
c = ConfId.new(m[1])
|
94
|
+
return get(c)
|
95
|
+
end
|
96
|
+
|
97
|
+
if m = method_name.match(/(.*)=$/)
|
98
|
+
c = ConfId.new(m[1])
|
99
|
+
set(c, args[0])
|
100
|
+
return args[0]
|
101
|
+
end
|
102
|
+
|
103
|
+
return c
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
$confh = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
|
110
|
+
# set cnf.foo.bar.baz, 3
|
111
|
+
# => $confh = {:foo=>{:bar=>{:baz=>3}}}
|
112
|
+
def set(_id, val)
|
113
|
+
a = $confh
|
114
|
+
id = _id.to_a
|
115
|
+
last = id.pop
|
116
|
+
for x in id
|
117
|
+
a = a[x]
|
118
|
+
end
|
119
|
+
a[last] = val
|
120
|
+
end
|
121
|
+
|
122
|
+
def get(id)
|
123
|
+
id = id.to_a
|
124
|
+
a = $confh
|
125
|
+
for x in id
|
126
|
+
return nil if a[x].nil?
|
127
|
+
return nil if a.empty?
|
128
|
+
a = a[x]
|
129
|
+
end
|
130
|
+
return a
|
131
|
+
end
|
132
|
+
|
133
|
+
$vimamsa_conf = Conf.new
|
134
|
+
|
135
|
+
def cnf()
|
136
|
+
return $vimamsa_conf
|
137
|
+
end
|
138
|
+
|
139
|
+
cnf.indent_based_on_last_line = true
|
140
|
+
cnf.extensions_to_open = [".txt", ".h", ".c", ".cpp", ".hpp", ".rb", ".inc", ".php", ".sh", ".m", ".gd", ".js", ".py"]
|
141
|
+
cnf.default_search_extensions = ["txt", "rb"]
|
142
|
+
|
143
|
+
cnf.log.verbose = 1
|
144
|
+
cnf.lsp.enabled = false
|
145
|
+
cnf.fexp.experimental = false
|
146
|
+
cnf.experimental = false
|
147
|
+
|
148
|
+
cnf.tab.width = 2
|
149
|
+
cnf.tab.to_spaces_default = false
|
150
|
+
cnf.tab.to_spaces_languages = ["c", "java", "ruby", "hyperplaintext", "php"]
|
151
|
+
cnf.tab.to_spaces_not_languages = ["makefile"]
|
152
|
+
cnf.workspace_folders = []
|
153
|
+
|
154
|
+
cnf.match.highlight.color = "#10bd8e"
|
155
|
+
|
data/lib/vimamsa/debug.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require "fileutils"
|
2
2
|
|
3
3
|
def debug(message, severity = 1)
|
4
|
-
if
|
4
|
+
if cnf.debug?
|
5
5
|
if severity > 1
|
6
6
|
# Add red colour and bold for attention
|
7
7
|
# https://en.wikipedia.org/wiki/ANSI_escape_code
|
@@ -18,7 +18,7 @@ def debug_print_buffer(c)
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def debug_dump_clipboard()
|
21
|
-
puts
|
21
|
+
puts vma.clipboard.inspect
|
22
22
|
end
|
23
23
|
|
24
24
|
def debug_dump_deltas()
|
@@ -59,8 +59,8 @@ def savedebug(message, e)
|
|
59
59
|
dbginfo["trace_str"] = dbginfo["trace"].join("\n")
|
60
60
|
dbginfo["edit_history"] = buf.edit_history
|
61
61
|
dbginfo["cnf"] = $cnf
|
62
|
-
dbginfo["register"] =
|
63
|
-
dbginfo["clipboard"] =
|
62
|
+
dbginfo["register"] = vma.register
|
63
|
+
dbginfo["clipboard"] = vma.clipboard
|
64
64
|
# dbginfo["last_event"] = $last_event
|
65
65
|
dbginfo["buffer"] = {}
|
66
66
|
dbginfo["buffer"]["str"] = buf.to_s
|
@@ -79,10 +79,6 @@ def savedebug(message, e)
|
|
79
79
|
puts save_fn_json
|
80
80
|
end
|
81
81
|
|
82
|
-
def run_tests()
|
83
|
-
run_test("01")
|
84
|
-
run_test("02")
|
85
|
-
end
|
86
82
|
|
87
83
|
def run_test(test_id)
|
88
84
|
target_results = read_file("", "tests/test_#{test_id}_output.txt")
|
data/lib/vimamsa/editor.rb
CHANGED
@@ -1,35 +1,13 @@
|
|
1
1
|
require "pty"
|
2
2
|
|
3
|
-
def exec_in_terminal(cmd, autoclose = false)
|
4
|
-
# debug "CMD:#{cmd}"
|
5
|
-
|
6
|
-
# global to prevent garbage collect unlink
|
7
|
-
$initf = Tempfile.new("bashinit")
|
8
|
-
# debug $initf.path
|
9
|
-
$initf.write(cmd)
|
10
|
-
if autoclose
|
11
|
-
$initf.write("\nsleep 10; exit;\n")
|
12
|
-
$initf.write("rm #{$initf.path}\n")
|
13
|
-
else
|
14
|
-
$initf.write("rm #{$initf.path}\n")
|
15
|
-
$initf.write("\nexec bash\n")
|
16
|
-
end
|
17
|
-
$initf.close
|
18
|
-
# PTY.spawn("gnome-terminal", "--tab", "--", "bash", "-i", $initf.path, "-c", "exec bash")
|
19
|
-
# fork { exec "gnome-terminal", "--tab", "--", "bash", "-i", $initf.path, "-c", "exec bash" }
|
20
|
-
# Just another execution
|
21
|
-
fork { exec "gnome-terminal", "--tab", "--", "bash", "-i", $initf.path, "-c", "exec bash" }
|
22
|
-
end
|
23
|
-
|
24
3
|
def handle_drag_and_drop(fname)
|
25
4
|
debug "EDITOR:handle_drag_and_drop"
|
26
5
|
buf.handle_drag_and_drop(fname)
|
27
6
|
end
|
28
7
|
|
29
|
-
|
30
8
|
class Editor
|
31
9
|
attr_reader :file_content_search_paths, :file_name_search_paths, :gui, :hook, :macro
|
32
|
-
attr_accessor :converters, :fh, :paint_stack, :kbd, :langsrv
|
10
|
+
attr_accessor :converters, :fh, :paint_stack, :kbd, :langsrv, :register, :cur_register, :clipboard
|
33
11
|
#attr_writer :call_func, :update_highlight
|
34
12
|
|
35
13
|
def initialize()
|
@@ -46,6 +24,19 @@ class Editor
|
|
46
24
|
@paint_stack = []
|
47
25
|
@_plugins = {}
|
48
26
|
@errors
|
27
|
+
@register = Hash.new("")
|
28
|
+
@cur_register = "a"
|
29
|
+
@clipboard = Clipboard.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_register(char)
|
33
|
+
@cur_register = char
|
34
|
+
message("Set register #{char}")
|
35
|
+
end
|
36
|
+
|
37
|
+
def paste_register(char)
|
38
|
+
$c = @cur_register #TODO:??
|
39
|
+
message("Paste: #{$c}")
|
49
40
|
end
|
50
41
|
|
51
42
|
def open_file_listener(added)
|
@@ -73,8 +64,7 @@ class Editor
|
|
73
64
|
@hook = $hook
|
74
65
|
register_plugin(:Hook, @hook)
|
75
66
|
@macro = Macro.new
|
76
|
-
|
77
|
-
register_plugin(:Macro, $macro)
|
67
|
+
register_plugin(:Macro, @macro)
|
78
68
|
$search = Search.new
|
79
69
|
register_plugin(:Search, $search)
|
80
70
|
|
@@ -91,7 +81,6 @@ class Editor
|
|
91
81
|
require "vimamsa/key_bindings_vimlike"
|
92
82
|
sleep(0.03)
|
93
83
|
|
94
|
-
FileManager.init
|
95
84
|
BufferManager.init
|
96
85
|
|
97
86
|
@gui.init_menu
|
@@ -130,13 +119,16 @@ class Editor
|
|
130
119
|
custom_script = read_file("", custom_fn)
|
131
120
|
eval(custom_script) if custom_script
|
132
121
|
|
122
|
+
Grep.init
|
123
|
+
FileManager.init
|
124
|
+
|
133
125
|
if conf(:enable_lsp)
|
134
126
|
require "vimamsa/langservp"
|
135
127
|
require "vimamsa/audio" # TODO:config
|
136
128
|
@langsrv["ruby"] = LangSrv.new("ruby")
|
137
129
|
@langsrv["cpp"] = LangSrv.new("cpp")
|
138
130
|
end
|
139
|
-
|
131
|
+
|
140
132
|
# build_options
|
141
133
|
|
142
134
|
fname = nil
|
@@ -306,35 +298,28 @@ def open_file_dialog()
|
|
306
298
|
gui_open_file_dialog(File.dirname(path))
|
307
299
|
end
|
308
300
|
|
309
|
-
|
310
|
-
def
|
311
|
-
|
312
|
-
if clipboard_contents != $clipboard[-1]
|
313
|
-
#TODO: HACK
|
314
|
-
$paste_lines = false
|
301
|
+
class Clipboard
|
302
|
+
def initialize
|
303
|
+
@clipboard = []
|
315
304
|
end
|
316
|
-
$clipboard << clipboard_contents
|
317
|
-
# debug $clipboard[-1]
|
318
|
-
$clipboard = $clipboard[-([$clipboard.size, max_clipboard_items].min)..-1]
|
319
|
-
end
|
320
305
|
|
321
|
-
def
|
322
|
-
|
323
|
-
|
306
|
+
def set(s)
|
307
|
+
if !(s.class <= String) or s.size == 0
|
308
|
+
debug s.inspect
|
309
|
+
debug [s, s.class, s.size]
|
310
|
+
log_error("s.class != String or s.size == 0")
|
311
|
+
return
|
312
|
+
end
|
313
|
+
@clipboard << s
|
314
|
+
set_system_clipboard(s)
|
315
|
+
vma.register[vma.cur_register] = s
|
316
|
+
debug "SET CLIPBOARD: [#{s}]"
|
317
|
+
debug "REGISTER: #{vma.cur_register}:#{vma.register[vma.cur_register]}"
|
318
|
+
end
|
324
319
|
|
325
|
-
def
|
326
|
-
|
327
|
-
debug s.inspect
|
328
|
-
debug [s, s.class, s.size]
|
329
|
-
log_error("s.class != String or s.size == 0")
|
330
|
-
# Ripl.start :binding => binding
|
331
|
-
return
|
320
|
+
def get()
|
321
|
+
return @clipboard[-1]
|
332
322
|
end
|
333
|
-
$clipboard << s
|
334
|
-
set_system_clipboard(s)
|
335
|
-
$register[$cur_register] = s
|
336
|
-
debug "SET CLIPBOARD: [#{s}]"
|
337
|
-
debug "REGISTER: #{$cur_register}:#{$register[$cur_register]}"
|
338
323
|
end
|
339
324
|
|
340
325
|
def set_cursor_pos(new_pos)
|
@@ -558,21 +543,21 @@ def load_buffer(fname)
|
|
558
543
|
return buffer
|
559
544
|
end
|
560
545
|
|
561
|
-
def jump_to_file(filename,
|
546
|
+
def jump_to_file(filename, tnum = nil, charn = nil)
|
562
547
|
open_new_file(filename)
|
563
548
|
|
564
549
|
# Link to character position
|
565
550
|
if !charn.nil?
|
566
551
|
if charn == "c"
|
567
|
-
buf.jump_to_pos(
|
552
|
+
buf.jump_to_pos(tnum) # tnum=character position
|
568
553
|
center_on_current_line
|
569
554
|
return
|
570
555
|
end
|
571
556
|
end
|
572
557
|
|
573
558
|
# Link to line
|
574
|
-
if !
|
575
|
-
buf.jump_to_line(
|
559
|
+
if !tnum.nil?
|
560
|
+
buf.jump_to_line(tnum) # tnum=line position
|
576
561
|
center_on_current_line
|
577
562
|
return
|
578
563
|
end
|
@@ -633,28 +618,6 @@ def get_file_line_pointer(s)
|
|
633
618
|
return nil
|
634
619
|
end
|
635
620
|
|
636
|
-
# TODO: Implement using https://github.com/blackwinter/ruby-filemagic
|
637
|
-
def file_is_text_file(fpath)
|
638
|
-
debug "file_is_text_file(#{fpath})"
|
639
|
-
fpath = File.expand_path(fpath)
|
640
|
-
return false if !File.exist?(fpath)
|
641
|
-
r = exec_cmd("file", fpath)
|
642
|
-
debug "DEBUG:#{r}"
|
643
|
-
return true if r.match(/UTF-8.*text/)
|
644
|
-
return true if r.match(/ASCII.*text/)
|
645
|
-
return false
|
646
|
-
end
|
647
|
-
|
648
|
-
def set_register(char)
|
649
|
-
$cur_register = char
|
650
|
-
message("Set register #{char}")
|
651
|
-
end
|
652
|
-
|
653
|
-
def paste_register(char)
|
654
|
-
$c = $register[char]
|
655
|
-
message("Paste: #{$c}")
|
656
|
-
end
|
657
|
-
|
658
621
|
def find_project_dir_of_fn(fn)
|
659
622
|
pcomp = Pathname.new(fn).each_filename.to_a
|
660
623
|
parent_dirs = (0..(pcomp.size - 2)).collect { |x| "/" + pcomp[0..x].join("/") }.reverse
|
data/lib/vimamsa/encrypt.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
require "openssl"
|
3
2
|
|
4
3
|
class Encrypt
|
@@ -13,16 +12,16 @@ class Encrypt
|
|
13
12
|
end
|
14
13
|
|
15
14
|
def encrypt(text)
|
16
|
-
cipher
|
15
|
+
cipher = @enc
|
17
16
|
encrypted = cipher.update text
|
18
17
|
encrypted << cipher.final
|
19
|
-
encrypted = encrypted.unpack(
|
18
|
+
encrypted = encrypted.unpack("H*")[0].upcase
|
20
19
|
@enc.reset
|
21
20
|
return encrypted
|
22
21
|
end
|
23
22
|
|
24
23
|
def decrypt(encrypted)
|
25
|
-
cipher
|
24
|
+
cipher = @dec
|
26
25
|
encrypted = [encrypted].pack("H*").unpack("C*").pack("c*")
|
27
26
|
plain = cipher.update encrypted
|
28
27
|
plain << cipher.final
|
@@ -32,16 +31,12 @@ class Encrypt
|
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
|
-
def decrypt_cur_buffer(password, b = nil)
|
36
|
-
vma.buf.decrypt(password)
|
37
|
-
end
|
38
34
|
|
39
35
|
def encrypt_cur_buffer()
|
40
|
-
callback = proc{|x|encrypt_cur_buffer_callback(x)}
|
41
|
-
gui_one_input_action("Encrypt", "Password:", "Encrypt", callback,{:hide=>true})
|
36
|
+
callback = proc { |x| encrypt_cur_buffer_callback(x) }
|
37
|
+
gui_one_input_action("Encrypt", "Password:", "Encrypt", callback, { :hide => true })
|
42
38
|
end
|
43
39
|
|
44
|
-
def encrypt_cur_buffer_callback(password,b=nil)
|
40
|
+
def encrypt_cur_buffer_callback(password, b = nil)
|
45
41
|
vma.buf.set_encrypted(password)
|
46
42
|
end
|
47
|
-
|
data/lib/vimamsa/file_manager.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
|
1
3
|
class FileManager
|
2
4
|
@@cur
|
3
5
|
|
4
6
|
def initialize()
|
5
7
|
@buf = nil
|
8
|
+
@cut_files = []
|
9
|
+
@copied_files = []
|
6
10
|
end
|
7
11
|
|
8
12
|
def self.chdir_parent()
|
@@ -14,7 +18,7 @@ class FileManager
|
|
14
18
|
end
|
15
19
|
|
16
20
|
def self.init()
|
17
|
-
reg_act(:start_file_selector, proc { FileManager.new.run;
|
21
|
+
reg_act(:start_file_selector, proc { FileManager.new.run; vma.kbd.set_mode(:file_exp); vma.kbd.set_default_mode(:file_exp) }, "File selector")
|
18
22
|
|
19
23
|
reg_act(:fexp_chdir_parent, proc { FileManager.chdir_parent }, "File selector")
|
20
24
|
reg_act(:fexp_select, proc { buf.module.select_line }, "")
|
@@ -32,6 +36,19 @@ class FileManager
|
|
32
36
|
bindkey "fexp o m", :fexp_sort_mtime
|
33
37
|
bindkey "fexp o f", :fexp_sort_fname
|
34
38
|
|
39
|
+
# These are not yet safe to use
|
40
|
+
if cnf.fexp.experimental?
|
41
|
+
reg_act(:fexp_cut_file, proc { FileManager.cur.cut_file }, "Cut file (to paste elsewhere)")
|
42
|
+
reg_act(:fexp_copy_file, proc { FileManager.cur.copy_file }, "Copy file (to paste elsewhere)")
|
43
|
+
reg_act(:fexp_delete_file, proc { FileManager.cur.delete_file }, "Delete current file")
|
44
|
+
reg_act(:fexp_paste_files, proc { FileManager.cur.paste_files }, "Move previously cut files here")
|
45
|
+
|
46
|
+
bindkey "fexp d d", :fexp_cut_file
|
47
|
+
bindkey "fexp y y", :fexp_copy_file
|
48
|
+
bindkey "fexp d D", :fexp_delete_file
|
49
|
+
bindkey "fexp p p", :fexp_paste_files
|
50
|
+
end
|
51
|
+
|
35
52
|
# bindkey "fexp l", [:fexp_right, proc { debug "==fexp_right==" }, ""]
|
36
53
|
bindkey "fexp h", :fexp_chdir_parent
|
37
54
|
bindkey "fexp esc", [:fexp_quit, proc { FileManager.cur.quit }, ""]
|
@@ -63,18 +80,106 @@ class FileManager
|
|
63
80
|
dir_to_buf(@ld)
|
64
81
|
end
|
65
82
|
|
83
|
+
def paste_files
|
84
|
+
if !@cut_files.empty?
|
85
|
+
message "MOVE FILES #{@cut_files.join(",")} TO #{@ld} "
|
86
|
+
# Thread.new {
|
87
|
+
for fn in @cut_files
|
88
|
+
FileUtils.move(fn, @ld)
|
89
|
+
puts "FileUtils.move(#{fn}, #{@ld})"
|
90
|
+
end
|
91
|
+
elsif !@copied_files.empty?
|
92
|
+
for fn in @copied_files
|
93
|
+
bn = File.basename(fn)
|
94
|
+
bnwe = File.basename(fn, ".*")
|
95
|
+
ext = File.extname(fn)
|
96
|
+
dst = "#{@ld}/#{bn}"
|
97
|
+
break if !File.exist?(fn)
|
98
|
+
if dst == fn #or File.exist?(dst)
|
99
|
+
i = 1
|
100
|
+
exists = true
|
101
|
+
while File.exist?(dst)
|
102
|
+
dst = "#{@ld}/#{bnwe}_copy#{i}#{ext}"
|
103
|
+
i += 1
|
104
|
+
end
|
105
|
+
elsif File.exist?(dst)
|
106
|
+
message("File #{dst} already exists")
|
107
|
+
break
|
108
|
+
#TODO: confirm if user wants to replace existing file
|
109
|
+
end
|
110
|
+
message "FileUtils.copy_entry(#{fn}, #{dst})"
|
111
|
+
FileUtils.copy_entry(fn, dst, preserve = false, dereference_root = false, remove_destination = false)
|
112
|
+
end
|
113
|
+
else
|
114
|
+
message "Nothing to paste, cut/copy some files first!"
|
115
|
+
return
|
116
|
+
end
|
117
|
+
# }
|
118
|
+
@cut_files = []
|
119
|
+
@copied_files = []
|
120
|
+
refresh
|
121
|
+
end
|
122
|
+
|
123
|
+
def cut_file
|
124
|
+
fn = cur_file
|
125
|
+
debug "CUT FILE #{fn}", 2
|
126
|
+
@cut_files << fn
|
127
|
+
@copied_files = []
|
128
|
+
end
|
129
|
+
|
130
|
+
def copy_file
|
131
|
+
fn = cur_file
|
132
|
+
debug "COPY FILE #{fn}", 2
|
133
|
+
@copied_files << fn
|
134
|
+
@cut_files = []
|
135
|
+
end
|
136
|
+
|
137
|
+
def delete_file_confirmed(*args)
|
138
|
+
debug args, 2
|
139
|
+
fn = @file_to_delete
|
140
|
+
message "Deleting file #{fn}"
|
141
|
+
# FileUtils.remove_file(fn)
|
142
|
+
FileUtils.remove_entry_secure(fn, force = false)
|
143
|
+
refresh
|
144
|
+
end
|
145
|
+
|
146
|
+
def delete_file
|
147
|
+
fn = cur_file
|
148
|
+
if File.file?(fn)
|
149
|
+
@file_to_delete = fn #TODO: set as parameter to confirm_box
|
150
|
+
Gui.confirm("Delete the file? \r #{fn}",
|
151
|
+
self.method("delete_file_confirmed"))
|
152
|
+
elsif File.directory?(fn)
|
153
|
+
@file_to_delete = fn #TODO: set as parameter to confirm_box
|
154
|
+
Gui.confirm("Delete the directory? \r #{fn}",
|
155
|
+
self.method("delete_file_confirmed"))
|
156
|
+
else
|
157
|
+
message "Can't delete #{fn}"
|
158
|
+
end
|
159
|
+
|
160
|
+
# TODO: FileUtils.remove_dir
|
161
|
+
|
162
|
+
#TODO:
|
163
|
+
end
|
164
|
+
|
66
165
|
def dir_to_buf(dirpath, b = nil)
|
67
166
|
# File.stat("testfile").mtime
|
68
167
|
|
168
|
+
debug "last file: #{vma.buffers.last_file}", 2
|
169
|
+
lastf = vma.buffers.last_file
|
170
|
+
jumpto = nil
|
171
|
+
if File.dirname(lastf) == dirpath
|
172
|
+
jumpto = File.basename(lastf)
|
173
|
+
end
|
69
174
|
vma.buffers.last_dir = dirpath
|
70
175
|
dirpath = File.expand_path(dirpath)
|
71
176
|
@header = []
|
72
177
|
@header << "#{dirpath}"
|
73
178
|
@header << "=" * 40
|
74
|
-
@ld = dirpath
|
179
|
+
@ld = dirpath # Path to current directory
|
75
180
|
@dlist = Dir.children(@ld).sort
|
76
|
-
@cdirs = []
|
77
|
-
@cfiles = []
|
181
|
+
@cdirs = [] # Dirs in current directory
|
182
|
+
@cfiles = [] # Files in current directory
|
78
183
|
for x in @dlist
|
79
184
|
fpath = fullp(x)
|
80
185
|
|
@@ -93,7 +198,6 @@ class FileManager
|
|
93
198
|
end
|
94
199
|
end
|
95
200
|
|
96
|
-
|
97
201
|
@cfiles.sort_by! { |x| x[1].mtime }.reverse! if @sort_by == :mtime
|
98
202
|
@cfiles.sort_by! { |x| x[1].size }.reverse! if @sort_by == :size
|
99
203
|
@cfiles.sort_by! { |x| x[0] } if @sort_by == :name
|
@@ -105,29 +209,54 @@ class FileManager
|
|
105
209
|
s << @cdirs.join("\n")
|
106
210
|
s << "\n"
|
107
211
|
s << "\n"
|
212
|
+
jumppos = nil
|
108
213
|
for f in @cfiles
|
214
|
+
if f[0] == jumpto
|
215
|
+
jumppos = s.size
|
216
|
+
end
|
109
217
|
s << "#{f[0]}\n"
|
110
218
|
# s << @cfiles.join("\n")
|
111
219
|
end
|
112
220
|
|
113
221
|
if @buf.nil?
|
114
|
-
@buf = create_new_buffer(s,"filemgr")
|
222
|
+
@buf = create_new_buffer(s, "filemgr")
|
223
|
+
@buf.default_mode = :file_exp
|
115
224
|
@buf.module = self
|
116
225
|
@buf.active_kbd_mode = :file_exp
|
117
226
|
else
|
118
227
|
@buf.set_content(s)
|
119
228
|
end
|
120
|
-
|
229
|
+
if jumppos
|
230
|
+
@buf.set_pos(jumppos)
|
231
|
+
else
|
232
|
+
@buf.set_line_and_column_pos(@header.size, 0)
|
233
|
+
end
|
121
234
|
end
|
122
235
|
|
123
236
|
def fullp(fn)
|
124
237
|
"#{@ld}/#{fn}"
|
125
238
|
end
|
126
239
|
|
240
|
+
def refresh
|
241
|
+
# TODO: only apply diff
|
242
|
+
lpos = @buf.lpos
|
243
|
+
# cpos = @buf.cpos
|
244
|
+
dir_to_buf(@ld)
|
245
|
+
@buf.set_line_and_column_pos(lpos, 0)
|
246
|
+
end
|
247
|
+
|
248
|
+
def cur_file
|
249
|
+
return nil if @buf.lpos < @header.size
|
250
|
+
fn = fullp(@buf.get_current_line[0..-2])
|
251
|
+
return fn
|
252
|
+
end
|
253
|
+
|
127
254
|
def select_line
|
128
|
-
return if @buf.lpos < @header.size
|
255
|
+
# return if @buf.lpos < @header.size
|
129
256
|
# debug "def select_line"
|
130
|
-
fn = fullp(@buf.get_current_line[0..-2])
|
257
|
+
# fn = fullp(@buf.get_current_line[0..-2])
|
258
|
+
fn = cur_file
|
259
|
+
return if fn.nil?
|
131
260
|
if File.directory?(fn)
|
132
261
|
debug "CHDIR: #{fn}"
|
133
262
|
dir_to_buf(fn)
|