reline 0.5.0.pre.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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.