reline 0.5.0.pre.1 → 0.5.0

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: a6fdc2426aceadd0680462674da1132c7042924e9fda18daecd68b82e459a867
4
- data.tar.gz: 5fc586dfacfd1cc5524320b0e3190982098fbdaf541a6ff56f9c153aa828560c
3
+ metadata.gz: 9b325efda8753fa1ecea3b1dabfd685416016ee334876673bf0d965c3a02095d
4
+ data.tar.gz: 4b22612ebce12cc96593f98535bfb9223eebbded388931ccbd8bbdb4d13ce1d1
5
5
  SHA512:
6
- metadata.gz: 052abb950ef133821f1c3bf43f4727e8ef6afe7210fb9a9f56df65ad1a16a96d54cfc519ecbab94c8b5502d8c6976fdfc7b5e87effb4f7b9e15a800ffaefa92f
7
- data.tar.gz: 617b9876da860ac3b08fd659e9ef8e7cda3afc189e496b34cd116d9850bee9ed176e68f129b4ceff6443f3f3992460ef22ddad9d16c2a6dbdf07a3ee020a25e0
6
+ metadata.gz: 29f19adce6163f38399da6119c3605039593d244c7119d601b413279a678cd87a5ad5eba5679f2ea7ccc1bdf7b4743987b2840cf4c0f69fa316c0d2fa84b5f45
7
+ data.tar.gz: be0b1ad84d01936ff721b3a18f196d0ee19817da6baf9200e4e6a96681e4b87594c55d1aa71071fcda63f35c4c8d0aefa7aa7a016c62c538d165e19f82e7d3b8
data/lib/reline/ansi.rb CHANGED
@@ -3,6 +3,8 @@ require 'io/wait'
3
3
  require_relative 'terminfo'
4
4
 
5
5
  class Reline::ANSI
