reline 0.3.1 → 0.3.3

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: 1009c9156a8c15c1f3c64a3cb89a0d6a1acef037185bfb76c24ed9df7e49cb2c
4
- data.tar.gz: 983ad1d570617a47d732402485a79eba8bd1acc6f3555f117ca6822cee52030d
3
+ metadata.gz: b0fe224245c6f66bdfa42b7fd6b0dc4c30f9645f0c1498fd7780ff17db642eec
4
+ data.tar.gz: af1b5a53e09f4b2c60ae20e153a4b3043ea3a19a38c58be697067c58f63feec7
5
5
  SHA512:
6
- metadata.gz: 424c026623c896ccd59fed73b5f61e7bb067dfdc8fe34a13bdb317895fb512eb666b25c76439e940915307e658e85dbbfcb8339ecfae5c5b72fa9239d1599778
7
- data.tar.gz: 93077ced9c8009d5c2f7f59eb013f8134394347c57660e7958244a2adfe60b2a09463ac2062d9ce31e5d75974b19665f7e800f2078bf9b461dfbada76c3e572e
6
+ metadata.gz: cb456e06f2cef817fe3ae8fa27e9666587f2b3175cdbc97714ab3638d5b11bf606595d772c4e100fc21d9f50ed6e55fb6b833c28bad6b4ae3c8838d2418e75f5
7
+ data.tar.gz: 6f3eb2f3feee78d7b4754c069a7d6c0d5d29af100bcb493bab2696c9b610c86de4fb3b201d624b6d00f218f1257a526d0c29bf95c79a1ed3daf117f0c95a2768
data/lib/reline/ansi.rb CHANGED
@@ -7,6 +7,9 @@ class Reline::ANSI
7
7
  CAPNAME_KEY_BINDINGS = {
8
8
  'khome' => :ed_move_to_beg,
9
9
  'kend' => :ed_move_to_end,
10
+ 'kdch1' => :key_delete,
11
+ 'kpp' => :ed_search_prev_history,
12
+ 'knp' => :ed_search_next_history,
10
13
  'kcuu1' => :ed_prev_history,
11
14
  'kcud1' => :ed_next_history,
12
15
  'kcuf1' => :ed_next_char,
@@ -29,8 +32,8 @@ class Reline::ANSI
29
32
  false
30
33
  end
31
34
 
32
- def self.set_default_key_bindings(config)
33
- if Reline::Terminfo.enabled?
35
+ def self.set_default_key_bindings(config, allow_terminfo: true)
36
+ if allow_terminfo && Reline::Terminfo.enabled?
34
37
  set_default_key_bindings_terminfo(config)
35
38
  else
36
39
  set_default_key_bindings_comprehensive_list(config)
@@ -142,6 +145,10 @@ class Reline::ANSI
142
145
  @@output = val
143
146
  end
144
147
 
148
+ def self.with_raw_input
149
+ @@input.raw { yield }
150
+ end
151
+
145
152
  @@buf = []
146
153
  def self.inner_getc
147
154
  unless @@buf.empty?
@@ -150,7 +157,7 @@ class Reline::ANSI
150
157
  until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
151
158
  Reline.core.line_editor.resize
152
159
  end
153
- (c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
160
+ (c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
154
161
  rescue Errno::EIO
155
162
  # Maybe the I/O has been closed.
156
163
  nil
data/lib/reline/config.rb CHANGED
@@ -45,6 +45,8 @@ class Reline::Config
45
45
  attr_accessor v
46
46
  end
47
47
 
48
+ attr_accessor :autocompletion
49
+
48
50
  def initialize
49
51
  @additional_key_bindings = {} # from inputrc
50
52
  @additional_key_bindings[:emacs] = {}
@@ -55,6 +57,7 @@ class Reline::Config
55
57
  @if_stack = nil
56
58
  @editing_mode_label = :emacs
57
59
  @keymap_label = :emacs
60
+ @keymap_prefix = []
58
61
  @key_actors = {}
59
62
  @key_actors[:emacs] = Reline::KeyActor::Emacs.new
60
63
  @key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
@@ -90,15 +93,7 @@ class Reline::Config
90
93
  end
91
94
 
92
95
  def editing_mode_is?(*val)
93
- (val.respond_to?(:any?) ? val : [val]).any?(@editing_mode_label)
94
- end
95
-
96
- def autocompletion=(val)
97
- @autocompletion = val
98
- end
99
-
100
- def autocompletion
101
- @autocompletion
96
+ val.any?(@editing_mode_label)
102
97
  end
103
98
 
104
99
  def keymap
@@ -221,7 +216,7 @@ class Reline::Config
221
216
  key, func_name = $1, $2
222
217
  keystroke, func = bind_key(key, func_name)
223
218
  next unless keystroke
224
- @additional_key_bindings[@keymap_label][keystroke] = func
219
+ @additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
225
220
  end
226
221
  end
227
222
  unless @if_stack.empty?
@@ -292,18 +287,29 @@ class Reline::Config
292
287
  when 'emacs'
293
288
  @editing_mode_label = :emacs
294
289
  @keymap_label = :emacs
290
+ @keymap_prefix = []
295
291
  when 'vi'
296
292
  @editing_mode_label = :vi_insert
297
293
  @keymap_label = :vi_insert
294
+ @keymap_prefix = []
298
295
  end
299
296
  when 'keymap'
300
297
  case value
301
- when 'emacs', 'emacs-standard', 'emacs-meta', 'emacs-ctlx'
298
+ when 'emacs', 'emacs-standard'
299
+ @keymap_label = :emacs
300
+ @keymap_prefix = []
301
+ when 'emacs-ctlx'
302
+ @keymap_label = :emacs
303
+ @keymap_prefix = [?\C-x.ord]
304
+ when 'emacs-meta'
302
305
  @keymap_label = :emacs
306
+ @keymap_prefix = [?\e.ord]
303
307
  when 'vi', 'vi-move', 'vi-command'
304
308
  @keymap_label = :vi_command
309
+ @keymap_prefix = []
305
310
  when 'vi-insert'
306
311
  @keymap_label = :vi_insert
312
+ @keymap_prefix = []
307
313
  end
308
314
  when 'keyseq-timeout'
309
315
  @keyseq_timeout = value.to_i
@@ -31,6 +31,10 @@ class Reline::GeneralIO
31
31
  @@input = val
32
32
  end
33
33
 
34
+ def self.with_raw_input
35
+ yield
36
+ end
37
+
34
38
  def self.getc
35
39
  unless @@buf.empty?
36
40
  return @@buf.shift
@@ -57,6 +61,12 @@ class Reline::GeneralIO
57
61
  Reline::CursorPos.new(1, 1)
58
62
  end
59
63
 
64
+ def self.hide_cursor
65
+ end
66
+
67
+ def self.show_cursor
68
+ end
69
+
60
70
  def self.move_cursor_column(val)
61
71
  end
62
72
 
@@ -52,6 +52,7 @@ class Reline::LineEditor
52
52
  MenuInfo = Struct.new('MenuInfo', :target, :list)
53
53
 
54
54
  PROMPT_LIST_CACHE_TIMEOUT = 0.5
55
+ MINIMUM_SCROLLBAR_HEIGHT = 1
55
56
 
56
57
  def initialize(config, encoding)
57
58
  @config = config
@@ -449,14 +450,10 @@ class Reline::LineEditor
449
450
  Reline::IOGate.move_cursor_up(@first_line_started_from + @started_from - @scroll_partial_screen)
450
451
  Reline::IOGate.move_cursor_column(0)
451
452
  @scroll_partial_screen = nil
452
- prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines)
453
- if @previous_line_index
454
- new_lines = whole_lines(index: @previous_line_index, line: @line)
455
- else
456
- new_lines = whole_lines
457
- end
453
+ new_lines = whole_lines
454
+ prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines)
458
455
  modify_lines(new_lines).each_with_index do |line, index|
459
- @output.write "#{prompt_list ? prompt_list[index] : prompt}#{line}\n"
456
+ @output.write "#{prompt_list ? prompt_list[index] : prompt}#{line}\r\n"
460
457
  Reline::IOGate.erase_after_cursor
461
458
  end
462
459
  @output.flush
@@ -466,15 +463,17 @@ class Reline::LineEditor
466
463
  new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line))
