vimamsa 0.1.15 → 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea3e4fa5b65895cba0a20cae08fad4f422008e786f4cd3ab405d39bf630f52db
4
- data.tar.gz: 65b80bb0e663f64d241e51130aac9e13106c58ff20f698c095e5cf43b416ce41
3
+ metadata.gz: e861051f02f35b286c8e97c225b69b9377f1d5cdf3dcf311de89a2ababb9dcd9
4
+ data.tar.gz: c27f3bc13a925dbd0293592f9d692a1918e91a7ce8047868c340098be76d1613
5
5
  SHA512:
6
- metadata.gz: 1c056fa3ed552a410b7a9f06ebfb0f2eb1444feba9a5810a520e8012a245b83bd156115566d2965095e8d7bacc184883e1bb16e724efa26c9abd0180c2640050
7
- data.tar.gz: 9196b537289ac4a08b09c53dbbdf03ccd5bec1cb50d3de4b40a03352cf64c0fc0776d489803a421d00d72bad72fd96cefc45865f27d1df5f22b67b9906c4edf9
6
+ metadata.gz: 2dbc0c1b7c6f42f0d4eca33c82b5a7e007ca549dda77b4e4d23056264a16b853b2cacbaa120ff24a1b25eb010aeea79efc955a6f3b9018bf9cca1249276f2410
7
+ data.tar.gz: b9e9deb8f5c3faf4a0f5e03757a8070d91e79e1bc959c991ca101df288fb62f809acc15154e7eab234647ad3d9b2d7a2b488b6013ff3a5c6db1978cf06e1654c
data/lib/vimamsa/ack.rb CHANGED
@@ -13,7 +13,6 @@ Will search all .txt files in the following directories:
13
13
  </span>"
14
14
 
15
15
  callback = proc { |x| FileContentSearch.search_buffer(x) }
16
- # gui_one_input_action(nfo, "Search:", "search", callback)
17
16
 
18
17
  params = {}
19
18
  params["inputs"] = {}
@@ -21,7 +20,6 @@ Will search all .txt files in the following directories:
21
20
  params["inputs"]["extensions"] = { :label => "Limit to file extensions:", :type => :entry }
22
21
  params["inputs"]["extensions"][:initial_text] = conf(:default_search_extensions).join(",")
23
22
  params["inputs"]["btn1"] = { :label => "Search", :type => :button }
24
- # callback = proc { |x| gui_replace_callback(x) }
25
23
 
26
24
  params[:callback] = callback
27
25
  PopupFormGenerator.new(params).run
@@ -106,20 +104,100 @@ Will search the following directories:
106
104
  If .vma_project exists in parent directory of current file, searches within that directory.
107
105
  </span>"
108
106
 
109
- callback = proc { |x| ack_buffer(x) }
107
+ callback = proc { |x| Ack.new.ack_buffer(x) }
110
108
  gui_one_input_action(nfo, "Search:", "search", callback)
111
109
  end
112
110
 
113
- def ack_buffer(_instr, b = nil)
114
- instr = Shellwords.escape(_instr)
115
- bufstr = ""
116
- for path in vma.get_content_search_paths
117
- bufstr += run_cmd("ack -Q --type-add=gd=.gd -ki --nohtml --nojs --nojson #{instr} #{path}")
111
+ def group_by_folder(list)
112
+ bh = {}
113
+ for b in list
114
+ fpath = b[:fpath]
115
+ if !fpath.nil?
116
+ bname = File.basename(b[:fpath])
117
+ dname = File.dirname(b[:fpath])
118
+ else
119
+ #TODO
120
+ end
121
+ bh[dname] ||= {}
122
+ bh[dname][:files] ||= []
123
+ bh[dname][:files] << { bname: bname, nfo: b }
124
+ end
125
+ arr = []
126
+
127
+ for k in bh.keys.sort
128
+ tp = tilde_path(k)
129
+ arr << { type: :dir, path: tp }
130
+ for f in bh[k][:files].sort_by { |x| x[:bname] }
131
+ arr << { type: :file, bname: f[:bname], nfo: f[:nfo] }
132
+ end
118
133
  end
119
- if bufstr.size > 5
120
- b = create_new_buffer(bufstr, "ack")
121
- Gui.highlight_match(b, _instr, color: cnf.match.highlight.color!)
122
- else
123
- message("No results for input:#{instr}")
134
+ return arr
135
+ end
136
+
137
+ class Ack
138
+ attr_reader :buf
139
+ @@cur = nil # Current object of class
140
+
141
+ def self.cur()
142
+ return @@cur
143
+ end
144
+
145
+ def self.init()
146
+ end
147
+
148
+ def initialize()
149
+ @buf = nil
150
+ @line_to_id = {}
151
+ end
152
+
153
+ def ack_buffer(_instr, b = nil)
154
+ instr = Shellwords.escape(_instr)
155
+ bufstr = ""
156
+ for path in vma.get_content_search_paths
157
+ bufstr += run_cmd("ack -Q --type-add=gd=.gd -ki --nohtml --nojs --nojson #{instr} #{path}")
158
+ end
159
+
160
+ b = ""
161
+ list = []
162
+ for x in bufstr.lines
163
+ if x.match(/(.*?):(\d+):(.+)/) # non greedy: *?
164
+ fn = $1
165
+ lineno = $2
166
+ matchpart = $3
167
+ pp [fn, lineno, matchpart]
168
+ b << "[#{fn},#{lineno},#{matchpart}]\n"
169
+ list << { fpath: fn, lineno: lineno, matchpart: matchpart }
170
+ end
171
+ end
172
+
173
+ gb = group_by_folder(list)
174
+ s = ""
175
+ @line_to_nfo = {}
176
+ i = 0
177
+ for x in gb
178
+ if x[:type] == :file
179
+ s << "╰─#{x[:bname]}:#{x[:nfo][:lineno]}:#{x[:nfo][:matchpart]}\n"
180
+ @line_to_nfo[i] = x
181
+ end
182
+ if x[:type] == :dir
183
+ s << "📂#{x[:path]}:\n"
184
+ end
185
+ i += 1
186
+ end
187
+
188
+ if s.size > 5
189
+ @buf = create_new_buffer(s, "ack")
190
+ @buf.module = self
191
+ @buf.line_action_handler = self.method("select_line")
192
+ Gui.highlight_match(@buf, _instr, color: cnf.match.highlight.color!)
193
+ else
194
+ message("No results for input:#{instr}")
195
+ end
196
+ end
197
+
198
+ def select_line(lineno)
199
+ debug "def select_line #{lineno}", 2
200
+ nfo = @line_to_nfo[lineno][:nfo]
201
+ jump_to_file(nfo[:fpath], nfo[:lineno].to_i)
124
202
  end
