reline 0.5.0 → 0.5.2

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: 9b325efda8753fa1ecea3b1dabfd685416016ee334876673bf0d965c3a02095d
4
- data.tar.gz: 4b22612ebce12cc96593f98535bfb9223eebbded388931ccbd8bbdb4d13ce1d1
3
+ metadata.gz: 68e79c30bbef8d97090f7126f96c5ee0c32fa95e6dc120a91240a6e9ff3864c6
4
+ data.tar.gz: 857716d3f9ab324efef98d3cb42acf2bba17848012a832c5631ca3e6d2f15733
5
5
  SHA512:
6
- metadata.gz: 29f19adce6163f38399da6119c3605039593d244c7119d601b413279a678cd87a5ad5eba5679f2ea7ccc1bdf7b4743987b2840cf4c0f69fa316c0d2fa84b5f45
7
- data.tar.gz: be0b1ad84d01936ff721b3a18f196d0ee19817da6baf9200e4e6a96681e4b87594c55d1aa71071fcda63f35c4c8d0aefa7aa7a016c62c538d165e19f82e7d3b8
6
+ metadata.gz: b25e6a151ded60963f660ccafceef8c221577b9f2328b9daa10dc381f5ea63c293a9759a786ab02610eb2fb07c52f3a200303fd9ac672210658884cb9a57c88c
7
+ data.tar.gz: 8433437480cf5acf7d87aefc632cc641e9325f163ab1d00d1df9cea5d5f3977f05250b20b366d7fd21ae275edd8f152ddc5879fa88340fbf35990e9b2a7e9725
data/lib/reline/ansi.rb CHANGED
@@ -151,7 +151,11 @@ class Reline::ANSI
151
151
  end
152
152
 
153
153
  def self.with_raw_input
154
- @@input.raw { yield }
154
+ if @@input.tty?
155
+ @@input.raw(intr: true) { yield }
156
+ else
157
+ yield
158
+ end
155
159
  end
156
160
 
157
161
  @@buf = []
@@ -159,11 +163,13 @@ class Reline::ANSI
159
163
  unless @@buf.empty?
160
164
  return @@buf.shift
161
165
  end
162
- until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
163
- timeout_second -= 0.1
166
+ until @@input.wait_readable(0.01)
167
+ timeout_second -= 0.01
164
168
  return nil if timeout_second <= 0
165
- Reline.core.line_editor.resize
169
+
170
+ Reline.core.line_editor.handle_signal
166
171
  end