467
464
  rendered = false
468
465
  if @add_newline_to_end_of_buffer
469
- rerender_added_newline(prompt, prompt_width)
466
+ clear_dialog_with_content
467
+ rerender_added_newline(prompt, prompt_width, prompt_list)
470
468
  @add_newline_to_end_of_buffer = false
471
469
  else
472
470
  if @just_cursor_moving and not @rerender_all
471
+ clear_dialog_with_content
473
472
  rendered = just_move_cursor
474
- render_dialog((prompt_width + @cursor) % @screen_size.last)
475
473
  @just_cursor_moving = false
476
474
  return
477
475
  elsif @previous_line_index or new_highest_in_this != @highest_in_this
476
+ clear_dialog_with_content
478
477
  rerender_changed_current_line
479
478
  @previous_line_index = nil
480
479
  rendered = true
@@ -488,11 +487,7 @@ class Reline::LineEditor
488
487
  if @is_multiline
489
488
  if finished?
490
489
  # Always rerender on finish because output_modifier_proc may return a different output.
491
- if @previous_line_index
492
- new_lines = whole_lines(index: @previous_line_index, line: @line)
493
- else
494
- new_lines = whole_lines
495
- end
490
+ new_lines = whole_lines
496
491
  line = modify_lines(new_lines)[@line_index]
497
492
  clear_dialog
498
493
  prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines)
@@ -653,7 +648,10 @@ class Reline::LineEditor
653
648
  end
654
649
 
655
650
  private def padding_space_with_escape_sequences(str, width)
656
- str + (' ' * (width - calculate_width(str, true)))
651
+ padding_width = width - calculate_width(str, true)
652
+ # padding_width should be only positive value. But macOS and Alacritty returns negative value.
653
+ padding_width = 0 if padding_width < 0
654
+ str + (' ' * padding_width)
657
655
  end
658
656
 
659
657
  private def render_each_dialog(dialog, cursor_column)
@@ -666,8 +664,10 @@ class Reline::LineEditor
666
664
  dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from)
667
665
  dialog_render_info = dialog.call(@last_key)
668
666
  if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
667
+ lines = whole_lines
669
668
  dialog.lines_backup = {
670
- lines: modify_lines(whole_lines),
669
+ unmodified_lines: lines,
670
+ lines: modify_lines(lines),
671
671
  line_index: @line_index,
672
672
  first_line_started_from: @first_line_started_from,
673
673
  started_from: @started_from,
@@ -698,17 +698,17 @@ class Reline::LineEditor
698
698
  dialog.scroll_top = dialog.pointer
699
699
  end
700
700
  pointer = dialog.pointer - dialog.scroll_top
701
+ else
702
+ dialog.scroll_top = 0
701
703
  end
702
704
  dialog.contents = dialog.contents[dialog.scroll_top, height]
703
705
  end
704
- if dialog.contents and dialog.scroll_top >= dialog.contents.size
705
- dialog.scroll_top = dialog.contents.size - height
706
- end
707
706
  if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
708
707
  bar_max_height = height * 2
709
708
  moving_distance = (dialog_render_info.contents.size - height) * 2
710
709
  position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
711
710
  bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
711
+ bar_height = MINIMUM_SCROLLBAR_HEIGHT if bar_height < MINIMUM_SCROLLBAR_HEIGHT
712
712
  dialog.scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
713
713
  else
714
714
  dialog.scrollbar_pos = nil
@@ -741,24 +741,21 @@ class Reline::LineEditor
741
741
  Reline::IOGate.move_cursor_column(dialog.column)
742
742
  dialog.contents.each_with_index do |item, i|
743
743
  if i == pointer
744
- bg_color = '45'
744
+ fg_color = dialog_render_info.pointer_fg_color
745
+ bg_color = dialog_render_info.pointer_bg_color
745
746
  else
746
- if dialog_render_info.bg_color
747
- bg_color = dialog_render_info.bg_color
748
- else
749
- bg_color = '46'
750
- end
747
+ fg_color = dialog_render_info.fg_color
748
+ bg_color = dialog_render_info.bg_color
751
749
  end
752
750
  str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
753
751
  str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
754
- @output.write "\e[#{bg_color}m#{str}"
755
- if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
752
+ @output.write "\e[#{bg_color}m\e[#{fg_color}m#{str}"
753
+ if dialog.scrollbar_pos
756
754
  @output.write "\e[37m"
757
755
  if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height)
758
756
  @output.write @full_block
759
757
  elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height)
760
758
  @output.write @upper_half_block
761
- str += ''
762
759
  elsif dialog.scrollbar_pos <= (i * 2 + 1) and (i * 2) < (dialog.scrollbar_pos + bar_height)
763
760
  @output.write @lower_half_block
764
761
  else
@@ -772,8 +769,10 @@ class Reline::LineEditor
772
769
  Reline::IOGate.move_cursor_column(cursor_column)
773
770
  move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1)
774
771
  Reline::IOGate.show_cursor
772
+ lines = whole_lines
775
773
  dialog.lines_backup = {
776
- lines: modify_lines(whole_lines),
774
+ unmodified_lines: lines,
775
+ lines: modify_lines(lines),
777
776
  line_index: @line_index,
778
777
  first_line_started_from: @first_line_started_from,
779
778
  started_from: @started_from,
@@ -783,7 +782,7 @@ class Reline::LineEditor
783
782
 
784
783
  private def reset_dialog(dialog, old_dialog)
785
784
  return if dialog.lines_backup.nil? or old_dialog.contents.nil?
786
- prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines])
785
+ prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:unmodified_lines])
787
786
  visual_lines = []
788
787
  visual_start = nil
789
788
  dialog.lines_backup[:lines].each_with_index { |l, i|
@@ -883,10 +882,18 @@ class Reline::LineEditor
883
882
  end
884
883
  end
885
884
 
885
+ private def clear_dialog_with_content
886
+ @dialogs.each do |dialog|
887
+ clear_each_dialog(dialog)
888
+ dialog.contents = nil
889
+ dialog.trap_key = nil
890
+ end
891
+ end
892
+
886
893
  private def clear_each_dialog(dialog)
887
894
  dialog.trap_key = nil
888
895
  return unless dialog.contents
889
- prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines])
896
+ prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:unmodified_lines])
890
897
  visual_lines = []
891
898
  visual_lines_under_dialog = []
892
899
  visual_start = nil
@@ -954,11 +961,20 @@ class Reline::LineEditor
954
961
  end
955
962
  end
956
963
 
957
- private def rerender_added_newline(prompt, prompt_width)
958
- scroll_down(1)
964
+ private def rerender_added_newline(prompt, prompt_width, prompt_list)
959
965
  @buffer_of_lines[@previous_line_index] = @line
960
966
  @line = @buffer_of_lines[@line_index]
961
- unless @in_pasting
967
+ @previous_line_index = nil
968
+ if @in_pasting
969
+ scroll_down(1)
970
+ else
971
+ lines = whole_lines
972
+ prev_line_prompt = @prompt_proc ? prompt_list[@line_index - 1] : prompt
973
+ prev_line_prompt_width = @prompt_proc ? calculate_width(prev_line_prompt, true) : prompt_width
974
+ prev_line = modify_lines(lines)[@line_index - 1]
975
+ move_cursor_up(@started_from)
976
+ render_partial(prev_line_prompt, prev_line_prompt_width, prev_line, @first_line_started_from + @started_from, with_control: false)
977
+ scroll_down(1)
962
978
  render_partial(prompt, prompt_width, @line, @first_line_started_from + @started_from + 1, with_control: false)