125
203
  end
@@ -6,13 +6,10 @@ class Action
6
6
  @id = id
7
7
  @method = method
8
8
  @opt = opt
9
-
10
- $actions[id] = self
9
+ vma.actions.register(id, self) # TODO: handle this in Editor class
11
10
  end
12
11
  end
13
12
 
14
- $actions = {}
15
-
16
13
  def reg_act(id, callfunc, name = "", opt = {})
17
14
  if callfunc.class == Proc
18
15
  a = Action.new(id, name, callfunc, opt)
@@ -31,108 +28,126 @@ def missing_callfunc
31
28
  debug "missing_callfunc"
32
29
  end
33
30
 
34
- #TODO: remove
35
- # def call(id)
36
- # call_action(id)
37
- # end
31
+ #TODO: remove?
32
+ def call_action(id)
33
+ vma.actions.call(id)
34
+ end
38
35
 
39
- $acth = []
36
+ class ActionList
37
+ def initialize
38
+ @acth = []
39
+ @actions = {}
40
+ end
40
41
 
41
- def call_action(id)
42
- $acth << id
43
- a = $actions[id]
44
- if a
45
- a.method.call()
46
- else
47
- message("Unknown action: " + id.inspect)
42
+ def register(id, obj)
43
+ @actions[id] = obj
48
44
  end
49
- end
50
45
 
51
- def last_action
52
- return $acth[-1]
53
- end
46
+ def include?(act)
47
+ return @actions.has_key?(act)
48
+ end
54
49
 
55
- def search_actions()
56
- l = []
57
- opt = { :title => "Search for actions", :desc => "Fuzzy search for actions. <up> or <down> to change selcted. <enter> to select current." }
58
- $select_keys = ["h", "l", "f", "d", "s", "a", "g", "z"]
50
+ def [](id)
51
+ @actions[id]
52
+ end
59
53
 
60
- gui_select_update_window(l, $select_keys.collect { |x| x.upcase },
61
- "search_actions_select_callback",
62
- "search_actions_update_callback",
63
- opt)
64
- end
54
+ def call(id)
55
+ @acth << id
56
+ a = @actions[id]
57
+ if a
58
+ a.method.call()
59
+ else
60
+ message("Unknown action: " + id.inspect)
61
+ end
62
+ end
65
63
 
66
- $item_list = []
64
+ def last_action
65
+ return @acth[-1]
66
+ end
67
67
 
68
- def search_actions_update_callback(search_str = "")
69
- return [] if search_str == ""
68
+ def gui_search()
69
+ l = []
70
+ opt = { :title => "Search for actions", :desc => "Fuzzy search for actions. <up> or <down> to change selcted. <enter> to select current.",
71
+ :columns => [{ :title => "Shortcut", :id => 0 }, { :title => "Action", :id => 1 }] }
70
72
 
71
- item_list2 = []
72
- for act_id in $actions.keys
73
- act = $actions[act_id]
74
- item = {}
75
- item[:key] = ""
73
+ @select_keys = ["h", "l", "f", "d", "s", "a", "g", "z"]
76
74
 
77
- for mode_str in ["C", "V"]
78
- c_kbd = vma.kbd.act_bindings[mode_str][act_id]
79
- if c_kbd.class == String
80
- item[:key] = "[#{mode_str} #{c_kbd}] "
81
- break
82
- end
83
- end
84
- # c_kbd = vma.kbd.act_bindings[mode_str][nfo[:action]]
85
- item[:action] = act_id
86
- item[:str] = act_id.to_s
87
- if $actions[act_id].method_name != ""
88
- item[:str] = $actions[act_id].method_name
89
- end
90
- item_list2 << item
75
+ gui_select_update_window(l, @select_keys.collect { |x| x.upcase },
76
+ self.method("search_actions_select_callback"),
77
+ self.method("search_actions_update_callback"),
78
+ opt)
91
79
  end
92
80
 
93
- item_list = item_list2
81
+ @item_list = []
94
82
 
95
- a = filter_items(item_list, 0, search_str)
96
- debug a.inspect
83
+ def search_actions_update_callback(search_str = "")
84
+ return [] if search_str == ""
97
85
 
98
- r = a.collect { |x| [x[0][0], 0, x] }
99
- debug r.inspect
100
- $item_list = r
86
+ item_list2 = []
87
+ for act_id in @actions.keys
88
+ act = @actions[act_id]
89
+ item = {}
90
+ item[:key] = ""
101
91
 
102
- # Ripl.start :binding => binding
92
+ for mode_str in ["C", "V"]
93
+ c_kbd = vma.kbd.act_bindings[mode_str][act_id]
94
+ if c_kbd.class == String
95
+ item[:key] = "[#{mode_str}] #{c_kbd} "
96
+ item[:key] = "" if item[:key].size > 15
97
+ break
98
+ end
99
+ end
100
+ # c_kbd = vma.kbd.act_bindings[mode_str][nfo[:action]]
101
+ item[:action] = act_id
102
+ item[:str] = act_id.to_s
103
+ if @actions[act_id].method_name != ""
104
+ item[:str] = @actions[act_id].method_name
105
+ end
106
+ item_list2 << item
107
+ end
103
108
 
104
- r = a.collect { |x| ["#{x[0][:key]}#{x[0][:str]}", 0, x] }
105
- return r
106
- end
109
+ item_list = item_list2
107
110
 
108
- def search_actions_select_callback(search_str, idx)
109
- item = $item_list[idx][2]
110
- acc = item[0][:action]
111
+ a = filter_items(item_list, 0, search_str)
112
+ debug a.inspect
111
113
 
112
- debug "Selected:" + acc.to_s
113
- gui_select_window_close(0)
114
+ r = a.collect { |x| [x[0][0], 0, x] }
115
+ debug r.inspect
116
+ @item_list = r
114
117
 