172
+ c = @@input.getbyte
167
173
  (c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
168
174
  rescue Errno::EIO
169
175
  # Maybe the I/O has been closed.
@@ -309,7 +315,7 @@ class Reline::ANSI
309
315
  end
310
316
 
311
317
  def self.hide_cursor
312
- if Reline::Terminfo.enabled?
318
+ if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
313
319
  begin
314
320
  @@output.write Reline::Terminfo.tigetstr('civis')
315
321
  rescue Reline::Terminfo::TerminfoError
@@ -321,7 +327,7 @@ class Reline::ANSI
321
327
  end
322
328
 
323
329
  def self.show_cursor
324
- if Reline::Terminfo.enabled?
330
+ if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
325
331
  begin
326
332
  @@output.write Reline::Terminfo.tigetstr('cnorm')
327
333
  rescue Reline::Terminfo::TerminfoError
@@ -46,6 +46,7 @@ class Reline::GeneralIO
46
46
  end
47
47
  c = nil
48
48
  loop do
49
+ Reline.core.line_editor.handle_signal
49
50
  result = @@input.wait_readable(0.1)
50
51
  next if result.nil?
51
52
  c = @@input.read(1)
@@ -49,13 +49,13 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
49
49
  # 23 ^W
50
50
  :em_kill_region,
51
51
  # 24 ^X
52
- :ed_sequence_lead_in,
52
+ :ed_unassigned,
53
53
  # 25 ^Y
54
54
  :em_yank,
55
55
  # 26 ^Z
56
56
  :ed_ignore,
57
57
  # 27 ^[
58
- :em_meta_next,
58
+ :ed_unassigned,
59
59
  # 28 ^\
60
60
  :ed_ignore,
61
61
  # 29 ^]
@@ -319,9 +319,9 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
319
319
  # 158 M-^^
320
320
  :ed_unassigned,
321
321
  # 159 M-^_
322
- :em_copy_prev_word,
323
- # 160 M-SPACE
324
322
  :ed_unassigned,
323
+ # 160 M-SPACE
324
+ :em_set_mark,
325
325
  # 161 M-!
326
326
  :ed_unassigned,
327
327
  # 162 M-"
@@ -415,7 +415,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
415
415
  # 206 M-N
416
416
  :vi_search_next,
417
417
  # 207 M-O
418
- :ed_sequence_lead_in,
418
+ :ed_unassigned,
419
419
  # 208 M-P
420
420
  :vi_search_prev,
421
421
  # 209 M-Q
@@ -431,15 +431,15 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
431
431
  # 214 M-V
432
432
  :ed_unassigned,
433
433
  # 215 M-W
434
- :em_copy_region,
434
+ :ed_unassigned,
435
435
  # 216 M-X
436
- :ed_command,
437
- # 217 M-Y
438
436
  :ed_unassigned,
437
+ # 217 M-Y
438
+ :em_yank_pop,
439
439
  # 218 M-Z
440
440
  :ed_unassigned,
441
441
  # 219 M-[
442
- :ed_sequence_lead_in,
442
+ :ed_unassigned,
443
443
  # 220 M-\
444
444
  :ed_unassigned,
445
445
  # 221 M-]
@@ -495,9 +495,9 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
495
495
  # 246 M-v
496
496
  :ed_unassigned,
497
497
  # 247 M-w
498
- :em_copy_region,
498
+ :ed_unassigned,
499
499
  # 248 M-x
500
- :ed_command,
500
+ :ed_unassigned,
501
501
  # 249 M-y
502
502
  :ed_unassigned,
503
503
  # 250 M-z
@@ -17,7 +17,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
17
17
  # 7 ^G
18
18
  :ed_unassigned,
19
19
  # 8 ^H
20
- :ed_unassigned,
20
+ :ed_prev_char,
21
21
  # 9 ^I
22
22
  :ed_unassigned,
23
23
  # 10 ^J
@@ -41,7 +41,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
41
41
  # 19 ^S
42
42
  :ed_ignore,
43
43
  # 20 ^T
44
- :ed_unassigned,
44
+ :ed_transpose_chars,
45
45
  # 21 ^U
46
46
  :vi_kill_line_prev,
47
47
  # 22 ^V
@@ -51,7 +51,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
51
51
  # 24 ^X
52
52
  :ed_unassigned,
53
53
  # 25 ^Y
54
- :ed_unassigned,
54
+ :em_yank,
55
55
  # 26 ^Z
56
56
  :ed_unassigned,
57
57
  # 27 ^[
@@ -75,7 +75,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
75
75
  # 36 $
76
76
  :ed_move_to_end,
77
77
  # 37 %
78
- :vi_match,
78
+ :ed_unassigned,
79
79
  # 38 &
80
80
  :ed_unassigned,
81
81
  # 39 '
@@ -89,11 +89,11 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
89
89
  # 43 +
90
90
  :ed_next_history,
91
91
  # 44 ,
92
- :vi_repeat_prev_char,
92
+ :ed_unassigned,
93
93
  # 45 -
94
94
  :ed_prev_history,
95
95
  # 46 .
96
- :vi_redo,
96
+ :ed_unassigned,
97
97
  # 47 /
98
98
  :vi_search_prev,
99
99
  # 48 0
@@ -117,9 +117,9 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
117
117
  # 57 9
118
118
  :ed_argument_digit,
119
119
  # 58 :
120
- :ed_command,
120
+ :ed_unassigned,
121
121
  # 59 ;
122
- :vi_repeat_next_char,
122
+ :ed_unassigned,
123
123
  # 60 <
124
124
  :ed_unassigned,
125
125
  # 61 =
@@ -157,21 +157,21 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
157
157
  # 77 M
158
158
  :ed_unassigned,
159
159
  # 78 N
160
- :vi_repeat_search_prev,
160
+ :ed_unassigned,
161
161
  # 79 O
162
- :ed_sequence_lead_in,
162
+ :ed_unassigned,
163
163
  # 80 P
164
164
  :vi_paste_prev,
165
165
  # 81 Q
166
166
  :ed_unassigned,
167
167
  # 82 R
168
- :vi_replace_mode,
168
+ :ed_unassigned,
169
169
  # 83 S
170
- :vi_substitute_line,
170
+ :ed_unassigned,
171
171
  # 84 T
172
172
  :vi_to_prev_char,
173
173
  # 85 U
174
- :vi_undo_line,
174
+ :ed_unassigned,
175
175
  # 86 V
176
176
  :ed_unassigned,
177
177
  # 87 W
@@ -179,11 +179,11 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
179
179
  # 88 X
180
180
  :ed_delete_prev_char,
181
181
  # 89 Y
182
- :vi_yank_end,
182
+ :ed_unassigned,
183
183
  # 90 Z
184
184
  :ed_unassigned,
185
185
  # 91 [
186
- :ed_sequence_lead_in,
186
+ :ed_unassigned,
187
187
  # 92 \
188
188
  :ed_unassigned,
189
189
  # 93 ]
@@ -191,7 +191,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
191
191
  # 94 ^
192
192
  :vi_first_print,
193
193
  # 95 _
194
- :vi_history_word,
194
+ :ed_unassigned,
195
195
  # 96 `
196
196
  :ed_unassigned,
197
197
  # 97 a
@@ -221,7 +221,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
221
221
  # 109 m
222
222
  :ed_unassigned,
223
223
  # 110 n
224
- :vi_repeat_search_next,
224
+ :ed_unassigned,
225
225
  # 111 o
226
226
  :ed_unassigned,
227
227
  # 112 p
@@ -231,11 +231,11 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
231
231
  # 114 r
232
232
  :vi_replace_char,
233
233
  # 115 s
234
- :vi_substitute_char,
234
+ :ed_unassigned,
235
235
  # 116 t
236
236
  :vi_to_next_char,
237
237
  # 117 u
238
- :vi_undo,
238
+ :ed_unassigned,
239
239
  # 118 v
240
240
  :vi_histedit,
241
241
  # 119 w
@@ -253,9 +253,9 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
253
253
  # 125 }
254
254
  :ed_unassigned,
255
255
  # 126 ~
256
- :vi_change_case,
257
- # 127 ^?
258
256
  :ed_unassigned,
257
+ # 127 ^?
258
+ :em_delete_prev_char,
259
259
  # 128 M-^@
260
260
  :ed_unassigned,
261
261
  # 129 M-^A
@@ -415,7 +415,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
415
415
  # 206 M-N
416
416
  :ed_unassigned,
417
417
  # 207 M-O
418
- :ed_sequence_lead_in,
418
+ :ed_unassigned,
419
419
  # 208 M-P
420
420
  :ed_unassigned,
421
421
  # 209 M-Q
@@ -439,7 +439,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
439
439
  # 218 M-Z
440
440
  :ed_unassigned,
441
441
  # 219 M-[
442
- :ed_sequence_lead_in,
442
+ :ed_unassigned,
443
443
  # 220 M-\
444
444
  :ed_unassigned,
445
445
  # 221 M-]
@@ -41,7 +41,7 @@ class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
41
41
  # 19 ^S
42
42
  :vi_search_next,
43
43
  # 20 ^T
44
- :ed_insert,
44
+ :ed_transpose_chars,
45
45
  # 21 ^U
46
46
  :vi_kill_line_prev,
47
47
  # 22 ^V
@@ -51,7 +51,7 @@ class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
51
51
  # 24 ^X
52
52
  :ed_insert,
53
53
  # 25 ^Y
54
- :ed_insert,
54
+ :em_yank,
55
55
  # 26 ^Z
56
56
  :ed_insert,
57
57
  # 27 ^[
@@ -33,23 +33,42 @@ class Reline::LineEditor
33
33
  vi_next_big_word
34
34
  vi_prev_big_word
35
35
  vi_end_big_word
36
- vi_repeat_next_char
37
- vi_repeat_prev_char
38
36
  }
