vimamsa 0.1.12 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -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; $kbd.set_mode(:file_exp) }, "File selector")
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
- @buf.set_line_and_column_pos(@header.size, 0)
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)
data/lib/vimamsa/gui.rb CHANGED
@@ -6,7 +6,6 @@ def gui_open_file_dialog(dirpath)
6
6
  :buttons => [["Open", :accept],
7
7
  ["Cancel", :cancel]])
8
8
  dialog.set_current_folder(Gio::File.new_for_path(dirpath))
9
- # dialog.set_current_folder(Gio::File.new_for_path("/tmp"))
10
9
 
11
10
  dialog.signal_connect("response") do |dialog, response_id|
12
11
  if response_id == Gtk::ResponseType::ACCEPT
@@ -24,7 +23,7 @@ def gui_file_saveas(dirpath)
24
23
  :action => :save,
25
24
  :buttons => [["Save", :accept],
26
25
  ["Cancel", :cancel]])
27
- # dialog.set_current_folder(dirpath) #TODO:gtk4
26
+ dialog.set_current_folder(Gio::File.new_for_path(dirpath))
28
27
  dialog.signal_connect("response") do |dialog, response_id|
29
28
  if response_id == Gtk::ResponseType::ACCEPT
30
29
  file_saveas(dialog.file.parse_name)
@@ -36,32 +35,6 @@ def gui_file_saveas(dirpath)
36
35
  dialog.show
37
36
  end
38
37
 
39
- def idle_func
40
- # debug "IDLEFUNC"
41
- if $idle_scroll_to_mark
42
- # $view.get_visible_rect
43
- vr = $view.visible_rect
44
-
45
- # iter = b.get_iter_at(:offset => i)
46
-
47
- b = $view.buffer
48
- iter = b.get_iter_at(:offset => b.cursor_position)
49
- iterxy = $view.get_iter_location(iter)
50
- # debug "ITERXY" + iterxy.inspect
51
-
52
- intr = iterxy.intersect(vr)
53
- if intr.nil?
54
- $view.set_cursor_pos($view.buffer.cursor_position)
55
- else
56
- $idle_scroll_to_mark = false
57
- end
58
-
59
- sleep(0.1)
60
- end
61
- sleep(0.01)
62
- return true
63
- end
64
-
65
38
  def center_on_current_line()
66
39
  b = $view.buffer
67
40
  iter = b.get_iter_at(:offset => b.cursor_position)
@@ -90,37 +63,7 @@ def page_down
90
63
  return true
91
64
  end
92
65
 
93
- def paste_system_clipboard()
94
66
 
95
- #TODO: Check if something useful in this old GTK3 code.
96
- utf8_string = Gdk::Atom.intern("UTF8_STRING")
97
-
98
- clipboard = Gtk::Clipboard.get_default($vmag.window.display)
99
- received_text = ""
100
-
101
- target_string = Gdk::Selection::TARGET_STRING
102
- ti = clipboard.request_contents(target_string)
103
-
104
- if clipboard.wait_is_text_available?
105
- received_text = clipboard.wait_for_text
106
- end
107
-
108
- if received_text != "" and !received_text.nil?
109
- max_clipboard_items = 100
110
- if received_text != $clipboard[-1]
111
- #TODO: HACK
112
- $paste_lines = false
113
- end
114
- $clipboard << received_text
115
- # debug $clipboard[-1]
116
- $clipboard = $clipboard[-([$clipboard.size, max_clipboard_items].min)..-1]
117
- end
118
- return received_text
119
- end
120
-
121
- def set_system_clipboard(arg)
122
- vma.gui.window.display.clipboard.set(arg)
123
- end
124
67
 
125
68
  def gui_create_buffer(id, bufo)
126
69
  debug "gui_create_buffer(#{id})"
@@ -128,7 +71,7 @@ def gui_create_buffer(id, bufo)
128
71
  view = VSourceView.new(nil, bufo)
129
72
 
130
73
  view.register_signals()