115
- if acc.class == String
116
- eval(acc)
117
- elsif acc.class == Symbol
118
- debug "Symbol"
119
- call_action(acc)
118
+ r = a.collect { |x| [x[0][:key], x[0][:str]] }
119
+ return r
120
120
  end
121
- end
122
121
 
123
- def filter_items(item_list, item_key, search_str)
124
- item_hash = {}
125
- # debug item_list.inspect
126
- scores = Parallel.map(item_list, in_threads: 8) do |item|
127
- if item[:str].class != String
128
- puts item.inspect
129
- exit!
122
+ def search_actions_select_callback(search_str, idx)
123
+ item = @item_list[idx][2]
124
+ acc = item[0][:action]
125
+
126
+ debug "Selected:" + acc.to_s
127
+ gui_select_window_close(0)
128
+
129
+ if acc.class == String
130
+ eval(acc)
131
+ elsif acc.class == Symbol
132
+ debug "Symbol"
133
+ call(acc)
130
134
  end
131
- [item, srn_dst(search_str, item[:str])]
132
135
  end
133
- scores.sort_by! { |x| -x[1] }
134
- debug scores.inspect
135
- scores = scores[0..30]
136
136
 
137
- return scores
137
+ def filter_items(item_list, item_key, search_str)
138
+ item_hash = {}
139
+ # debug item_list.inspect
140
+ scores = Parallel.map(item_list, in_threads: 8) do |item|
141
+ if item[:str].class != String
142
+ puts item.inspect
143
+ exit!
144
+ end
145
+ [item, srn_dst(search_str, item[:str])]
146
+ end
147
+ scores.sort_by! { |x| -x[1] }
148
+ debug scores.inspect
149
+ scores = scores[0..30]
150
+
151
+ return scores
152
+ end
138
153
  end
@@ -12,7 +12,7 @@ $update_highlight = false
12
12
  $ifuncon = false
13
13
 
14
14
  class Buffer < String
15
- attr_reader :pos, :lpos, :cpos, :deltas, :edit_history, :fname, :call_func, :pathname, :basename, :dirname, :update_highlight, :marks, :is_highlighted, :syntax_detect_failed, :id, :lang, :images, :last_save, :access_time
15
+ attr_reader :pos, :lpos, :cpos, :deltas, :edit_history, :fname, :call_func, :pathname, :basename, :dirname, :update_highlight, :marks, :is_highlighted, :syntax_detect_failed, :id, :lang, :images, :last_save, :access_time, :selection_active
16
16
  attr_writer :call_func, :update_highlight
17
17
  attr_accessor :gui_update_highlight, :update_hl_startpos, :update_hl_endpos, :hl_queue, :syntax_parser, :highlights, :gui_reset_highlight, :is_parsing_syntax, :line_ends, :bt, :line_action_handler, :module, :active_kbd_mode, :title, :subtitle, :paste_lines, :mode_stack, :default_mode
18
18
 
@@ -93,8 +93,9 @@ class Buffer < String
93
93
  end
94
94
 
95
95
  #Check if this buffer is attached to any windows
96
- def is_active
96
+ def is_active?
97
97
  for k in vma.gui.windows.keys
98
+ next if vma.gui.windows[k][:sw].child.nil?
98
99
  return true if vma.gui.windows[k][:sw].child.bufo == self
99
100
  end
100
101
  return false
@@ -1050,7 +1051,7 @@ class Buffer < String
1050
1051
 
1051
1052
  # Activated when enter/return pressed
1052
1053
  def handle_line_action()
1053
- if line_action_handler.class == Proc
1054
+ if line_action_handler.class == Proc or line_action_handler.class == Method
1054
1055
  # Custom handler
1055
1056
  line_action_handler.call(lpos)
1056
1057
  else
@@ -1257,18 +1258,28 @@ class Buffer < String
1257
1258
  @need_redraw = false
1258
1259
  end
1259
1260
 
1260
- def start_visual_mode()
1261
- @visual_mode = true
1262
- @selection_start = @pos
1263
- $kbd.set_mode(:visual)
1261
+ def selection_active?
1262
+ @selection_active
1264
1263
  end
1265
1264
 
1265
+ def end_selection()
1266
+ @selection_start = nil
1267
+ @selection_active = false
1268
+ @visual_mode = false
1269
+ #TODO: remove @visual_mode
1270
+ end
1271
+
1266
1272
  def start_selection()
1267
- @visual_mode = true
1268
1273
  @selection_start = @pos
1269
- $kbd.set_mode(:visual)
1270
- #TODO: implement without setting kbd mode
1274
+ @selection_active = true
1275
+ @visual_mode = true
1276
+ end
1277
+
1278
+ # Start selection if not already started
1279
+ def continue_selection()
1280
+ start_selection if !@selection_active
1271
1281
  end
1282
+
1272
1283
 
1273
1284
  def copy_active_selection(x = nil)
1274
1285
  debug "!COPY SELECTION"
@@ -1296,6 +1307,7 @@ class Buffer < String
1296
1307
  txt.gsub!(/\w+/, &:capitalize) if op == :capitalize
1297
1308
  txt.swapcase! if op == :swapcase
1298
1309
  txt.reverse! if op == :reverse
1310
+ txt = to_camel_case(txt) if op == :camelcase
1299
1311
 
1300
1312
  replace_range(r, txt)
1301
1313
  end_visual_mode
@@ -1373,13 +1385,13 @@ class Buffer < String
1373
1385
 
1374
1386
  def end_visual_mode()
1375
1387
  debug "end_visual_mode, #{vma.kbd.get_mode}, #{visual_mode?}", 2
1376
- vma.kbd.dump_state
1377
1388
  return if vma.kbd.get_mode != :visual
1378
1389
  if !visual_mode?
1379
1390
  debug "end_visual_mode, !visual_mode?"
1380
1391
  # TODO: should not happen
1381
1392
  end
1382
1393
  debug "End visual mode"
1394
+ end_selection
1383
1395
  vma.kbd.to_previous_mode
1384
1396
  @visual_mode = false
1385
1397
  return true
@@ -155,6 +155,7 @@ class BufferList
155
155
  end
156
156
 
157
157
  # hpt_scan_images() if cnf.debug? # experimental
158
+ return bu
158
159
  end
159
160
 
160
161
  def to_s
@@ -199,7 +200,7 @@ class BufferList
199
200
 
200
201
  def get_last_non_active_buffer