39
37
 
40
38
  module CompletionState
41
39
  NORMAL = :normal
42
40
  COMPLETION = :completion
43
41
  MENU = :menu
44
- JOURNEY = :journey
45
42
  MENU_WITH_PERFECT_MATCH = :menu_with_perfect_match
46
43
  PERFECT_MATCH = :perfect_match
47
44
  end
48
45
 
49
46
  RenderedScreen = Struct.new(:base_y, :lines, :cursor_y, keyword_init: true)
50
47
 
51
- CompletionJourneyData = Struct.new(:preposing, :postposing, :list, :pointer)
52
- MenuInfo = Struct.new(:target, :list)
48
+ CompletionJourneyState = Struct.new(:line_index, :pre, :target, :post, :list, :pointer)
49
+
50
+ class MenuInfo
51
+ attr_reader :list
52
+
53
+ def initialize(list)
54
+ @list = list
55
+ end
56
+
57
+ def lines(screen_width)
58
+ return [] if @list.empty?
59
+
60
+ list = @list.sort
61
+ sizes = list.map { |item| Reline::Unicode.calculate_width(item) }
62
+ item_width = sizes.max + 2
63
+ num_cols = [screen_width / item_width, 1].max
64
+ num_rows = list.size.fdiv(num_cols).ceil
65
+ list_with_padding = list.zip(sizes).map { |item, size| item + ' ' * (item_width - size) }
66
+ aligned = (list_with_padding + [nil] * (num_rows * num_cols - list_with_padding.size)).each_slice(num_rows).to_a.transpose
67
+ aligned.map do |row|
68
+ row.join.rstrip
69
+ end
70
+ end
71
+ end
53
72
 
54
73
  MINIMUM_SCROLLBAR_HEIGHT = 1
55
74
 
@@ -117,9 +136,6 @@ class Reline::LineEditor
117
136
  @screen_size = Reline::IOGate.get_screen_size
118
137
  reset_variables(prompt, encoding: encoding)
119
138
  @rendered_screen.base_y = Reline::IOGate.cursor_pos.y
120
- Reline::IOGate.set_winch_handler do
121
- @resized = true
122
- end
123
139
  if ENV.key?('RELINE_ALT_SCROLLBAR')
124
140
  @full_block = '::'
125
141
  @upper_half_block = "''"
@@ -143,7 +159,12 @@ class Reline::LineEditor
143
159
  end
144
160
  end
145
161
 
146
- def resize
162
+ def handle_signal
163
+ handle_interrupted
164
+ handle_resized
165
+ end
166
+
167
+ private def handle_resized
147
168
  return unless @resized
148
169
 
149
170
  @screen_size = Reline::IOGate.get_screen_size
@@ -156,25 +177,35 @@ class Reline::LineEditor
156
177
  render_differential
157
178
  end
158
179
 
180
+ private def handle_interrupted
181
+ return unless @interrupted
182
+
183
+ @interrupted = false
184
+ clear_dialogs
185
+ scrolldown = render_differential
186
+ Reline::IOGate.scroll_down scrolldown
187
+ Reline::IOGate.move_cursor_column 0
188
+ @rendered_screen.lines = []
189
+ @rendered_screen.cursor_y = 0
190
+ case @old_trap
191
+ when 'DEFAULT', 'SYSTEM_DEFAULT'
192
+ raise Interrupt
193
+ when 'IGNORE'
194
+ # Do nothing
195
+ when 'EXIT'
196
+ exit
197
+ else
198
+ @old_trap.call if @old_trap.respond_to?(:call)
199
+ end
200
+ end
201
+
159
202
  def set_signal_handlers
160
- @old_trap = Signal.trap('INT') {
161
- clear_dialogs
162
- scrolldown = render_differential
163
- Reline::IOGate.scroll_down scrolldown
164
- Reline::IOGate.move_cursor_column 0
165
- @rendered_screen.lines = []
166
- @rendered_screen.cursor_y = 0
167
- case @old_trap
168
- when 'DEFAULT', 'SYSTEM_DEFAULT'
169
- raise Interrupt
170
- when 'IGNORE'
171
- # Do nothing
172
- when 'EXIT'
173
- exit
174
- else
175
- @old_trap.call if @old_trap.respond_to?(:call)
176
- end
177
- }
203
+ Reline::IOGate.set_winch_handler do
204
+ @resized = true
205
+ end
206
+ @old_trap = Signal.trap('INT') do
207
+ @interrupted = true
208
+ end
178
209
  end
179
210
 
180
211
  def finalize
@@ -191,16 +222,16 @@ class Reline::LineEditor
191
222
  @encoding = encoding
192
223
  @is_multiline = false
193
224
  @finished = false
194
- @cleared = false
195
225
  @history_pointer = nil
196
226
  @kill_ring ||= Reline::KillRing.new
197
227
  @vi_clipboard = ''
198
228
  @vi_arg = nil
199
229
  @waiting_proc = nil
200
- @waiting_operator_proc = nil
201
- @waiting_operator_vi_arg = nil
202
- @completion_journey_data = nil
230
+ @vi_waiting_operator = nil
231
+ @vi_waiting_operator_arg = nil
232
+ @completion_journey_state = nil
203
233
  @completion_state = CompletionState::NORMAL
234
+ @completion_occurs = false
204
235
  @perfect_matched = nil
205
236
  @menu_info = nil
206
237
  @searching_prompt = nil
@@ -213,6 +244,7 @@ class Reline::LineEditor
213
244
  @in_pasting = false
214
245
  @auto_indent_proc = nil
215
246
  @dialogs = []
247
+ @interrupted = false
216
248
  @resized = false
217
249
  @cache = {}
218
250
  @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0)
@@ -458,7 +490,7 @@ class Reline::LineEditor
458
490
  [[0, Reline::Unicode.calculate_width(l, true), l]]
459
491
  end
460
492
  if @menu_info
461
- @menu_info.list.sort!.each do |item|
493
+ @menu_info.lines(screen_width).each do |item|
462
494
  new_lines << [[0, Reline::Unicode.calculate_width(item), item]]
463
495
  end