963
979
  end
964
980
  @cursor = @cursor_max = calculate_width(@line)
@@ -967,7 +983,6 @@ class Reline::LineEditor
967
983
  @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
968
984
  @first_line_started_from += @started_from + 1
969
985
  @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
970
- @previous_line_index = nil
971
986
  end
972
987
 
973
988
  def just_move_cursor
@@ -980,22 +995,18 @@ class Reline::LineEditor
980
995
  calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
981
996
  end
982
997
  first_line_diff = new_first_line_started_from - @first_line_started_from
983
- new_cursor, new_cursor_max, new_started_from, new_byte_pointer = calculate_nearest_cursor(@buffer_of_lines[@line_index], @cursor, @started_from, @byte_pointer, false)
984
- new_started_from = calculate_height_by_width(prompt_width + new_cursor) - 1
998
+ @cursor, @cursor_max, _, @byte_pointer = calculate_nearest_cursor(@buffer_of_lines[@line_index], @cursor, @started_from, @byte_pointer, false)
999
+ new_started_from = calculate_height_by_width(prompt_width + @cursor) - 1
985
1000
  calculate_scroll_partial_screen(@highest_in_all, new_first_line_started_from + new_started_from)
986
1001
  @previous_line_index = nil
1002
+ @line = @buffer_of_lines[@line_index]
987
1003
  if @rerender_all
988
- @line = @buffer_of_lines[@line_index]
989
1004
  rerender_all_lines
990
1005
  @rerender_all = false
991
1006
  true
992
1007
  else
993
- @line = @buffer_of_lines[@line_index]
994
1008
  @first_line_started_from = new_first_line_started_from
995
1009
  @started_from = new_started_from
996
- @cursor = new_cursor
997
- @cursor_max = new_cursor_max
998
- @byte_pointer = new_byte_pointer
999
1010
  move_cursor_down(first_line_diff + @started_from)
1000
1011
  Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
1001
1012
  false
@@ -1003,11 +1014,7 @@ class Reline::LineEditor
1003
1014
  end
1004
1015
 
1005
1016
  private def rerender_changed_current_line
1006
- if @previous_line_index
1007
- new_lines = whole_lines(index: @previous_line_index, line: @line)
1008
- else
1009
- new_lines = whole_lines
1010
- end
1017
+ new_lines = whole_lines
1011
1018
  prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines)
1012
1019
  all_height = calculate_height_by_lines(new_lines, prompt_list || prompt)
1013
1020
  diff = all_height - @highest_in_all
@@ -1361,8 +1368,8 @@ class Reline::LineEditor
1361
1368
  @completion_state = CompletionState::MENU
1362
1369
  end
1363
1370
  if not just_show_list and target < completed
1364
- @line = preposing + completed + completion_append_character.to_s + postposing
1365
- line_to_pointer = preposing + completed + completion_append_character.to_s
1371
+ @line = (preposing + completed + completion_append_character.to_s + postposing).split("\n")[@line_index] || String.new(encoding: @encoding)
1372
+ line_to_pointer = (preposing + completed + completion_append_character.to_s).split("\n").last || String.new(encoding: @encoding)
1366
1373
  @cursor_max = calculate_width(@line)
1367
1374
  @cursor = calculate_width(line_to_pointer)
1368
1375
  @byte_pointer = line_to_pointer.bytesize
@@ -1420,7 +1427,7 @@ class Reline::LineEditor
1420
1427
  if @waiting_operator_proc
1421
1428
  if VI_MOTIONS.include?(method_symbol)
1422
1429
  old_cursor, old_byte_pointer = @cursor, @byte_pointer
1423
- @vi_arg = @waiting_operator_vi_arg if @waiting_operator_vi_arg > 1
1430
+ @vi_arg = @waiting_operator_vi_arg if @waiting_operator_vi_arg&.> 1
1424
1431
  block.(true)
1425
1432
  unless @waiting_proc
1426
1433
  cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer
@@ -1688,7 +1695,7 @@ class Reline::LineEditor
1688
1695
  return if not @check_new_auto_indent and @previous_line_index # move cursor up or down
1689
1696
  if @check_new_auto_indent and @previous_line_index and @previous_line_index > 0 and @line_index > @previous_line_index
1690
1697
  # Fix indent of a line when a newline is inserted to the next
1691
- new_lines = whole_lines(index: @previous_line_index, line: @line)
1698
+ new_lines = whole_lines
1692
1699
  new_indent = @auto_indent_proc.(new_lines[0..-3].push(''), @line_index - 1, 0, true)
1693
1700
  md = @line.match(/\A */)
1694
1701
  prev_indent = md[0].count(' ')
@@ -1703,23 +1710,20 @@ class Reline::LineEditor
1703
1710
  @line = ' ' * new_indent + @line.lstrip
1704
1711
  end
1705
1712
  end
1706
- if @previous_line_index
1707
- new_lines = whole_lines(index: @previous_line_index, line: @line)
1708
- else
1709
- new_lines = whole_lines
1710
- end
1713
+ new_lines = whole_lines
1711
1714
  new_indent = @auto_indent_proc.(new_lines, @line_index, @byte_pointer, @check_new_auto_indent)
1712
- new_indent = @cursor_max if new_indent&.> @cursor_max
1713
1715
  if new_indent&.>= 0
1714
1716
  md = new_lines[@line_index].match(/\A */)
1715
1717
  prev_indent = md[0].count(' ')
1716
1718
  if @check_new_auto_indent
1717
- @buffer_of_lines[@line_index] = ' ' * new_indent + @buffer_of_lines[@line_index].lstrip
1719
+ line = @buffer_of_lines[@line_index] = ' ' * new_indent + @buffer_of_lines[@line_index].lstrip
1718
1720
  @cursor = new_indent
1721
+ @cursor_max = calculate_width(line)
1719
1722
  @byte_pointer = new_indent
1720
1723
  else
1721
1724
  @line = ' ' * new_indent + @line.lstrip
1722
1725
  @cursor += new_indent - prev_indent
1726
+ @cursor_max = calculate_width(@line)
1723
1727
  @byte_pointer += new_indent - prev_indent
1724
1728
  end
1725
1729
  end
@@ -1793,11 +1797,7 @@ class Reline::LineEditor
1793
1797
  target = before
1794
1798
  end
1795
1799
  if @is_multiline
1796
- if @previous_line_index
1797
- lines = whole_lines(index: @previous_line_index, line: @line)
1798
- else
1799
- lines = whole_lines
1800
- end
1800
+ lines = whole_lines
1801
1801
  if @line_index > 0
1802
1802
  preposing = lines[0..(@line_index - 1)].join("\n") + "\n" + preposing
1803
1803
  end
@@ -1897,9 +1897,10 @@ class Reline::LineEditor
1897
1897
  @cursor_max = calculate_width(@line)
1898
1898
  end
1899
1899
 
1900
- def whole_lines(index: @line_index, line: @line)
1900
+ def whole_lines
1901
+ index = @previous_line_index || @line_index
1901
1902
  temp_lines = @buffer_of_lines.dup
1902
- temp_lines[index] = line
1903
+ temp_lines[index] = @line
1903
1904
  temp_lines
1904
1905
  end
1905
1906
 
@@ -1907,11 +1908,7 @@ class Reline::LineEditor
1907
1908
  if @buffer_of_lines.size == 1 and @line.nil?
1908
1909
  nil
1909
1910
  else
1910
- if @previous_line_index
1911
- whole_lines(index: @previous_line_index, line: @line).join("\n")
1912
- else
1913
- whole_lines.join("\n")
1914
- end
1911
+ whole_lines.join("\n")
1915
1912
  end
1916
1913
  end
1917
1914
 
@@ -1943,8 +1940,10 @@ class Reline::LineEditor
1943
1940
  end
1944
1941
 
