vimamsa 0.1.0 → 0.1.5
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/.vma_project +0 -0
- data/README.md +110 -16
- data/exe/vimamsa +40 -0
- data/ext/vmaext/vmaext.c +0 -3
- data/lang/hyperplaintext.lang +129 -0
- data/lib/vimamsa.rb +3 -1
- data/lib/vimamsa/ack.rb +35 -0
- data/lib/vimamsa/actions.rb +125 -0
- data/lib/vimamsa/buffer.rb +1760 -0
- data/lib/vimamsa/buffer_list.rb +207 -0
- data/lib/vimamsa/constants.rb +44 -0
- data/lib/vimamsa/debug.rb +142 -0
- data/lib/vimamsa/default_key_bindings.rb +448 -0
- data/lib/vimamsa/easy_jump.rb +161 -0
- data/lib/vimamsa/editor.rb +667 -0
- data/lib/vimamsa/encrypt.rb +47 -0
- data/lib/vimamsa/file_finder.rb +103 -0
- data/lib/vimamsa/file_history.rb +100 -0
- data/lib/vimamsa/file_manager.rb +144 -0
- data/lib/vimamsa/hook.rb +46 -0
- data/lib/vimamsa/hyper_plain_text.rb +61 -0
- data/lib/vimamsa/key_binding_tree.rb +603 -0
- data/lib/vimamsa/macro.rb +177 -0
- data/lib/vimamsa/main.rb +71 -0
- data/lib/vimamsa/rbvma.rb +1072 -0
- data/lib/vimamsa/search.rb +100 -0
- data/lib/vimamsa/search_replace.rb +333 -0
- data/lib/vimamsa/text_transforms.rb +32 -0
- data/lib/vimamsa/util.rb +101 -0
- data/lib/vimamsa/version.rb +1 -1
- data/styles/134272-molokai.xml +33 -0
- data/styles/dark.xml +152 -0
- data/styles/molokai_edit.xml +49 -0
- data/vimamsa.gemspec +4 -2
- metadata +66 -10
- data/ext/vimamsa/extconf.rb +0 -11
- data/ext/vimamsa/vimamsa.c +0 -174
@@ -0,0 +1,161 @@
|
|
1
|
+
|
2
|
+
# Similar feature as Vim EasyMotion https://github.com/easymotion/vim-easymotion
|
3
|
+
class EasyJump
|
4
|
+
def initialize()
|
5
|
+
make_jump_sequence
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def easy_jump(direction)
|
10
|
+
# message "EASY JUMP"
|
11
|
+
visible_range = get_visible_area()
|
12
|
+
visible_text = $buffer[visible_range[0]..visible_range[1]]
|
13
|
+
wsmarks = scan_word_start_marks(visible_text)
|
14
|
+
line_starts = scan_indexes(visible_text, /^/)
|
15
|
+
lsh = Hash[line_starts.collect { |x| [x, true] }]
|
16
|
+
wsmh = Hash[wsmarks.collect { |x| [x, true] }]
|
17
|
+
|
18
|
+
wsmarks.select! { |x|
|
19
|
+
r = true
|
20
|
+
r = false if lsh[x] or lsh[x - 1] or lsh[x - 2]
|
21
|
+
r
|
22
|
+
}
|
23
|
+
|
24
|
+
linestart_buf = (line_starts).collect { |x| x + visible_range[0] }
|
25
|
+
wsmarks_buf = (wsmarks).collect { |x| x + visible_range[0] }
|
26
|
+
|
27
|
+
# All line starts should be accessible with just two key presses, so put them first in order
|
28
|
+
# Other word start positions ordered by distance from current pos
|
29
|
+
wsmarks_buf.sort_by! { |x| (x - $buffer.pos).abs }
|
30
|
+
$easy_jump_wsmarks = linestart_buf + wsmarks_buf
|
31
|
+
|
32
|
+
$jump_sequence = make_jump_sequence($easy_jump_wsmarks.size)
|
33
|
+
|
34
|
+
$input_char_call_func = method(:easy_jump_input_char)
|
35
|
+
$kbd.set_mode(:readchar)
|
36
|
+
$easy_jump_input = ""
|
37
|
+
easy_jump_draw
|
38
|
+
end
|
39
|
+
|
40
|
+
def easy_jump_input_char(c)
|
41
|
+
# vma.paint_stack = []
|
42
|
+
puts "EASY JUMP: easy_jump_input_char [#{c}]"
|
43
|
+
$easy_jump_input << c.upcase
|
44
|
+
if $jump_sequence.include?($easy_jump_input)
|
45
|
+
jshash = Hash[$jump_sequence.map.with_index.to_a]
|
46
|
+
nthword = jshash[$easy_jump_input]
|
47
|
+
puts "nthword:#{nthword} #{[$easy_jump_wsmarks[nthword],$jump_sequence[nthword]]}"
|
48
|
+
$buffer.set_pos($easy_jump_wsmarks[nthword])
|
49
|
+
$kbd.set_mode(:command)
|
50
|
+
$input_char_call_func = nil
|
51
|
+
$jump_sequence = []
|
52
|
+
$vmag.clear_overlay()
|
53
|
+
end
|
54
|
+
if $easy_jump_input.size > 2
|
55
|
+
$kbd.set_mode(:command)
|
56
|
+
$input_char_call_func = nil
|
57
|
+
$jump_sequence = []
|
58
|
+
$vmag.clear_overlay()
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def easy_jump_draw()
|
63
|
+
# puts $jump_sequence.inspect
|
64
|
+
# puts $easy_jump_wsmarks.inspect
|
65
|
+
$vmag.start_overlay_draw
|
66
|
+
for i in 0..($easy_jump_wsmarks.size - 1)
|
67
|
+
$vmag.overlay_draw_text($jump_sequence[i], $easy_jump_wsmarks[i])
|
68
|
+
end
|
69
|
+
$vmag.end_overlay_draw
|
70
|
+
|
71
|
+
return
|
72
|
+
return if $jump_sequence.empty?
|
73
|
+
puts "EASY JUMP DRAW"
|
74
|
+
screen_cord = cpp_function_wrapper(0, [$easy_jump_wsmarks])
|
75
|
+
screen_cord = screen_cord[1..$jump_sequence.size]
|
76
|
+
screen_cord.each_with_index { |point, i|
|
77
|
+
mark_str = $jump_sequence[i]
|
78
|
+
#puts "draw #{point[0]}x#{point[1]}"
|
79
|
+
draw_text(mark_str, point[0] + 3, point[1])
|
80
|
+
#break if m > $cpos
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def make_jump_sequence(num_items)
|
85
|
+
left_hand = "asdfvgbqwertzxc123".upcase.split("")
|
86
|
+
right_hand = "jklhnnmyuiop890".upcase.split("")
|
87
|
+
|
88
|
+
sequence = []
|
89
|
+
left_hand_fast = "asdf".upcase.split("")
|
90
|
+
right_hand_fast = "jkl;".upcase.split("")
|
91
|
+
|
92
|
+
left_hand_slow = "wergc".upcase.split("") # v
|
93
|
+
right_hand_slow = "uiophnm,".upcase.split("")
|
94
|
+
|
95
|
+
left_hand_slow2 = "tzx23".upcase.split("")
|
96
|
+
right_hand_slow2 = "yb9'".upcase.split("")
|
97
|
+
|
98
|
+
# Rmoved characters that can be mixed: O0Q, 8B, I1, VY
|
99
|
+
|
100
|
+
left_fast_slow = Array.new(left_hand_fast).concat(left_hand_slow)
|
101
|
+
right_fast_slow = Array.new(right_hand_fast).concat(right_hand_slow)
|
102
|
+
|
103
|
+
left_hand_all = Array.new(left_hand_fast).concat(left_hand_slow).concat(left_hand_slow2)
|
104
|
+
right_hand_all = Array.new(right_hand_fast).concat(right_hand_slow).concat(right_hand_slow2)
|
105
|
+
|
106
|
+
left_hand_fast.each { |x|
|
107
|
+
left_hand_fast.each { |y|
|
108
|
+
sequence << "#{x}#{y}"
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
right_hand_fast.each { |x|
|
113
|
+
right_hand_fast.each { |y|
|
114
|
+
sequence << "#{x}#{y}"
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
right_hand_fast.each { |x|
|
119
|
+
left_hand_fast.each { |y|
|
120
|
+
sequence << "#{x}#{y}"
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
left_hand_fast.each { |x|
|
125
|
+
right_hand_fast.each { |y|
|
126
|
+
sequence << "#{x}#{y}"
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
left_hand_slow.each { |x|
|
131
|
+
right_fast_slow.each { |y|
|
132
|
+
sequence << "#{x}#{y}"
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
right_hand_slow.each { |x|
|
137
|
+
left_fast_slow.each { |y|
|
138
|
+
sequence << "#{x}#{y}"
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
left_hand_slow2.each { |x|
|
143
|
+
right_hand_all.each { |y|
|
144
|
+
left_hand_all.each { |z|
|
145
|
+
sequence << "#{x}#{y}#{z}"
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
right_hand_slow2.each { |x|
|
151
|
+
left_hand_all.each { |y|
|
152
|
+
right_hand_all.each { |z|
|
153
|
+
sequence << "#{x}#{y}#{z}"
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}
|
157
|
+
|
158
|
+
#printf("Size of sequence: %d\n",sequence.size)
|
159
|
+
#puts sequence.inspect
|
160
|
+
return sequence
|
161
|
+
end
|
@@ -0,0 +1,667 @@
|
|
1
|
+
require "pty"
|
2
|
+
|
3
|
+
def exec_in_terminal(cmd)
|
4
|
+
# puts "CMD:#{cmd}"
|
5
|
+
|
6
|
+
# global to prevent garbage collect unlink
|
7
|
+
$initf = Tempfile.new("bashinit")
|
8
|
+
# puts $initf.path
|
9
|
+
$initf.write(cmd)
|
10
|
+
$initf.write("rm #{$initf.path}\n")
|
11
|
+
$initf.write("\nexec bash\n")
|
12
|
+
$initf.close
|
13
|
+
# PTY.spawn("gnome-terminal", "--tab", "--", "bash", "-i", $initf.path, "-c", "exec bash")
|
14
|
+
fork { exec "gnome-terminal", "--tab", "--", "bash", "-i", $initf.path, "-c", "exec bash" }
|
15
|
+
end
|
16
|
+
|
17
|
+
def handle_drag_and_drop(fname)
|
18
|
+
debug "EDITOR:handle_drag_and_drop"
|
19
|
+
buf.handle_drag_and_drop(fname)
|
20
|
+
end
|
21
|
+
|
22
|
+
class Editor
|
23
|
+
attr_reader :file_content_search_paths, :file_name_search_paths
|
24
|
+
attr_accessor :converters, :fh, :paint_stack
|
25
|
+
#attr_writer :call_func, :update_highlight
|
26
|
+
|
27
|
+
def initialize()
|
28
|
+
# Thread.new{10000.times{|x|sleep(3);10000.times{|y|y+2};puts "FOOTHREAD #{x}"}}
|
29
|
+
|
30
|
+
# Search for content inside files (e.g. using ack/grep) in:
|
31
|
+
@file_content_search_paths = []
|
32
|
+
|
33
|
+
# Search for files based on filenames in:
|
34
|
+
@file_name_search_paths = []
|
35
|
+
|
36
|
+
#Regexp gsubs or other small modifiers of text
|
37
|
+
@converters = {}
|
38
|
+
@paint_stack = []
|
39
|
+
@_plugins = {}
|
40
|
+
end
|
41
|
+
|
42
|
+
def open_file_listener(added)
|
43
|
+
if !added.empty?
|
44
|
+
for fp in added
|
45
|
+
sleep 0.1
|
46
|
+
x = IO.read(fp)
|
47
|
+
File.delete(fp)
|
48
|
+
for f in x.lines
|
49
|
+
f.gsub!("\n", "")
|
50
|
+
if File.exist?(f)
|
51
|
+
if file_is_text_file(f)
|
52
|
+
jump_to_file(f)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def start
|
61
|
+
# $highlight = {}
|
62
|
+
|
63
|
+
# GLib::Idle.add
|
64
|
+
# Ripl.start :binding => binding
|
65
|
+
# GLib::Idle.add(proc{ puts "IDLEFUNC"})
|
66
|
+
# GLib::Idle.add(proc { idle_func })
|
67
|
+
|
68
|
+
$hook = Hook.new
|
69
|
+
register_plugin(:Hook, $hook)
|
70
|
+
$macro = Macro.new
|
71
|
+
register_plugin(:Macro, $macro)
|
72
|
+
$search = Search.new
|
73
|
+
register_plugin(:Search, $search)
|
74
|
+
|
75
|
+
$buffers = BufferList.new
|
76
|
+
$minibuffer = Buffer.new(">", "")
|
77
|
+
|
78
|
+
require "vimamsa/text_transforms"
|
79
|
+
|
80
|
+
debug "ARGV: " + ARGV.inspect
|
81
|
+
# build_key_bindings_tree
|
82
|
+
$kbd = KeyBindingTree.new()
|
83
|
+
$kbd.add_mode("C", :command)
|
84
|
+
$kbd.add_mode("I", :insert)
|
85
|
+
$kbd.add_mode("V", :visual)
|
86
|
+
$kbd.add_mode("M", :minibuffer)
|
87
|
+
$kbd.add_mode("R", :readchar)
|
88
|
+
$kbd.add_mode("B", :browse)
|
89
|
+
$kbd.set_default_mode(:command)
|
90
|
+
require "vimamsa/default_key_bindings"
|
91
|
+
sleep(0.03)
|
92
|
+
|
93
|
+
FileManager.init
|
94
|
+
|
95
|
+
dot_dir = File.expand_path("~/.vimamsa")
|
96
|
+
Dir.mkdir(dot_dir) unless File.exist?(dot_dir)
|
97
|
+
listen_dir = File.expand_path("~/.vimamsa/listen")
|
98
|
+
Dir.mkdir(listen_dir) unless File.exist?(dot_dir)
|
99
|
+
listener = Listen.to(listen_dir) do |modified, added, removed|
|
100
|
+
puts(modified: modified, added: added, removed: removed)
|
101
|
+
open_file_listener(added)
|
102
|
+
end
|
103
|
+
listener.start
|
104
|
+
|
105
|
+
$cnf[:theme] = "Twilight_edit"
|
106
|
+
$cnf[:syntax_highlight] = true
|
107
|
+
settings_path = get_dot_path("settings.rb")
|
108
|
+
if File.exist?(settings_path)
|
109
|
+
$cnf = eval(IO.read(settings_path))
|
110
|
+
end
|
111
|
+
|
112
|
+
# set_qt_style(1)
|
113
|
+
|
114
|
+
# Limit file search to these extensions:
|
115
|
+
$find_extensions = [".txt", ".h", ".c", ".cpp", ".hpp", ".rb"]
|
116
|
+
|
117
|
+
dotfile = read_file("", "~/.vimamsarc")
|
118
|
+
eval(dotfile) if dotfile
|
119
|
+
|
120
|
+
# build_options
|
121
|
+
|
122
|
+
fname = nil
|
123
|
+
if conf(:startup_file)
|
124
|
+
fname_ = File.expand_path(conf(:startup_file))
|
125
|
+
if File.exist?(fname_)
|
126
|
+
fname = fname_
|
127
|
+
end
|
128
|
+
end
|
129
|
+
fname = ARGV[0] if ARGV.size >= 1 and File.file?(File.expand_path(ARGV[0]))
|
130
|
+
# vma.add_content_search_path(Dir.pwd)
|
131
|
+
for fn in ARGV
|
132
|
+
fn = File.expand_path(fn)
|
133
|
+
if File.directory?(fn)
|
134
|
+
vma.add_content_search_path(fn)
|
135
|
+
$search_dirs << fn
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if fname
|
140
|
+
buffer = Buffer.new(read_file("", fname), fname)
|
141
|
+
else
|
142
|
+
buffer = Buffer.new("INIT\n")
|
143
|
+
end
|
144
|
+
$buffers << buffer
|
145
|
+
|
146
|
+
# load_theme($cnf[:theme])
|
147
|
+
|
148
|
+
# render_buffer($buffer, 1) #TODO
|
149
|
+
|
150
|
+
# gui_select_buffer_init #TODO
|
151
|
+
# gui_file_finder_init #TODO
|
152
|
+
|
153
|
+
#Load plugins
|
154
|
+
require "vimamsa/file_history.rb"
|
155
|
+
@fh = FileHistory.new
|
156
|
+
# @_plugins[:FileFinder] = FileFinder.new
|
157
|
+
@_plugins[:FileHistory] = @fh
|
158
|
+
|
159
|
+
register_plugin(:FileHistory, @fh)
|
160
|
+
register_plugin(:FileFinder, FileFinder.new)
|
161
|
+
# To access via vma.FileFinder
|
162
|
+
# self.define_singleton_method(:FileFinder) { @_plugins[:FileFinder] }
|
163
|
+
|
164
|
+
$hook.call(:after_init)
|
165
|
+
end
|
166
|
+
|
167
|
+
def register_plugin(name, obj)
|
168
|
+
@_plugins[name] = obj
|
169
|
+
# To access via e.g. vma.FileFinder
|
170
|
+
self.define_singleton_method(name) { obj }
|
171
|
+
end
|
172
|
+
|
173
|
+
def buf()
|
174
|
+
return $buffer
|
175
|
+
end
|
176
|
+
|
177
|
+
def marshal_save(varname, vardata)
|
178
|
+
save_var_to_file(varname, Marshal.dump(vardata))
|
179
|
+
end
|
180
|
+
|
181
|
+
def marshal_load(varname, default_data = nil)
|
182
|
+
mdata = load_var_from_file(varname)
|
183
|
+
if mdata
|
184
|
+
return Marshal.load(mdata)
|
185
|
+
else
|
186
|
+
return default_data
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def save_var_to_file(varname, vardata)
|
191
|
+
fn = get_dot_path(varname)
|
192
|
+
f = File.open(fn, "w")
|
193
|
+
File.binwrite(f, vardata)
|
194
|
+
f.close
|
195
|
+
end
|
196
|
+
|
197
|
+
def load_var_from_file(varname)
|
198
|
+
fn = get_dot_path(varname)
|
199
|
+
if File.exist?(fn)
|
200
|
+
vardata = IO.binread(fn)
|
201
|
+
if vardata
|
202
|
+
debug("Successfully red #{varname} from file #{fn}")
|
203
|
+
return vardata
|
204
|
+
end
|
205
|
+
end
|
206
|
+
return nil
|
207
|
+
end
|
208
|
+
|
209
|
+
def plug()
|
210
|
+
return @_plugins
|
211
|
+
end
|
212
|
+
|
213
|
+
def shutdown()
|
214
|
+
$hook.call(:shutdown)
|
215
|
+
save_state
|
216
|
+
end
|
217
|
+
|
218
|
+
def save_state
|
219
|
+
end
|
220
|
+
|
221
|
+
def add_content_search_path(pathstr)
|
222
|
+
p = File.expand_path(pathstr)
|
223
|
+
if !@file_content_search_paths.include?(p)
|
224
|
+
@file_content_search_paths << p
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Register converter
|
229
|
+
def reg_conv(converter, converter_id)
|
230
|
+
@converters[converter_id] = converter
|
231
|
+
reg_act(converter_id, proc { $buffer.convert_selected_text(converter_id) }, "Converter #{converter_id}", [:selection])
|
232
|
+
# reg_act(converter_id, "$buffer.convert_selected_text(:#{converter_id})", "Converter #{converter_id}", [:selection])
|
233
|
+
end
|
234
|
+
|
235
|
+
def apply_conv(converter_id, txt)
|
236
|
+
@converters[converter_id].apply(txt)
|
237
|
+
end
|
238
|
+
|
239
|
+
def get_content_search_paths()
|
240
|
+
r = @file_content_search_paths.clone
|
241
|
+
p = find_project_dir_of_cur_buffer()
|
242
|
+
|
243
|
+
if p and !@file_content_search_paths.include?(p)
|
244
|
+
r.insert(0, p)
|
245
|
+
end
|
246
|
+
return r
|
247
|
+
end
|
248
|
+
|
249
|
+
def can_open_extension?(filepath)
|
250
|
+
exts = $cnf[:extensions_to_open]
|
251
|
+
extname = Pathname.new(filepath).extname.downcase
|
252
|
+
can_open = exts.include?(extname)
|
253
|
+
puts "CAN OPEN?: #{can_open}"
|
254
|
+
return can_open
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def _quit()
|
259
|
+
vma.shutdown
|
260
|
+
exit
|
261
|
+
end
|
262
|
+
|
263
|
+
def fatal_error(msg)
|
264
|
+
puts msg
|
265
|
+
exit!
|
266
|
+
end
|
267
|
+
|
268
|
+
def file_saveas(filename)
|
269
|
+
$buffer.set_filename(filename)
|
270
|
+
$buffer.save()
|
271
|
+
end
|
272
|
+
|
273
|
+
def open_file_dialog()
|
274
|
+
path = ""
|
275
|
+
path = $buffer.fname if $buffer.fname
|
276
|
+
qt_open_file_dialog(File.dirname(path))
|
277
|
+
end
|
278
|
+
|
279
|
+
def system_clipboard_changed(clipboard_contents)
|
280
|
+
max_clipboard_items = 100
|
281
|
+
if clipboard_contents != $clipboard[-1]
|
282
|
+
#TODO: HACK
|
283
|
+
$paste_lines = false
|
284
|
+
end
|
285
|
+
$clipboard << clipboard_contents
|
286
|
+
# puts $clipboard[-1]
|
287
|
+
$clipboard = $clipboard[-([$clipboard.size, max_clipboard_items].min)..-1]
|
288
|
+
end
|
289
|
+
|
290
|
+
def set_clipboard(s)
|
291
|
+
if !(s.class <= String) or s.size == 0
|
292
|
+
puts s.inspect
|
293
|
+
puts [s, s.class, s.size]
|
294
|
+
log_error("s.class != String or s.size == 0")
|
295
|
+
Ripl.start :binding => binding
|
296
|
+
return
|
297
|
+
end
|
298
|
+
$clipboard << s
|
299
|
+
set_system_clipboard(s)
|
300
|
+
$register[$cur_register] = s
|
301
|
+
debug "SET CLIPBOARD: [#{s}]"
|
302
|
+
debug "REGISTER: #{$cur_register}:#{$register[$cur_register]}"
|
303
|
+
end
|
304
|
+
|
305
|
+
def set_cursor_pos(new_pos)
|
306
|
+
buf.set_pos(new_pos)
|
307
|
+
#render_buffer($buffer)
|
308
|
+
debug "New pos: #{new_pos}lpos:#{$buffer.lpos} cpos:#{$buffer.cpos}"
|
309
|
+
end
|
310
|
+
|
311
|
+
def set_last_command(cmd)
|
312
|
+
$command_history << cmd
|
313
|
+
end
|
314
|
+
|
315
|
+
def can_save_to_directory?(dpath)
|
316
|
+
return false if !File.exist?(dpath)
|
317
|
+
return false if !File.directory?(dpath)
|
318
|
+
return false if !File.writable?(dpath)
|
319
|
+
return true
|
320
|
+
end
|
321
|
+
|
322
|
+
def repeat_last_action()
|
323
|
+
cmd = $command_history.last
|
324
|
+
cmd[:method].call *cmd[:params] if cmd != nil
|
325
|
+
end
|
326
|
+
|
327
|
+
def repeat_last_find()
|
328
|
+
return if !defined? $last_find_command
|
329
|
+
$buffer.jump_to_next_instance_of_char($last_find_command[:char],
|
330
|
+
$last_find_command[:direction])
|
331
|
+
end
|
332
|
+
|
333
|
+
def set_next_command_count(num)
|
334
|
+
if $next_command_count != nil
|
335
|
+
$next_command_count = $next_command_count * 10 + num.to_i
|
336
|
+
else
|
337
|
+
$next_command_count = num.to_i
|
338
|
+
end
|
339
|
+
debug("NEXT COMMAND COUNT: #{$next_command_count}")
|
340
|
+
end
|
341
|
+
|
342
|
+
def start_minibuffer_cmd(bufname, bufstr, cmd)
|
343
|
+
$kbd.set_mode(:minibuffer)
|
344
|
+
$minibuffer = Buffer.new(bufstr, "")
|
345
|
+
$minibuffer.call_func = method(cmd)
|
346
|
+
end
|
347
|
+
|
348
|
+
def show_key_bindings()
|
349
|
+
kbd_s = "❙Key bindings❙\n"
|
350
|
+
kbd_s << "=======================================\n"
|
351
|
+
kbd_s << $kbd.to_s
|
352
|
+
kbd_s << "\n=======================================\n"
|
353
|
+
create_new_file(nil, kbd_s)
|
354
|
+
end
|
355
|
+
|
356
|
+
def diff_buffer()
|
357
|
+
bufstr = ""
|
358
|
+
orig_path = $buffer.fname
|
359
|
+
infile = Tempfile.new("out")
|
360
|
+
infile = Tempfile.new("in")
|
361
|
+
infile.write($buffer.to_s)
|
362
|
+
infile.flush
|
363
|
+
cmd = "diff -w '#{orig_path}' #{infile.path}"
|
364
|
+
# puts cmd
|
365
|
+
bufstr << run_cmd(cmd)
|
366
|
+
# puts bufstr
|
367
|
+
infile.close; infile.unlink
|
368
|
+
create_new_file(nil, bufstr)
|
369
|
+
end
|
370
|
+
|
371
|
+
def invoke_command()
|
372
|
+
start_minibuffer_cmd("", "", :execute_command)
|
373
|
+
end
|
374
|
+
|
375
|
+
def execute_command(input_str)
|
376
|
+
begin
|
377
|
+
out_str = eval(input_str, TOPLEVEL_BINDING) #TODO: Other binding?
|
378
|
+
$minibuffer.clear
|
379
|
+
$minibuffer << out_str.to_s #TODO: segfaults, why?
|
380
|
+
rescue SyntaxError
|
381
|
+
debug("SYNTAX ERROR with eval cmd #{action}: " + $!.to_s)
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
def minibuffer_end()
|
386
|
+
debug "minibuffer_end"
|
387
|
+
$kbd.set_mode(:command)
|
388
|
+
minibuffer_input = $minibuffer.to_s[0..-2]
|
389
|
+
return $minibuffer.call_func.call(minibuffer_input)
|
390
|
+
end
|
391
|
+
|
392
|
+
def minibuffer_cancel()
|
393
|
+
debug "minibuffer_cancel"
|
394
|
+
$kbd.set_mode(:command)
|
395
|
+
minibuffer_input = $minibuffer.to_s[0..-2]
|
396
|
+
# $minibuffer.call_func.call('')
|
397
|
+
end
|
398
|
+
|
399
|
+
def minibuffer_new_char(c)
|
400
|
+
if c == "\r"
|
401
|
+
raise "Should not come here"
|
402
|
+
debug "MINIBUFFER END"
|
403
|
+
else
|
404
|
+
$minibuffer.insert_txt(c)
|
405
|
+
debug "MINIBUFFER: #{c}"
|
406
|
+
end
|
407
|
+
#$buffer = $minibuffer
|
408
|
+
end
|
409
|
+
|
410
|
+
def readchar_new_char(c)
|
411
|
+
$input_char_call_func.call(c)
|
412
|
+
end
|
413
|
+
|
414
|
+
def minibuffer_delete()
|
415
|
+
$minibuffer.delete(BACKWARD_CHAR)
|
416
|
+
end
|
417
|
+
|
418
|
+
def message(s)
|
419
|
+
s = "[#{DateTime.now().strftime("%H:%M")}] #{s}"
|
420
|
+
puts s
|
421
|
+
|
422
|
+
$vmag.add_to_minibuf(s)
|
423
|
+
# $minibuffer = Buffer.new(s, "")
|
424
|
+
# $minibuffer[0..-1] = s # TODO
|
425
|
+
#render_minibuffer
|
426
|
+
end
|
427
|
+
|
428
|
+
GUESS_ENCODING_ORDER = [
|
429
|
+
Encoding::US_ASCII,
|
430
|
+
Encoding::UTF_8,
|
431
|
+
Encoding::Shift_JIS,
|
432
|
+
Encoding::EUC_JP,
|
433
|
+
Encoding::EucJP_ms,
|
434
|
+
Encoding::Big5,
|
435
|
+
Encoding::UTF_16BE,
|
436
|
+
Encoding::UTF_16LE,
|
437
|
+
Encoding::UTF_32BE,
|
438
|
+
Encoding::UTF_32LE,
|
439
|
+
Encoding::CP949,
|
440
|
+
Encoding::Emacs_Mule,
|
441
|
+
Encoding::EUC_KR,
|
442
|
+
Encoding::EUC_TW,
|
443
|
+
Encoding::GB18030,
|
444
|
+
Encoding::GBK,
|
445
|
+
Encoding::Stateless_ISO_2022_JP,
|
446
|
+
Encoding::CP51932,
|
447
|
+
Encoding::EUC_CN,
|
448
|
+
Encoding::GB12345,
|
449
|
+
Encoding::Windows_31J,
|
450
|
+
Encoding::MacJapanese,
|
451
|
+
Encoding::UTF8_MAC,
|
452
|
+
Encoding::BINARY,
|
453
|
+
]
|
454
|
+
|
455
|
+
def create_new_file(filename = nil, file_contents = "\n")
|
456
|
+
debug "NEW FILE CREATED"
|
457
|
+
buffer = Buffer.new(file_contents)
|
458
|
+
# qt_set_current_buffer(buffer.id) #TODO: remove?
|
459
|
+
$buffers << buffer
|
460
|
+
return buffer
|
461
|
+
end
|
462
|
+
|
463
|
+
def filter_buffer(buf)
|
464
|
+
i = 0
|
465
|
+
while i < buf.size
|
466
|
+
if buf[i].ord == 160
|
467
|
+
buf[i] = " "
|
468
|
+
#TODO: hack. fix properly
|
469
|
+
end
|
470
|
+
i += 1
|
471
|
+
end
|
472
|
+
return buf
|
473
|
+
end
|
474
|
+
|
475
|
+
def load_buffer(fname)
|
476
|
+
return if !File.exist?(fname)
|
477
|
+
existing_buffer = $buffers.get_buffer_by_filename(fname)
|
478
|
+
if existing_buffer != nil
|
479
|
+
$buffer_history << existing_buffer
|
480
|
+
return
|
481
|
+
end
|
482
|
+
debug("LOAD BUFFER: #{fname}")
|
483
|
+
buffer = Buffer.new(read_file("", fname), fname)
|
484
|
+
# qt_set_current_buffer(buffer.id)
|
485
|
+
buffer.set_active
|
486
|
+
debug("DONE LOAD: #{fname}")
|
487
|
+
#buf = filter_buffer(buffer)
|
488
|
+
# debug("END FILTER: #{fname}")
|
489
|
+
$buffers << buffer
|
490
|
+
#$buffer_history << $buffers.size - 1
|
491
|
+
end
|
492
|
+
|
493
|
+
def jump_to_file(filename, linenum = 0)
|
494
|
+
open_new_file(filename)
|
495
|
+
if linenum > 0
|
496
|
+
$buffer.jump_to_line(linenum)
|
497
|
+
center_on_current_line
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
#TODO: needed?
|
502
|
+
def open_existing_file(filename)
|
503
|
+
open_new_file(filename)
|
504
|
+
end
|
505
|
+
|
506
|
+
def open_new_file(filename, file_contents = "")
|
507
|
+
#TODO: expand path
|
508
|
+
filename = File.expand_path(filename)
|
509
|
+
b = $buffers.get_buffer_by_filename(filename)
|
510
|
+
# File is already opened to existing buffer
|
511
|
+
if b != nil
|
512
|
+
message "Switching to: #{filename}"
|
513
|
+
$buffers.set_current_buffer(b)
|
514
|
+
else
|
515
|
+
message "New file opened: #{filename}"
|
516
|
+
fname = filename
|
517
|
+
load_buffer(fname)
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
def scan_word_start_marks(search_str)
|
522
|
+
# \Z = end of string, just before last newline.
|
523
|
+
wsmarks = scan_indexes(search_str, /(?<=[^\p{Word}])\p{Word}|\Z/)
|
524
|
+
return wsmarks
|
525
|
+
end
|
526
|
+
|
527
|
+
def draw_text(str, x, y)
|
528
|
+
vma.paint_stack << [4, x, y, str]
|
529
|
+
end
|
530
|
+
|
531
|
+
def center_on_current_line__2del()
|
532
|
+
center_where_cursor
|
533
|
+
end
|
534
|
+
|
535
|
+
def hook_draw()
|
536
|
+
# TODO: as hook.register
|
537
|
+
# easy_jump_draw()
|
538
|
+
end
|
539
|
+
|
540
|
+
def render_buffer(buffer = 0, reset = 0)
|
541
|
+
tmpbuf = $buffer.to_s
|
542
|
+
debug "pos:#{$buffer.pos} L:#{$buffer.lpos} C:#{$buffer.cpos}"
|
543
|
+
pos = $buffer.pos
|
544
|
+
selection_start = $buffer.selection_start
|
545
|
+
|
546
|
+
if $buffer.need_redraw?
|
547
|
+
reset = 1
|
548
|
+
end
|
549
|
+
t1 = Time.now
|
550
|
+
hook_draw()
|
551
|
+
|
552
|
+
render_text(tmpbuf, pos, selection_start, reset) #TODO: remove?
|
553
|
+
|
554
|
+
if $buffer.need_redraw?
|
555
|
+
hpt_scan_images() if $debug #experimental
|
556
|
+
end
|
557
|
+
|
558
|
+
$buffer.highlight
|
559
|
+
if Time.now - t1 > 1 / 100.0
|
560
|
+
debug "SLOW render"
|
561
|
+
debug "Render time: #{Time.now - t1}"
|
562
|
+
end
|
563
|
+
$buffer.set_redrawed if reset == 1
|
564
|
+
end
|
565
|
+
|
566
|
+
def get_dot_path(sfx)
|
567
|
+
dot_dir = File.expand_path("~/.vimamsa")
|
568
|
+
Dir.mkdir(dot_dir) unless File.exist?(dot_dir)
|
569
|
+
dpath = "#{dot_dir}/#{sfx}"
|
570
|
+
return dpath
|
571
|
+
end
|
572
|
+
|
573
|
+
def get_file_line_pointer(s)
|
574
|
+
#"/code/vimamsa/lib/vimamsa/buffer_select.rb:31:def"
|
575
|
+
# m = s.match(/(~[a-z]*)?\/.*\//)
|
576
|
+
m = s.match(/((~[a-z]*)?\/.*\/\S+):(\d+)/)
|
577
|
+
if m != nil
|
578
|
+
if File.exist?(File.expand_path(m[1]))
|
579
|
+
return [m[1], m[3].to_i]
|
580
|
+
end
|
581
|
+
end
|
582
|
+
return nil
|
583
|
+
end
|
584
|
+
|
585
|
+
def open_url(url)
|
586
|
+
system("xdg-open", url)
|
587
|
+
end
|
588
|
+
|
589
|
+
def open_with_default_program(url)
|
590
|
+
system("xdg-open", url)
|
591
|
+
end
|
592
|
+
|
593
|
+
def run_cmd(cmd)
|
594
|
+
tmpf = Tempfile.new("vmarun", "/tmp").path
|
595
|
+
cmd = "#{cmd} > #{tmpf}"
|
596
|
+
puts "CMD:\n#{cmd}"
|
597
|
+
system("bash", "-c", cmd)
|
598
|
+
res_str = File.read(tmpf)
|
599
|
+
return res_str
|
600
|
+
end
|
601
|
+
|
602
|
+
require "open3"
|
603
|
+
|
604
|
+
def exec_cmd(bin_name, arg1 = nil, arg2 = nil, arg3 = nil, arg4 = nil, arg5 = nil)
|
605
|
+
assert_binary_exists(bin_name)
|
606
|
+
if !arg5.nil?
|
607
|
+
p = Open3.popen2(bin_name, arg1, arg2, arg3, arg4, arg5)
|
608
|
+
elsif !arg4.nil?
|
609
|
+
p = Open3.popen2(bin_name, arg1, arg2, arg3, arg4)
|
610
|
+
elsif !arg3.nil?
|
611
|
+
p = Open3.popen2(bin_name, arg1, arg2, arg3)
|
612
|
+
elsif !arg2.nil?
|
613
|
+
p = Open3.popen2(bin_name, arg1, arg2)
|
614
|
+
elsif !arg1.nil?
|
615
|
+
p = Open3.popen2(bin_name, arg1)
|
616
|
+
else
|
617
|
+
p = Open3.popen2(bin_name)
|
618
|
+
end
|
619
|
+
|
620
|
+
ret_str = p[1].read
|
621
|
+
return ret_str
|
622
|
+
end
|
623
|
+
|
624
|
+
def file_is_text_file(fpath)
|
625
|
+
puts "file_is_text_file(#{fpath})"
|
626
|
+
fpath = File.expand_path(fpath)
|
627
|
+
return false if !File.exist?(fpath)
|
628
|
+
r = exec_cmd("file", fpath)
|
629
|
+
puts "DEBUG:#{r}"
|
630
|
+
return true if r.match(/UTF-8.*text/)
|
631
|
+
return true if r.match(/ASCII.*text/)
|
632
|
+
return false
|
633
|
+
end
|
634
|
+
|
635
|
+
def set_register(char)
|
636
|
+
$cur_register = char
|
637
|
+
message("Set register #{char}")
|
638
|
+
end
|
639
|
+
|
640
|
+
def paste_register(char)
|
641
|
+
$c = $register[char]
|
642
|
+
message("Paste: #{$c}")
|
643
|
+
end
|
644
|
+
|
645
|
+
def find_project_dir_of_fn(fn)
|
646
|
+
pcomp = Pathname.new(fn).each_filename.to_a
|
647
|
+
parent_dirs = (0..(pcomp.size - 2)).collect { |x| "/" + pcomp[0..x].join("/") }.reverse
|
648
|
+
projdir = nil
|
649
|
+
for pdir in parent_dirs
|
650
|
+
candfn = "#{pdir}/.vma_project"
|
651
|
+
if File.exist?(candfn)
|
652
|
+
projdir = pdir
|
653
|
+
break
|
654
|
+
end
|
655
|
+
end
|
656
|
+
return projdir
|
657
|
+
end
|
658
|
+
|
659
|
+
def find_project_dir_of_cur_buffer()
|
660
|
+
# Find "project dir" of current file. If currently editing file in path "/foo/bar/baz/fn.txt" and file named "/foo/bar/.vma_project" exists, then dir /foo/bar is treated as project dir and subject to e.g. ack search.
|
661
|
+
pdir = nil
|
662
|
+
if $buffer.fname
|
663
|
+
pdir = find_project_dir_of_fn($buffer.fname)
|
664
|
+
end
|
665
|
+
# puts "Proj dir of current file: #{pdir}"
|
666
|
+
return pdir
|
667
|
+
end
|