464
496
  @menu_info = nil # TODO: do not change state here
@@ -508,10 +540,6 @@ class Reline::LineEditor
508
540
  new_lines.size - y
509
541
  end
510
542
 
511
- def current_row
512
- wrapped_lines.flatten[wrapped_cursor_y]
513
- end
514
-
515
543
  def upper_space_height(wrapped_cursor_y)
516
544
  wrapped_cursor_y - screen_scroll_top
517
545
  end
@@ -520,23 +548,13 @@ class Reline::LineEditor
520
548
  screen_height - wrapped_cursor_y + screen_scroll_top - @rendered_screen.base_y - 1
521
549
  end
522
550
 
523
- def handle_cleared
524
- return unless @cleared
525
-
526
- @cleared = false
527
- Reline::IOGate.clear_screen
528
- @screen_size = Reline::IOGate.get_screen_size
529
- @rendered_screen.lines = []
530
- @rendered_screen.base_y = 0
531
- @rendered_screen.cursor_y = 0
532
- end
533
-
534
551
  def rerender
535
- handle_cleared
536
552
  render_differential unless @in_pasting
537
553
  end
538
554
 
539
555
  class DialogProcScope
556
+ CompletionJourneyData = Struct.new(:preposing, :postposing, :list, :pointer)
557
+
540
558
  def initialize(line_editor, config, proc_to_exec, context)
541
559
  @line_editor = line_editor
542
560
  @config = config
@@ -600,7 +618,7 @@ class Reline::LineEditor
600
618
  end
601
619
 
602
620
  def completion_journey_data
603
- @line_editor.instance_variable_get(:@completion_journey_data)
621
+ @line_editor.dialog_proc_scope_completion_journey_data
604
622
  end
605
623
 
606
624
  def config
@@ -771,7 +789,7 @@ class Reline::LineEditor
771
789
  if after = @output_modifier_proc&.call("#{before.join("\n")}\n", complete: complete)
772
790
  after.lines("\n").map { |l| l.chomp('') }
773
791
  else
774
- before
792
+ before.map { |l| Reline::Unicode.escape_for_print(l) }
775
793
  end
776
794
  end
777
795
 
@@ -779,8 +797,8 @@ class Reline::LineEditor
779
797
  @config.editing_mode
780
798
  end
781
799
 
782
- private def menu(target, list)
783
- @menu_info = MenuInfo.new(target, list)
800
+ private def menu(_target, list)
801
+ @menu_info = MenuInfo.new(list)
784
802
  end
785
803
 
786
804
  private def complete_internal_proc(list, is_menu)
@@ -829,9 +847,9 @@ class Reline::LineEditor
829
847
  [target, preposing, completed, postposing]
830
848
  end
831
849
 
832
- private def complete(list, just_show_list = false)
850
+ private def complete(list, just_show_list)
833
851
  case @completion_state
834
- when CompletionState::NORMAL, CompletionState::JOURNEY
852
+ when CompletionState::NORMAL
835
853
  @completion_state = CompletionState::COMPLETION
836
854
  when CompletionState::PERFECT_MATCH
837
855
  @dig_perfect_match_proc&.(@perfect_matched)
@@ -871,80 +889,64 @@ class Reline::LineEditor
871
889
  end
872
890
  end
873
891
 
874
- private def move_completed_list(list, direction)
875
- case @completion_state
876
- when CompletionState::NORMAL, CompletionState::COMPLETION,
877
- CompletionState::MENU, CompletionState::MENU_WITH_PERFECT_MATCH
878
- @completion_state = CompletionState::JOURNEY
879
- result = retrieve_completion_block
880
- return if result.nil?
881
- preposing, target, postposing = result
882
- @completion_journey_data = CompletionJourneyData.new(
883
- preposing, postposing,
884
- [target] + list.select{ |item| item.start_with?(target) }, 0)
885
- if @completion_journey_data.list.size == 1
886
- @completion_journey_data.pointer = 0
887
- else
888
- case direction
889
- when :up
890
- @completion_journey_data.pointer = @completion_journey_data.list.size - 1
891
- when :down
892
- @completion_journey_data.pointer = 1
893
- end
894
- end
895
- @completion_state = CompletionState::JOURNEY
896
- else
897
- case direction
898
- when :up
899
- @completion_journey_data.pointer -= 1
900
- if @completion_journey_data.pointer < 0
901
- @completion_journey_data.pointer = @completion_journey_data.list.size - 1
902
- end
903
- when :down
904
- @completion_journey_data.pointer += 1
905
- if @completion_journey_data.pointer >= @completion_journey_data.list.size
906
- @completion_journey_data.pointer = 0
907
- end
908
- end
892
+ def dialog_proc_scope_completion_journey_data
893
+ return nil unless @completion_journey_state
894
+ line_index = @completion_journey_state.line_index
895
+ pre_lines = @buffer_of_lines[0...line_index].map { |line| line + "\n" }
896
+ post_lines = @buffer_of_lines[(line_index + 1)..-1].map { |line| line + "\n" }
897
+ DialogProcScope::CompletionJourneyData.new(
898
+ pre_lines.join + @completion_journey_state.pre,
899
+ @completion_journey_state.post + post_lines.join,
900
+ @completion_journey_state.list,
901
+ @completion_journey_state.pointer
902
+ )
903
+ end
904
+
905
+ private def move_completed_list(direction)
906
+ @completion_journey_state ||= retrieve_completion_journey_state
907
+ return false unless @completion_journey_state
908
+
909
+ if (delta = { up: -1, down: +1 }[direction])
910
+ @completion_journey_state.pointer = (@completion_journey_state.pointer + delta) % @completion_journey_state.list.size
909
911
  end