201
202
  for bu in slist.reverse
202
- return bu.id if !bu.is_active
203
+ return bu.id if !bu.is_active?
203
204
  end
204
205
  return nil
205
206
  end
@@ -34,7 +34,7 @@ class BufferManager
34
34
  def close_selected
35
35
  idx = buf_of_current_line()
36
36
  r = @buf.current_line_range
37
- Gui.hilight_range(@buf,r, color:"#666666ff")
37
+ Gui.hilight_range(@buf, r, color: "#666666ff")
38
38
  if idx.nil?
39
39
  message("buf already closed")
40
40
  return
@@ -68,21 +68,34 @@ class BufferManager
68
68
  s << "\n"
69
69
  i = 0
70
70
  jump_to_line = 0
71
- for b in vma.buffers.list.sort_by { |x| x.list_str }
72
- if b.id == vma.buf.id # current file
73
- # s << " "
74
- jump_to_line = i
71
+ lastdir = nil
72
+ bh = {}
73
+ for b in vma.buffers.list
74
+ if !b.fname.nil?
75
+ bname = File.basename(b.fname)
76
+ dname = File.dirname(b.fname)
77
+ else
78
+ bname = b.list_str
79
+ dname = "*"
75
80
  end
76
- x = b.list_str
77
- s << "#{x}\n"
78
- @line_to_id[i] = b.id
81
+ bh[dname] ||= []
82
+ bh[dname] << {bname: bname, buf: b}
83
+ end
84
+ for k in bh.keys.sort
85
+ d = tilde_path(k)
86
+ s << "📂#{d}:\n" # Note: to close?: 📁
79
87
  i += 1
88
+ for bnfo in bh[k].sort_by{|x|x[:bname]}
89
+ s << "╰─#{bnfo[:bname]}\n"
90
+
91
+ @line_to_id[i] = bnfo[:buf].id
92
+ jump_to_line = i if bnfo[:buf].id == vma.buf.id # current file
93
+ i += 1
94
+ end
80
95
  end
81
-
82
-
83
-
96
+
84
97
  if @buf.nil?
85
- @buf = create_new_buffer(s,"bufmgr")
98
+ @buf = create_new_buffer(s, "bufmgr")
86
99
  @buf.default_mode = :buf_mgr
87
100
  @buf.module = self
88
101
  @buf.active_kbd_mode = :buf_mgr
data/lib/vimamsa/conf.rb CHANGED
@@ -159,3 +159,6 @@ cnf.font.size = 11
159
159
  cnf.font.family = "Monospace"
160
160
 
161
161
 
162
+ cnf.macro.animation_delay = 0.02
163
+
164
+
@@ -5,9 +5,8 @@ def handle_drag_and_drop(fname)
5
5
  buf.handle_drag_and_drop(fname)
6
6
  end
7
7
 
8
-
9
8
  class Editor
10
- attr_reader :file_content_search_paths, :file_name_search_paths, :gui, :hook, :macro
9
+ attr_reader :file_content_search_paths, :file_name_search_paths, :gui, :hook, :macro, :actions
11
10
  attr_accessor :converters, :fh, :paint_stack, :kbd, :langsrv, :register, :cur_register, :clipboard
12
11
  #attr_writer :call_func, :update_highlight
13
12
 
@@ -63,6 +62,10 @@ class Editor
63
62
 
64
63
  $hook = Hook.new
65
64
  @hook = $hook
65
+ require "vimamsa/actions"
66
+ @actions = ActionList.new
67
+ require "vimamsa/key_actions"
68
+
66
69
  register_plugin(:Hook, @hook)
67
70
  @macro = Macro.new
68
71
  register_plugin(:Macro, @macro)
@@ -548,12 +551,13 @@ def load_buffer(fname)
548
551
  end
549
552
 
550
553
  def jump_to_file(filename, tnum = nil, charn = nil)
551
- open_new_file(filename)
554
+ b = open_new_file(filename)
555
+ # debug "open_new_file #{filename}, #{tnum} = nil, #{charn}",2
552
556
 
553
557
  # Link to character position
554
558
  if !charn.nil?
555
559
  if charn == "c"
556
- buf.jump_to_pos(tnum) # tnum=character position
560
+ b.jump_to_pos(tnum) # tnum=character position
557
561
  center_on_current_line
558
562
  return
559
563
  end
@@ -561,7 +565,7 @@ def jump_to_file(filename, tnum = nil, charn = nil)
561
565
 
562
566
  # Link to line
563
567
  if !tnum.nil?
564
- buf.jump_to_line(tnum) # tnum=line position
568
+ b.jump_to_line(tnum) # tnum=line position
565
569
  center_on_current_line
566
570
  return
567
571
  end
@@ -579,7 +583,7 @@ def open_new_file(filename, file_contents = "")
579
583
  # File is already opened to existing buffer
580
584
  if b != nil
581
585
  message "Switching to: #{filename}"
582
- vma.buffers.set_current_buffer(b)
586
+ bu = vma.buffers.set_current_buffer(b)
583
587
  else
584
588
  if !is_path_writable(filename)
585
589
  message("Path #{filename} cannot be written to")
@@ -593,9 +597,10 @@ def open_new_file(filename, file_contents = "")
593
597
  end
594
598
  message "New file opened: #{filename}"
595
599
  fname = filename
596
- bf = load_buffer(fname)
597
- vma.buffers.set_current_buffer_by_id(bf.id)
600
+ bu = load_buffer(fname)
601
+ vma.buffers.set_current_buffer_by_id(bu.id)
598
602
  end
603
+ return bu
599
604
  end
600
605
 
601
606
  def scan_word_start_marks(search_str)
@@ -76,12 +76,12 @@ end
76
76
 
77
77
  def gui_file_history_update_callback(search_str = "")
78
78
  debug "gui_file_history_update_callback: #{search_str}"
79
- return [] if $vma.fh.history.empty?
79
+ return [] if vma.fh.history.empty?
80
80
  $search_list = []
81
- files = $vma.fh.history.keys.sort.collect { |x| [x, 0] }
81
+ files = vma.fh.history.keys.sort.collect { |x| [x, 0] }
82
82
 
83
83
  if (search_str.size > 1)
84
- files = fuzzy_filter(search_str, $vma.fh.history.keys, 40)
84
+ files = fuzzy_filter(search_str, vma.fh.history.keys, 40)
85
85
  end