6
+ RESET_COLOR = "\e[0m"
7
+
6
8
  CAPNAME_KEY_BINDINGS = {
7
9
  'khome' => :ed_move_to_beg,
8
10
  'kend' => :ed_move_to_end,
data/lib/reline/face.rb CHANGED
@@ -186,9 +186,9 @@ class Reline::Face
186
186
  conf.define :scrollbar, style: :reset
187
187
  end
188
188
  config(:completion_dialog) do |conf|
189
- conf.define :default, foreground: :white, background: :cyan
190
- conf.define :enhanced, foreground: :white, background: :magenta
191
- conf.define :scrollbar, foreground: :white, background: :cyan
189
+ conf.define :default, foreground: :bright_white, background: :gray
190
+ conf.define :enhanced, foreground: :black, background: :white
191
+ conf.define :scrollbar, foreground: :white, background: :gray
192
192
  end
193
193
  end
194
194
 
@@ -1,6 +1,8 @@
1
1
  require 'io/wait'
2
2
 
3
3
  class Reline::GeneralIO
4
+ RESET_COLOR = '' # Do not send color reset sequence
5
+
4
6
  def self.reset(encoding: nil)
5
7
  @@pasting = false
6
8
  if encoding
@@ -100,14 +102,6 @@ class Reline::GeneralIO
100
102
  @@pasting
101
103
  end
102
104
 
103
- def self.start_pasting
104
- @@pasting = true
105
- end
106
-
107
- def self.finish_pasting
108
- @@pasting = false
109
- end
110
-
111
105
  def self.prep
112
106
  end
113
107
 
@@ -62,7 +62,7 @@ class Reline::History < Array
62
62
  private def check_index(index)
63
63
  index += size if index < 0
64
64
  if index < -2147483648 or 2147483647 < index
65
- raise RangeError.new("integer #{index} too big to convert to `int'")
65
+ raise RangeError.new("integer #{index} too big to convert to 'int'")
66
66
  end
67
67
  # If history_size is negative, history size is unlimited.
68
68
  if @config.history_size.positive?
@@ -14,7 +14,7 @@ class Reline::KillRing
14
14
  end
15
15
 
16
16
  def ==(other)
17
- object_id == other.object_id
17
+ equal?(other)
18
18
  end
19
19
  end
20
20
 
@@ -68,7 +68,7 @@ class Reline::KillRing
68
68
  def append(string, before_p = false)
69
69
  case @state
70
70
  when State::FRESH, State::YANK
71
- @ring << RingPoint.new(string)
71
+ @ring << RingPoint.new(+string)
72
72
  @state = State::CONTINUED
73
73
  when State::CONTINUED, State::PROCESSED
74
74
  if before_p
@@ -46,16 +46,16 @@ class Reline::LineEditor
46
46
  PERFECT_MATCH = :perfect_match
47
47
  end
48
48
 
49
+ RenderedScreen = Struct.new(:base_y, :lines, :cursor_y, keyword_init: true)
50
+
49
51
  CompletionJourneyData = Struct.new(:preposing, :postposing, :list, :pointer)
50
52
  MenuInfo = Struct.new(:target, :list)
51
53
 
52
- PROMPT_LIST_CACHE_TIMEOUT = 0.5
53
54
  MINIMUM_SCROLLBAR_HEIGHT = 1
54
55
 
55
56
  def initialize(config, encoding)
56
57
  @config = config
57
58
  @completion_append_character = ''
58
- @cursor_base_y = 0
59
59
  @screen_size = Reline::IOGate.get_screen_size
60
60
  reset_variables(encoding: encoding)
61
61
  end
@@ -65,6 +65,9 @@ class Reline::LineEditor
65
65
  end
66
66
 
67
67
  def set_pasting_state(in_pasting)
68
+ # While pasting, text to be inserted is stored to @continuous_insertion_buffer.
69
+ # After pasting, this buffer should be force inserted.
70
+ process_insert(force: true) if @in_pasting && !in_pasting
68
71
  @in_pasting = in_pasting
69
72
  end
70
73
 
@@ -82,7 +85,7 @@ class Reline::LineEditor
82
85
  end
83
86
  end
84
87
 
85
- private def check_multiline_prompt(buffer)
88
+ private def check_multiline_prompt(buffer, mode_string)
86
89
  if @vi_arg
87
90
  prompt = "(arg: #{@vi_arg}) "
88
91
  elsif @searching_prompt
@@ -94,7 +97,6 @@ class Reline::LineEditor
94
97
  prompt_list = @prompt_proc.(buffer).map { |pr| pr.gsub("\n", "\\n") }
95
98
  prompt_list.map!{ prompt } if @vi_arg or @searching_prompt
96
99
  prompt_list = [prompt] if prompt_list.empty?
97
- mode_string = check_mode_string
98
100
  prompt_list = prompt_list.map{ |pr| mode_string + pr } if mode_string
99
101
  prompt = prompt_list[@line_index]
100
102
  prompt = prompt_list[0] if prompt.nil?
@@ -106,16 +108,15 @@ class Reline::LineEditor
106
108
  end
107
109
  prompt_list
108
110
  else
109
- mode_string = check_mode_string
110
111
  prompt = mode_string + prompt if mode_string
111
112
  [prompt] * buffer.size
112
113
  end
113
114
  end
114
115
 
115
116
  def reset(prompt = '', encoding:)
116
- @cursor_base_y = Reline::IOGate.cursor_pos.y
117
117
  @screen_size = Reline::IOGate.get_screen_size
118
118
  reset_variables(prompt, encoding: encoding)
119
+ @rendered_screen.base_y = Reline::IOGate.cursor_pos.y
119
120
  Reline::IOGate.set_winch_handler do
120
121
  @resized = true
121
122
  end
@@ -145,27 +146,24 @@ class Reline::LineEditor
145
146
  def resize
146
147
  return unless @resized
147
148
 
148
- Reline::IOGate.hide_cursor
149
149
  @screen_size = Reline::IOGate.get_screen_size
150
150
  @resized = false
151
151
  scroll_into_view
152
- Reline::IOGate.move_cursor_up @cursor_y
153
- @cursor_base_y = Reline::IOGate.cursor_pos.y
154
- @cursor_y = 0
155
- @rendered_screen_cache = nil
152
+ Reline::IOGate.move_cursor_up @rendered_screen.cursor_y
153
+ @rendered_screen.base_y = Reline::IOGate.cursor_pos.y
154
+ @rendered_screen.lines = []
155
+ @rendered_screen.cursor_y = 0
156
156
  render_differential
157
- Reline::IOGate.show_cursor
158
157
  end
159
158
 
160
159
  def set_signal_handlers
161
160
  @old_trap = Signal.trap('INT') {
162
- Reline::IOGate.hide_cursor
163
161
  clear_dialogs
164
162
  scrolldown = render_differential
165
163
  Reline::IOGate.scroll_down scrolldown
166
164
  Reline::IOGate.move_cursor_column 0
167
- @rendered_screen_cache = nil
168
- Reline::IOGate.show_cursor
165
+ @rendered_screen.lines = []
166
+ @rendered_screen.cursor_y = 0
169
167
  case @old_trap
170
168
  when 'DEFAULT', 'SYSTEM_DEFAULT'
171
169
  raise Interrupt
@@ -205,9 +203,9 @@ class Reline::LineEditor
205
203
  @completion_state = CompletionState::NORMAL
206
204
  @perfect_matched = nil
207
205
  @menu_info = nil
208
- @first_prompt = true
209
206
  @searching_prompt = nil
210
207
  @first_char = true
208
+ @just_cursor_moving = false
211
209
  @eof = false
212
210
  @continuous_insertion_buffer = String.new(encoding: @encoding)
213
211
  @scroll_partial_screen = 0
@@ -216,9 +214,8 @@ class Reline::LineEditor
216
214
  @auto_indent_proc = nil
217
215
  @dialogs = []
218
216
  @resized = false
219
- @cursor_y = 0
220
217
  @cache = {}
221
- @rendered_screen_cache = nil
218
+ @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0)
222
219
  reset_line
223
220
  end
224
221
 
@@ -266,20 +263,6 @@ class Reline::LineEditor
266
263
  Reline::Unicode.split_by_width(str, max_width, @encoding)
267
264
  end
268
265
 
269
- private def scroll_down(val)
270
- if @cursor_base_y + @cursor_y + val < screen_height
271
- Reline::IOGate.move_cursor_down(val)
272
- @cursor_y += val
273
- else
274
- move = screen_height - @cursor_base_y - @cursor_y - 1
275
- scroll = val - move
276
- Reline::IOGate.scroll_down(move)
277
- Reline::IOGate.scroll_down(scroll)
278
- @cursor_y += move
279
- @cursor_base_y = [@cursor_base_y - scroll, 0].max
280
- end
281
- end
282
-
283
266
  def current_byte_pointer_cursor
284
267
  calculate_width(current_line.byteslice(0, @byte_pointer))
285
268
  end
@@ -334,8 +317,8 @@ class Reline::LineEditor
334
317
  end
335
318
 
336
319
  def prompt_list
337
- with_cache(__method__, whole_lines, @vi_arg, @searching_prompt) do |lines|
338
- check_multiline_prompt(lines)
320
+ with_cache(__method__, whole_lines, check_mode_string, @vi_arg, @searching_prompt) do |lines, mode_string|
321
+ check_multiline_prompt(lines, mode_string)
339
322
  end
340
323
  end
341
324
 
@@ -387,12 +370,12 @@ class Reline::LineEditor
387
370
  # do nothing
388
371
  elsif level == :blank
389
372
  Reline::IOGate.move_cursor_column base_x
390
- @output.write "\e[0m#{' ' * width}"
373
+ @output.write "#{Reline::IOGate::RESET_COLOR}#{' ' * width}"
391
374
  else
392
375
  x, w, content = new_items[level]
393
376
  content = Reline::Unicode.take_range(content, base_x - x, width) unless x == base_x && w == width
394
377
  Reline::IOGate.move_cursor_column base_x
395
- @output.write "\e[0m#{content}\e[0m"
378
+ @output.write "#{Reline::IOGate::RESET_COLOR}#{content}#{Reline::IOGate::RESET_COLOR}"
396
379
  end
397
380
  base_x += width
398
381
  end
@@ -402,12 +385,14 @@ class Reline::LineEditor
402
385
  end
403
386
  end
404
387
 
405
- def editor_cursor_position
406
- line = ' ' * calculate_width(prompt_list[@line_index], true) + whole_lines[@line_index].byteslice(0, @byte_pointer)
407
- wrapped_line_before_cursor = split_by_width(line, screen_width).first.compact
408
- editor_cursor_y = wrapped_lines[0...@line_index].sum(&:size) + wrapped_line_before_cursor.size - 1
409
- editor_cursor_x = calculate_width(wrapped_line_before_cursor.last)
410
- [editor_cursor_x, editor_cursor_y]
388
+ # Calculate cursor position in word wrapped content.
389
+ def wrapped_cursor_position
390
+ prompt_width = calculate_width(prompt_list[@line_index], true)
391
+ line_before_cursor = whole_lines[@line_index].byteslice(0, @byte_pointer)
392
+ wrapped_line_before_cursor = split_by_width(' ' * prompt_width + line_before_cursor, screen_width).first.compact
393
+ wrapped_cursor_y = wrapped_lines[0...@line_index].sum(&:size) + wrapped_line_before_cursor.size - 1
394
+ wrapped_cursor_x = calculate_width(wrapped_line_before_cursor.last)
395
+ [wrapped_cursor_x, wrapped_cursor_y]
411
396
  end
412
397
 
413
398
  def clear_dialogs
@@ -418,19 +403,23 @@ class Reline::LineEditor
418
403
  end
419
404
 
420
405
  def update_dialogs(key = nil)
421
- @dialog_initialzed = true
422
- editor_cursor_x, editor_cursor_y = editor_cursor_position
406
+ wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
423
407
  @dialogs.each do |dialog|
424
408
  dialog.trap_key = nil
425
- update_each_dialog(dialog, editor_cursor_x, editor_cursor_y - screen_scroll_top, key)
409
+ update_each_dialog(dialog, wrapped_cursor_x, wrapped_cursor_y - screen_scroll_top, key)
426
410
  end
427
411
  end
428
412
 
413
+ def render_finished
414
+ clear_rendered_lines
415
+ render_full_content
416
+ end
417
+
429
418
  def clear_rendered_lines
430
- Reline::IOGate.move_cursor_up @cursor_y
419
+ Reline::IOGate.move_cursor_up @rendered_screen.cursor_y
431
420
  Reline::IOGate.move_cursor_column 0
432
421
 
433
- num_lines = @rendered_screen_cache&.size
422
+ num_lines = @rendered_screen.lines.size
434
423
  return unless num_lines && num_lines >= 1
435
424
 
436
425
  Reline::IOGate.move_cursor_down num_lines - 1
@@ -439,7 +428,8 @@ class Reline::LineEditor
439
428
  Reline::IOGate.move_cursor_up 1
440
429
  end
441
430
  Reline::IOGate.erase_after_cursor
442
- @rendered_screen_cache = nil
431
+ @rendered_screen.lines = []
432
+ @rendered_screen.cursor_y = 0
443
433
  end
444
434
 
445
435
  def render_full_content
@@ -455,18 +445,15 @@ class Reline::LineEditor
455
445
  return unless prompt && !@is_multiline
456
446
 
457
447
  # Readline's test `TestRelineAsReadline#test_readline` requires first output to be prompt, not cursor reset escape sequence.
458
- @rendered_screen_cache = [[[0, Reline::Unicode.calculate_width(prompt, true), prompt]]]
448
+ @rendered_screen.lines = [[[0, Reline::Unicode.calculate_width(prompt, true), prompt]]]
449
+ @rendered_screen.cursor_y = 0
459
450
  @output.write prompt
460
451
  end
461
452
 
462
453
  def render_differential
463
- unless @dialog_initialzed
464
- update_dialogs
465
- end
466
-
467
- editor_cursor_x, editor_cursor_y = editor_cursor_position
454
+ wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
468
455
 
469
- rendered_lines = @rendered_screen_cache || []
456
+ rendered_lines = @rendered_screen.lines
470
457
  new_lines = wrapped_lines.flatten[screen_scroll_top, screen_height].map do |l|
471
458
  [[0, Reline::Unicode.calculate_width(l, true), l]]
472
459
  end
@@ -480,7 +467,7 @@ class Reline::LineEditor
480
467
  @dialogs.each_with_index do |dialog, index|
481
468
  next unless dialog.contents
482
469
 
483
- x_range, y_range = dialog_range dialog, editor_cursor_y - screen_scroll_top
470
+ x_range, y_range = dialog_range dialog, wrapped_cursor_y - screen_scroll_top
484
471
  y_range.each do |row|
485
472
  next if row < 0 || row >= screen_height
486
473
  dialog_rows = new_lines[row] ||= []
@@ -488,74 +475,65 @@ class Reline::LineEditor
488
475
  end
489
476
  end
490
477
 
491
- num_lines = [[new_lines.size, rendered_lines.size].max, screen_height].min
492
- scroll_down(num_lines - 1 - @cursor_y) if (num_lines - 1 - @cursor_y) > 0
493
- @cursor_y = num_lines - 1
494
- num_lines.times do |i|
495
- rendered_line = rendered_lines[i] || []
496
- line_to_render = new_lines[i] || []
497
- next if rendered_line == line_to_render
498
-
499
- Reline::IOGate.move_cursor_down i - @cursor_y
500
- @cursor_y = i
501
- unless rendered_lines[i]
502
- Reline::IOGate.move_cursor_column 0
503
- Reline::IOGate.erase_after_cursor
478
+ cursor_y = @rendered_screen.cursor_y
479
+ if new_lines != rendered_lines
480
+ # Hide cursor while rendering to avoid cursor flickering.
481
+ Reline::IOGate.hide_cursor
482
+ num_lines = [[new_lines.size, rendered_lines.size].max, screen_height].min
483
+ if @rendered_screen.base_y + num_lines > screen_height
484
+ Reline::IOGate.scroll_down(num_lines - cursor_y - 1)
485
+ @rendered_screen.base_y = screen_height - num_lines
486
+ cursor_y = num_lines - 1
487
+ end
488
+ num_lines.times do |i|
489
+ rendered_line = rendered_lines[i] || []
490
+ line_to_render = new_lines[i] || []
491
+ next if rendered_line == line_to_render
492
+
493
+ Reline::IOGate.move_cursor_down i - cursor_y
494
+ cursor_y = i
495
+ unless rendered_lines[i]
496
+ Reline::IOGate.move_cursor_column 0
497
+ Reline::IOGate.erase_after_cursor
498
+ end
499
+ render_line_differential(rendered_line, line_to_render)
504
500
  end
505
- render_line_differential(rendered_line, line_to_render)
501
+ @rendered_screen.lines = new_lines
502
+ Reline::IOGate.show_cursor
506
503
  end
507
- @rendered_screen_cache = new_lines
508
- y = editor_cursor_y - screen_scroll_top
509
- Reline::IOGate.move_cursor_column editor_cursor_x
510
- Reline::IOGate.move_cursor_down y - @cursor_y
511
- @cursor_y = y
512
- new_lines.size - @cursor_y
504
+ y = wrapped_cursor_y - screen_scroll_top
505
+ Reline::IOGate.move_cursor_column wrapped_cursor_x
506
+ Reline::IOGate.move_cursor_down y - cursor_y
507
+ @rendered_screen.cursor_y = y
508
+ new_lines.size - y
513
509
  end
514
510
 
515
511
  def current_row
516
- wrapped_lines.flatten[editor_cursor_y]
512
+ wrapped_lines.flatten[wrapped_cursor_y]
517
513
  end
518
514
 
519
- def upper_space_height
520
- @cursor_y - 1
515
+ def upper_space_height(wrapped_cursor_y)
516
+ wrapped_cursor_y - screen_scroll_top
521
517
  end
522
518
 
523
- def rest_height
524
- screen_height - @cursor_y - @cursor_base_y - 1
525
- end
526
-
527
- def rerender_all
528
- Reline::IOGate.hide_cursor
529
- process_insert(force: true)
530
- handle_cleared
531
- render_differential unless @in_pasting
532
- Reline::IOGate.show_cursor
519
+ def rest_height(wrapped_cursor_y)
520
+ screen_height - wrapped_cursor_y + screen_scroll_top - @rendered_screen.base_y - 1
533
521
  end
534
522
 
535
523
  def handle_cleared
536
524
  return unless @cleared
537
525
 
538
526
  @cleared = false
539
- @rendered_screen_cache = nil
540
527
  Reline::IOGate.clear_screen
541
528
  @screen_size = Reline::IOGate.get_screen_size
542
- @cursor_base_y = 0
543
- @cursor_y = 0
544
- scroll_into_view
545
- render_differential
529
+ @rendered_screen.lines = []
530
+ @rendered_screen.base_y = 0
531
+ @rendered_screen.cursor_y = 0
546
532
  end
547
533
 
548
534
  def rerender
549
- Reline::IOGate.hide_cursor
550
- finished = finished?
551
535
  handle_cleared
552
- if finished
553
- clear_rendered_lines
554
- render_full_content
555
- elsif !@in_pasting
556
- render_differential
557
- end
558
- Reline::IOGate.show_cursor
536
+ render_differential unless @in_pasting
559
537
  end
560
538
 
561
539
  class DialogProcScope
@@ -617,8 +595,8 @@ class Reline::LineEditor
617
595
  end
618
596
 
619
597
  def preferred_dialog_height
620
- _editor_cursor_x, editor_cursor_y = @line_editor.editor_cursor_position
621
- [editor_cursor_y - @line_editor.screen_scroll_top, @line_editor.rest_height, (screen_height + 6) / 5].max
598
+ _wrapped_cursor_x, wrapped_cursor_y = @line_editor.wrapped_cursor_position
599
+ [@line_editor.upper_space_height(wrapped_cursor_y), @line_editor.rest_height(wrapped_cursor_y), (screen_height + 6) / 5].max
622
600
  end
623
601
 
624
602
  def completion_journey_data
@@ -747,16 +725,15 @@ class Reline::LineEditor
747
725
  else
748
726
  scrollbar_pos = nil
749
727
  end
750
- upper_space = upper_space_height
751
728
  dialog.column = dialog_render_info.pos.x
752
729
  dialog.width += @block_elem_width if scrollbar_pos
753
730
  diff = (dialog.column + dialog.width) - screen_width
754
731
  if diff > 0
755
732
  dialog.column -= diff
756
733
  end
757
- if (rest_height - dialog_render_info.pos.y) >= height
734
+ if rest_height(screen_scroll_top + cursor_row) - dialog_render_info.pos.y >= height
758
735
  dialog.vertical_offset = dialog_render_info.pos.y + 1
759
- elsif upper_space >= height
736
+ elsif cursor_row >= height
760
737
  dialog.vertical_offset = dialog_render_info.pos.y - height
761
738
  else
762
739
  dialog.vertical_offset = dialog_render_info.pos.y + 1
@@ -831,7 +808,7 @@ class Reline::LineEditor
831
808
  item_mbchars = item.grapheme_clusters
832
809
  end
833
810
  size = [memo_mbchars.size, item_mbchars.size].min
834
- result = ''
811
+ result = +''
835
812
  size.times do |i|
836
813
  if @config.completion_ignore_case
837
814
  if memo_mbchars[i].casecmp?(item_mbchars[i])
@@ -888,7 +865,7 @@ class Reline::LineEditor
888
865
  end
889
866
  if not just_show_list and target < completed
890
867
  @buffer_of_lines[@line_index] = (preposing + completed + completion_append_character.to_s + postposing).split("\n")[@line_index] || String.new(encoding: @encoding)
891
- line_to_pointer = (preposing + completed + completion_append_character.to_s).split("\n").last || String.new(encoding: @encoding)
868
+ line_to_pointer = (preposing + completed + completion_append_character.to_s).split("\n")[@line_index] || String.new(encoding: @encoding)
892
869
  @byte_pointer = line_to_pointer.bytesize
893
870
  end
894
871
  end
@@ -1169,12 +1146,12 @@ class Reline::LineEditor
1169
1146
  end
1170
1147
 
1171
1148
  def scroll_into_view
1172
- _editor_cursor_x, editor_cursor_y = editor_cursor_position
1173
- if editor_cursor_y < screen_scroll_top
1174
- @scroll_partial_screen = editor_cursor_y
1149
+ _wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
1150
+ if wrapped_cursor_y < screen_scroll_top
1151
+ @scroll_partial_screen = wrapped_cursor_y
1175
1152
  end
1176
- if editor_cursor_y >= screen_scroll_top + screen_height
1177
- @scroll_partial_screen = editor_cursor_y - screen_height + 1
1153
+ if wrapped_cursor_y >= screen_scroll_top + screen_height
1154
+ @scroll_partial_screen = wrapped_cursor_y - screen_height + 1
1178
1155
  end
1179
1156
  end
1180
1157
 
@@ -1233,7 +1210,6 @@ class Reline::LineEditor
1233
1210
  end
1234
1211
 
1235
1212
  def set_current_line(line, byte_pointer = nil)
1236
- @modified = true
1237
1213
  cursor = current_byte_pointer_cursor
1238
1214
  @buffer_of_lines[@line_index] = line
1239
1215
  if byte_pointer
@@ -1993,6 +1969,13 @@ class Reline::LineEditor
1993
1969
  end
1994
1970
  alias_method :kill_line, :ed_kill_line
1995
1971
 
1972
+ # Editline:: +vi_change_to_eol+ (vi command: +C+) + Kill and change from the cursor to the end of the line.
1973
+ private def vi_change_to_eol(key)
1974
+ ed_kill_line(key)
1975
+
1976
+ @config.editing_mode = :vi_insert
1977
+ end
1978
+
1996
1979
  # Editline:: +vi-kill-line-prev+ (vi: +Ctrl-U+) Delete the string from the
1997
1980
  # beginning of the edit buffer to the cursor and save it to the
1998
1981
  # cut buffer.
@@ -2291,7 +2274,7 @@ class Reline::LineEditor
2291
2274
  end
2292
2275
 
2293
2276
  private def ed_delete_prev_char(key, arg: 1)
2294
- deleted = ''
2277
+ deleted = +''
2295
2278
  arg.times do
2296
2279
  if @byte_pointer > 0
2297
2280
  byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.5.0.pre.1'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -1,6 +1,8 @@
1
1
  require 'fiddle/import'
2
2
 
3
3
  class Reline::Windows
4
+ RESET_COLOR = "\e[0m"
5
+
4
6
  def self.encoding
5
7
  Encoding::UTF_8
6
8
  end
@@ -85,7 +87,7 @@ class Reline::Windows
85
87
  def call(*args)
86
88
  import = @proto.split("")
87
89
  args.each_with_index do |x, i|
88
- args[i], = [x == 0 ? nil : x].pack("p").unpack(POINTER_TYPE) if import[i] == "S"
90
+ args[i], = [x == 0 ? nil : +x].pack("p").unpack(POINTER_TYPE) if import[i] == "S"
89
91
  args[i], = [x].pack("I").unpack("i") if import[i] == "I"
90
92
  end
91
93
  ret, = @func.call(*args)
data/lib/reline.rb CHANGED
@@ -78,7 +78,6 @@ module Reline
78
78
  @dialog_proc_list = {}
79
79
  yield self
80
80
  @completion_quote_character = nil
81
- @bracketed_paste_finished = false
82
81
  end
83
82
 
84
83
  def io_gate
@@ -280,6 +279,7 @@ module Reline
280
279
 
281
280
  if line_editor.eof?
282
281
  line_editor.reset_line
282
+ # Return nil if the input is aborted by C-d.
283
283
  nil
284
284
  else
285
285
  whole_buffer
@@ -331,8 +331,10 @@ module Reline
331
331
  line_editor.auto_indent_proc = auto_indent_proc
332
332
  line_editor.dig_perfect_match_proc = dig_perfect_match_proc
333
333
  pre_input_hook&.call
334
- @dialog_proc_list.each_pair do |name_sym, d|
335
- line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
334
+ unless Reline::IOGate == Reline::GeneralIO
335
+ @dialog_proc_list.each_pair do |name_sym, d|
336
+ line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
337
+ end
336
338
  end
337
339
 
338
340
  unless config.test_mode
@@ -342,28 +344,23 @@ module Reline
342
344
  end
343
345
 
344
346
  line_editor.print_nomultiline_prompt(prompt)
347
+ line_editor.update_dialogs
345
348
  line_editor.rerender
346
349
 
347
350
  begin
348
351
  line_editor.set_signal_handlers
349
- prev_pasting_state = false
350
352
  loop do
351
- prev_pasting_state = io_gate.in_pasting?
352
353
  read_io(config.keyseq_timeout) { |inputs|
353
354
  line_editor.set_pasting_state(io_gate.in_pasting?)
354
- inputs.each { |c| line_editor.update(c) }
355
- line_editor.rerender
356
- if @bracketed_paste_finished
357
- line_editor.rerender_all
358
- @bracketed_paste_finished = false
359
- end
355
+ inputs.each { |key| line_editor.update(key) }
360
356
  }
361
- if prev_pasting_state == true and not io_gate.in_pasting? and not line_editor.finished?
362
- line_editor.set_pasting_state(false)
363
- prev_pasting_state = false
364
- line_editor.rerender_all
357
+ if line_editor.finished?
358
+ line_editor.render_finished
359
+ break
360
+ else
361
+ line_editor.set_pasting_state(io_gate.in_pasting?)
362
+ line_editor.rerender
365
363
  end
366
- break if line_editor.finished?
367
364
  end
368
365
  io_gate.move_cursor_column(0)
369
366
  rescue Errno::EIO
@@ -398,7 +395,6 @@ module Reline
398
395
  c = io_gate.getc(Float::INFINITY)
399
396
  if c == -1
400
397
  result = :unmatched
401
- @bracketed_paste_finished = true
402
398
  else
403
399
  buffer << c
404
400
  result = key_stroke.match_status(buffer)
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.pre.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-01 00:00:00.000000000 Z
11
+ date: 2024-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console
@@ -57,7 +57,10 @@ files:
57
57
  homepage: https://github.com/ruby/reline
58
58
  licenses:
59
59
  - Ruby
60
- metadata: {}
60
+ metadata:
61
+ bug_tracker_uri: https://github.com/ruby/reline/issues
62
+ changelog_uri: https://github.com/ruby/reline/releases
63
+ source_code_uri: https://github.com/ruby/reline
61
64
  post_install_message:
62
65
  rdoc_options: []
63
66
  require_paths:
@@ -69,11 +72,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
72
  version: '2.6'
70
73
  required_rubygems_version: !ruby/object:Gem::Requirement
71
74
  requirements:
72
- - - ">"
75
+ - - ">="
73
76
  - !ruby/object:Gem::Version
74
- version: 1.3.1
77
+ version: '0'
75
78
  requirements: []
76
- rubygems_version: 3.4.10
79
+ rubygems_version: 3.5.3
77
80
  signing_key:
78
81
  specification_version: 4
79
82
  summary: Alternative GNU Readline or Editline implementation by pure Ruby.