131
- $debug = true
74
+ cnf.debug = true
132
75
 
133
76
  ssm = GtkSource::StyleSchemeManager.new
134
77
  ssm.set_search_path(ssm.search_path << ppath("styles/"))
@@ -145,6 +88,7 @@ def gui_create_buffer(id, bufo)
145
88
  provider.load(data: "textview { font-family: Monospace; font-size: 11pt; }")
146
89
  view.style_context.add_provider(provider)
147
90
  view.wrap_mode = :char
91
+ pp $cnf
148
92
  view.set_tab_width(conf(:tab_width))
149
93
 
150
94
  $vmag.buffers[id] = view
@@ -313,9 +257,15 @@ class VMAgui
313
257
  # Run proc after animated scrolling has stopped (e.g. after page down)
314
258
  def run_after_scrolling(p)
315
259
  Thread.new {
260
+ # After running
261
+ # view.signal_emit("move-cursor", Gtk::MovementStep.new(:PAGES)
262
+ # have to wait for animated page down scrolling to actually start
263
+ # Then have to wait determine that it has stopped if scrolling adjustment stops changing. There should be a better way to do this.
264
+ sleep 0.1
316
265
  while Time.now - @last_adj_time < 0.1
317
266
  sleep 0.1
318
267
  end
268
+ debug "SCROLLING ENDED", 2
319
269
  run_as_idle p
320
270
  }
321
271
  end
@@ -346,6 +296,7 @@ class VMAgui
346
296
  end
347
297
 
348
298
  def handle_deltas()
299
+ view.delete_cursor_char
349
300
  while d = buf.deltas.shift
350
301
  pos = d[0]
351
302
  op = d[1]
@@ -624,6 +575,7 @@ class VMAgui
624
575
  @sw = Gtk::ScrolledWindow.new
625
576
  @sw.set_policy(:automatic, :automatic)
626
577
 
578
+
627
579
  @last_adj_time = Time.now