86
86
 
87
87
  $search_list = files
data/lib/vimamsa/gui.rb CHANGED
@@ -2,6 +2,31 @@ $idle_scroll_to_mark = false
2
2
 
3
3
  $removed_controllers = []
4
4
 
5
+ # Run one iteration of GMainLoop
6
+ # https://developer.gnome.org/documentation/tutorials/main-contexts.html
7
+ def iterate_gui_main_loop
8
+ GLib::MainContext.default.iteration(true)
9
+ end
10
+
11
+ # Wait for window resize to take effect
12
+ # GTk3 had a resize notify event which got removed in gtk4
13
+ # https://discourse.gnome.org/t/gtk4-any-way-to-connect-to-a-window-resize-signal/14869/3
14
+ def wait_for_resize(window, tries = 200)
15
+ i = 0
16
+ widthold = @window.width
17
+ heightold = @window.height
18
+ while true
19
+ iterate_gui_main_loop
20
+ break if widthold != window.width
21
+ break if heightold != window.height
22
+ if i >= tries
23
+ debug "i >= tries", 2
24
+ break
25
+ end
26
+ i += 1
27
+ end
28
+ end
29
+
5
30
  def gui_remove_controllers(widget)
6
31
  clist = widget.observe_controllers
7
32
  to_remove = []
@@ -102,7 +127,7 @@ def gui_create_buffer(id, bufo)
102
127
  view.set_buffer(buf1)
103
128
 
104
129
  provider = Gtk::CssProvider.new
105
-
130
+
106
131
  provider.load(data: "textview { font-family: #{cnf.font.family!}; font-size: #{cnf.font.size!}pt; }")
107
132
  view.style_context.add_provider(provider)
108
133
  view.wrap_mode = :char
@@ -549,11 +574,24 @@ class VMAgui
549
574
 
550
575
  def idle_set_size()
551
576
  # Need to wait for a while to window to be maximized to get correct @window.width
552
- sleep 0.1
577
+ @window.maximize
578
+ wait_for_resize(@window)
579
+ # Set new size as half of the screeen
553
580
  width = @window.width / 2
554
581
  height = @window.height - 5
582
+ width = 600 if width < 600
583
+ height = 600 if height < 600
584
+
585
+ #Minimum size:
586
+ @window.set_size_request(600, 600)
587
+ @window.set_default_size(width, height)
588
+ debug "size #{[width, height]}", 2
555
589
  @window.unmaximize
590
+
591
+ #set_default_size doesn't always have effect if run immediately
592
+ wait_for_resize(@window)
556
593
  @window.set_default_size(width, height)
594
+
557
595
  return false
558
596
  end
559
597
 
@@ -569,10 +607,6 @@ class VMAgui
569
607
  @window = Gtk::ApplicationWindow.new(app)
570
608
  @window.set_application(app)
571
609
 
572
- @window.maximize
573
- # Need to let Gtk process after maximize
574
- run_as_idle proc { idle_set_size }
575
-
576
610
  @window.title = "Multiple Views"
577
611
  @vpaned = Gtk::Paned.new(:vertical)
578
612
 
@@ -664,6 +698,8 @@ class VMAgui
664
698
 
665
699
  @window.show
666
700
 
701
+ run_as_idle proc { idle_set_size }
702
+
667
703
  prov = Gtk::CssProvider.new
668
704
  # See gtk-4.9.4/gtk/theme/Default/_common.scss on how to theme
669
705
  # gtksourceview/gtksourcestyleschemepreview.c
@@ -49,6 +49,8 @@ module Vimamsa
49
49
 
50
50
  add_to_menu "Actions.debug.dumpkbd", { :label => "Dump kbd state", :action => :kbd_dump_state }
51
51
 
52
+
53
+ add_to_menu "View.BufferManager", { :label => "Show open files", :action => :start_buf_manager }
52
54
  add_to_menu "View.TwoColumn", { :label => "Toggle two column mode", :action => :toggle_two_column }
53
55
 
54
56
 
@@ -12,6 +12,8 @@ class SelectUpdateWindow
12
12
 
13
13
  def update_item_list(item_list)
14
14
  # debug item_list.inspect
15
+ return if item_list.empty?
16
+
15
17
  @model.clear
16
18
  for item in item_list
17
19
  iter = @model.append
@@ -52,9 +52,9 @@ class VSourceView < GtkSource::View
52
52
 
53
53
  # Mainly after page-up or page-down
54
54
  signal_connect("move-cursor") do |widget, event|
55
- if event.name == "GTK_MOVEMENT_PAGES" and (last_action == "page_up" or last_action == "page_down")
56
- handle_scrolling()
57
- end
55
+ # if event.name == "GTK_MOVEMENT_PAGES" and (vma.actions.last_action == "page_up" or vma.actions.last_action == "page_down")
56
+ # handle_scrolling()
57
+ # end
58
58
 
59
59
  # handle_scrolling()
60
60
  # curpos = buffer.cursor_position
@@ -148,11 +148,14 @@ class VSourceView < GtkSource::View
148
148
  @cnt_drag.signal_connect "drag-end" do |gesture, offsetx, offsety|
149
149
  debug "drag-end", 2
150
150
  if offsetx.abs < 5 and offsety.abs < 5
151
- debug "Not enough drag",2
152
- @range_start = nil
153
- elsif !buf.visual_mode? and vma.kbd.get_scope != :editor
151
+ debug "Not enough drag", 2
152
+ buf.end_selection
153
+ # elsif !buf.visual_mode? and vma.kbd.get_scope != :editor
154
+ elsif vma.kbd.get_scope != :editor
154
155
  # Can't transition from editor wide mode to buffer specific mode
155
- buf.start_visual_mode
156
+ vma.kbd.set_mode(:visual)
157
+ else
158
+ buf.end_selection
156
159
  end
157
160
  @range_start = nil
158
161
  end
@@ -523,6 +526,31 @@ class VSourceView < GtkSource::View
523
526
  end
524
527
  end
525
528
 
