textbringer 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +1 -1
- data/CHANGES.md +6 -0
- data/README.md +1 -1
- data/lib/textbringer.rb +12 -1
- data/lib/textbringer/buffer.rb +7 -2
- data/lib/textbringer/commands.rb +0 -677
- data/lib/textbringer/commands/buffers.rb +101 -0
- data/lib/textbringer/commands/clipboard.rb +35 -0
- data/lib/textbringer/commands/ctags.rb +14 -7
- data/lib/textbringer/commands/dabbrev.rb +39 -32
- data/lib/textbringer/commands/files.rb +76 -0
- data/lib/textbringer/commands/isearch.rb +144 -0
- data/lib/textbringer/commands/misc.rb +240 -0
- data/lib/textbringer/commands/replace.rb +82 -0
- data/lib/textbringer/commands/windows.rb +72 -0
- data/lib/textbringer/controller.rb +17 -19
- data/lib/textbringer/errors.rb +6 -0
- data/lib/textbringer/modes/ruby_mode.rb +73 -53
- data/lib/textbringer/utils.rb +21 -7
- data/lib/textbringer/version.rb +1 -1
- data/lib/textbringer/window.rb +27 -9
- data/textbringer.gemspec +6 -3
- metadata +57 -8
- data/lib/textbringer/modes.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc327e0ef70cebb198dee6defdcf209902b5af3d
|
4
|
+
data.tar.gz: fb3012f45cd4396e2d5fa0538ee62de453bd1faa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbf9922744735e4b1e8f8c1c5e4d00c40f12e5c50b295bfecd95fa8e66ffb8c0de455ff47aa148414f7e99acb599a27ac84fb52c29e0062e9075d39af54cbc15
|
7
|
+
data.tar.gz: dd2f32a52ede7bbc6df718689bebbfe403305b9e46b29d46128d7b0ae5bced73830e1ba6a34b66473b19b6cf6d9d95e2eff3292aefe21bb43464bb5cc8ce54ad
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/textbringer.svg)](https://badge.fury.io/rb/textbringer)
|
4
4
|
[![Build Status](https://travis-ci.org/shugo/textbringer.svg?branch=master)](https://travis-ci.org/shugo/textbringer)
|
5
5
|
[![Build status](https://ci.appveyor.com/api/projects/status/n20vtpfgcgii5jtc?svg=true)](https://ci.appveyor.com/project/shugo31737/textbringer)
|
6
|
+
[![codecov](https://codecov.io/gh/shugo/textbringer/branch/master/graph/badge.svg)](https://codecov.io/gh/shugo/textbringer)
|
6
7
|
|
7
8
|
Textbringer is a member of a demon race that takes on the form of a text
|
8
9
|
editor.
|
@@ -65,4 +66,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/shugo/
|
|
65
66
|
## License
|
66
67
|
|
67
68
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
68
|
-
|
data/lib/textbringer.rb
CHANGED
@@ -6,7 +6,18 @@ require_relative "textbringer/window"
|
|
6
6
|
require_relative "textbringer/keymap"
|
7
7
|
require_relative "textbringer/utils"
|
8
8
|
require_relative "textbringer/commands"
|
9
|
+
require_relative "textbringer/commands/buffers"
|
10
|
+
require_relative "textbringer/commands/windows"
|
11
|
+
require_relative "textbringer/commands/files"
|
12
|
+
require_relative "textbringer/commands/misc"
|
13
|
+
require_relative "textbringer/commands/isearch"
|
14
|
+
require_relative "textbringer/commands/replace"
|
9
15
|
require_relative "textbringer/commands/dabbrev"
|
10
16
|
require_relative "textbringer/commands/ctags"
|
11
|
-
require_relative "textbringer/
|
17
|
+
require_relative "textbringer/commands/clipboard"
|
18
|
+
require_relative "textbringer/mode"
|
19
|
+
require_relative "textbringer/modes/fundamental_mode"
|
20
|
+
require_relative "textbringer/modes/programming_mode"
|
21
|
+
require_relative "textbringer/modes/ruby_mode"
|
22
|
+
require_relative "textbringer/modes/backtrace_mode"
|
12
23
|
require_relative "textbringer/controller"
|
data/lib/textbringer/buffer.rb
CHANGED
@@ -239,7 +239,7 @@ module Textbringer
|
|
239
239
|
end
|
240
240
|
|
241
241
|
def file_encoding=(enc)
|
242
|
-
@file_encoding = enc
|
242
|
+
@file_encoding = Encoding.find(enc)
|
243
243
|
@binary = enc == Encoding::ASCII_8BIT
|
244
244
|
end
|
245
245
|
|
@@ -1111,8 +1111,9 @@ module Textbringer
|
|
1111
1111
|
end
|
1112
1112
|
|
1113
1113
|
def apply_mode(mode_class)
|
1114
|
+
@keymap = nil
|
1114
1115
|
@mode = mode_class.new(self)
|
1115
|
-
run_hooks(mode_class.hook_name)
|
1116
|
+
Utils.run_hooks(mode_class.hook_name)
|
1116
1117
|
end
|
1117
1118
|
|
1118
1119
|
def indent_to(column)
|
@@ -1397,6 +1398,10 @@ module Textbringer
|
|
1397
1398
|
def empty?
|
1398
1399
|
@ring.empty?
|
1399
1400
|
end
|
1401
|
+
|
1402
|
+
def size
|
1403
|
+
@ring.size
|
1404
|
+
end
|
1400
1405
|
end
|
1401
1406
|
|
1402
1407
|
KILL_RING = KillRing.new
|
data/lib/textbringer/commands.rb
CHANGED
@@ -26,682 +26,5 @@ module Textbringer
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
module_function :undefine_command
|
29
|
-
|
30
|
-
define_command(:version) do
|
31
|
-
message("Textbringer #{Textbringer::VERSION} "\
|
32
|
-
"(ruby #{RUBY_VERSION} [#{RUBY_PLATFORM}])")
|
33
|
-
end
|
34
|
-
|
35
|
-
[
|
36
|
-
:forward_char,
|
37
|
-
:backward_char,
|
38
|
-
:forward_word,
|
39
|
-
:backward_word,
|
40
|
-
:next_line,
|
41
|
-
:previous_line,
|
42
|
-
:delete_char,
|
43
|
-
:backward_delete_char,
|
44
|
-
].each do |name|
|
45
|
-
define_command(name) do |n = number_prefix_arg|
|
46
|
-
Buffer.current.send(name, n)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
[
|
51
|
-
:beginning_of_line,
|
52
|
-
:end_of_line,
|
53
|
-
:beginning_of_buffer,
|
54
|
-
:end_of_buffer,
|
55
|
-
:exchange_point_and_mark,
|
56
|
-
:copy_region,
|
57
|
-
:kill_region,
|
58
|
-
:yank,
|
59
|
-
:newline,
|
60
|
-
:delete_region,
|
61
|
-
:transpose_chars
|
62
|
-
].each do |name|
|
63
|
-
define_command(name) do
|
64
|
-
Buffer.current.send(name)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
define_command(:set_mark_command) do
|
69
|
-
Buffer.current.set_mark
|
70
|
-
message("Mark set")
|
71
|
-
end
|
72
|
-
|
73
|
-
define_command(:goto_char) do
|
74
|
-
|n = read_from_minibuffer("Go to char: ")|
|
75
|
-
Buffer.current.goto_char(n.to_i)
|
76
|
-
Window.current.recenter_if_needed
|
77
|
-
end
|
78
|
-
|
79
|
-
define_command(:goto_line) do
|
80
|
-
|n = read_from_minibuffer("Go to line: ")|
|
81
|
-
Buffer.current.goto_line(n.to_i)
|
82
|
-
Window.current.recenter_if_needed
|
83
|
-
end
|
84
|
-
|
85
|
-
define_command(:self_insert) do |n = number_prefix_arg|
|
86
|
-
c = Controller.current.last_key
|
87
|
-
merge_undo = Controller.current.last_command == :self_insert
|
88
|
-
n.times do
|
89
|
-
Buffer.current.insert(c, merge_undo)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
define_command(:quoted_insert) do |n = number_prefix_arg|
|
94
|
-
c = Controller.current.read_char
|
95
|
-
if !c.is_a?(String)
|
96
|
-
raise "Invalid key"
|
97
|
-
end
|
98
|
-
n.times do
|
99
|
-
Buffer.current.insert(c)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
define_command(:kill_line) do
|
104
|
-
Buffer.current.kill_line(Controller.current.last_command == :kill_region)
|
105
|
-
Controller.current.this_command = :kill_region
|
106
|
-
end
|
107
|
-
|
108
|
-
define_command(:kill_word) do
|
109
|
-
Buffer.current.kill_word(Controller.current.last_command == :kill_region)
|
110
|
-
Controller.current.this_command = :kill_region
|
111
|
-
end
|
112
|
-
|
113
|
-
define_command(:yank_pop) do
|
114
|
-
if Controller.current.last_command != :yank
|
115
|
-
raise EditorError, "Previous command was not a yank"
|
116
|
-
end
|
117
|
-
Buffer.current.yank_pop
|
118
|
-
Controller.current.this_command = :yank
|
119
|
-
end
|
120
|
-
|
121
|
-
RE_SEARCH_STATUS = {
|
122
|
-
last_regexp: nil
|
123
|
-
}
|
124
|
-
|
125
|
-
define_command(:re_search_forward) do
|
126
|
-
|s = read_from_minibuffer("RE search: ",
|
127
|
-
default: RE_SEARCH_STATUS[:last_regexp])|
|
128
|
-
RE_SEARCH_STATUS[:last_regexp] = s
|
129
|
-
Buffer.current.re_search_forward(s)
|
130
|
-
end
|
131
|
-
|
132
|
-
define_command(:re_search_backward) do
|
133
|
-
|s = read_from_minibuffer("RE search backward: ",
|
134
|
-
default: RE_SEARCH_STATUS[:last_regexp])|
|
135
|
-
RE_SEARCH_STATUS[:last_regexp] = s
|
136
|
-
Buffer.current.re_search_backward(s)
|
137
|
-
end
|
138
|
-
|
139
|
-
def match_beginning(n)
|
140
|
-
Buffer.current.match_beginning(n)
|
141
|
-
end
|
142
|
-
|
143
|
-
def match_end(n)
|
144
|
-
Buffer.current.match_end(n)
|
145
|
-
end
|
146
|
-
|
147
|
-
def match_string(n)
|
148
|
-
Buffer.current.match_string(n)
|
149
|
-
end
|
150
|
-
|
151
|
-
def replace_match(s)
|
152
|
-
Buffer.current.replace_match(s)
|
153
|
-
end
|
154
|
-
|
155
|
-
define_command(:query_replace_regexp) do
|
156
|
-
|regexp = read_from_minibuffer("Query replace regexp: "),
|
157
|
-
to_str = read_from_minibuffer("with: ")|
|
158
|
-
n = 0
|
159
|
-
begin
|
160
|
-
loop do
|
161
|
-
re_search_forward(regexp)
|
162
|
-
Window.current.recenter_if_needed
|
163
|
-
Buffer.current.set_visible_mark(match_beginning(0))
|
164
|
-
begin
|
165
|
-
Window.redisplay
|
166
|
-
c = read_single_char("Replace?", [?y, ?n, ?!, ?q, ?.])
|
167
|
-
case c
|
168
|
-
when ?y
|
169
|
-
replace_match(to_str)
|
170
|
-
n += 1
|
171
|
-
when ?n
|
172
|
-
# do nothing
|
173
|
-
when ?!
|
174
|
-
replace_match(to_str)
|
175
|
-
n += 1 + Buffer.current.replace_regexp_forward(regexp, to_str)
|
176
|
-
Buffer.current.merge_undo(2)
|
177
|
-
break
|
178
|
-
when ?q
|
179
|
-
break
|
180
|
-
when ?.
|
181
|
-
replace_match(to_str)
|
182
|
-
n += 1
|
183
|
-
break
|
184
|
-
end
|
185
|
-
ensure
|
186
|
-
Buffer.current.delete_visible_mark
|
187
|
-
end
|
188
|
-
end
|
189
|
-
rescue SearchError
|
190
|
-
end
|
191
|
-
if n == 1
|
192
|
-
message("Replaced 1 occurrence")
|
193
|
-
else
|
194
|
-
message("Replaced #{n} occurrences")
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
define_command(:undo) do
|
199
|
-
Buffer.current.undo
|
200
|
-
message("Undo!")
|
201
|
-
end
|
202
|
-
|
203
|
-
define_command(:redo) do
|
204
|
-
Buffer.current.redo
|
205
|
-
message("Redo!")
|
206
|
-
end
|
207
|
-
|
208
|
-
define_command(:resize_window) do
|
209
|
-
Window.resize
|
210
|
-
end
|
211
|
-
|
212
|
-
define_command(:recenter) do
|
213
|
-
Window.current.recenter
|
214
|
-
Window.redraw
|
215
|
-
end
|
216
|
-
|
217
|
-
define_command(:scroll_up) do
|
218
|
-
Window.current.scroll_up
|
219
|
-
end
|
220
|
-
|
221
|
-
define_command(:scroll_down) do
|
222
|
-
Window.current.scroll_down
|
223
|
-
end
|
224
|
-
|
225
|
-
define_command(:delete_window) do
|
226
|
-
Window.delete_window
|
227
|
-
end
|
228
|
-
|
229
|
-
define_command(:delete_other_windows) do
|
230
|
-
Window.delete_other_windows
|
231
|
-
end
|
232
|
-
|
233
|
-
define_command(:split_window) do
|
234
|
-
Window.current.split
|
235
|
-
end
|
236
|
-
|
237
|
-
define_command(:other_window) do
|
238
|
-
Window.other_window
|
239
|
-
end
|
240
|
-
|
241
|
-
define_command(:exit_textbringer) do |status = 0|
|
242
|
-
if Buffer.any? { |buffer| /\A\*/ !~ buffer.name && buffer.modified? }
|
243
|
-
return unless yes_or_no?("Unsaved buffers exist; exit anyway?")
|
244
|
-
end
|
245
|
-
exit(status)
|
246
|
-
end
|
247
|
-
|
248
|
-
define_command(:suspend_textbringer) do
|
249
|
-
Curses.close_screen
|
250
|
-
Process.kill(:STOP, $$)
|
251
|
-
end
|
252
|
-
|
253
|
-
define_command(:pwd) do
|
254
|
-
message(Dir.pwd)
|
255
|
-
end
|
256
|
-
|
257
|
-
define_command(:chdir) do
|
258
|
-
|dir_name = read_file_name("Change directory: ")|
|
259
|
-
Dir.chdir(dir_name)
|
260
|
-
end
|
261
|
-
|
262
|
-
define_command(:find_file) do
|
263
|
-
|file_name = read_file_name("Find file: ")|
|
264
|
-
buffer = Buffer.find_file(file_name)
|
265
|
-
if buffer.new_file?
|
266
|
-
message("New file")
|
267
|
-
end
|
268
|
-
switch_to_buffer(buffer)
|
269
|
-
shebang = buffer.save_excursion {
|
270
|
-
buffer.beginning_of_buffer
|
271
|
-
buffer.looking_at?(/#!.*$/) ? buffer.match_string(0) : nil
|
272
|
-
}
|
273
|
-
mode = Mode.list.find { |m|
|
274
|
-
(m.file_name_pattern &&
|
275
|
-
m.file_name_pattern =~ File.basename(buffer.file_name)) ||
|
276
|
-
(m.interpreter_name_pattern &&
|
277
|
-
m.interpreter_name_pattern =~ shebang)
|
278
|
-
} || FundamentalMode
|
279
|
-
send(mode.command_name)
|
280
|
-
end
|
281
|
-
|
282
|
-
define_command(:switch_to_buffer) do
|
283
|
-
|buffer_name = read_buffer("Switch to buffer: ")|
|
284
|
-
if buffer_name.is_a?(Buffer)
|
285
|
-
buffer = buffer_name
|
286
|
-
else
|
287
|
-
buffer = Buffer[buffer_name]
|
288
|
-
end
|
289
|
-
if buffer
|
290
|
-
Window.current.buffer = Buffer.current = buffer
|
291
|
-
else
|
292
|
-
message("No such buffer: #{buffer_name}")
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
define_command(:save_buffer) do
|
297
|
-
if Buffer.current.file_name.nil?
|
298
|
-
Buffer.current.file_name = read_file_name("File to save in: ")
|
299
|
-
next if Buffer.current.file_name.nil?
|
300
|
-
end
|
301
|
-
if Buffer.current.file_modified?
|
302
|
-
unless yes_or_no?("File changed on disk. Save anyway?")
|
303
|
-
message("Cancelled")
|
304
|
-
next
|
305
|
-
end
|
306
|
-
end
|
307
|
-
Buffer.current.save
|
308
|
-
message("Wrote #{Buffer.current.file_name}")
|
309
|
-
end
|
310
|
-
|
311
|
-
define_command(:write_file) do
|
312
|
-
|file_name = read_file_name("Write file: ")|
|
313
|
-
if File.directory?(file_name)
|
314
|
-
file_name = File.expand_path(Buffer.current.name, file_name)
|
315
|
-
end
|
316
|
-
if File.exist?(file_name)
|
317
|
-
unless y_or_n?("File `#{file_name}' exists; overwrite?")
|
318
|
-
message("Cancelled")
|
319
|
-
next
|
320
|
-
end
|
321
|
-
end
|
322
|
-
Buffer.current.save(file_name)
|
323
|
-
message("Wrote #{Buffer.current.file_name}")
|
324
|
-
end
|
325
|
-
|
326
|
-
define_command(:kill_buffer) do
|
327
|
-
|name = read_buffer("Kill buffer: ", default: Buffer.current.name)|
|
328
|
-
if name.is_a?(Buffer)
|
329
|
-
buffer = name
|
330
|
-
else
|
331
|
-
buffer = Buffer[name]
|
332
|
-
end
|
333
|
-
if buffer.modified?
|
334
|
-
next unless yes_or_no?("The last change is not saved; kill anyway?")
|
335
|
-
message("Arioch! Arioch! Blood and souls for my Lord Arioch!")
|
336
|
-
end
|
337
|
-
buffer.kill
|
338
|
-
if Buffer.count == 0
|
339
|
-
buffer = Buffer.new_buffer("*scratch*")
|
340
|
-
switch_to_buffer(buffer)
|
341
|
-
elsif Buffer.current.nil?
|
342
|
-
switch_to_buffer(Buffer.last)
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
define_command(:set_buffer_file_encoding) do
|
347
|
-
|enc = read_from_minibuffer("File encoding: ",
|
348
|
-
default: Buffer.current.file_encoding.name)|
|
349
|
-
Buffer.current.file_encoding = Encoding.find(enc)
|
350
|
-
end
|
351
|
-
|
352
|
-
define_command(:set_buffer_file_format) do
|
353
|
-
|format = read_from_minibuffer("File format: ",
|
354
|
-
default: Buffer.current.file_format.to_s)|
|
355
|
-
Buffer.current.file_format = format
|
356
|
-
end
|
357
|
-
|
358
|
-
define_command(:execute_command) do
|
359
|
-
|cmd = read_command_name("M-x ").strip.intern|
|
360
|
-
unless Commands.list.include?(cmd)
|
361
|
-
raise EditorError, "Undefined command: #{cmd}"
|
362
|
-
end
|
363
|
-
Controller.current.this_command = cmd
|
364
|
-
send(cmd)
|
365
|
-
end
|
366
|
-
|
367
|
-
define_command(:eval_expression) do
|
368
|
-
|s = read_from_minibuffer("Eval: ")|
|
369
|
-
message(eval(s, TOPLEVEL_BINDING, "(eval_expression)", 1).inspect)
|
370
|
-
end
|
371
|
-
|
372
|
-
define_command(:eval_buffer) do
|
373
|
-
buffer = Buffer.current
|
374
|
-
result = eval(buffer.to_s, TOPLEVEL_BINDING,
|
375
|
-
buffer.file_name || buffer.name, 1)
|
376
|
-
message(result.inspect)
|
377
|
-
end
|
378
|
-
|
379
|
-
define_command(:eval_region) do
|
380
|
-
buffer = Buffer.current
|
381
|
-
b, e = buffer.point, buffer.mark
|
382
|
-
if e < b
|
383
|
-
b, e = e, b
|
384
|
-
end
|
385
|
-
result = eval(buffer.substring(b, e), TOPLEVEL_BINDING,
|
386
|
-
"(eval_region)", 1)
|
387
|
-
message(result.inspect)
|
388
|
-
end
|
389
|
-
|
390
|
-
define_command(:exit_recursive_edit) do
|
391
|
-
if @recursive_edit_level == 0
|
392
|
-
raise EditorError, "No recursive edit is in progress"
|
393
|
-
end
|
394
|
-
throw RECURSIVE_EDIT_TAG, false
|
395
|
-
end
|
396
|
-
|
397
|
-
define_command(:abort_recursive_edit) do
|
398
|
-
if @recursive_edit_level == 0
|
399
|
-
raise EditorError, "No recursive edit is in progress"
|
400
|
-
end
|
401
|
-
throw RECURSIVE_EDIT_TAG, true
|
402
|
-
end
|
403
|
-
|
404
|
-
define_command(:top_level) do
|
405
|
-
throw TOP_LEVEL_TAG
|
406
|
-
end
|
407
|
-
|
408
|
-
define_command(:complete_minibuffer) do
|
409
|
-
minibuffer = Buffer.minibuffer
|
410
|
-
completion_proc = minibuffer[:completion_proc]
|
411
|
-
if completion_proc
|
412
|
-
s = completion_proc.call(minibuffer.to_s)
|
413
|
-
if s
|
414
|
-
minibuffer.delete_region(minibuffer.point_min,
|
415
|
-
minibuffer.point_max)
|
416
|
-
minibuffer.insert(s)
|
417
|
-
end
|
418
|
-
end
|
419
|
-
end
|
420
|
-
|
421
|
-
UNIVERSAL_ARGUMENT_MAP = Keymap.new
|
422
|
-
(?0..?9).each do |c|
|
423
|
-
UNIVERSAL_ARGUMENT_MAP.define_key(c, :digit_argument)
|
424
|
-
GLOBAL_MAP.define_key("\e#{c}", :digit_argument)
|
425
|
-
end
|
426
|
-
UNIVERSAL_ARGUMENT_MAP.define_key(?-, :negative_argument)
|
427
|
-
UNIVERSAL_ARGUMENT_MAP.define_key(?\C-u, :universal_argument_more)
|
428
|
-
|
429
|
-
def universal_argument_mode
|
430
|
-
set_transient_map(UNIVERSAL_ARGUMENT_MAP)
|
431
|
-
end
|
432
|
-
|
433
|
-
define_command(:universal_argument) do
|
434
|
-
Controller.current.prefix_arg = [4]
|
435
|
-
universal_argument_mode
|
436
|
-
end
|
437
|
-
|
438
|
-
def current_prefix_arg
|
439
|
-
Controller.current.current_prefix_arg
|
440
|
-
end
|
441
|
-
|
442
|
-
def number_prefix_arg
|
443
|
-
arg = current_prefix_arg
|
444
|
-
case arg
|
445
|
-
when Integer
|
446
|
-
arg
|
447
|
-
when Array
|
448
|
-
arg.first
|
449
|
-
when :-
|
450
|
-
-1
|
451
|
-
else
|
452
|
-
1
|
453
|
-
end
|
454
|
-
end
|
455
|
-
|
456
|
-
define_command(:digit_argument) do
|
457
|
-
|arg = current_prefix_arg|
|
458
|
-
n = last_key.to_i
|
459
|
-
Controller.current.prefix_arg =
|
460
|
-
case arg
|
461
|
-
when Integer
|
462
|
-
arg * 10 + (arg < 0 ? -n : n)
|
463
|
-
when :-
|
464
|
-
-n
|
465
|
-
else
|
466
|
-
n
|
467
|
-
end
|
468
|
-
universal_argument_mode
|
469
|
-
end
|
470
|
-
|
471
|
-
define_command(:negative_argument) do
|
472
|
-
|arg = current_prefix_arg|
|
473
|
-
Controller.current.prefix_arg =
|
474
|
-
case arg
|
475
|
-
when Integer
|
476
|
-
-arg
|
477
|
-
when :-
|
478
|
-
nil
|
479
|
-
else
|
480
|
-
:-
|
481
|
-
end
|
482
|
-
universal_argument_mode
|
483
|
-
end
|
484
|
-
|
485
|
-
define_command(:universal_argument_more) do
|
486
|
-
|arg = current_prefix_arg|
|
487
|
-
Controller.current.prefix_arg =
|
488
|
-
case arg
|
489
|
-
when Array
|
490
|
-
[4 * arg.first]
|
491
|
-
when :-
|
492
|
-
[-4]
|
493
|
-
else
|
494
|
-
nil
|
495
|
-
end
|
496
|
-
if Controller.current.prefix_arg
|
497
|
-
universal_argument_mode
|
498
|
-
end
|
499
|
-
end
|
500
|
-
|
501
|
-
define_command(:keyboard_quit) do
|
502
|
-
raise Quit
|
503
|
-
end
|
504
|
-
|
505
|
-
define_command(:recursive_edit) do
|
506
|
-
Controller.current.recursive_edit
|
507
|
-
end
|
508
|
-
|
509
|
-
ISEARCH_MODE_MAP = Keymap.new
|
510
|
-
(?\x20..?\x7e).each do |c|
|
511
|
-
ISEARCH_MODE_MAP.define_key(c, :isearch_printing_char)
|
512
|
-
end
|
513
|
-
ISEARCH_MODE_MAP.define_key(?\t, :isearch_printing_char)
|
514
|
-
ISEARCH_MODE_MAP.handle_undefined_key do |key|
|
515
|
-
if key.is_a?(String) && /[\0-\x7f]/ !~ key
|
516
|
-
:isearch_printing_char
|
517
|
-
else
|
518
|
-
nil
|
519
|
-
end
|
520
|
-
end
|
521
|
-
ISEARCH_MODE_MAP.define_key(:backspace, :isearch_delete_char)
|
522
|
-
ISEARCH_MODE_MAP.define_key(?\C-h, :isearch_delete_char)
|
523
|
-
ISEARCH_MODE_MAP.define_key(?\C-s, :isearch_repeat_forward)
|
524
|
-
ISEARCH_MODE_MAP.define_key(?\C-r, :isearch_repeat_backward)
|
525
|
-
ISEARCH_MODE_MAP.define_key(?\n, :isearch_exit)
|
526
|
-
ISEARCH_MODE_MAP.define_key(?\C-g, :isearch_abort)
|
527
|
-
|
528
|
-
ISEARCH_STATUS = {
|
529
|
-
forward: true,
|
530
|
-
string: "",
|
531
|
-
last_string: "",
|
532
|
-
start: 0,
|
533
|
-
last_pos: 0
|
534
|
-
}
|
535
|
-
|
536
|
-
define_command(:isearch_forward) do
|
537
|
-
isearch_mode(true)
|
538
|
-
end
|
539
|
-
|
540
|
-
define_command(:isearch_backward) do
|
541
|
-
isearch_mode(false)
|
542
|
-
end
|
543
|
-
|
544
|
-
def isearch_mode(forward)
|
545
|
-
ISEARCH_STATUS[:forward] = forward
|
546
|
-
ISEARCH_STATUS[:string] = String.new
|
547
|
-
Controller.current.overriding_map = ISEARCH_MODE_MAP
|
548
|
-
run_hooks(:isearch_mode_hook)
|
549
|
-
add_hook(:pre_command_hook, :isearch_pre_command_hook)
|
550
|
-
ISEARCH_STATUS[:start] = ISEARCH_STATUS[:last_pos] = Buffer.current.point
|
551
|
-
if Buffer.current != Buffer.minibuffer
|
552
|
-
message(isearch_prompt, log: false)
|
553
|
-
end
|
554
|
-
end
|
555
|
-
|
556
|
-
def isearch_prompt
|
557
|
-
if ISEARCH_STATUS[:forward]
|
558
|
-
"I-search: "
|
559
|
-
else
|
560
|
-
"I-search backward: "
|
561
|
-
end
|
562
|
-
end
|
563
|
-
|
564
|
-
def isearch_pre_command_hook
|
565
|
-
if /\Aisearch_/ !~ Controller.current.this_command
|
566
|
-
isearch_done
|
567
|
-
end
|
568
|
-
end
|
569
|
-
|
570
|
-
def isearch_done
|
571
|
-
Buffer.current.delete_visible_mark
|
572
|
-
Controller.current.overriding_map = nil
|
573
|
-
remove_hook(:pre_command_hook, :isearch_pre_command_hook)
|
574
|
-
ISEARCH_STATUS[:last_string] = ISEARCH_STATUS[:string]
|
575
|
-
end
|
576
|
-
|
577
|
-
define_command(:isearch_exit) do
|
578
|
-
isearch_done
|
579
|
-
end
|
580
|
-
|
581
|
-
define_command(:isearch_abort) do
|
582
|
-
goto_char(Buffer.current[:isearch_start])
|
583
|
-
isearch_done
|
584
|
-
raise Quit
|
585
|
-
end
|
586
|
-
|
587
|
-
define_command(:isearch_printing_char) do
|
588
|
-
c = Controller.current.last_key
|
589
|
-
ISEARCH_STATUS[:string].concat(c)
|
590
|
-
isearch_search
|
591
|
-
end
|
592
|
-
|
593
|
-
define_command(:isearch_delete_char) do
|
594
|
-
ISEARCH_STATUS[:string].chop!
|
595
|
-
isearch_search
|
596
|
-
end
|
597
|
-
|
598
|
-
def isearch_search
|
599
|
-
forward = ISEARCH_STATUS[:forward]
|
600
|
-
options = if /\A[A-Z]/ =~ ISEARCH_STATUS[:string]
|
601
|
-
nil
|
602
|
-
else
|
603
|
-
Regexp::IGNORECASE
|
604
|
-
end
|
605
|
-
re = Regexp.new(Regexp.quote(ISEARCH_STATUS[:string]), options)
|
606
|
-
last_pos = ISEARCH_STATUS[:last_pos]
|
607
|
-
offset = forward ? last_pos : last_pos - ISEARCH_STATUS[:string].bytesize
|
608
|
-
if Buffer.current.byteindex(forward, re, offset)
|
609
|
-
if Buffer.current != Buffer.minibuffer
|
610
|
-
message(isearch_prompt + ISEARCH_STATUS[:string], log: false)
|
611
|
-
end
|
612
|
-
Buffer.current.set_visible_mark(forward ? match_beginning(0) :
|
613
|
-
match_end(0))
|
614
|
-
goto_char(forward ? match_end(0) : match_beginning(0))
|
615
|
-
else
|
616
|
-
if Buffer.current != Buffer.minibuffer
|
617
|
-
message("Falling " + isearch_prompt + ISEARCH_STATUS[:string],
|
618
|
-
log: false)
|
619
|
-
end
|
620
|
-
end
|
621
|
-
end
|
622
|
-
|
623
|
-
def isearch_repeat_forward
|
624
|
-
isearch_repeat(true)
|
625
|
-
end
|
626
|
-
|
627
|
-
def isearch_repeat_backward
|
628
|
-
isearch_repeat(false)
|
629
|
-
end
|
630
|
-
|
631
|
-
def isearch_repeat(forward)
|
632
|
-
ISEARCH_STATUS[:forward] = forward
|
633
|
-
ISEARCH_STATUS[:last_pos] = Buffer.current.point
|
634
|
-
if ISEARCH_STATUS[:string].empty?
|
635
|
-
ISEARCH_STATUS[:string] = ISEARCH_STATUS[:last_string]
|
636
|
-
end
|
637
|
-
isearch_search
|
638
|
-
end
|
639
|
-
|
640
|
-
define_command(:shell_execute) do
|
641
|
-
|cmd = read_from_minibuffer("Shell execute: "),
|
642
|
-
buffer_name = "*Shell output*"|
|
643
|
-
buffer = Buffer.find_or_new(buffer_name)
|
644
|
-
switch_to_buffer(buffer)
|
645
|
-
buffer.read_only = false
|
646
|
-
buffer.clear
|
647
|
-
Window.redisplay
|
648
|
-
signals = [:INT, :TERM, :KILL]
|
649
|
-
begin
|
650
|
-
if /mswin32|mingw32/ =~ RUBY_PLATFORM
|
651
|
-
opts = {}
|
652
|
-
else
|
653
|
-
opts = {pgroup: true}
|
654
|
-
end
|
655
|
-
Open3.popen2e(cmd, opts) do |input, output, wait_thread|
|
656
|
-
input.close
|
657
|
-
loop do
|
658
|
-
status = output.wait_readable(0.5)
|
659
|
-
if status == false
|
660
|
-
break # EOF
|
661
|
-
end
|
662
|
-
if status
|
663
|
-
begin
|
664
|
-
s = output.read_nonblock(1024).force_encoding("utf-8").
|
665
|
-
scrub("\u{3013}").gsub(/\r\n/, "\n")
|
666
|
-
buffer.insert(s)
|
667
|
-
Window.redisplay
|
668
|
-
rescue EOFError
|
669
|
-
break
|
670
|
-
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
|
671
|
-
next
|
672
|
-
end
|
673
|
-
end
|
674
|
-
if received_keyboard_quit?
|
675
|
-
if signals.empty?
|
676
|
-
keyboard_quit
|
677
|
-
else
|
678
|
-
sig = signals.shift
|
679
|
-
message("Send #{sig} to #{wait_thread.pid}")
|
680
|
-
Process.kill(sig, -wait_thread.pid)
|
681
|
-
end
|
682
|
-
end
|
683
|
-
end
|
684
|
-
status = wait_thread.value
|
685
|
-
pid = status.pid
|
686
|
-
if status.exited?
|
687
|
-
code = status.exitstatus
|
688
|
-
message("Process #{pid} exited with status code #{code}")
|
689
|
-
elsif status.signaled?
|
690
|
-
signame = Signal.signame(status.termsig)
|
691
|
-
message("Process #{pid} was killed by #{signame}")
|
692
|
-
else
|
693
|
-
message("Process #{pid} exited")
|
694
|
-
end
|
695
|
-
end
|
696
|
-
ensure
|
697
|
-
buffer.read_only = true
|
698
|
-
end
|
699
|
-
end
|
700
|
-
end
|
701
|
-
|
702
|
-
class Quit < StandardError
|
703
|
-
def initialize
|
704
|
-
super("Quit")
|
705
|
-
end
|
706
29
|
end
|
707
30
|
end
|