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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c4c0499915d9509f0f2ef8d8b30b8a3c87955c9c
4
- data.tar.gz: 017b6339f497de93887ee252df2b1da9b3c20bae
3
+ metadata.gz: cc327e0ef70cebb198dee6defdcf209902b5af3d
4
+ data.tar.gz: fb3012f45cd4396e2d5fa0538ee62de453bd1faa
5
5
  SHA512:
6
- metadata.gz: 813608d1b0cd0f5a120256a49f5509a75f0d4c8a05c1f803e3b6625f8161f3a249a944fc447e16dc50eb9fb9754f2e8b6ab2d55bca0df4ef9a45887151d04637
7
- data.tar.gz: a3b1267f21be52ef1e9136cc530cf7b0f0cd158d636940d0143980b79a54ef96cefbb354aae2e9eb877942097ee90044e2e8d4991cbfb55671c5f049fc8bb365
6
+ metadata.gz: cbf9922744735e4b1e8f8c1c5e4d00c40f12e5c50b295bfecd95fa8e66ffb8c0de455ff47aa148414f7e99acb599a27ac84fb52c29e0062e9075d39af54cbc15
7
+ data.tar.gz: dd2f32a52ede7bbc6df718689bebbfe403305b9e46b29d46128d7b0ae5bced73830e1ba6a34b66473b19b6cf6d9d95e2eff3292aefe21bb43464bb5cc8ce54ad
data/.gitignore CHANGED
@@ -7,4 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
- tags
10
+ /tags
@@ -5,7 +5,7 @@ rvm:
5
5
  - 2.4.0
6
6
  cache: bundler
7
7
  script:
8
- - bundle exec rake test
8
+ - xvfb-run bundle exec rake test
9
9
  - bundle exec bundle-audit check --update
10
10
  notifications:
11
11
  email:
data/CHANGES.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.1.5
2
+
3
+ * Support clipboard.
4
+ * Added tests.
5
+ * Bug fixes.
6
+
1
7
  ## 0.1.4
2
8
 
3
9
  * Add dabbrev_expand (M-/).
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
-
@@ -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/modes"
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"
@@ -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
@@ -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