reline 0.5.12 → 0.6.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 +4 -4
- data/lib/reline/io/ansi.rb +36 -21
- data/lib/reline/io/dumb.rb +11 -0
- data/lib/reline/io/windows.rb +11 -1
- data/lib/reline/io.rb +14 -0
- data/lib/reline/key_actor/base.rb +10 -4
- data/lib/reline/key_actor/emacs.rb +96 -96
- data/lib/reline/key_actor/vi_command.rb +182 -182
- data/lib/reline/key_actor/vi_insert.rb +137 -137
- data/lib/reline/key_stroke.rb +10 -11
- data/lib/reline/line_editor.rb +95 -164
- data/lib/reline/unicode.rb +100 -346
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +12 -12
- metadata +6 -4
data/lib/reline/line_editor.rb
CHANGED
@@ -13,7 +13,6 @@ class Reline::LineEditor
|
|
13
13
|
attr_accessor :prompt_proc
|
14
14
|
attr_accessor :auto_indent_proc
|
15
15
|
attr_accessor :dig_perfect_match_proc
|
16
|
-
attr_writer :output
|
17
16
|
|
18
17
|
VI_MOTIONS = %i{
|
19
18
|
ed_prev_char
|
@@ -253,7 +252,7 @@ class Reline::LineEditor
|
|
253
252
|
@rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0)
|
254
253
|
@input_lines = [[[""], 0, 0]]
|
255
254
|
@input_lines_position = 0
|
256
|
-
@
|
255
|
+
@restoring = false
|
257
256
|
@prev_action_state = NullActionState
|
258
257
|
@next_action_state = NullActionState
|
259
258
|
reset_line
|
@@ -414,7 +413,7 @@ class Reline::LineEditor
|
|
414
413
|
# do nothing
|
415
414
|
elsif level == :blank
|
416
415
|
Reline::IOGate.move_cursor_column base_x
|
417
|
-
|
416
|
+
Reline::IOGate.write "#{Reline::IOGate.reset_color_sequence}#{' ' * width}"
|
418
417
|
else
|
419
418
|
x, w, content = new_items[level]
|
420
419
|
cover_begin = base_x != 0 && new_levels[base_x - 1] == level
|
@@ -424,7 +423,7 @@ class Reline::LineEditor
|
|
424
423
|
content, pos = Reline::Unicode.take_mbchar_range(content, base_x - x, width, cover_begin: cover_begin, cover_end: cover_end, padding: true)
|
425
424
|
end
|
426
425
|
Reline::IOGate.move_cursor_column x + pos
|
427
|
-
|
426
|
+
Reline::IOGate.write "#{Reline::IOGate.reset_color_sequence}#{content}#{Reline::IOGate.reset_color_sequence}"
|
428
427
|
end
|
429
428
|
base_x += width
|
430
429
|
end
|
@@ -437,7 +436,7 @@ class Reline::LineEditor
|
|
437
436
|
# Calculate cursor position in word wrapped content.
|
438
437
|
def wrapped_cursor_position
|
439
438
|
prompt_width = calculate_width(prompt_list[@line_index], true)
|
440
|
-
line_before_cursor = whole_lines[@line_index].byteslice(0, @byte_pointer)
|
439
|
+
line_before_cursor = Reline::Unicode.escape_for_print(whole_lines[@line_index].byteslice(0, @byte_pointer))
|
441
440
|
wrapped_line_before_cursor = split_line_by_width(' ' * prompt_width + line_before_cursor, screen_width)
|
442
441
|
wrapped_cursor_y = wrapped_prompt_and_input_lines[0...@line_index].sum(&:size) + wrapped_line_before_cursor.size - 1
|
443
442
|
wrapped_cursor_x = calculate_width(wrapped_line_before_cursor.last)
|
@@ -460,19 +459,21 @@ class Reline::LineEditor
|
|
460
459
|
end
|
461
460
|
|
462
461
|
def render_finished
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
462
|
+
Reline::IOGate.buffered_output do
|
463
|
+
render_differential([], 0, 0)
|
464
|
+
lines = @buffer_of_lines.size.times.map do |i|
|
465
|
+
line = Reline::Unicode.strip_non_printing_start_end(prompt_list[i]) + modified_lines[i]
|
466
|
+
wrapped_lines = split_line_by_width(line, screen_width)
|
467
|
+
wrapped_lines.last.empty? ? "#{line} " : line
|
468
|
+
end
|
469
|
+
Reline::IOGate.write lines.map { |l| "#{l}\r\n" }.join
|
468
470
|
end
|
469
|
-
@output.puts lines.map { |l| "#{l}\r\n" }.join
|
470
471
|
end
|
471
472
|
|
472
473
|
def print_nomultiline_prompt
|
473
474
|
Reline::IOGate.disable_auto_linewrap(true) if Reline::IOGate.win?
|
474
475
|
# Readline's test `TestRelineAsReadline#test_readline` requires first output to be prompt, not cursor reset escape sequence.
|
475
|
-
|
476
|
+
Reline::IOGate.write Reline::Unicode.strip_non_printing_start_end(@prompt) if @prompt && !@is_multiline
|
476
477
|
ensure
|
477
478
|
Reline::IOGate.disable_auto_linewrap(false) if Reline::IOGate.win?
|
478
479
|
end
|
@@ -503,7 +504,9 @@ class Reline::LineEditor
|
|
503
504
|
end
|
504
505
|
end
|
505
506
|
|
506
|
-
|
507
|
+
Reline::IOGate.buffered_output do
|
508
|
+
render_differential new_lines, wrapped_cursor_x, wrapped_cursor_y - screen_scroll_top
|
509
|
+
end
|
507
510
|
end
|
508
511
|
|
509
512
|
# Reflects lines to be rendered and new cursor position to the screen
|
@@ -807,11 +810,11 @@ class Reline::LineEditor
|
|
807
810
|
target = target.downcase if @config.completion_ignore_case
|
808
811
|
list.select do |item|
|
809
812
|
next unless item
|
810
|
-
|
811
813
|
unless Encoding.compatible?(target.encoding, item.encoding)
|
812
|
-
#
|
813
|
-
|
814
|
-
|
814
|
+
# Workaround for Readline test
|
815
|
+
if defined?(::Readline) && ::Readline == ::Reline
|
816
|
+
raise Encoding::CompatibilityError, "incompatible character encodings: #{target.encoding} and #{item.encoding}"
|
817
|
+
end
|
815
818
|
end
|
816
819
|
|
817
820
|
if @config.completion_ignore_case
|
@@ -970,10 +973,18 @@ class Reline::LineEditor
|
|
970
973
|
@drop_terminate_spaces = false
|
971
974
|
end
|
972
975
|
|
976
|
+
ARGUMENT_DIGIT_METHODS = %i[ed_digit vi_zero ed_argument_digit]
|
977
|
+
VI_WAITING_ACCEPT_METHODS = %i[vi_change_meta vi_delete_meta vi_yank ed_insert ed_argument_digit]
|
978
|
+
|
973
979
|
private def process_key(key, method_symbol)
|
974
|
-
if
|
975
|
-
cleanup_waiting
|
976
|
-
|
980
|
+
if @waiting_proc
|
981
|
+
cleanup_waiting unless key.size == 1
|
982
|
+
end
|
983
|
+
if @vi_waiting_operator
|
984
|
+
cleanup_waiting unless VI_WAITING_ACCEPT_METHODS.include?(method_symbol) || VI_MOTIONS.include?(method_symbol)
|
985
|
+
end
|
986
|
+
|
987
|
+
if @waiting_proc
|
977
988
|
old_byte_pointer = @byte_pointer
|
978
989
|
@waiting_proc.call(key)
|
979
990
|
if @vi_waiting_operator
|
@@ -987,23 +998,14 @@ class Reline::LineEditor
|
|
987
998
|
return
|
988
999
|
end
|
989
1000
|
|
1001
|
+
# Reject multibyte input (converted to ed_insert) in vi_command mode
|
1002
|
+
return if method_symbol == :ed_insert && @config.editing_mode_is?(:vi_command)
|
1003
|
+
|
990
1004
|
if method_symbol and respond_to?(method_symbol, true)
|
991
1005
|
method_obj = method(method_symbol)
|
992
1006
|
end
|
993
|
-
if
|
994
|
-
if
|
995
|
-
run_for_operators(key, method_symbol) do |with_operator|
|
996
|
-
wrap_method_call(method_symbol, method_obj, key, with_operator)
|
997
|
-
end
|
998
|
-
else
|
999
|
-
wrap_method_call(method_symbol, method_obj, key) if method_obj
|
1000
|
-
end
|
1001
|
-
@kill_ring.process
|
1002
|
-
if @vi_arg
|
1003
|
-
@vi_arg = nil
|
1004
|
-
end
|
1005
|
-
elsif @vi_arg
|
1006
|
-
if key.chr =~ /[0-9]/
|
1007
|
+
if @vi_arg
|
1008
|
+
if ARGUMENT_DIGIT_METHODS.include?(method_symbol)
|
1007
1009
|
ed_argument_digit(key)
|
1008
1010
|
else
|
1009
1011
|
if argumentable?(method_obj)
|
@@ -1012,13 +1014,9 @@ class Reline::LineEditor
|
|
1012
1014
|
end
|
1013
1015
|
elsif method_obj
|
1014
1016
|
wrap_method_call(method_symbol, method_obj, key)
|
1015
|
-
else
|
1016
|
-
ed_insert(key) unless @config.editing_mode_is?(:vi_command)
|
1017
1017
|
end
|
1018
1018
|
@kill_ring.process
|
1019
|
-
|
1020
|
-
@vi_arg = nil
|
1021
|
-
end
|
1019
|
+
@vi_arg = nil
|
1022
1020
|
end
|
1023
1021
|
elsif method_obj
|
1024
1022
|
if method_symbol == :ed_argument_digit
|
@@ -1029,21 +1027,6 @@ class Reline::LineEditor
|
|
1029
1027
|
end
|
1030
1028
|
end
|
1031
1029
|
@kill_ring.process
|
1032
|
-
else
|
1033
|
-
ed_insert(key) unless @config.editing_mode_is?(:vi_command)
|
1034
|
-
end
|
1035
|
-
end
|
1036
|
-
|
1037
|
-
private def normal_char(key)
|
1038
|
-
if key.char < 0x80
|
1039
|
-
method_symbol = @config.editing_mode.get_method(key.combined_char)
|
1040
|
-
process_key(key.combined_char, method_symbol)
|
1041
|
-
else
|
1042
|
-
process_key(key.char.chr(encoding), nil)
|
1043
|
-
end
|
1044
|
-
if @config.editing_mode_is?(:vi_command) and @byte_pointer > 0 and @byte_pointer == current_line.bytesize
|
1045
|
-
byte_size = Reline::Unicode.get_prev_mbchar_size(@buffer_of_lines[@line_index], @byte_pointer)
|
1046
|
-
@byte_pointer -= byte_size
|
1047
1030
|
end
|
1048
1031
|
end
|
1049
1032
|
|
@@ -1060,23 +1043,23 @@ class Reline::LineEditor
|
|
1060
1043
|
def input_key(key)
|
1061
1044
|
save_old_buffer
|
1062
1045
|
@config.reset_oneshot_key_bindings
|
1063
|
-
@dialogs.each do |dialog|
|
1064
|
-
if key.char.instance_of?(Symbol) and key.char == dialog.name
|
1065
|
-
return
|
1066
|
-
end
|
1067
|
-
end
|
1068
1046
|
if key.char.nil?
|
1069
1047
|
process_insert(force: true)
|
1070
1048
|
@eof = buffer_empty?
|
1071
1049
|
finish
|
1072
1050
|
return
|
1073
1051
|
end
|
1052
|
+
@dialogs.each do |dialog|
|
1053
|
+
if key.method_symbol == dialog.name
|
1054
|
+
return
|
1055
|
+
end
|
1056
|
+
end
|
1074
1057
|
@completion_occurs = false
|
1075
1058
|
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1059
|
+
process_key(key.char, key.method_symbol)
|
1060
|
+
if @config.editing_mode_is?(:vi_command) and @byte_pointer > 0 and @byte_pointer == current_line.bytesize
|
1061
|
+
byte_size = Reline::Unicode.get_prev_mbchar_size(@buffer_of_lines[@line_index], @byte_pointer)
|
1062
|
+
@byte_pointer -= byte_size
|
1080
1063
|
end
|
1081
1064
|
|
1082
1065
|
@prev_action_state, @next_action_state = @next_action_state, NullActionState
|
@@ -1086,8 +1069,8 @@ class Reline::LineEditor
|
|
1086
1069
|
@completion_journey_state = nil
|
1087
1070
|
end
|
1088
1071
|
|
1089
|
-
push_input_lines unless @
|
1090
|
-
@
|
1072
|
+
push_input_lines unless @restoring
|
1073
|
+
@restoring = false
|
1091
1074
|
|
1092
1075
|
if @in_pasting
|
1093
1076
|
clear_dialogs
|
@@ -1201,18 +1184,6 @@ class Reline::LineEditor
|
|
1201
1184
|
process_auto_indent
|
1202
1185
|
end
|
1203
1186
|
|
1204
|
-
def set_current_lines(lines, byte_pointer = nil, line_index = 0)
|
1205
|
-
cursor = current_byte_pointer_cursor
|
1206
|
-
@buffer_of_lines = lines
|
1207
|
-
@line_index = line_index
|
1208
|
-
if byte_pointer
|
1209
|
-
@byte_pointer = byte_pointer
|
1210
|
-
else
|
1211
|
-
calculate_nearest_cursor(cursor)
|
1212
|
-
end
|
1213
|
-
process_auto_indent
|
1214
|
-
end
|
1215
|
-
|
1216
1187
|
def retrieve_completion_block
|
1217
1188
|
quote_characters = Reline.completer_quote_characters
|
1218
1189
|
before = current_line.byteslice(0, @byte_pointer).grapheme_clusters
|
@@ -1255,7 +1226,6 @@ class Reline::LineEditor
|
|
1255
1226
|
end
|
1256
1227
|
|
1257
1228
|
def insert_multiline_text(text)
|
1258
|
-
save_old_buffer
|
1259
1229
|
pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer)
|
1260
1230
|
post = @buffer_of_lines[@line_index].byteslice(@byte_pointer..)
|
1261
1231
|
lines = (pre + Reline::Unicode.safe_encode(text, encoding).gsub(/\r\n?/, "\n") + post).split("\n", -1)
|
@@ -1263,7 +1233,6 @@ class Reline::LineEditor
|
|
1263
1233
|
@buffer_of_lines[@line_index, 1] = lines
|
1264
1234
|
@line_index += lines.size - 1
|
1265
1235
|
@byte_pointer = @buffer_of_lines[@line_index].bytesize - post.bytesize
|
1266
|
-
push_input_lines
|
1267
1236
|
end
|
1268
1237
|
|
1269
1238
|
def insert_text(text)
|
@@ -1429,21 +1398,11 @@ class Reline::LineEditor
|
|
1429
1398
|
# digit or if the existing argument is already greater than a
|
1430
1399
|
# million.
|
1431
1400
|
# GNU Readline:: +self-insert+ (a, b, A, 1, !, …) Insert yourself.
|
1432
|
-
private def ed_insert(
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
return
|
1438
|
-
end
|
1439
|
-
str = key
|
1440
|
-
else
|
1441
|
-
begin
|
1442
|
-
key.chr.encode(Encoding::UTF_8)
|
1443
|
-
rescue Encoding::UndefinedConversionError
|
1444
|
-
return
|
1445
|
-
end
|
1446
|
-
str = key.chr
|
1401
|
+
private def ed_insert(str)
|
1402
|
+
begin
|
1403
|
+
str.encode(Encoding::UTF_8)
|
1404
|
+
rescue Encoding::UndefinedConversionError
|
1405
|
+
return
|
1447
1406
|
end
|
1448
1407
|
if @in_pasting
|
1449
1408
|
@continuous_insertion_buffer << str
|
@@ -1457,21 +1416,16 @@ class Reline::LineEditor
|
|
1457
1416
|
alias_method :ed_digit, :ed_insert
|
1458
1417
|
alias_method :self_insert, :ed_insert
|
1459
1418
|
|
1460
|
-
private def
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
else
|
1468
|
-
ed_insert(key)
|
1469
|
-
end
|
1419
|
+
private def insert_raw_char(str, arg: 1)
|
1420
|
+
arg.times do
|
1421
|
+
if str == "\C-j" or str == "\C-m"
|
1422
|
+
key_newline(str)
|
1423
|
+
elsif str != "\0"
|
1424
|
+
# Ignore NUL.
|
1425
|
+
ed_insert(str)
|
1470
1426
|
end
|
1471
|
-
|
1472
|
-
}
|
1427
|
+
end
|
1473
1428
|
end
|
1474
|
-
alias_method :quoted_insert, :ed_quoted_insert
|
1475
1429
|
|
1476
1430
|
private def ed_next_char(key, arg: 1)
|
1477
1431
|
byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
|
@@ -1520,13 +1474,13 @@ class Reline::LineEditor
|
|
1520
1474
|
lambda do |key|
|
1521
1475
|
search_again = false
|
1522
1476
|
case key
|
1523
|
-
when "\C-h"
|
1477
|
+
when "\C-h", "\C-?"
|
1524
1478
|
grapheme_clusters = search_word.grapheme_clusters
|
1525
1479
|
if grapheme_clusters.size > 0
|
1526
1480
|
grapheme_clusters.pop
|
1527
1481
|
search_word = grapheme_clusters.join
|
1528
1482
|
end
|
1529
|
-
when "\C-r"
|
1483
|
+
when "\C-r", "\C-s"
|
1530
1484
|
search_again = true if search_key == key
|
1531
1485
|
search_key = key
|
1532
1486
|
else
|
@@ -1543,10 +1497,10 @@ class Reline::LineEditor
|
|
1543
1497
|
end
|
1544
1498
|
if @history_pointer
|
1545
1499
|
case search_key
|
1546
|
-
when "\C-r"
|
1500
|
+
when "\C-r"
|
1547
1501
|
history_pointer_base = 0
|
1548
1502
|
history = Reline::HISTORY[0..(@history_pointer - 1)]
|
1549
|
-
when "\C-s"
|
1503
|
+
when "\C-s"
|
1550
1504
|
history_pointer_base = @history_pointer + 1
|
1551
1505
|
history = Reline::HISTORY[(@history_pointer + 1)..-1]
|
1552
1506
|
end
|
@@ -1556,10 +1510,10 @@ class Reline::LineEditor
|
|
1556
1510
|
end
|
1557
1511
|
elsif @history_pointer
|
1558
1512
|
case search_key
|
1559
|
-
when "\C-r"
|
1513
|
+
when "\C-r"
|
1560
1514
|
history_pointer_base = 0
|
1561
1515
|
history = Reline::HISTORY[0..@history_pointer]
|
1562
|
-
when "\C-s"
|
1516
|
+
when "\C-s"
|
1563
1517
|
history_pointer_base = @history_pointer
|
1564
1518
|
history = Reline::HISTORY[@history_pointer..-1]
|
1565
1519
|
end
|
@@ -1568,11 +1522,11 @@ class Reline::LineEditor
|
|
1568
1522
|
history = Reline::HISTORY
|
1569
1523
|
end
|
1570
1524
|
case search_key
|
1571
|
-
when "\C-r"
|
1525
|
+
when "\C-r"
|
1572
1526
|
hit_index = history.rindex { |item|
|
1573
1527
|
item.include?(search_word)
|
1574
1528
|
}
|
1575
|
-
when "\C-s"
|
1529
|
+
when "\C-s"
|
1576
1530
|
hit_index = history.index { |item|
|
1577
1531
|
item.include?(search_word)
|
1578
1532
|
}
|
@@ -1583,9 +1537,9 @@ class Reline::LineEditor
|
|
1583
1537
|
end
|
1584
1538
|
end
|
1585
1539
|
case search_key
|
1586
|
-
when "\C-r"
|
1540
|
+
when "\C-r"
|
1587
1541
|
prompt_name = 'reverse-i-search'
|
1588
|
-
when "\C-s"
|
1542
|
+
when "\C-s"
|
1589
1543
|
prompt_name = 'i-search'
|
1590
1544
|
end
|
1591
1545
|
prompt_name = "failed #{prompt_name}" unless hit
|
@@ -1597,16 +1551,15 @@ class Reline::LineEditor
|
|
1597
1551
|
backup = @buffer_of_lines.dup, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history
|
1598
1552
|
searcher = generate_searcher(key)
|
1599
1553
|
@searching_prompt = "(reverse-i-search)`': "
|
1600
|
-
termination_keys = ["\C-j"
|
1601
|
-
termination_keys.concat(@config.isearch_terminators.chars
|
1554
|
+
termination_keys = ["\C-j"]
|
1555
|
+
termination_keys.concat(@config.isearch_terminators.chars) if @config.isearch_terminators
|
1602
1556
|
@waiting_proc = ->(k) {
|
1603
|
-
|
1604
|
-
if k == "\C-g".ord
|
1557
|
+
if k == "\C-g"
|
1605
1558
|
# cancel search and restore buffer
|
1606
1559
|
@buffer_of_lines, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history = backup
|
1607
1560
|
@searching_prompt = nil
|
1608
1561
|
@waiting_proc = nil
|
1609
|
-
elsif !termination_keys.include?(k) && (
|
1562
|
+
elsif !termination_keys.include?(k) && (k.match?(/[[:print:]]/) || k == "\C-h" || k == "\C-?" || k == "\C-r" || k == "\C-s")
|
1610
1563
|
search_word, prompt_name, hit_pointer = searcher.call(k)
|
1611
1564
|
Reline.last_incremental_search = search_word
|
1612
1565
|
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
|
@@ -1822,7 +1775,7 @@ class Reline::LineEditor
|
|
1822
1775
|
alias_method :kill_whole_line, :em_kill_line
|
1823
1776
|
|
1824
1777
|
private def em_delete(key)
|
1825
|
-
if buffer_empty? and key == "\C-d"
|
1778
|
+
if buffer_empty? and key == "\C-d"
|
1826
1779
|
@eof = true
|
1827
1780
|
finish
|
1828
1781
|
elsif @byte_pointer < current_line.bytesize
|
@@ -2240,20 +2193,9 @@ class Reline::LineEditor
|
|
2240
2193
|
end
|
2241
2194
|
|
2242
2195
|
private def ed_argument_digit(key)
|
2243
|
-
|
2244
|
-
|
2245
|
-
|
2246
|
-
unescaped_key = key ^ 0b10000000
|
2247
|
-
unless unescaped_key.chr.to_i.zero?
|
2248
|
-
@vi_arg = unescaped_key.chr.to_i
|
2249
|
-
end
|
2250
|
-
end
|
2251
|
-
else
|
2252
|
-
@vi_arg = key.chr.to_i
|
2253
|
-
end
|
2254
|
-
else
|
2255
|
-
@vi_arg = @vi_arg * 10 + key.chr.to_i
|
2256
|
-
end
|
2196
|
+
# key is expected to be `ESC digit` or `digit`
|
2197
|
+
num = key[/\d/].to_i
|
2198
|
+
@vi_arg = (@vi_arg || 0) * 10 + num
|
2257
2199
|
end
|
2258
2200
|
|
2259
2201
|
private def vi_to_column(key, arg: 0)
|
@@ -2272,7 +2214,7 @@ class Reline::LineEditor
|
|
2272
2214
|
before = current_line.byteslice(0, @byte_pointer)
|
2273
2215
|
remaining_point = @byte_pointer + byte_size
|
2274
2216
|
after = current_line.byteslice(remaining_point, current_line.bytesize - remaining_point)
|
2275
|
-
set_current_line(before + k
|
2217
|
+
set_current_line(before + k + after)
|
2276
2218
|
@waiting_proc = nil
|
2277
2219
|
elsif arg > 1
|
2278
2220
|
byte_size = 0
|
@@ -2282,7 +2224,7 @@ class Reline::LineEditor
|
|
2282
2224
|
before = current_line.byteslice(0, @byte_pointer)
|
2283
2225
|
remaining_point = @byte_pointer + byte_size
|
2284
2226
|
after = current_line.byteslice(remaining_point, current_line.bytesize - remaining_point)
|
2285
|
-
replaced = k
|
2227
|
+
replaced = k * arg
|
2286
2228
|
set_current_line(before + replaced + after, @byte_pointer + replaced.bytesize)
|
2287
2229
|
@waiting_proc = nil
|
2288
2230
|
end
|
@@ -2298,11 +2240,6 @@ class Reline::LineEditor
|
|
2298
2240
|
end
|
2299
2241
|
|
2300
2242
|
private def search_next_char(key, arg, need_prev_char: false, inclusive: false)
|
2301
|
-
if key.instance_of?(String)
|
2302
|
-
inputted_char = key
|
2303
|
-
else
|
2304
|
-
inputted_char = key.chr
|
2305
|
-
end
|
2306
2243
|
prev_total = nil
|
2307
2244
|
total = nil
|
2308
2245
|
found = false
|
@@ -2313,7 +2250,7 @@ class Reline::LineEditor
|
|
2313
2250
|
width = Reline::Unicode.get_mbchar_width(mbchar)
|
2314
2251
|
total = [mbchar.bytesize, width]
|
2315
2252
|
else
|
2316
|
-
if
|
2253
|
+
if key == mbchar
|
2317
2254
|
arg -= 1
|
2318
2255
|
if arg.zero?
|
2319
2256
|
found = true
|
@@ -2350,11 +2287,6 @@ class Reline::LineEditor
|
|
2350
2287
|
end
|
2351
2288
|
|
2352
2289
|
private def search_prev_char(key, arg, need_next_char = false)
|
2353
|
-
if key.instance_of?(String)
|
2354
|
-
inputted_char = key
|
2355
|
-
else
|
2356
|
-
inputted_char = key.chr
|
2357
|
-
end
|
2358
2290
|
prev_total = nil
|
2359
2291
|
total = nil
|
2360
2292
|
found = false
|
@@ -2365,7 +2297,7 @@ class Reline::LineEditor
|
|
2365
2297
|
width = Reline::Unicode.get_mbchar_width(mbchar)
|
2366
2298
|
total = [mbchar.bytesize, width]
|
2367
2299
|
else
|
2368
|
-
if
|
2300
|
+
if key == mbchar
|
2369
2301
|
arg -= 1
|
2370
2302
|
if arg.zero?
|
2371
2303
|
found = true
|
@@ -2417,24 +2349,23 @@ class Reline::LineEditor
|
|
2417
2349
|
@config.editing_mode = :vi_insert
|
2418
2350
|
end
|
2419
2351
|
|
2420
|
-
private def
|
2421
|
-
@
|
2352
|
+
private def move_undo_redo(direction)
|
2353
|
+
@restoring = true
|
2354
|
+
return unless (0..@input_lines.size - 1).cover?(@input_lines_position + direction)
|
2422
2355
|
|
2423
|
-
|
2356
|
+
@input_lines_position += direction
|
2357
|
+
buffer_of_lines, byte_pointer, line_index = @input_lines[@input_lines_position]
|
2358
|
+
@buffer_of_lines = buffer_of_lines.dup
|
2359
|
+
@line_index = line_index
|
2360
|
+
@byte_pointer = byte_pointer
|
2361
|
+
end
|
2424
2362
|
|
2425
|
-
|
2426
|
-
|
2427
|
-
set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
|
2363
|
+
private def undo(_key)
|
2364
|
+
move_undo_redo(-1)
|
2428
2365
|
end
|
2429
2366
|
|
2430
2367
|
private def redo(_key)
|
2431
|
-
|
2432
|
-
|
2433
|
-
return if @input_lines_position >= @input_lines.size - 1
|
2434
|
-
|
2435
|
-
@input_lines_position += 1
|
2436
|
-
target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
|
2437
|
-
set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
|
2368
|
+
move_undo_redo(+1)
|
2438
2369
|
end
|
2439
2370
|
|
2440
2371
|
private def prev_action_state_value(type)
|