529
+ def after_action
530
+ delete_cursorchar
531
+ iterate_gui_main_loop
532
+ handle_deltas
533
+ iterate_gui_main_loop
534
+ draw_cursor
535
+ iterate_gui_main_loop
536
+ end
537
+
538
+ def set_cursor_color(ctype)
539
+ if @ctype != ctype
540
+ bg = $confh[:mode][ctype][:cursor][:background]
541
+ if bg.class == String
542
+ if !@cursor_prov.nil?
543
+ self.style_context.remove_provider(@cursor_prov)
544
+ end
545
+ prov = Gtk::CssProvider.new
546
+ prov.load(data: ".view text selection { background-color: #{bg}; color: #ffffff; }")
547
+ self.style_context.add_provider(prov)
548
+ @cursor_prov = prov
549
+ end
550
+ @ctype == ctype
551
+ end
552
+ end
553
+
526
554
  def draw_cursor
527
555
  # if @tt.nil?
528
556
  # @tt = buffer.create_tag("font_tag")
@@ -531,9 +559,12 @@ class VSourceView < GtkSource::View
531
559
 
532
560
  mode = vma.kbd.get_mode
533
561
  ctype = vma.kbd.get_cursor_type
562
+ ctype = :visual if vma.buf.selection_active?
563
+
534
564
  delete_cursorchar
535
565
  vma.gui.remove_overlay_cursor
536
- if ctype == :command
566
+ if [:command, :replace, :browse].include?(ctype)
567
+ set_cursor_color(ctype)
537
568
  if @bufo[@bufo.pos] == "\n"
538
569
  # If we are at end of line, it's not possible to draw the cursor by making a selection. I tried to do this by drawing an overlay, but that generates issues. If moving the cursor causes the ScrolledWindow to be scrolled, these errors randomly appear and the whole view shows blank:
539
570
  # (ruby:21016): Gtk-WARNING **: 19:52:23.181: Trying to snapshot GtkSourceView 0x55a97524c8c0 without a current allocation
@@ -559,7 +590,9 @@ class VSourceView < GtkSource::View
559
590
  buffer.select_range(itr, itr2)
560
591
  end
561
592
  # elsif @bufo.visual_mode?
593
+
562
594
  elsif ctype == :visual
595
+ set_cursor_color(ctype)
563
596
  # debug "VISUAL MODE"
564
597
  (_start, _end) = @bufo.get_visual_mode_range2
565
598
  # debug "#{_start}, #{_end}"