910
- completed = @completion_journey_data.list[@completion_journey_data.pointer]
911
- line_to_pointer = (@completion_journey_data.preposing + completed).split("\n")[@line_index] || String.new(encoding: @encoding)
912
- new_line = line_to_pointer + (@completion_journey_data.postposing.split("\n").first || '')
913
- set_current_line(new_line, line_to_pointer.bytesize)
912
+ completed = @completion_journey_state.list[@completion_journey_state.pointer]
913
+ set_current_line(@completion_journey_state.pre + completed + @completion_journey_state.post, @completion_journey_state.pre.bytesize + completed.bytesize)
914
+ true
915
+ end
916
+
917
+ private def retrieve_completion_journey_state
918
+ preposing, target, postposing = retrieve_completion_block
919
+ list = call_completion_proc
920
+ return unless list.is_a?(Array)
921
+
922
+ candidates = list.select{ |item| item.start_with?(target) }
923
+ return if candidates.empty?
924
+
925
+ pre = preposing.split("\n", -1).last || ''
926
+ post = postposing.split("\n", -1).first || ''
927
+ CompletionJourneyState.new(
928
+ @line_index, pre, target, post, [target] + candidates, 0
929
+ )
914
930
  end
915
931
 
916
932
  private def run_for_operators(key, method_symbol, &block)
917
- if @waiting_operator_proc
933
+ if @vi_waiting_operator
918
934
  if VI_MOTIONS.include?(method_symbol)
919
935
  old_byte_pointer = @byte_pointer
920
- @vi_arg = @waiting_operator_vi_arg if @waiting_operator_vi_arg&.> 1
936
+ @vi_arg = (@vi_arg || 1) * @vi_waiting_operator_arg
921
937
  block.(true)
922
938
  unless @waiting_proc
923
939
  byte_pointer_diff = @byte_pointer - old_byte_pointer
924
940
  @byte_pointer = old_byte_pointer
925
- @waiting_operator_proc.(byte_pointer_diff)
926
- else
927
- old_waiting_proc = @waiting_proc
928
- old_waiting_operator_proc = @waiting_operator_proc
929
- current_waiting_operator_proc = @waiting_operator_proc
930
- @waiting_proc = proc { |k|
931
- old_byte_pointer = @byte_pointer
932
- old_waiting_proc.(k)
933
- byte_pointer_diff = @byte_pointer - old_byte_pointer
934
- @byte_pointer = old_byte_pointer
935
- current_waiting_operator_proc.(byte_pointer_diff)
936
- @waiting_operator_proc = old_waiting_operator_proc
937
- }
941
+ send(@vi_waiting_operator, byte_pointer_diff)
942
+ cleanup_waiting
938
943
  end
939
944
  else
940
945
  # Ignores operator when not motion is given.
941
946
  block.(false)
947
+ cleanup_waiting
942
948
  end
943
- @waiting_operator_proc = nil
944
- @waiting_operator_vi_arg = nil
945
- if @vi_arg
946
- @vi_arg = nil
947
- end
949
+ @vi_arg = nil
948
950
  else
949
951
  block.(false)
950
952
  end
@@ -961,7 +963,7 @@ class Reline::LineEditor
961
963
  end
962
964
 
963
965
  def wrap_method_call(method_symbol, method_obj, key, with_operator = false)
964
- if @config.editing_mode_is?(:emacs, :vi_insert) and @waiting_proc.nil? and @waiting_operator_proc.nil?
966
+ if @config.editing_mode_is?(:emacs, :vi_insert) and @vi_waiting_operator.nil?
965
967
  not_insertion = method_symbol != :ed_insert
966
968
  process_insert(force: not_insertion)
967
969
  end
@@ -980,11 +982,32 @@ class Reline::LineEditor
980
982
  end
981
983
  end
982
984
 
985
+ private def cleanup_waiting
986
+ @waiting_proc = nil
987
+ @vi_waiting_operator = nil
988
+ @vi_waiting_operator_arg = nil
989
+ @searching_prompt = nil
990
+ @drop_terminate_spaces = false
991
+ end
992
+
983
993
  private def process_key(key, method_symbol)
994
+ if key.is_a?(Symbol)
995
+ cleanup_waiting
996
+ elsif @waiting_proc
997
+ old_byte_pointer = @byte_pointer
998
+ @waiting_proc.call(key)
999
+ if @vi_waiting_operator
1000
+ byte_pointer_diff = @byte_pointer - old_byte_pointer
1001
+ @byte_pointer = old_byte_pointer
1002
+ send(@vi_waiting_operator, byte_pointer_diff)
1003
+ cleanup_waiting
1004
+ end
1005
+ @kill_ring.process
1006
+ return
1007
+ end
1008
+
984
1009
  if method_symbol and respond_to?(method_symbol, true)
985
1010
  method_obj = method(method_symbol)
986
- else
987
- method_obj = nil
988
1011
  end
989
1012
  if method_symbol and key.is_a?(Symbol)
990
1013
  if @vi_arg and argumentable?(method_obj)
@@ -1006,8 +1029,6 @@ class Reline::LineEditor
1006
1029
  run_for_operators(key, method_symbol) do |with_operator|
1007
1030
  wrap_method_call(method_symbol, method_obj, key, with_operator)
1008
1031
  end
1009
- elsif @waiting_proc
1010
- @waiting_proc.(key)
1011
1032
  elsif method_obj
1012
1033
  wrap_method_call(method_symbol, method_obj, key)
1013
1034
  else
@@ -1018,9 +1039,6 @@ class Reline::LineEditor
1018
1039
  @vi_arg = nil
1019
1040
  end
1020
1041
  end
1021
- elsif @waiting_proc
1022
- @waiting_proc.(key)
1023
- @kill_ring.process
1024
1042
  elsif method_obj
1025
1043
  if method_symbol == :ed_argument_digit
1026
1044
  wrap_method_call(method_symbol, method_obj, key)
@@ -1097,52 +1115,51 @@ class Reline::LineEditor
1097
1115
  end
1098
1116
  old_lines = @buffer_of_lines.dup
1099
1117
  @first_char = false
1100
- completion_occurs = false
1118
+ @completion_occurs = false
1101
1119
  if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord
1102
- unless @config.disable_completion
1103
- result = call_completion_proc
1104
- if result.is_a?(Array)
1105
- completion_occurs = true
1106
- process_insert
1107
- if @config.autocompletion
1108
- move_completed_list(result, :down)
1109
- else
1110
- complete(result)
1120
+ if !@config.disable_completion
1121
+ process_insert(force: true)
1122
+ if @config.autocompletion
1123
+ @completion_state = CompletionState::NORMAL
1124
+ @completion_occurs = move_completed_list(:down)
1125
+ else
1126
+ @completion_journey_state = nil
1127
+ result = call_completion_proc
1128
+ if result.is_a?(Array)
1129
+ @completion_occurs = true
1130
+ complete(result, false)
1111
1131
  end