1945
1942
  private def key_delete(key)
1946
- if @config.editing_mode_is?(:vi_insert, :emacs)
1943
+ if @config.editing_mode_is?(:vi_insert)
1947
1944
  ed_delete_next_char(key)
1945
+ elsif @config.editing_mode_is?(:emacs)
1946
+ em_delete(key)
1948
1947
  end
1949
1948
  end
1950
1949
 
@@ -2223,6 +2222,8 @@ class Reline::LineEditor
2223
2222
  @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
2224
2223
  @line_index = @buffer_of_lines.size - 1
2225
2224
  @line = @buffer_of_lines.last
2225
+ @byte_pointer = @line.bytesize
2226
+ @cursor = @cursor_max = calculate_width(@line)
2226
2227
  @rerender_all = true
2227
2228
  @searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
2228
2229
  else
@@ -2648,7 +2649,7 @@ class Reline::LineEditor
2648
2649
  alias_method :kill_whole_line, :em_kill_line
2649
2650
 
2650
2651
  private def em_delete(key)
2651
- if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
2652
+ if @line.empty? and (not @is_multiline or @buffer_of_lines.size == 1) and key == "\C-d".ord
2652
2653
  @line = nil
2653
2654
  if @buffer_of_lines.size > 1
2654
2655
  scroll_down(@highest_in_all - @first_line_started_from)
@@ -35,7 +35,7 @@ module Reline::Terminfo
35
35
  # Gem module isn't defined in test-all of the Ruby repository, and
36
36
  # Fiddle in Ruby 3.0.0 or later supports Fiddle::TYPE_VARIADIC.
37
37
  fiddle_supports_variadic = true
38
- elsif Fiddle.const_defined?(:VERSION) and Gem::Version.create(Fiddle::VERSION) >= Gem::Version.create('1.0.1')
38
+ elsif Fiddle.const_defined?(:VERSION,false) and Gem::Version.create(Fiddle::VERSION) >= Gem::Version.create('1.0.1')
39
39
  # Fiddle::TYPE_VARIADIC is supported from Fiddle 1.0.1.
40
40
  fiddle_supports_variadic = true
41
41
  else
@@ -92,9 +92,9 @@ module Reline::Terminfo
92
92
  end
93
93
 
94
94
  def self.setupterm(term, fildes)
95
- errret_int = String.new("\x00" * 8, encoding: 'ASCII-8BIT')
95
+ errret_int = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT)
96
96
  ret = @setupterm.(term, fildes, errret_int)
97
- errret = errret_int.unpack1('i')
97
+ errret = errret_int[0, Fiddle::SIZEOF_INT].unpack1('i')
98
98
  case ret
99
99
  when 0 # OK
100
100
  0
@@ -121,6 +121,7 @@ module Reline::Terminfo
121
121
  end
122
122
 
123
123
  def self.tigetstr(capname)
124
+ raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
124
125
  capability = @tigetstr.(capname)
125
126
  case capability.to_i
126
127
  when 0, -1
@@ -138,6 +139,7 @@ module Reline::Terminfo
138
139
  end
139
140
 
140
141
  def self.tigetflag(capname)
142
+ raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
141
143
  flag = @tigetflag.(capname).to_i
142
144
  case flag
143
145
  when -1
@@ -149,6 +151,7 @@ module Reline::Terminfo
149
151
  end
150
152
 
151
153
  def self.tigetnum(capname)
154
+ raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
152
155
  num = @tigetnum.(capname).to_i
153
156
  case num
154
157
  when -2
@@ -84,8 +84,13 @@ class Reline::Unicode::EastAsianWidth
84
84
  \u{17000}-\u{187F7}
85
85
  \u{18800}-\u{18CD5}
86
86
  \u{18D00}-\u{18D08}
87
- \u{1B000}-\u{1B11E}
87
+ \u{1AFF0}-\u{1AFF3}
88
+ \u{1AFF5}-\u{1AFFB}
89
+ \u{1AFFD}-\u{1AFFE}
90
+ \u{1B000}-\u{1B122}
91
+ \u{1B132}
88
92
  \u{1B150}-\u{1B152}
93
+ \u{1B155}
89
94
  \u{1B164}-\u{1B167}
90
95
  \u{1B170}-\u{1B2FB}
91
96
  \u{1F004}
@@ -119,21 +124,21 @@ class Reline::Unicode::EastAsianWidth
119
124
  \u{1F6CC}
120
125
  \u{1F6D0}-\u{1F6D2}
121
126
  \u{1F6D5}-\u{1F6D7}
127
+ \u{1F6DC}-\u{1F6DF}
122
128
  \u{1F6EB}-\u{1F6EC}
123
129
  \u{1F6F4}-\u{1F6FC}
124
130
  \u{1F7E0}-\u{1F7EB}
131
+ \u{1F7F0}
125
132
  \u{1F90C}-\u{1F93A}
126
133
  \u{1F93C}-\u{1F945}
127
- \u{1F947}-\u{1F978}
128
- \u{1F97A}-\u{1F9CB}
129
- \u{1F9CD}-\u{1F9FF}
130
- \u{1FA70}-\u{1FA74}
131
- \u{1FA78}-\u{1FA7A}
132
- \u{1FA80}-\u{1FA86}
133
- \u{1FA90}-\u{1FAA8}
134
- \u{1FAB0}-\u{1FAB6}
135
- \u{1FAC0}-\u{1FAC2}
136
- \u{1FAD0}-\u{1FAD6}
134
+ \u{1F947}-\u{1F9FF}
135
+ \u{1FA70}-\u{1FA7C}
136
+ \u{1FA80}-\u{1FA88}
137
+ \u{1FA90}-\u{1FABD}
138
+ \u{1FABF}-\u{1FAC5}
139
+ \u{1FACE}-\u{1FADB}
140
+ \u{1FAE0}-\u{1FAE8}
141
+ \u{1FAF0}-\u{1FAF8}
137
142
  \u{20000}-\u{2FFFD}
138
143
  \u{30000}-\u{3FFFD}
139
144
  ).join }]/
@@ -403,8 +408,7 @@ class Reline::Unicode::EastAsianWidth
403
408
  \u{0591}-\u{05C7}
404
409
  \u{05D0}-\u{05EA}
405
410
  \u{05EF}-\u{05F4}
406
- \u{0600}-\u{061C}
407
- \u{061E}-\u{070D}
411
+ \u{0600}-\u{070D}
408
412
  \u{070F}-\u{074A}
409
413
  \u{074D}-\u{07B1}
410
414
  \u{07C0}-\u{07FA}
@@ -413,9 +417,9 @@ class Reline::Unicode::EastAsianWidth
413
417
  \u{0840}-\u{085B}
414
418
  \u{085E}
415
419
  \u{0860}-\u{086A}
416
- \u{08A0}-\u{08B4}
417
- \u{08B6}-\u{08C7}
418
- \u{08D3}-\u{0983}
420
+ \u{0870}-\u{088E}
421
+ \u{0890}-\u{0891}
422
+ \u{0898}-\u{0983}
419
423
  \u{0985}-\u{098C}
420
424
  \u{098F}-\u{0990}
421
425
  \u{0993}-\u{09A8}
@@ -493,11 +497,12 @@ class Reline::Unicode::EastAsianWidth
493
497
  \u{0C0E}-\u{0C10}
494
498
  \u{0C12}-\u{0C28}
495
499
  \u{0C2A}-\u{0C39}
496
- \u{0C3D}-\u{0C44}
500
+ \u{0C3C}-\u{0C44}
497
501
  \u{0C46}-\u{0C48}
498
502
  \u{0C4A}-\u{0C4D}
499
503
  \u{0C55}-\u{0C56}
500
504
  \u{0C58}-\u{0C5A}
505
+ \u{0C5D}
501
506
  \u{0C60}-\u{0C63}
502
507
  \u{0C66}-\u{0C6F}