@@ -166,7 +166,7 @@ act_list = {
166
166
  # { :proc => proc { },
167
167
  # :desc => "", :group => : },
168
168
 
169
- :search_actions => { :proc => proc { search_actions },
169
+ :search_actions => { :proc => proc { vma.actions.gui_search },
170
170
  :desc => "Search actions", :group => :search },
171
171
 
172
172
  :toggle_active_window => { :proc => proc { vma.gui.toggle_active_window },
@@ -67,6 +67,7 @@ class KeyBindingTree
67
67
  end
68
68
 
69
69
  def set_mode(label)
70
+ return if get_mode == :label
70
71
  @match_state = [@modes[label]] # used for matching input
71
72
  @mode_root_state = @modes[label]
72
73
  # @default_mode = label
@@ -112,11 +113,11 @@ class KeyBindingTree
112
113
 
113
114
  def to_previous_mode()
114
115
  debug "to_previous_mode",2
115
- pp @default_mode_stack
116
+ debug @default_mode_stack
116
117
  if @default_mode_stack.size > 1
117
118
  @default_mode_stack.pop
118
119
  end
119
- pp @default_mode_stack
120
+ debug @default_mode_stack
120
121
  __set_mode(@default_mode_stack[-1])
121
122
  end
122
123
 
@@ -290,8 +291,8 @@ class KeyBindingTree
290
291
  else
291
292
  method_desc = t.action
292
293
  if t.action.class == Symbol
293
- if !$actions[t.action].nil?
294
- a = $actions[t.action].method_name
294
+ if vma.actions.include?(t.action)
295
+ a = vma.actions[t.action].method_name
295
296
  if !a.nil? and !a.empty?
296
297
  method_desc = a
297
298
  end
@@ -477,7 +478,7 @@ class KeyBindingTree
477
478
  # return
478
479
  # end
479
480
  # $action_list << { :action => action, :key => key }
480
- if !$actions.has_key?(action)
481
+ if !vma.actions.include?(action)
481
482
  if action.class == String
482
483
  reg_act(action, proc { eval(action) }, action)
483
484
  end
@@ -566,7 +567,7 @@ class KeyBindingTree
566
567
  end
567
568
 
568
569
  def handle_key_bindigs_action(action, c)
569
- $acth << action
570
+ # $acth << action #TODO:needed here?
570
571
  @method_handles_repeat = false #TODO:??
571
572
  n = 1
572
573
  if @next_command_count and !(action.class == String and action.include?("set_next_command_count"))
@@ -619,8 +620,6 @@ def bindkey(key, action)
619
620
  $kbd.bindkey(key, action)
620
621
  end
621
622
 
622
- $action_list = []
623
-
624
623
  def exec_action(action)
625
624
  $kbd.last_action = $kbd.cur_action
626
625
  $kbd.cur_action = action
@@ -4,16 +4,44 @@ vma.kbd.add_mode("V", :visual, :visual)
4
4
  vma.kbd.add_mode("M", :minibuffer) #TODO: needed?
5
5
  vma.kbd.add_mode("R", :readchar)
6
6
  vma.kbd.add_minor_mode("audio", :audio, :command)
7
- vma.kbd.add_mode("B", :browse, :command, scope: :editor)
8
- vma.kbd.add_mode("X", :replace, :command, name: "Replace")
7
+ vma.kbd.add_mode("B", :browse, :browse, scope: :editor)
8
+ vma.kbd.add_mode("X", :replace, :replace, name: "Replace")
9
9
  vma.kbd.set_default_mode(:command)
10
10
  vma.kbd.__set_mode(:command) #TODO:needed?
11
- # vma.kbd.show_state_trail
12
-
11
+ # cnf.mode.command.cursor.background = "#fc6f03"
12
+ cnf.mode.command.cursor.background = "#05c5a0"
13
+ cnf.mode.default.cursor.background = "#03fcca"
14
+ # cnf.mode.visual.cursor.background = "#10bd8e"
15
+ # cnf.mode.visual.cursor.background = "#e95420"
16
+ # cnf.mode.visual.cursor.background = "#cb3804"
17
+ cnf.mode.visual.cursor.background = "#bc6040"
18
+ cnf.mode.replace.cursor.background = "#fc0331"
19
+ cnf.mode.browse.cursor.background = "#f803fc"
20
+
21
+ def _insert_move(op)
22
+ if op == :pagedown
23
+ vma.gui.page_down
24
+ elsif op == :pageup
25
+ vma.gui.page_up
26
+ else
27
+ buf.move(op)
28
+ end
29
+ end
30
+
31
+ def insert_select_move(op)
32
+ buf.continue_selection
33
+ _insert_move(op)
34
+ end
35
+
36
+ def insert_move(op)
37
+ buf.end_selection
38
+ _insert_move(op)
39
+ end
13
40
 
14
41
  bindkey ["VCB M", "B m"], :run_last_macro
15
42
 
16
43
  bindkey "VC s", :easy_jump
44
+ bindkey "I alt-s", :easy_jump
17
45
  bindkey "VC , m f", [:find_macro_gui, proc { vma.macro.find_macro_gui }, "Find named macro"]
18
46
  bindkey "C , m n", [:gui_name_macro, proc { vma.macro.gui_name_macro }, "Name last macro"]
19
47
  bindkey "C , j r", :jump_to_random
@@ -78,8 +106,8 @@ bindkey "B z", "center_on_current_line();call_action(:exit_browse_mode)"
78
106
  bindkey "B enter || B return || B esc || B j || B ctrl!", :exit_browse_mode
79
107
  bindkey "B s", :page_up
80
108
  bindkey "B d", :page_down
81
- bindkey "B r", proc { vma.gui.page_down(multip:0.25)}
82
- bindkey "B e", proc { vma.gui.page_up(multip:0.25)}
109
+ bindkey "B r", proc { vma.gui.page_down(multip: 0.25) }
110
+ bindkey "B e", proc { vma.gui.page_up(multip: 0.25) }
83
111
 
84
112
  bindkey "B i", :jump_to_start_of_buffer
85
113
  bindkey "B o", :jump_to_end_of_buffer
@@ -120,24 +148,41 @@ default_keys = {
120
148
  # "VC j" => "buf.move(FORWARD_LINE)",
121
149
  # "VC k" => "buf.move(BACKWARD_LINE)",
122
150
 
123
- "VC pagedown" => :page_down,
124
- "VC pageup" => :page_up,
151
+ "VCI pagedown" => :page_down,
152
+ "VCI pageup" => :page_up,
125
153
 
126
154
  "I down(vma.buf.view.autocp_active)" => "vma.buf.view.autocp_select_next",
127
155
  "I tab(vma.buf.view.autocp_active)" => "vma.buf.view.autocp_select_next",
128
156
  "I up(vma.buf.view.autocp_active)" => "vma.buf.view.autocp_select_previous",
129
157
  "I shift-tab(vma.buf.view.autocp_active)" => "vma.buf.view.autocp_select_previous",
130
158
  "I enter(vma.buf.view.autocp_active)" => "vma.buf.view.autocp_select",
131
-
132
- "I tab" => 'buf.insert_tab',
133
- "I shift-tab" => 'buf.unindent',
134
-
159
+
160
+ "I tab" => "buf.insert_tab",
161
+ "I shift-tab" => "buf.unindent",
162
+
135
163
  "I enter" => :insert_new_line,
136
164
 
137
- "VCIX left" => "buf.move(BACKWARD_CHAR)",
138
- "VCIX right" => "buf.move(FORWARD_CHAR)",
139
- "VCIX down" => "buf.move(FORWARD_LINE)",
140
- "VCIX up" => "buf.move(BACKWARD_LINE)",
165
+ "I shift-down" => "insert_select_move(BACKWARD_CHAR)",
166
+ "I shift-right" => "insert_select_move(FORWARD_CHAR)",
167
+ "I shift-down" => "insert_select_move(FORWARD_LINE)",
168
+ "I shift-up" => "insert_select_move(BACKWARD_LINE)",
169
+ "I shift-pagedown" => "insert_select_move(:pagedown)",
170
+ "I shift-pageup" => "insert_select_move(:pageup)",
171
+
172
+ "I left" => "insert_move(BACKWARD_CHAR)",
173
+ "I right" => "insert_move(FORWARD_CHAR)",
174
+ "I down" => "insert_move(FORWARD_LINE)",
175
+ "I up" => "insert_move(BACKWARD_LINE)",
176
+ "I pagedown" => "insert_move(:pagedown)",
177
+ "I pageup" => "insert_move(:pageup)",
178
+
179
+ #TODO:
180
+ "I @shift-click" => "insert_mode_shift_click(charpos)",
181
+
182
+ "VCX left" => "buf.move(BACKWARD_CHAR)",
183
+ "VCX right" => "buf.move(FORWARD_CHAR)",
184
+ "VCX down" => "buf.move(FORWARD_LINE)",
185
+ "VCX up" => "buf.move(BACKWARD_LINE)",
141
186
 
142
187
  "VC w" => "buf.jump_word(FORWARD,WORD_START)",
143
188
  "VC b" => "buf.jump_word(BACKWARD,WORD_START)",
@@ -184,7 +229,7 @@ default_keys = {
184
229
  "C , d c" => "debug_dump_clipboard",
185
230
  "C , d d" => "debug_dump_deltas",
186
231
  "C , d m" => :kbd_dump_state,
187
-
232
+
188
233
  "VC O" => "buf.jump(END_OF_LINE)",
189
234
  "VC $" => "buf.jump(END_OF_LINE)",
190
235
 
@@ -201,7 +246,7 @@ default_keys = {
201
246
 
202
247
  # Command mode only:
203
248
  "C ctrl-r" => "buf.redo()", # TODO:???
204
- "C v" => "buf.start_visual_mode",
249
+ "C v" => "buf.start_selection;vma.kbd.set_mode(:visual)",
205
250
  "C P" => "buf.paste(BEFORE)", # TODO: implement as replace for visual mode
206
251
  "C space <char>" => "buf.insert_txt(<char>)",
207
252
  "C space space" => "buf.insert_txt(' ')",
@@ -261,7 +306,7 @@ default_keys = {
261
306
  "C i" => "vma.kbd.set_mode(:insert)",
262
307
  "C R" => "vma.kbd.set_mode(:replace)",
263
308
  "C ctrl!" => "vma.kbd.set_mode(:insert)",
264
-
309
+
265
310
  # Replace mode
266
311
  "X esc || X ctrl!" => "vma.kbd.to_previous_mode",
267
312
  "X <char>" => "buf.replace_with_char(<char>);buf.move(FORWARD_CHAR)",
@@ -304,12 +349,13 @@ default_keys = {
304
349
 
305
350
  "I ctrl-h" => :show_autocomplete,
306
351
  "I ctrl-j" => "vma.buf.view.hide_completions",
307
-
308
352
 
309
353
  "I space" => 'buf.insert_txt(" ")',
310
354
  # "I return" => 'buf.insert_new_line()',
311
355
  }
312
356
 
357
+ bindkey "C , i p", "generate_password_to_buf(15)"
358
+
313
359
  default_keys.each { |key, value|
314
360
  bindkey(key, value)
315
361
  }
@@ -176,7 +176,9 @@ class LangSrv
176
176
  def open_file(fp, fc = nil)
177
177
  debug "open_file", 2
178
178
  fc = IO.read(fp) if fc.nil?
179
- fpuri = URI.join("file:///", fp).to_s
179
+
180
+ encoded_filepath = URI.encode_www_form_component(fp)
181
+ fpuri = URI.parse("file://#{encoded_filepath}")
180
182
 
181
183
  a = LSP::Interface::DidOpenTextDocumentParams.new(
182
184
  text_document: LSP::Interface::TextDocumentItem.new(
data/lib/vimamsa/macro.rb CHANGED
@@ -127,9 +127,12 @@ class Macro
127
127
  ret = exec_action(a)
128
128
  if ret == false
129
129
  error "Error while running macro"
130
- isok=false
130
+ isok = false
131
131
  break
132
132
  end
133
+
134
+ vma.buf.view.after_action
135
+ sleep cnf.macro.animation_delay!
133
136
  end
134
137
  end
135
138
  @running_macro = false
data/lib/vimamsa/rbvma.rb CHANGED
@@ -18,9 +18,7 @@ require "vimamsa/util"
18
18
  require "vimamsa/main"
19
19
  require "vimamsa/terminal"
20
20
 
21
- require "vimamsa/actions"
22
21
  require "vimamsa/key_binding_tree"
23
- require "vimamsa/key_actions"
24
22
 
25
23
  require "vimamsa/clipboard"
26
24
 
data/lib/vimamsa/tests.rb CHANGED
@@ -1,26 +1,26 @@
1
1
  require "digest"
2
2
 
3
3
  def run_tests()
4
- tests = ["test_paste_0","test_delete_0"]
4
+ tests = ["test_paste_0", "test_delete_0"]
5
5
  stats = []
6
6
  for t in tests
7
7
  r = eval(t)
8
8
  if r == true
9
9
  stats << "test #{t} OK"
10
10
  else
11
- stats << "test #{t} FAILED"
11
+ stats << "test #{t} FAILED"
12
12
  end
13
13
  end
14
- debug "TEST RESULTS:",2
14
+ debug "TEST RESULTS:", 2
15
15
  puts stats.join("\n")
16
16
  puts "===================="
17
-
18
17
  end
19
18
 
20
-
21
19
  #
22
20
 
23
21
  def test_paste_0(runmacro = true)
22
+ return
23
+ #TODO: update macro
24
24
  b = create_new_buffer(file_contents = "\n", prefix = "buf", setcurrent = true)
25
25
 
26
26
  b.insert_txt(JABBERWOCKY)
@@ -47,7 +47,7 @@ def test_paste_0(runmacro = true)
47
47
  end
48
48
  end
49
49
 
50
- def macro_test(macro, correct_hex, runmacro=true)
50
+ def macro_test(macro, correct_hex, runmacro = true)
51
51
  b = create_new_buffer(file_contents = "\n", prefix = "buf", setcurrent = true)
52
52
  b.insert_txt(JABBERWOCKY)
53
53
  b.insert_txt(LOREM_IPSUM)
@@ -117,6 +117,3 @@ O frabjous day! Callooh! Callay!”
117
117
  All mimsy were the borogoves,
118
118
  And the mome raths outgrabe.
119
119
  "
120
-
121
-
122
-
data/lib/vimamsa/util.rb CHANGED
@@ -1,5 +1,42 @@
1
1
  require "open3"
2
2
 
3
+ VOWELS = %w(a e i o u)
4
+ CONSONANTS = %w(b c d f g h j k l m n p q r s t v w x y z)
5
+
6
+ def tilde_path(abspath)
7
+ userhome = File.expand_path("~/")
8
+ abspath.sub(/^#{Regexp.escape(userhome)}\//, "~/")
9
+ end
10
+
11
+ def to_camel_case(str)
12
+ words = str.split(/\W+/) # Split the input string into words
13
+ camel_case_words = words.map.with_index do |word, index|
14
+ index == 0 ? word.downcase : word.capitalize
15
+ end
16
+ camel_case_words.join
17
+ end
18
+
19
+ def generate_password(length)
20
+ password = ""
21
+ while password.size < length
22
+ i = password.size + 1
23
+ if i.even?
24
+ char = CONSONANTS.sample
25
+ else
26
+ char = VOWELS.sample
27
+ end
28
+ char.upcase! if rand < 0.2
29
+ password << char
30
+ password << (1..10).to_a.sample.to_s if rand < 0.25
31
+ end
32
+ password
33
+ end
34
+
35
+ def generate_password_to_buf(length)
36
+ passw = generate_password(length)
37
+ vma.buf.insert_txt(passw)
38
+ end
39
+
3
40
  # Get all indexes for start of matching regexp
4
41
  def scan_indexes(txt, regex)
5
42
  # indexes = txt.enum_for(:scan, regex).map { Regexp.last_match.begin(0) + 1 }
@@ -1,3 +1,3 @@
1
1
  module Vimamsa
2
- VERSION = "0.1.15"
2
+ VERSION = "0.1.17"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vimamsa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.15
4
+ version: 0.1.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sami Sieranoja
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-17 00:00:00.000000000 Z
11
+ date: 2023-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -298,7 +298,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
298
298
  - !ruby/object:Gem::Version
299
299
  version: '0'
300
300
  requirements: []
301
- rubygems_version: 3.3.26
301
+ rubygems_version: 3.2.3
302
302
  signing_key:
303
303
  specification_version: 4
304
304
  summary: Vimamsa