1112
1132
  end
1113
1133
  end
1114
- elsif @config.editing_mode_is?(:emacs, :vi_insert) and key.char == :completion_journey_up
1115
- if not @config.disable_completion and @config.autocompletion
1116
- result = call_completion_proc
1117
- if result.is_a?(Array)
1118
- completion_occurs = true
1119
- process_insert
1120
- move_completed_list(result, :up)
1121
- end
1122
- end
1123
- elsif not @config.disable_completion and @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char)
1124
- unless @config.disable_completion
1125
- result = call_completion_proc
1126
- if result.is_a?(Array)
1127
- completion_occurs = true
1128
- process_insert
1129
- move_completed_list(result, "\C-p".ord == key.char ? :up : :down)
1130
- end
1134
+ elsif @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char)
1135
+ # In vi mode, move completed list even if autocompletion is off
1136
+ if not @config.disable_completion
1137
+ process_insert(force: true)
1138
+ @completion_state = CompletionState::NORMAL
1139
+ @completion_occurs = move_completed_list("\C-p".ord == key.char ? :up : :down)
1131
1140
  end
1132
1141
  elsif Symbol === key.char and respond_to?(key.char, true)
1133
1142
  process_key(key.char, key.char)
1134
1143
  else
1135
1144
  normal_char(key)
1136
1145
  end
1137
- unless completion_occurs
1146
+ unless @completion_occurs
1138
1147
  @completion_state = CompletionState::NORMAL
1139
- @completion_journey_data = nil
1148
+ @completion_journey_state = nil
1140
1149
  end
1150
+
1141
1151
  if @in_pasting
1142
1152
  clear_dialogs
1143
- else
1144
- return old_lines != @buffer_of_lines
1153
+ return
1154
+ end
1155
+
1156
+ modified = old_lines != @buffer_of_lines
1157
+ if !@completion_occurs && modified && !@config.disable_completion && @config.autocompletion
1158
+ # Auto complete starts only when edited
1159
+ process_insert(force: true)
1160
+ @completion_journey_state = retrieve_completion_journey_state
1145
1161
  end
1162
+ modified
1146
1163
  end
1147
1164
 
1148
1165
  def scroll_into_view
@@ -1194,10 +1211,11 @@ class Reline::LineEditor
1194
1211
  new_indent = @auto_indent_proc.(@buffer_of_lines.take(line_index + 1).push(''), line_index, byte_pointer, add_newline)
1195
1212
  return unless new_indent
1196
1213
 
1197
- @buffer_of_lines[line_index] = ' ' * new_indent + line.lstrip
1214
+ new_line = ' ' * new_indent + line.lstrip
1215
+ @buffer_of_lines[line_index] = new_line
1198
1216
  if @line_index == line_index
1199
- old_indent = line[/\A */].size
1200
- @byte_pointer = [@byte_pointer + new_indent - old_indent, 0].max
1217
+ indent_diff = new_line.bytesize - line.bytesize
1218
+ @byte_pointer = [@byte_pointer + indent_diff, 0].max
1201
1219
  end
1202
1220
  end
1203
1221
 
@@ -1405,6 +1423,14 @@ class Reline::LineEditor
1405
1423
  end
1406
1424
  end
1407
1425
 
1426
+ private def completion_journey_up(key)
1427
+ if not @config.disable_completion and @config.autocompletion
1428
+ @completion_state = CompletionState::NORMAL
1429
+ @completion_occurs = move_completed_list(:up)
1430
+ end
1431
+ end
1432
+ alias_method :menu_complete_backward, :completion_journey_up
1433
+
1408
1434
  # Editline:: +ed-unassigned+ This editor command always results in an error.
1409
1435
  # GNU Readline:: There is no corresponding macro.
1410
1436
  private def ed_unassigned(key) end # do nothing
@@ -1506,6 +1532,7 @@ class Reline::LineEditor
1506
1532
  @byte_pointer = 0
1507
1533
  end
1508
1534
  alias_method :beginning_of_line, :ed_move_to_beg
1535
+ alias_method :vi_zero, :ed_move_to_beg
1509
1536
 
1510
1537
  private def ed_move_to_end(key)
1511
1538
  @byte_pointer = 0
@@ -2020,7 +2047,7 @@ class Reline::LineEditor
2020
2047
  private def em_delete_or_list(key)
2021
2048
  if current_line.empty? or @byte_pointer < current_line.bytesize
2022
2049
  em_delete(key)
2023
- else # show completed list
2050
+ elsif !@config.autocompletion # show completed list
2024
2051
  result = call_completion_proc
2025
2052
  if result.is_a?(Array)
2026
2053
  complete(result, true)
@@ -2046,7 +2073,11 @@ class Reline::LineEditor
2046
2073
  alias_method :yank_pop, :em_yank_pop
2047
2074
 
2048
2075
  private def ed_clear_screen(key)
2049
- @cleared = true
2076
+ Reline::IOGate.clear_screen
2077
+ @screen_size = Reline::IOGate.get_screen_size
2078
+ @rendered_screen.lines = []
2079
+ @rendered_screen.base_y = 0
2080
+ @rendered_screen.cursor_y = 0
2050
2081
  end
2051
2082
  alias_method :clear_screen, :ed_clear_screen
2052
2083
 
@@ -2287,50 +2318,63 @@ class Reline::LineEditor
2287
2318
  copy_for_vi(deleted)
2288
2319
  end
2289
2320
 
2290
- private def vi_zero(key)
2291
- @byte_pointer = 0
2321
+ private def vi_change_meta(key, arg: nil)
2322
+ if @vi_waiting_operator
2323
+ set_current_line('', 0) if @vi_waiting_operator == :vi_change_meta_confirm && arg.nil?
2324
+ @vi_waiting_operator = nil
2325
+ @vi_waiting_operator_arg = nil
2326
+ else
2327
+ @drop_terminate_spaces = true
2328
+ @vi_waiting_operator = :vi_change_meta_confirm
2329
+ @vi_waiting_operator_arg = arg || 1
2330
+ end
2292
2331
  end