503
508
  \u{0C77}-\u{0C8C}
@@ -509,10 +514,10 @@ class Reline::Unicode::EastAsianWidth
509
514
  \u{0CC6}-\u{0CC8}
510
515
  \u{0CCA}-\u{0CCD}
511
516
  \u{0CD5}-\u{0CD6}
512
- \u{0CDE}
517
+ \u{0CDD}-\u{0CDE}
513
518
  \u{0CE0}-\u{0CE3}
514
519
  \u{0CE6}-\u{0CEF}
515
- \u{0CF1}-\u{0CF2}
520
+ \u{0CF1}-\u{0CF3}
516
521
  \u{0D00}-\u{0D0C}
517
522
  \u{0D0E}-\u{0D10}
518
523
  \u{0D12}-\u{0D44}
@@ -542,7 +547,7 @@ class Reline::Unicode::EastAsianWidth
542
547
  \u{0EA7}-\u{0EBD}
543
548
  \u{0EC0}-\u{0EC4}
544
549
  \u{0EC6}
545
- \u{0EC8}-\u{0ECD}
550
+ \u{0EC8}-\u{0ECE}
546
551
  \u{0ED0}-\u{0ED9}
547
552
  \u{0EDC}-\u{0EDF}
548
553
  \u{0F00}-\u{0F47}
@@ -577,9 +582,8 @@ class Reline::Unicode::EastAsianWidth
577
582
  \u{13F8}-\u{13FD}
578
583
  \u{1400}-\u{169C}
579
584
  \u{16A0}-\u{16F8}
580
- \u{1700}-\u{170C}
581
- \u{170E}-\u{1714}
582
- \u{1720}-\u{1736}
585
+ \u{1700}-\u{1715}
586
+ \u{171F}-\u{1736}
583
587
  \u{1740}-\u{1753}
584
588
  \u{1760}-\u{176C}
585
589
  \u{176E}-\u{1770}
@@ -587,8 +591,7 @@ class Reline::Unicode::EastAsianWidth
587
591
  \u{1780}-\u{17DD}
588
592
  \u{17E0}-\u{17E9}
589
593
  \u{17F0}-\u{17F9}
590
- \u{1800}-\u{180E}
591
- \u{1810}-\u{1819}
594
+ \u{1800}-\u{1819}
592
595
  \u{1820}-\u{1878}
593
596
  \u{1880}-\u{18AA}
594
597
  \u{18B0}-\u{18F5}
@@ -607,9 +610,9 @@ class Reline::Unicode::EastAsianWidth
607
610
  \u{1A7F}-\u{1A89}
608
611
  \u{1A90}-\u{1A99}
609
612
  \u{1AA0}-\u{1AAD}
610
- \u{1AB0}-\u{1AC0}
611
- \u{1B00}-\u{1B4B}
612
- \u{1B50}-\u{1B7C}
613
+ \u{1AB0}-\u{1ACE}
614
+ \u{1B00}-\u{1B4C}
615
+ \u{1B50}-\u{1B7E}
613
616
  \u{1B80}-\u{1BF3}
614
617
  \u{1BFC}-\u{1C37}
615
618
  \u{1C3B}-\u{1C49}
@@ -617,8 +620,7 @@ class Reline::Unicode::EastAsianWidth
617
620
  \u{1C90}-\u{1CBA}
618
621
  \u{1CBD}-\u{1CC7}
619
622
  \u{1CD0}-\u{1CFA}
620
- \u{1D00}-\u{1DF9}
621
- \u{1DFB}-\u{1F15}
623
+ \u{1D00}-\u{1F15}
622
624
  \u{1F18}-\u{1F1D}
623
625
  \u{1F20}-\u{1F45}
624
626
  \u{1F48}-\u{1F4D}
@@ -653,7 +655,7 @@ class Reline::Unicode::EastAsianWidth
653
655
  \u{2090}-\u{209C}
654
656
  \u{20A0}-\u{20A8}
655
657
  \u{20AA}-\u{20AB}
656
- \u{20AD}-\u{20BF}
658
+ \u{20AD}-\u{20C0}
657
659
  \u{20D0}-\u{20F0}
658
660
  \u{2100}-\u{2102}
659
661
  \u{2104}
@@ -767,9 +769,7 @@ class Reline::Unicode::EastAsianWidth
767
769
  \u{2B51}-\u{2B54}
768
770
  \u{2B5A}-\u{2B73}
769
771
  \u{2B76}-\u{2B95}
770
- \u{2B97}-\u{2C2E}
771
- \u{2C30}-\u{2C5E}
772
- \u{2C60}-\u{2CF3}
772
+ \u{2B97}-\u{2CF3}
773
773
  \u{2CF9}-\u{2D25}
774
774
  \u{2D27}
775
775
  \u{2D2D}
@@ -784,14 +784,16 @@ class Reline::Unicode::EastAsianWidth
784
784
  \u{2DC8}-\u{2DCE}
785
785
  \u{2DD0}-\u{2DD6}
786
786
  \u{2DD8}-\u{2DDE}
787
- \u{2DE0}-\u{2E52}
787
+ \u{2DE0}-\u{2E5D}
788
788
  \u{303F}
789
789
  \u{4DC0}-\u{4DFF}
790
790
  \u{A4D0}-\u{A62B}
791
791
  \u{A640}-\u{A6F7}
792
- \u{A700}-\u{A7BF}
793
- \u{A7C2}-\u{A7CA}
794
- \u{A7F5}-\u{A82C}
792
+ \u{A700}-\u{A7CA}
793
+ \u{A7D0}-\u{A7D1}
794
+ \u{A7D3}
795
+ \u{A7D5}-\u{A7D9}
796
+ \u{A7F2}-\u{A82C}
795
797
  \u{A830}-\u{A839}
796
798
  \u{A840}-\u{A877}
797
799
  \u{A880}-\u{A8C5}
@@ -823,11 +825,11 @@ class Reline::Unicode::EastAsianWidth
823
825
  \u{FB3E}
824
826
  \u{FB40}-\u{FB41}
825
827
  \u{FB43}-\u{FB44}
826
- \u{FB46}-\u{FBC1}
827
- \u{FBD3}-\u{FD3F}
828
- \u{FD50}-\u{FD8F}
828
+ \u{FB46}-\u{FBC2}
829
+ \u{FBD3}-\u{FD8F}
829
830
  \u{FD92}-\u{FDC7}
830
- \u{FDF0}-\u{FDFD}
831
+ \u{FDCF}
832
+ \u{FDF0}-\u{FDFF}
831
833
  \u{FE20}-\u{FE2F}
832
834
  \u{FE70}-\u{FE74}
833
835
  \u{FE76}-\u{FEFC}
@@ -861,10 +863,20 @@ class Reline::Unicode::EastAsianWidth
861
863
  \u{104D8}-\u{104FB}
862
864
  \u{10500}-\u{10527}
863
865
  \u{10530}-\u{10563}
864
- \u{1056F}
866
+ \u{1056F}-\u{1057A}
867
+ \u{1057C}-\u{1058A}
868
+ \u{1058C}-\u{10592}
869
+ \u{10594}-\u{10595}
870
+ \u{10597}-\u{105A1}
871
+ \u{105A3}-\u{105B1}
872
+ \u{105B3}-\u{105B9}
873
+ \u{105BB}-\u{105BC}
865
874
  \u{10600}-\u{10736}
866
875
  \u{10740}-\u{10755}
867
876
  \u{10760}-\u{10767}
877
+ \u{10780}-\u{10785}
878
+ \u{10787}-\u{107B0}
879
+ \u{107B2}-\u{107BA}
868
880
  \u{10800}-\u{10805}
869
881
  \u{10808}
870
882
  \u{1080A}-\u{10835}
@@ -906,13 +918,14 @@ class Reline::Unicode::EastAsianWidth
906
918
  \u{10E80}-\u{10EA9}
