vimamsa 0.1.12 → 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.
@@ -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)