2293
2332
 
2294
- private def vi_change_meta(key, arg: 1)
2295
- @drop_terminate_spaces = true
2296
- @waiting_operator_proc = proc { |byte_pointer_diff|
2297
- if byte_pointer_diff > 0
2298
- line, cut = byteslice!(current_line, @byte_pointer, byte_pointer_diff)
2299
- elsif byte_pointer_diff < 0
2300
- line, cut = byteslice!(current_line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff)
2301
- end
2302
- set_current_line(line)
2303
- copy_for_vi(cut)
2304
- @byte_pointer += byte_pointer_diff if byte_pointer_diff < 0
2305
- @config.editing_mode = :vi_insert
2306
- @drop_terminate_spaces = false
2307
- }
2308
- @waiting_operator_vi_arg = arg
2333
+ private def vi_change_meta_confirm(byte_pointer_diff)
2334
+ vi_delete_meta_confirm(byte_pointer_diff)
2335
+ @config.editing_mode = :vi_insert
2336
+ @drop_terminate_spaces = false
2309
2337
  end
2310
2338
 
2311
- private def vi_delete_meta(key, arg: 1)
2312
- @waiting_operator_proc = proc { |byte_pointer_diff|
2313
- if byte_pointer_diff > 0
2314
- line, cut = byteslice!(current_line, @byte_pointer, byte_pointer_diff)
2315
- elsif byte_pointer_diff < 0
2316
- line, cut = byteslice!(current_line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff)
2317
- end
2318
- copy_for_vi(cut)
2319
- set_current_line(line || '', @byte_pointer + (byte_pointer_diff < 0 ? byte_pointer_diff : 0))
2320
- }
2321
- @waiting_operator_vi_arg = arg
2339
+ private def vi_delete_meta(key, arg: nil)
2340
+ if @vi_waiting_operator
2341
+ set_current_line('', 0) if @vi_waiting_operator == :vi_delete_meta_confirm && arg.nil?
2342
+ @vi_waiting_operator = nil
2343
+ @vi_waiting_operator_arg = nil
2344
+ else
2345
+ @vi_waiting_operator = :vi_delete_meta_confirm
2346
+ @vi_waiting_operator_arg = arg || 1
2347
+ end
2322
2348
  end
2323
2349
 
2324
- private def vi_yank(key, arg: 1)
2325
- @waiting_operator_proc = proc { |byte_pointer_diff|
2326
- if byte_pointer_diff > 0
2327
- cut = current_line.byteslice(@byte_pointer, byte_pointer_diff)
2328
- elsif byte_pointer_diff < 0
2329
- cut = current_line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff)
2330
- end
2331
- copy_for_vi(cut)
2332
- }
2333
- @waiting_operator_vi_arg = arg
2350
+ private def vi_delete_meta_confirm(byte_pointer_diff)
2351
+ if byte_pointer_diff > 0
2352
+ line, cut = byteslice!(current_line, @byte_pointer, byte_pointer_diff)
2353
+ elsif byte_pointer_diff < 0
2354
+ line, cut = byteslice!(current_line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff)
2355
+ end
2356
+ copy_for_vi(cut)
2357
+ set_current_line(line || '', @byte_pointer + (byte_pointer_diff < 0 ? byte_pointer_diff : 0))
2358
+ end
2359
+
2360
+ private def vi_yank(key, arg: nil)
2361
+ if @vi_waiting_operator
2362
+ copy_for_vi(current_line) if @vi_waiting_operator == :vi_yank_confirm && arg.nil?
2363
+ @vi_waiting_operator = nil
2364
+ @vi_waiting_operator_arg = nil
2365
+ else
2366
+ @vi_waiting_operator = :vi_yank_confirm
2367
+ @vi_waiting_operator_arg = arg || 1
2368
+ end
2369
+ end
2370
+
2371
+ private def vi_yank_confirm(byte_pointer_diff)
2372
+ if byte_pointer_diff > 0
2373
+ cut = current_line.byteslice(@byte_pointer, byte_pointer_diff)
2374
+ elsif byte_pointer_diff < 0
2375
+ cut = current_line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff)
2376
+ end
2377
+ copy_for_vi(cut)
2334
2378
  end
2335
2379
 
2336
2380
  private def vi_list_or_eof(key)
@@ -2435,18 +2479,11 @@ class Reline::LineEditor
2435
2479
  end
2436
2480
 
2437
2481
  private def vi_to_column(key, arg: 0)
2438
- current_row_width = calculate_width(current_row)
2439
- @byte_pointer, = current_line.grapheme_clusters.inject([0, 0]) { |total, gc|
2440
- # total has [byte_size, cursor]
2482
+ # Implementing behavior of vi, not Readline's vi-mode.
2483
+ @byte_pointer, = current_line.grapheme_clusters.inject([0, 0]) { |(total_byte_size, total_width), gc|
2441
2484
  mbchar_width = Reline::Unicode.get_mbchar_width(gc)
2442
- if (total.last + mbchar_width) >= arg
2443
- break total
2444
- elsif (total.last + mbchar_width) >= current_row_width
2445
- break total
2446
- else
2447
- total = [total.first + gc.bytesize, total.last + mbchar_width]
2448
- total
2449
- end
2485
+ break [total_byte_size, total_width] if (total_width + mbchar_width) >= arg
2486
+ [total_byte_size + gc.bytesize, total_width + mbchar_width]
2450
2487
  }
2451
2488
  end
2452
2489
 
@@ -2594,6 +2631,11 @@ class Reline::LineEditor
2594
2631
  end
2595
2632
  alias_method :exchange_point_and_mark, :em_exchange_mark
2596
2633
 
2597
- private def em_meta_next(key)
2634
+ private def emacs_editing_mode(key)
2635
+ @config.editing_mode = :emacs
2636
+ end
2637
+
2638
+ private def vi_editing_mode(key)
2639
+ @config.editing_mode = :vi_insert
2598
2640
  end
2599
2641
  end
@@ -80,23 +80,11 @@ module Reline::Terminfo
80
80
  def self.setupterm(term, fildes)
81
81
  errret_int = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT)