907
919
  \u{10EAB}-\u{10EAD}
908
920
  \u{10EB0}-\u{10EB1}
909
- \u{10F00}-\u{10F27}
921
+ \u{10EFD}-\u{10F27}
910
922
  \u{10F30}-\u{10F59}
923
+ \u{10F70}-\u{10F89}
911
924
  \u{10FB0}-\u{10FCB}
912
925
  \u{10FE0}-\u{10FF6}
913
926
  \u{11000}-\u{1104D}
914
- \u{11052}-\u{1106F}
915
- \u{1107F}-\u{110C1}
927
+ \u{11052}-\u{11075}
928
+ \u{1107F}-\u{110C2}
916
929
  \u{110CD}
917
930
  \u{110D0}-\u{110E8}
918
931
  \u{110F0}-\u{110F9}
@@ -922,7 +935,7 @@ class Reline::Unicode::EastAsianWidth
922
935
  \u{11180}-\u{111DF}
923
936
  \u{111E1}-\u{111F4}
924
937
  \u{11200}-\u{11211}
925
- \u{11213}-\u{1123E}
938
+ \u{11213}-\u{11241}
926
939
  \u{11280}-\u{11286}
927
940
  \u{11288}
928
941
  \u{1128A}-\u{1128D}
@@ -954,11 +967,11 @@ class Reline::Unicode::EastAsianWidth
954
967
  \u{11600}-\u{11644}
955
968
  \u{11650}-\u{11659}
956
969
  \u{11660}-\u{1166C}
957
- \u{11680}-\u{116B8}
970
+ \u{11680}-\u{116B9}
958
971
  \u{116C0}-\u{116C9}
959
972
  \u{11700}-\u{1171A}
960
973
  \u{1171D}-\u{1172B}
961
- \u{11730}-\u{1173F}
974
+ \u{11730}-\u{11746}
962
975
  \u{11800}-\u{1183B}
963
976
  \u{118A0}-\u{118F2}
964
977
  \u{118FF}-\u{11906}
@@ -974,7 +987,8 @@ class Reline::Unicode::EastAsianWidth
974
987
  \u{119DA}-\u{119E4}
975
988
  \u{11A00}-\u{11A47}
976
989
  \u{11A50}-\u{11AA2}
977
- \u{11AC0}-\u{11AF8}
990
+ \u{11AB0}-\u{11AF8}
991
+ \u{11B00}-\u{11B09}
978
992
  \u{11C00}-\u{11C08}
979
993
  \u{11C0A}-\u{11C36}
980
994
  \u{11C38}-\u{11C45}
@@ -996,19 +1010,23 @@ class Reline::Unicode::EastAsianWidth
996
1010
  \u{11D93}-\u{11D98}
997
1011
  \u{11DA0}-\u{11DA9}
998
1012
  \u{11EE0}-\u{11EF8}
1013
+ \u{11F00}-\u{11F10}
1014
+ \u{11F12}-\u{11F3A}
1015
+ \u{11F3E}-\u{11F59}
999
1016
  \u{11FB0}
1000
1017
  \u{11FC0}-\u{11FF1}
1001
1018
  \u{11FFF}-\u{12399}
1002
1019
  \u{12400}-\u{1246E}
1003
1020
  \u{12470}-\u{12474}
1004
1021
  \u{12480}-\u{12543}
1005
- \u{13000}-\u{1342E}
1006
- \u{13430}-\u{13438}
1022
+ \u{12F90}-\u{12FF2}
1023
+ \u{13000}-\u{13455}
1007
1024
  \u{14400}-\u{14646}
1008
1025
  \u{16800}-\u{16A38}
1009
1026
  \u{16A40}-\u{16A5E}
1010
1027
  \u{16A60}-\u{16A69}
1011
- \u{16A6E}-\u{16A6F}
1028
+ \u{16A6E}-\u{16ABE}
1029
+ \u{16AC0}-\u{16AC9}
1012
1030
  \u{16AD0}-\u{16AED}
1013
1031
  \u{16AF0}-\u{16AF5}
1014
1032
  \u{16B00}-\u{16B45}
@@ -1025,10 +1043,14 @@ class Reline::Unicode::EastAsianWidth
1025
1043
  \u{1BC80}-\u{1BC88}
1026
1044
  \u{1BC90}-\u{1BC99}
1027
1045
  \u{1BC9C}-\u{1BCA3}
1046
+ \u{1CF00}-\u{1CF2D}
1047
+ \u{1CF30}-\u{1CF46}
1048
+ \u{1CF50}-\u{1CFC3}
1028
1049
  \u{1D000}-\u{1D0F5}
1029
1050
  \u{1D100}-\u{1D126}
1030
- \u{1D129}-\u{1D1E8}
1051
+ \u{1D129}-\u{1D1EA}
1031
1052
  \u{1D200}-\u{1D245}
1053
+ \u{1D2C0}-\u{1D2D3}
1032
1054
  \u{1D2E0}-\u{1D2F3}
1033
1055
  \u{1D300}-\u{1D356}
1034
1056
  \u{1D360}-\u{1D378}
@@ -1055,17 +1077,27 @@ class Reline::Unicode::EastAsianWidth
1055
1077
  \u{1D7CE}-\u{1DA8B}
1056
1078
  \u{1DA9B}-\u{1DA9F}
1057
1079
  \u{1DAA1}-\u{1DAAF}
1080
+ \u{1DF00}-\u{1DF1E}
1081
+ \u{1DF25}-\u{1DF2A}
1058
1082
  \u{1E000}-\u{1E006}
1059
1083
  \u{1E008}-\u{1E018}
1060
1084
  \u{1E01B}-\u{1E021}
1061
1085
  \u{1E023}-\u{1E024}
1062
1086
  \u{1E026}-\u{1E02A}
1087
+ \u{1E030}-\u{1E06D}
1088
+ \u{1E08F}
1063
1089
  \u{1E100}-\u{1E12C}
1064
1090
  \u{1E130}-\u{1E13D}
1065
1091
  \u{1E140}-\u{1E149}
1066
1092
  \u{1E14E}-\u{1E14F}
1093
+ \u{1E290}-\u{1E2AE}
1067
1094
  \u{1E2C0}-\u{1E2F9}
1068
1095
  \u{1E2FF}
1096
+ \u{1E4D0}-\u{1E4F9}
1097
+ \u{1E7E0}-\u{1E7E6}
1098
+ \u{1E7E8}-\u{1E7EB}
1099
+ \u{1E7ED}-\u{1E7EE}
1100
+ \u{1E7F0}-\u{1E7FE}
1069
1101
  \u{1E800}-\u{1E8C4}
1070
1102
  \u{1E8C7}-\u{1E8D6}
1071
1103
  \u{1E900}-\u{1E94B}
@@ -1142,8 +1174,8 @@ class Reline::Unicode::EastAsianWidth
1142
1174
  \u{1F6D3}-\u{1F6D4}
1143
1175
  \u{1F6E0}-\u{1F6EA}
1144
1176
  \u{1F6F0}-\u{1F6F3}
1145
- \u{1F700}-\u{1F773}
1146
- \u{1F780}-\u{1F7D8}
1177
+ \u{1F700}-\u{1F776}
1178
+ \u{1F77B}-\u{1F7D9}
1147
1179
  \u{1F800}-\u{1F80B}
1148
1180
  \u{1F810}-\u{1F847}
1149
1181
  \u{1F850}-\u{1F859}
@@ -160,16 +160,21 @@ class Reline::Unicode
160
160
  width = 0
161
161
  rest = str.encode(Encoding::UTF_8)
162
162
  in_zero_width = false
163
+ seq = String.new(encoding: encoding)
163
164
  rest.scan(WIDTH_SCANNER) do |gc|
164
165
  case
165
166
  when gc[NON_PRINTING_START_INDEX]
166
167
  in_zero_width = true
168
+ lines.last << NON_PRINTING_START
167
169
  when gc[NON_PRINTING_END_INDEX]