628
580
  @sw.vadjustment.signal_connect("value-changed") { |x|
629
581
  # pp x.page_increment
@@ -0,0 +1,113 @@
1
+ module Gui
2
+ def self.confirm(title, callback)
3
+ params = {}
4
+ params["title"] = title
5
+ params["inputs"] = {}
6
+ params["inputs"]["yes_btn"] = { :label => "Yes", :type => :button, :default_focus => true }
7
+ params[:callback] = callback
8
+ PopupFormGenerator.new(params).run
9
+ end
10
+ end
11
+
12
+ module Gtk
13
+ class Frame
14
+ def margin=(a)
15
+ self.margin_bottom = a
16
+ self.margin_top = a
17
+ self.margin_end = a
18
+ self.margin_start = a
19
+ end
20
+ end
21
+
22
+ class Box
23
+ def margin=(a)
24
+ self.margin_bottom = a
25
+ self.margin_top = a
26
+ self.margin_end = a
27
+ self.margin_start = a
28
+ end
29
+ end
30
+ end
31
+
32
+ def set_margin_all(widget, m)
33
+ widget.margin_bottom = m
34
+ widget.margin_top = m
35
+ widget.margin_end = m
36
+ widget.margin_start = m
37
+ end
38
+
39
+ class OneInputAction
40
+ def initialize(main_window, title, field_label, button_title, callback, opt = {})
41
+ @window = Gtk::Window.new()
42
+ # @window.screen = main_window.screen
43
+ # @window.title = title
44
+ @window.title = ""
45
+
46
+ frame = Gtk::Frame.new()
47
+ # frame.margin = 20
48
+ @window.set_child(frame)
49
+
50
+ infolabel = Gtk::Label.new
51
+ infolabel.markup = title
52
+
53
+ vbox = Gtk::Box.new(:vertical, 8)
54
+ vbox.margin = 10
55
+ frame.set_child(vbox)
56
+
57
+ hbox = Gtk::Box.new(:horizontal, 8)
58
+ # @window.add(hbox)
59
+ vbox.pack_end(infolabel, :expand => false, :fill => false, :padding => 0)
60
+ vbox.pack_end(hbox, :expand => false, :fill => false, :padding => 0)
61
+
62
+ button = Gtk::Button.new(:label => button_title)
63
+ cancel_button = Gtk::Button.new(:label => "Cancel")
64
+
65
+ label = Gtk::Label.new(field_label)
66
+
67
+ @entry1 = Gtk::Entry.new
68
+
69
+ if opt[:hide]
70
+ @entry1.visibility = false
71
+ end
72
+
73
+ button.signal_connect "clicked" do
74
+ callback.call(@entry1.text)
75
+ @window.destroy
76
+ end
77
+
78
+ cancel_button.signal_connect "clicked" do
79
+ @window.destroy
80
+ end
81
+
82
+ press = Gtk::EventControllerKey.new
83
+ press.set_propagation_phase(Gtk::PropagationPhase::CAPTURE)
84
+ @window.add_controller(press)
85
+ press.signal_connect "key-pressed" do |gesture, keyval, keycode, y|
86
+ if keyval == Gdk::Keyval::KEY_Return
87
+ callback.call(@entry1.text)
88
+ @window.destroy
89
+ true
90
+ elsif keyval == Gdk::Keyval::KEY_Escape
91
+ @window.destroy
92
+ true
93
+ else
94
+ false
95
+ end
96
+ end
97
+
98
+ hbox.pack_end(label, :expand => false, :fill => false, :padding => 0)
99
+ hbox.pack_end(@entry1, :expand => false, :fill => false, :padding => 0)
100
+ hbox.pack_end(button, :expand => false, :fill => false, :padding => 0)
101
+ hbox.pack_end(cancel_button, :expand => false, :fill => false, :padding => 0)
102
+ return
103
+ end
104
+
105
+ def run
106
+ if !@window.visible?
107
+ @window.show
108
+ else
109
+ @window.destroy
110
+ end
111
+ @window
112
+ end
113
+ end
@@ -69,13 +69,19 @@ class SelectUpdateWindow
69
69
 
70
70
  @window.add(vbox)
71
71
 
72
+ if !opt[:desc].nil?
73
+ descl = Gtk::Label.new(opt[:desc])
74
+ set_margin_all(descl,15)
75
+ # vbox.append(descl, :expand => false, :fill => false, :padding => 0)
76
+ vbox.append(descl)
77
+ end
78
+
72
79
  @entry = Gtk::SearchEntry.new
73
80
  @entry.width_chars = 45
74
81
  container = Gtk::Box.new(:horizontal, 10)
75
82
  # container.halign = :start
76
83
  container.halign = :center
77
- container.pack_start(@entry,
78
- :expand => false, :fill => false, :padding => 0)
84
+ container.append(@entry)
79
85
 
80
86
  # create tree view
81
87
  @model = Gtk::ListStore.new(String, String)
@@ -135,11 +141,6 @@ class SelectUpdateWindow
135
141
  @entry.signal_connect("changed") { debug "[changed] " }
136
142
  @entry.signal_connect("next-match") { debug "[next-match] " }
137
143
 
138
- if !opt[:desc].nil?
139
- descl = Gtk::Label.new(opt[:desc])
140
- vbox.pack_start(descl, :expand => false, :fill => false, :padding => 0)
141
- end
142
-
143
144
  # label = Gtk::Label.new(<<-EOF)
144
145
  # Search:
145
146
  # EOF
@@ -147,7 +148,7 @@ class SelectUpdateWindow
147
148
  # label = Gtk::Label.new("Input:")
148
149
  # vbox.pack_start(label, :expand => false, :fill => false, :padding => 0)
149
150
 
150
- vbox.pack_start(container, :expand => false, :fill => false, :padding => 0)
151
+ vbox.append(container)
151
152
  sw = Gtk::ScrolledWindow.new(nil, nil)
152
153
  # sw.shadow_type = :etched_in #TODO:gtk4
153
154
  sw.set_policy(:never, :automatic)