82
82
  ret = @setupterm.(term, fildes, errret_int)
83
- errret = errret_int[0, Fiddle::SIZEOF_INT].unpack1('i')
84
83
  case ret
85
84
  when 0 # OK
86
- 0
85
+ @term_supported = true
87
86
  when -1 # ERR
88
- case errret
89
- when 1
90
- raise TerminfoError.new('The terminal is hardcopy, cannot be used for curses applications.')
91
- when 0
92
- raise TerminfoError.new('The terminal could not be found, or that it is a generic type, having too little information for curses applications to run.')
93
- when -1
94
- raise TerminfoError.new('The terminfo database could not be found.')
95
- else # unknown
96
- -1
97
- end
98
- else # unknown
99
- -2
87
+ @term_supported = false
100
88
  end
101
89
  end
102
90
 
@@ -148,9 +136,14 @@ module Reline::Terminfo
148
136
  num
149
137
  end
150
138
 
139
+ # NOTE: This means Fiddle and curses are enabled.
151
140
  def self.enabled?
152
141
  true
153
142
  end
143
+
144
+ def self.term_supported?
145
+ @term_supported
146
+ end
154
147
  end if Reline::Terminfo.curses_dl
155
148
 
156
149
  module Reline::Terminfo
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.5.0'
2
+ VERSION = '0.5.2'
3
3
  end
@@ -259,7 +259,7 @@ class Reline::Windows
259
259
  def self.check_input_event
260
260
  num_of_events = 0.chr * 8
261
261
  while @@output_buf.empty?
262
- Reline.core.line_editor.resize
262
+ Reline.core.line_editor.handle_signal
263
263
  if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec
264
264
  # prevent for background consolemode change
265
265
  @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
data/lib/reline.rb CHANGED
@@ -75,6 +75,7 @@ module Reline
75
75
 
76
76
  def initialize
77
77
  self.output = STDOUT
78
+ @mutex = Mutex.new
78
79
  @dialog_proc_list = {}
79
80
  yield self
80
81
  @completion_quote_character = nil
@@ -219,26 +220,16 @@ module Reline
219
220
 
220
221
  Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() {
221
222
  # autocomplete
222
- return nil unless config.autocompletion
223
- if just_cursor_moving and completion_journey_data.nil?
224
- # Auto complete starts only when edited
225
- return nil
226
- end
227
- pre, target, post = retrieve_completion_block(true)
228
- if target.nil? or target.empty? or (completion_journey_data&.pointer == -1 and target.size <= 3)
229
- return nil
230
- end
231
- if completion_journey_data and completion_journey_data.list
232
- result = completion_journey_data.list.dup
233
- result.shift
234
- pointer = completion_journey_data.pointer - 1
235
- else
236
- result = call_completion_proc_with_checking_args(pre, target, post)
237
- pointer = nil
238
- end
239
- if result and result.size == 1 and result[0] == target and pointer != 0
240
- result = nil
241
- end
223
+ return unless config.autocompletion
224
+
225
+ journey_data = completion_journey_data
226
+ return unless journey_data
227
+
228
+ target = journey_data.list[journey_data.pointer]
229
+ result = journey_data.list.drop(1)
230
+ pointer = journey_data.pointer - 1
231
+ return if target.empty? || (result == [target] && pointer < 0)
232
+
242
233
  target_width = Reline::Unicode.calculate_width(target)
243
234
  x = cursor_pos.x - target_width
244
235
  if x < 0
@@ -264,12 +255,15 @@ module Reline
264
255
  Reline::DEFAULT_DIALOG_CONTEXT = Array.new
265
256
 
266
257
  def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
267
- Reline.update_iogate
268
- io_gate.with_raw_input do
258
+ @mutex.synchronize do
269
259
  unless confirm_multiline_termination
270
260
  raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
271
261
  end
272
- inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
262
+
263
+ Reline.update_iogate
264
+ io_gate.with_raw_input do
265
+ inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
266
+ end
273
267
 
274
268
  whole_buffer = line_editor.whole_buffer.dup
275
269
  whole_buffer.taint if RUBY_VERSION < '2.7'
@@ -288,17 +282,21 @@ module Reline
288
282
  end
289
283
 
290
284
  def readline(prompt = '', add_hist = false)
291
- Reline.update_iogate
292
- inner_readline(prompt, add_hist, false)
285
+ @mutex.synchronize do
286
+ Reline.update_iogate
287
+ io_gate.with_raw_input do
288
+ inner_readline(prompt, add_hist, false)
289
+ end
293
290
 
294
- line = line_editor.line.dup
295
- line.taint if RUBY_VERSION < '2.7'
296
- if add_hist and line and line.chomp("\n").size > 0
297
- Reline::HISTORY << line.chomp("\n")
298
- end
291
+ line = line_editor.line.dup
292
+ line.taint if RUBY_VERSION < '2.7'
293
+ if add_hist and line and line.chomp("\n").size > 0
294
+ Reline::HISTORY << line.chomp("\n")
295
+ end
299
296
 
300
- line_editor.reset_line if line_editor.line.nil?
301
- line
297
+ line_editor.reset_line if line_editor.line.nil?
298
+ line
299
+ end
302
300
  end
303
301
 
304
302
  private def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination)
@@ -365,19 +363,10 @@ module Reline
365
363
  io_gate.move_cursor_column(0)
366
364
  rescue Errno::EIO
367
365
  # Maybe the I/O has been closed.
368
- rescue StandardError => e
369
- line_editor.finalize
370
- io_gate.deprep(otio)
371
- raise e
372
- rescue Exception
373
- # Including Interrupt
366
+ ensure
374
367
  line_editor.finalize
375
368
  io_gate.deprep(otio)
376
- raise
377
369
  end
378
-
379
- line_editor.finalize
380
- io_gate.deprep(otio)
381
370
  end
382
371
 
383
372
  # GNU Readline waits for "keyseq-timeout" milliseconds to see if the ESC
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-25 00:00:00.000000000 Z
11
+ date: 2024-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console