168
170
  in_zero_width = false
171
+ lines.last << NON_PRINTING_END
169
172
  when gc[CSI_REGEXP_INDEX]
170
173
  lines.last << gc[CSI_REGEXP_INDEX]
174
+ seq << gc[CSI_REGEXP_INDEX]
171
175
  when gc[OSC_REGEXP_INDEX]
172
176
  lines.last << gc[OSC_REGEXP_INDEX]
177
+ seq << gc[OSC_REGEXP_INDEX]
173
178
  when gc[GRAPHEME_CLUSTER_INDEX]
174
179
  gc = gc[GRAPHEME_CLUSTER_INDEX]
175
180
  unless in_zero_width
@@ -177,7 +182,7 @@ class Reline::Unicode
177
182
  if (width += mbchar_width) > max_width
178
183
  width = mbchar_width
179
184
  lines << nil
180
- lines << String.new(encoding: encoding)
185
+ lines << seq.dup
181
186
  height += 1
182
187
  end
183
188
  end
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.3.1'
2
+ VERSION = '0.3.3'
3
3
  end
@@ -95,7 +95,7 @@ class Reline::Windows
95
95
  end
96
96
 
97
97
  VK_RETURN = 0x0D
98
- VK_MENU = 0x12
98
+ VK_MENU = 0x12 # ALT key
99
99
  VK_LMENU = 0xA4
100
100
  VK_CONTROL = 0x11
101
101
  VK_SHIFT = 0x10
@@ -249,7 +249,7 @@ class Reline::Windows
249
249
  # no char, only control keys
250
250
  return if key.char_code == 0 and key.control_keys.any?
251
251
 
252
- @@output_buf.push("\e".ord) if key.control_keys.include?(:ALT)
252
+ @@output_buf.push("\e".ord) if key.control_keys.include?(:ALT) and !key.control_keys.include?(:CTRL)
253
253
 
254
254
  @@output_buf.concat(key.char.bytes)
255
255
  end
@@ -291,6 +291,10 @@ class Reline::Windows
291
291
  end
292
292
  end
293
293
 
294
+ def self.with_raw_input
295
+ yield
296
+ end
297
+
294
298
  def self.getc
295
299
  check_input_event
296
300
  @@output_buf.shift
data/lib/reline.rb CHANGED
@@ -11,6 +11,7 @@ require 'reline/terminfo'
11
11
  require 'rbconfig'
12
12
 
13
13
  module Reline
14
+ # NOTE: For making compatible with the rb-readline gem
14
15
  FILENAME_COMPLETION_PROC = nil
15
16
  USERNAME_COMPLETION_PROC = nil
16
17
 
@@ -33,7 +34,18 @@ module Reline
33
34
  alias_method :==, :match?
34
35
  end
35
36
  CursorPos = Struct.new(:x, :y)
36
- DialogRenderInfo = Struct.new(:pos, :contents, :bg_color, :width, :height, :scrollbar, keyword_init: true)
37
+ DialogRenderInfo = Struct.new(
38
+ :pos,
39
+ :contents,
40
+ :bg_color,
41
+ :pointer_bg_color,
42
+ :fg_color,
43
+ :pointer_fg_color,
44
+ :width,
45
+ :height,
46
+ :scrollbar,
47
+ keyword_init: true
48
+ )
37
49
 
38
50
  class Core
39
51
  ATTR_READER_NAMES = %i(
@@ -58,6 +70,11 @@ module Reline
58
70
  attr_accessor :last_incremental_search
59
71
  attr_reader :output
60
72
 
73
+ extend Forwardable
74
+ def_delegators :config,
75
+ :autocompletion,
76
+ :autocompletion=
77
+
61
78
  def initialize
62
79
  self.output = STDOUT
63
80
  @dialog_proc_list = {}
@@ -123,14 +140,6 @@ module Reline
123
140
  @completion_proc = p
124
141
  end
125
142
 
126
- def autocompletion
127
- @config.autocompletion
128
- end
129
-
130
- def autocompletion=(val)
131
- @config.autocompletion = val
132
- end
133
-
134
143
  def output_modifier_proc=(p)
135
144
  raise ArgumentError unless p.respond_to?(:call) or p.nil?
136
145
  @output_modifier_proc = p
@@ -243,24 +252,35 @@ module Reline
243
252
  context.push(cursor_pos_to_render, result, pointer, dialog)
244
253
  end
245
254
  dialog.pointer = pointer
246
- DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, scrollbar: true, height: 15)
255
+ DialogRenderInfo.new(
256
+ pos: cursor_pos_to_render,
257
+ contents: result,
258
+ scrollbar: true,
259
+ height: 15,
260
+ bg_color: 46,
261
+ pointer_bg_color: 45,
262
+ fg_color: 37,
263
+ pointer_fg_color: 37
264
+ )
247
265
  }
248
266
  Reline::DEFAULT_DIALOG_CONTEXT = Array.new
249
267
 
250
268
  def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
251
- unless confirm_multiline_termination
252
- raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
253
- end
254
- inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
269
+ Reline::IOGate.with_raw_input do
270
+ unless confirm_multiline_termination
271
+ raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
272
+ end
273
+ inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
255
274
 
256
- whole_buffer = line_editor.whole_buffer.dup
257
- whole_buffer.taint if RUBY_VERSION < '2.7'
258
- if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
259
- Reline::HISTORY << whole_buffer
260
- end
275
+ whole_buffer = line_editor.whole_buffer.dup
276
+ whole_buffer.taint if RUBY_VERSION < '2.7'
277
+ if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
278
+ Reline::HISTORY << whole_buffer
279
+ end
261
280
 
262
- line_editor.reset_line if line_editor.whole_buffer.nil?
263
- whole_buffer
281
+ line_editor.reset_line if line_editor.whole_buffer.nil?
282
+ whole_buffer
283
+ end
264
284
  end
265
285
 
266
286
  def readline(prompt = '', add_hist = false)
@@ -466,7 +486,7 @@ module Reline
466
486
  end
467
487
 
468
488
  private def may_req_ambiguous_char_width
469
- @ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or STDOUT.is_a?(File)
489
+ @ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or !STDOUT.tty?
470
490
  return if defined? @ambiguous_width
471
491
  Reline::IOGate.move_cursor_column(0)
472
492
  begin
@@ -563,24 +583,21 @@ module Reline
563
583
  end
564
584
 
565
585
  require 'reline/general_io'
566
- if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
567
- require 'reline/windows'
568
- if Reline::Windows.msys_tty?
569
- Reline::IOGate = if ENV['TERM'] == 'dumb'
570
- Reline::GeneralIO
571
- else
572
- require 'reline/ansi'
573
- Reline::ANSI
574
- end
586
+ io = Reline::GeneralIO
587
+ unless ENV['TERM'] == 'dumb'
588
+ case RbConfig::CONFIG['host_os']
589
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
590
+ require 'reline/windows'
591
+ tty = (io = Reline::Windows).msys_tty?
575
592
  else
576
- Reline::IOGate = Reline::Windows
593
+ tty = $stdout.tty?
577
594
  end
595
+ end
596
+ Reline::IOGate = if tty
597
+ require 'reline/ansi'
598
+ Reline::ANSI
578
599
  else
579
- Reline::IOGate = if $stdout.isatty
580
- require 'reline/ansi'
581
- Reline::ANSI
582
- else
583
- Reline::GeneralIO
584
- end
600
+ io
585
601
  end
602
+
586
603
  Reline::HISTORY = Reline::History.new(Reline.core.config)
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.3.1
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-02 00:00:00.000000000 Z
11
+ date: 2023-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console
@@ -47,7 +47,6 @@ files:
47
47
  - lib/reline/key_stroke.rb
48
48
  - lib/reline/kill_ring.rb
49
49
  - lib/reline/line_editor.rb
50
- - lib/reline/sibori.rb
51
50
  - lib/reline/terminfo.rb
52
51
  - lib/reline/unicode.rb
53
52
  - lib/reline/unicode/east_asian_width.rb
@@ -66,14 +65,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
66
65
  requirements:
67
66
  - - ">="
68
67
  - !ruby/object:Gem::Version
69
- version: '2.5'
68
+ version: '2.6'
70
69
  required_rubygems_version: !ruby/object:Gem::Requirement
71
70
  requirements:
72
71
  - - ">="
73
72
  - !ruby/object:Gem::Version
74
73
  version: '0'
75
74
  requirements: []
76
- rubygems_version: 3.0.3.1
75
+ rubygems_version: 3.4.8
77
76
  signing_key:
78
77
  specification_version: 4
79
78
  summary: Alternative GNU Readline or Editline implementation by pure Ruby.
data/lib/reline/sibori.rb DELETED
@@ -1,170 +0,0 @@
1
- require 'reline/unicode'
2
-
3
- =begin
4
-
5
- \ |
6
- \ | <--- whipped cream
7
- \ |
8
- \ |
9
- \-~~|
10
- \ | <--- shibori kutigane (piping nozzle in Japanese)
11
- \Ml
12
- (\ __ __
13
- ( \--( ) )
14
- (__(__)__) <--- compressed whipped cream
15
- =end
16
-
17
- class Sibori
18
- attr_writer :output
19
-
20
- def initialize(width, height, cursor_pos)
21
- @width = width
22
- @height = height
23
- @cursor_pos = cursor_pos
24
- @screen = [String.new]
25
- @line_index = 0
26
- @byte_pointer_in_line = 0
27
- @cleared = false
28
- clone_screen
29
- end
30
-
31
- def clone_screen
32
- @prev_screen = @screen.map { |line|
33
- line.dup
34
- }
35
- @prev_cursor_pos = @cursor_pos.dup
36
- @prev_line_index = @line_index
37
- end
38
-
39
- def print(str)
40
- #$stderr.puts "print #{str.inspect}"
41
- line = @screen[@line_index]
42
- before = line.byteslice(0, @byte_pointer_in_line)
43
- str_width = Reline::Unicode.calculate_width(str, true)
44
- after_cursor = line.byteslice(@byte_pointer_in_line..-1)
45
- after_cursor_width = Reline::Unicode.calculate_width(after_cursor, true)
46
- rest = ''
47
- if after_cursor_width > str_width
48
- rest_byte_pointer = @byte_pointer_in_line + width_to_bytesize(after_cursor, str_width)
49
- rest = line.byteslice(rest_byte_pointer..-1)
50
- end
51
- @screen[@line_index] = before + str + rest
52
- @byte_pointer_in_line += str.bytesize
53
- @cursor_pos.x += Reline::Unicode.calculate_width(str, true)
54
- end
55
-
56
- def move_cursor_column(col)
57
- #$stderr.puts "move_cursor_column(#{col})"
58
- @byte_pointer_in_line = width_to_bytesize(@screen[@line_index], col)
59
- @cursor_pos.x = col
60
- end
61
-
62
- def move_cursor_up(val)
63
- #$stderr.puts "move_cursor_up(#{val})"
64
- if @line_index.positive?
65
- @line_index -= val
66
- @byte_pointer_in_line = width_to_bytesize(@screen[@line_index], @cursor_pos.x)
67
- @cursor_pos.y -= val
68
- end
69
- end
70
-
71
- def move_cursor_down(val)
72
- #$stderr.puts "move_cursor_down(#{val})"
73
- if @line_index < @height - 1
74
- #$stderr.puts "@line_index #{@line_index} @screen.size #{@screen.size} @height #{@height}"
75
- #$stderr.puts @screen.inspect
76
- @line_index += val
77
- @screen[@line_index] = String.new if @line_index == @screen.size
78
- @byte_pointer_in_line = width_to_bytesize(@screen[@line_index], @cursor_pos.x)
79
- @cursor_pos.y += val
80
- end
81
- end
82
-
83
- def scroll_down(val)
84
- #$stderr.puts "scroll_down(#{val})"
85
- if val >= @height
86
- clear_screen
87
- @line_index = @screen.size - 1
88
- return
89
- end
90
- @screen.size.times do |n|
91
- if n < @screen.size - val
92
- #$stderr.puts "A @screen[#{val} + #{n}] (#{@screen[val + n].inspect}) to @screen[#{n}]"
93
- @screen[n] = @screen[val + n]
94
- else
95
- #$stderr.puts "B String.new to @screen[#{n}]"
96
- @screen[n] = String.new
97
- end
98
- end
99
- @line_index += val
100
- end
101
-
102
- def erase_after_cursor
103
- #$stderr.puts "erase_after_cursor"
104
- @screen[@line_index] = @screen[@line_index].byteslice(0, @byte_pointer_in_line)
105
- end
106
-
107
- def clear_screen
108
- #$stderr.puts "clear_screen"
109
- @screen = [String.new]
110
- @line_index = 0
111
- @byte_pointer_in_line = 0
112
- @cursor_pos.x = @cursor_pos.y = 0
113
- @cleared = true
114
- Reline::IOGate.clear_screen
115
- end
116
-
117
- private def width_to_bytesize(str, width)
118
- lines, _ = Reline::Unicode.split_by_width(str, width)
119
- lines.first.bytesize
120
- end
121
-
122
- def render
123
- #$stderr.puts ?* * 100
124
- Reline::IOGate.move_cursor_up(@prev_line_index) if @prev_line_index.positive?
125
- #$stderr.puts "! move_cursor_up(#{@prev_line_index})" if @prev_line_index.positive?
126
- #$stderr.puts "@prev_line_index #{@prev_line_index} @line_index #{@line_index}"
127
- if @screen.size > @prev_screen.size
128
- #$stderr.puts ?a * 100
129
- down = @screen.size - @prev_screen.size
130
- #$stderr.puts "#{@prev_cursor_pos.y} #{down} #{@height}"
131
- if @prev_cursor_pos.y + down > (@height - 1)
132
- #$stderr.puts ?b * 100
133
- scroll = (@prev_cursor_pos.y + down) - (@height - 1)
134
- Reline::IOGate.scroll_down(scroll)
135
- #$stderr.puts "! scroll_down(#{scroll})"
136
- #$stderr.puts "down #{down}"
137
- Reline::IOGate.move_cursor_up(@screen.size - 1 - scroll)
138
- #$stderr.puts "! move_cursor_up(#{@screen.size - 1})"
139
- else
140
- #$stderr.puts ?c * 100
141
- end
142
- end
143
- @screen.size.times do |n|
144
- Reline::IOGate.move_cursor_column(0)
145
- #$stderr.puts "! move_cursor_column(0)"
146
- @output.write @screen[n]
147
- #$stderr.puts "! print #{@screen[n].inspect}"
148
- Reline::IOGate.erase_after_cursor
149
- #$stderr.puts "! erase_after_cursor"
150
- Reline::IOGate.move_cursor_down(1) if n != (@screen.size - 1)
151
- #$stderr.puts "! move_cursor_down(1)" if n != (@screen.size - 1)
152
- end
153
- up = @screen.size - 1 - @line_index
154
- Reline::IOGate.move_cursor_up(up) if up.positive?
155
- #$stderr.puts "! move_cursor_up(#{up})" if up.positive?
156
- column = Reline::Unicode.calculate_width(@screen[@line_index].byteslice(0, @byte_pointer_in_line), true)
157
- Reline::IOGate.move_cursor_column(column)
158
- #$stderr.puts "! move_cursor_column(#{column}) #{@byte_pointer_in_line}"
159
- clone_screen
160
- #$stderr.puts ?- * 10
161
- end
162
-
163
- def prep
164
- Reline::IOGate.prep
165
- end
166
-
167
- def deprep
168
- Reline::IOGate.deprep
169
- end
170
- end