reline 0.5.1 → 0.5.3
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/key_actor/emacs.rb +11 -11
- data/lib/reline/key_actor/vi_command.rb +23 -23
- data/lib/reline/key_actor/vi_insert.rb +2 -2
- data/lib/reline/line_editor.rb +303 -452
- data/lib/reline/unicode.rb +2 -2
- data/lib/reline/version.rb +1 -1
- metadata +2 -2
data/lib/reline/line_editor.rb
CHANGED
@@ -33,8 +33,6 @@ class Reline::LineEditor
|
|
33
33
|
vi_next_big_word
|
34
34
|
vi_prev_big_word
|
35
35
|
vi_end_big_word
|
36
|
-
vi_repeat_next_char
|
37
|
-
vi_repeat_prev_char
|
38
36
|
}
|
39
37
|
|
40
38
|
module CompletionState
|
@@ -114,7 +112,11 @@ class Reline::LineEditor
|
|
114
112
|
else
|
115
113
|
prompt = @prompt
|
116
114
|
end
|
117
|
-
if
|
115
|
+
if !@is_multiline
|
116
|
+
mode_string = check_mode_string
|
117
|
+
prompt = mode_string + prompt if mode_string
|
118
|
+
[prompt] + [''] * (buffer.size - 1)
|
119
|
+
elsif @prompt_proc
|
118
120
|
prompt_list = @prompt_proc.(buffer).map { |pr| pr.gsub("\n", "\\n") }
|
119
121
|
prompt_list.map!{ prompt } if @vi_arg or @searching_prompt
|
120
122
|
prompt_list = [prompt] if prompt_list.empty?
|
@@ -229,10 +231,11 @@ class Reline::LineEditor
|
|
229
231
|
@vi_clipboard = ''
|
230
232
|
@vi_arg = nil
|
231
233
|
@waiting_proc = nil
|
232
|
-
@
|
233
|
-
@
|
234
|
+
@vi_waiting_operator = nil
|
235
|
+
@vi_waiting_operator_arg = nil
|
234
236
|
@completion_journey_state = nil
|
235
237
|
@completion_state = CompletionState::NORMAL
|
238
|
+
@completion_occurs = false
|
236
239
|
@perfect_matched = nil
|
237
240
|
@menu_info = nil
|
238
241
|
@searching_prompt = nil
|
@@ -292,8 +295,8 @@ class Reline::LineEditor
|
|
292
295
|
end
|
293
296
|
end
|
294
297
|
|
295
|
-
private def split_by_width(str, max_width)
|
296
|
-
Reline::Unicode.split_by_width(str, max_width, @encoding)
|
298
|
+
private def split_by_width(str, max_width, offset: 0)
|
299
|
+
Reline::Unicode.split_by_width(str, max_width, @encoding, offset: offset)
|
297
300
|
end
|
298
301
|
|
299
302
|
def current_byte_pointer_cursor
|
@@ -367,7 +370,7 @@ class Reline::LineEditor
|
|
367
370
|
@scroll_partial_screen
|
368
371
|
end
|
369
372
|
|
370
|
-
def
|
373
|
+
def wrapped_prompt_and_input_lines
|
371
374
|
with_cache(__method__, @buffer_of_lines.size, modified_lines, prompt_list, screen_width) do |n, lines, prompts, width, prev_cache_key, cached_value|
|
372
375
|
prev_n, prev_lines, prev_prompts, prev_width = prev_cache_key
|
373
376
|
cached_wraps = {}
|
@@ -378,9 +381,14 @@ class Reline::LineEditor
|
|
378
381
|
end
|
379
382
|
|
380
383
|
n.times.map do |i|
|
381
|
-
prompt = prompts[i]
|
382
|
-
line = lines[i]
|
383
|
-
cached_wraps[[prompt, line]]
|
384
|
+
prompt = prompts[i] || ''
|
385
|
+
line = lines[i] || ''
|
386
|
+
if (cached = cached_wraps[[prompt, line]])
|
387
|
+
next cached
|
388
|
+
end
|
389
|
+
*wrapped_prompts, code_line_prompt = split_by_width(prompt, width).first.compact
|
390
|
+
wrapped_lines = split_by_width(line, width, offset: calculate_width(code_line_prompt)).first.compact
|
391
|
+
wrapped_prompts.map { |p| [p, ''] } + [[code_line_prompt, wrapped_lines.first]] + wrapped_lines.drop(1).map { |c| ['', c] }
|
384
392
|
end
|
385
393
|
end
|
386
394
|
end
|
@@ -423,7 +431,7 @@ class Reline::LineEditor
|
|
423
431
|
prompt_width = calculate_width(prompt_list[@line_index], true)
|
424
432
|
line_before_cursor = whole_lines[@line_index].byteslice(0, @byte_pointer)
|
425
433
|
wrapped_line_before_cursor = split_by_width(' ' * prompt_width + line_before_cursor, screen_width).first.compact
|
426
|
-
wrapped_cursor_y =
|
434
|
+
wrapped_cursor_y = wrapped_prompt_and_input_lines[0...@line_index].sum(&:size) + wrapped_line_before_cursor.size - 1
|
427
435
|
wrapped_cursor_x = calculate_width(wrapped_line_before_cursor.last)
|
428
436
|
[wrapped_cursor_x, wrapped_cursor_y]
|
429
437
|
end
|
@@ -487,8 +495,9 @@ class Reline::LineEditor
|
|
487
495
|
wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
|
488
496
|
|
489
497
|
rendered_lines = @rendered_screen.lines
|
490
|
-
new_lines =
|
491
|
-
|
498
|
+
new_lines = wrapped_prompt_and_input_lines.flatten(1)[screen_scroll_top, screen_height].map do |prompt, line|
|
499
|
+
prompt_width = Reline::Unicode.calculate_width(prompt, true)
|
500
|
+
[[0, prompt_width, prompt], [prompt_width, Reline::Unicode.calculate_width(line, true), line]]
|
492
501
|
end
|
493
502
|
if @menu_info
|
494
503
|
@menu_info.lines(screen_width).each do |item|
|
@@ -504,7 +513,8 @@ class Reline::LineEditor
|
|
504
513
|
y_range.each do |row|
|
505
514
|
next if row < 0 || row >= screen_height
|
506
515
|
dialog_rows = new_lines[row] ||= []
|
507
|
-
|
516
|
+
# index 0 is for prompt, index 1 is for line, index 2.. is for dialog
|
517
|
+
dialog_rows[index + 2] = [x_range.begin, dialog.width, dialog.contents[row - y_range.begin]]
|
508
518
|
end
|
509
519
|
end
|
510
520
|
|
@@ -541,10 +551,6 @@ class Reline::LineEditor
|
|
541
551
|
new_lines.size - y
|
542
552
|
end
|
543
553
|
|
544
|
-
def current_row
|
545
|
-
wrapped_lines.flatten[wrapped_cursor_y]
|
546
|
-
end
|
547
|
-
|
548
554
|
def upper_space_height(wrapped_cursor_y)
|
549
555
|
wrapped_cursor_y - screen_scroll_top
|
550
556
|
end
|
@@ -881,10 +887,12 @@ class Reline::LineEditor
|
|
881
887
|
@completion_state = CompletionState::PERFECT_MATCH
|
882
888
|
else
|
883
889
|
@completion_state = CompletionState::MENU_WITH_PERFECT_MATCH
|
890
|
+
complete(list, true) if @config.show_all_if_ambiguous
|
884
891
|
end
|
885
892
|
@perfect_matched = completed
|
886
893
|
else
|
887
894
|
@completion_state = CompletionState::MENU
|
895
|
+
complete(list, true) if @config.show_all_if_ambiguous
|
888
896
|
end
|
889
897
|
if not just_show_list and target < completed
|
890
898
|
@buffer_of_lines[@line_index] = (preposing + completed + completion_append_character.to_s + postposing).split("\n")[@line_index] || String.new(encoding: @encoding)
|
@@ -935,37 +943,23 @@ class Reline::LineEditor
|
|
935
943
|
end
|
936
944
|
|
937
945
|
private def run_for_operators(key, method_symbol, &block)
|
938
|
-
if @
|
946
|
+
if @vi_waiting_operator
|
939
947
|
if VI_MOTIONS.include?(method_symbol)
|
940
948
|
old_byte_pointer = @byte_pointer
|
941
|
-
@vi_arg = @
|
949
|
+
@vi_arg = (@vi_arg || 1) * @vi_waiting_operator_arg
|
942
950
|
block.(true)
|
943
951
|
unless @waiting_proc
|
944
952
|
byte_pointer_diff = @byte_pointer - old_byte_pointer
|
945
953
|
@byte_pointer = old_byte_pointer
|
946
|
-
@
|
947
|
-
|
948
|
-
old_waiting_proc = @waiting_proc
|
949
|
-
old_waiting_operator_proc = @waiting_operator_proc
|
950
|
-
current_waiting_operator_proc = @waiting_operator_proc
|
951
|
-
@waiting_proc = proc { |k|
|
952
|
-
old_byte_pointer = @byte_pointer
|
953
|
-
old_waiting_proc.(k)
|
954
|
-
byte_pointer_diff = @byte_pointer - old_byte_pointer
|
955
|
-
@byte_pointer = old_byte_pointer
|
956
|
-
current_waiting_operator_proc.(byte_pointer_diff)
|
957
|
-
@waiting_operator_proc = old_waiting_operator_proc
|
958
|
-
}
|
954
|
+
send(@vi_waiting_operator, byte_pointer_diff)
|
955
|
+
cleanup_waiting
|
959
956
|
end
|
960
957
|
else
|
961
958
|
# Ignores operator when not motion is given.
|
962
959
|
block.(false)
|
960
|
+
cleanup_waiting
|
963
961
|
end
|
964
|
-
@
|
965
|
-
@waiting_operator_vi_arg = nil
|
966
|
-
if @vi_arg
|
967
|
-
@vi_arg = nil
|
968
|
-
end
|
962
|
+
@vi_arg = nil
|
969
963
|
else
|
970
964
|
block.(false)
|
971
965
|
end
|
@@ -982,7 +976,7 @@ class Reline::LineEditor
|
|
982
976
|
end
|
983
977
|
|
984
978
|
def wrap_method_call(method_symbol, method_obj, key, with_operator = false)
|
985
|
-
if @config.editing_mode_is?(:emacs, :vi_insert) and @
|
979
|
+
if @config.editing_mode_is?(:emacs, :vi_insert) and @vi_waiting_operator.nil?
|
986
980
|
not_insertion = method_symbol != :ed_insert
|
987
981
|
process_insert(force: not_insertion)
|
988
982
|
end
|
@@ -1001,11 +995,32 @@ class Reline::LineEditor
|
|
1001
995
|
end
|
1002
996
|
end
|
1003
997
|
|
998
|
+
private def cleanup_waiting
|
999
|
+
@waiting_proc = nil
|
1000
|
+
@vi_waiting_operator = nil
|
1001
|
+
@vi_waiting_operator_arg = nil
|
1002
|
+
@searching_prompt = nil
|
1003
|
+
@drop_terminate_spaces = false
|
1004
|
+
end
|
1005
|
+
|
1004
1006
|
private def process_key(key, method_symbol)
|
1007
|
+
if key.is_a?(Symbol)
|
1008
|
+
cleanup_waiting
|
1009
|
+
elsif @waiting_proc
|
1010
|
+
old_byte_pointer = @byte_pointer
|
1011
|
+
@waiting_proc.call(key)
|
1012
|
+
if @vi_waiting_operator
|
1013
|
+
byte_pointer_diff = @byte_pointer - old_byte_pointer
|
1014
|
+
@byte_pointer = old_byte_pointer
|
1015
|
+
send(@vi_waiting_operator, byte_pointer_diff)
|
1016
|
+
cleanup_waiting
|
1017
|
+
end
|
1018
|
+
@kill_ring.process
|
1019
|
+
return
|
1020
|
+
end
|
1021
|
+
|
1005
1022
|
if method_symbol and respond_to?(method_symbol, true)
|
1006
1023
|
method_obj = method(method_symbol)
|
1007
|
-
else
|
1008
|
-
method_obj = nil
|
1009
1024
|
end
|
1010
1025
|
if method_symbol and key.is_a?(Symbol)
|
1011
1026
|
if @vi_arg and argumentable?(method_obj)
|
@@ -1027,8 +1042,6 @@ class Reline::LineEditor
|
|
1027
1042
|
run_for_operators(key, method_symbol) do |with_operator|
|
1028
1043
|
wrap_method_call(method_symbol, method_obj, key, with_operator)
|
1029
1044
|
end
|
1030
|
-
elsif @waiting_proc
|
1031
|
-
@waiting_proc.(key)
|
1032
1045
|
elsif method_obj
|
1033
1046
|
wrap_method_call(method_symbol, method_obj, key)
|
1034
1047
|
else
|
@@ -1039,9 +1052,6 @@ class Reline::LineEditor
|
|
1039
1052
|
@vi_arg = nil
|
1040
1053
|
end
|
1041
1054
|
end
|
1042
|
-
elsif @waiting_proc
|
1043
|
-
@waiting_proc.(key)
|
1044
|
-
@kill_ring.process
|
1045
1055
|
elsif method_obj
|
1046
1056
|
if method_symbol == :ed_argument_digit
|
1047
1057
|
wrap_method_call(method_symbol, method_obj, key)
|
@@ -1118,42 +1128,35 @@ class Reline::LineEditor
|
|
1118
1128
|
end
|
1119
1129
|
old_lines = @buffer_of_lines.dup
|
1120
1130
|
@first_char = false
|
1121
|
-
completion_occurs = false
|
1131
|
+
@completion_occurs = false
|
1122
1132
|
if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord
|
1123
1133
|
if !@config.disable_completion
|
1124
1134
|
process_insert(force: true)
|
1125
1135
|
if @config.autocompletion
|
1126
1136
|
@completion_state = CompletionState::NORMAL
|
1127
|
-
completion_occurs = move_completed_list(:down)
|
1137
|
+
@completion_occurs = move_completed_list(:down)
|
1128
1138
|
else
|
1129
1139
|
@completion_journey_state = nil
|
1130
1140
|
result = call_completion_proc
|
1131
1141
|
if result.is_a?(Array)
|
1132
|
-
completion_occurs = true
|
1142
|
+
@completion_occurs = true
|
1133
1143
|
complete(result, false)
|
1134
1144
|
end
|
1135
1145
|
end
|
1136
1146
|
end
|
1137
|
-
elsif @config.editing_mode_is?(:emacs, :vi_insert) and key.char == :completion_journey_up
|
1138
|
-
if not @config.disable_completion and @config.autocompletion
|
1139
|
-
process_insert(force: true)
|
1140
|
-
@completion_state = CompletionState::NORMAL
|
1141
|
-
completion_occurs = move_completed_list(:up)
|
1142
|
-
end
|
1143
1147
|
elsif @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char)
|
1144
1148
|
# In vi mode, move completed list even if autocompletion is off
|
1145
1149
|
if not @config.disable_completion
|
1146
1150
|
process_insert(force: true)
|
1147
1151
|
@completion_state = CompletionState::NORMAL
|
1148
|
-
completion_occurs = move_completed_list("\C-p".ord == key.char ? :up : :down)
|
1152
|
+
@completion_occurs = move_completed_list("\C-p".ord == key.char ? :up : :down)
|
1149
1153
|
end
|
1150
1154
|
elsif Symbol === key.char and respond_to?(key.char, true)
|
1151
1155
|
process_key(key.char, key.char)
|
1152
1156
|
else
|
1153
1157
|
normal_char(key)
|
1154
1158
|
end
|
1155
|
-
|
1156
|
-
unless completion_occurs
|
1159
|
+
unless @completion_occurs
|
1157
1160
|
@completion_state = CompletionState::NORMAL
|
1158
1161
|
@completion_journey_state = nil
|
1159
1162
|
end
|
@@ -1164,7 +1167,7 @@ class Reline::LineEditor
|
|
1164
1167
|
end
|
1165
1168
|
|
1166
1169
|
modified = old_lines != @buffer_of_lines
|
1167
|
-
if
|
1170
|
+
if !@completion_occurs && modified && !@config.disable_completion && @config.autocompletion
|
1168
1171
|
# Auto complete starts only when edited
|
1169
1172
|
process_insert(force: true)
|
1170
1173
|
@completion_journey_state = retrieve_completion_journey_state
|
@@ -1230,7 +1233,7 @@ class Reline::LineEditor
|
|
1230
1233
|
end
|
1231
1234
|
|
1232
1235
|
def line()
|
1233
|
-
|
1236
|
+
@buffer_of_lines.join("\n") unless eof?
|
1234
1237
|
end
|
1235
1238
|
|
1236
1239
|
def current_line
|
@@ -1314,14 +1317,12 @@ class Reline::LineEditor
|
|
1314
1317
|
end
|
1315
1318
|
target = before
|
1316
1319
|
end
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n")
|
1324
|
-
end
|
1320
|
+
lines = whole_lines
|
1321
|
+
if @line_index > 0
|
1322
|
+
preposing = lines[0..(@line_index - 1)].join("\n") + "\n" + preposing
|
1323
|
+
end
|
1324
|
+
if (lines.size - 1) > @line_index
|
1325
|
+
postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n")
|
1325
1326
|
end
|
1326
1327
|
[preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
|
1327
1328
|
end
|
@@ -1343,20 +1344,16 @@ class Reline::LineEditor
|
|
1343
1344
|
|
1344
1345
|
def delete_text(start = nil, length = nil)
|
1345
1346
|
if start.nil? and length.nil?
|
1346
|
-
if @
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
@byte_pointer = 0
|
1357
|
-
end
|
1358
|
-
else
|
1359
|
-
set_current_line('', 0)
|
1347
|
+
if @buffer_of_lines.size == 1
|
1348
|
+
@buffer_of_lines[@line_index] = ''
|
1349
|
+
@byte_pointer = 0
|
1350
|
+
elsif @line_index == (@buffer_of_lines.size - 1) and @line_index > 0
|
1351
|
+
@buffer_of_lines.pop
|
1352
|
+
@line_index -= 1
|
1353
|
+
@byte_pointer = 0
|
1354
|
+
elsif @line_index < (@buffer_of_lines.size - 1)
|
1355
|
+
@buffer_of_lines.delete_at(@line_index)
|
1356
|
+
@byte_pointer = 0
|
1360
1357
|
end
|
1361
1358
|
elsif not start.nil? and not length.nil?
|
1362
1359
|
if current_line
|
@@ -1433,6 +1430,14 @@ class Reline::LineEditor
|
|
1433
1430
|
end
|
1434
1431
|
end
|
1435
1432
|
|
1433
|
+
private def completion_journey_up(key)
|
1434
|
+
if not @config.disable_completion and @config.autocompletion
|
1435
|
+
@completion_state = CompletionState::NORMAL
|
1436
|
+
@completion_occurs = move_completed_list(:up)
|
1437
|
+
end
|
1438
|
+
end
|
1439
|
+
alias_method :menu_complete_backward, :completion_journey_up
|
1440
|
+
|
1436
1441
|
# Editline:: +ed-unassigned+ This editor command always results in an error.
|
1437
1442
|
# GNU Readline:: There is no corresponding macro.
|
1438
1443
|
private def ed_unassigned(key) end # do nothing
|
@@ -1504,7 +1509,7 @@ class Reline::LineEditor
|
|
1504
1509
|
byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
|
1505
1510
|
if (@byte_pointer < current_line.bytesize)
|
1506
1511
|
@byte_pointer += byte_size
|
1507
|
-
elsif @
|
1512
|
+
elsif @config.editing_mode_is?(:emacs) and @byte_pointer == current_line.bytesize and @line_index < @buffer_of_lines.size - 1
|
1508
1513
|
@byte_pointer = 0
|
1509
1514
|
@line_index += 1
|
1510
1515
|
end
|
@@ -1517,7 +1522,7 @@ class Reline::LineEditor
|
|
1517
1522
|
if @byte_pointer > 0
|
1518
1523
|
byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
|
1519
1524
|
@byte_pointer -= byte_size
|
1520
|
-
elsif @
|
1525
|
+
elsif @config.editing_mode_is?(:emacs) and @byte_pointer == 0 and @line_index > 0
|
1521
1526
|
@line_index -= 1
|
1522
1527
|
@byte_pointer = current_line.bytesize
|
1523
1528
|
end
|
@@ -1534,6 +1539,7 @@ class Reline::LineEditor
|
|
1534
1539
|
@byte_pointer = 0
|
1535
1540
|
end
|
1536
1541
|
alias_method :beginning_of_line, :ed_move_to_beg
|
1542
|
+
alias_method :vi_zero, :ed_move_to_beg
|
1537
1543
|
|
1538
1544
|
private def ed_move_to_end(key)
|
1539
1545
|
@byte_pointer = 0
|
@@ -1544,131 +1550,95 @@ class Reline::LineEditor
|
|
1544
1550
|
end
|
1545
1551
|
alias_method :end_of_line, :ed_move_to_end
|
1546
1552
|
|
1547
|
-
private def generate_searcher
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
case
|
1554
|
-
when "\C-
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1553
|
+
private def generate_searcher(search_key)
|
1554
|
+
search_word = String.new(encoding: @encoding)
|
1555
|
+
multibyte_buf = String.new(encoding: 'ASCII-8BIT')
|
1556
|
+
hit_pointer = nil
|
1557
|
+
lambda do |key|
|
1558
|
+
search_again = false
|
1559
|
+
case key
|
1560
|
+
when "\C-h".ord, "\C-?".ord
|
1561
|
+
grapheme_clusters = search_word.grapheme_clusters
|
1562
|
+
if grapheme_clusters.size > 0
|
1563
|
+
grapheme_clusters.pop
|
1564
|
+
search_word = grapheme_clusters.join
|
1565
|
+
end
|
1566
|
+
when "\C-r".ord, "\C-s".ord
|
1567
|
+
search_again = true if search_key == key
|
1568
|
+
search_key = key
|
1569
|
+
else
|
1570
|
+
multibyte_buf << key
|
1571
|
+
if multibyte_buf.dup.force_encoding(@encoding).valid_encoding?
|
1572
|
+
search_word << multibyte_buf.dup.force_encoding(@encoding)
|
1573
|
+
multibyte_buf.clear
|
1574
|
+
end
|
1558
1575
|
end
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
grapheme_clusters = search_word.grapheme_clusters
|
1568
|
-
if grapheme_clusters.size > 0
|
1569
|
-
grapheme_clusters.pop
|
1570
|
-
search_word = grapheme_clusters.join
|
1571
|
-
end
|
1572
|
-
when "\C-r".ord, "\C-s".ord
|
1573
|
-
search_again = true if prev_search_key == key
|
1574
|
-
prev_search_key = key
|
1575
|
-
else
|
1576
|
-
multibyte_buf << key
|
1577
|
-
if multibyte_buf.dup.force_encoding(@encoding).valid_encoding?
|
1578
|
-
search_word << multibyte_buf.dup.force_encoding(@encoding)
|
1579
|
-
multibyte_buf.clear
|
1576
|
+
hit = nil
|
1577
|
+
if not search_word.empty? and @line_backup_in_history&.include?(search_word)
|
1578
|
+
hit_pointer = Reline::HISTORY.size
|
1579
|
+
hit = @line_backup_in_history
|
1580
|
+
else
|
1581
|
+
if search_again
|
1582
|
+
if search_word.empty? and Reline.last_incremental_search
|
1583
|
+
search_word = Reline.last_incremental_search
|
1580
1584
|
end
|
1581
|
-
|
1582
|
-
|
1583
|
-
if not search_word.empty? and @line_backup_in_history&.include?(search_word)
|
1584
|
-
@history_pointer = nil
|
1585
|
-
hit = @line_backup_in_history
|
1586
|
-
else
|
1587
|
-
if search_again
|
1588
|
-
if search_word.empty? and Reline.last_incremental_search
|
1589
|
-
search_word = Reline.last_incremental_search
|
1590
|
-
end
|
1591
|
-
if @history_pointer
|
1592
|
-
case prev_search_key
|
1593
|
-
when "\C-r".ord
|
1594
|
-
history_pointer_base = 0
|
1595
|
-
history = Reline::HISTORY[0..(@history_pointer - 1)]
|
1596
|
-
when "\C-s".ord
|
1597
|
-
history_pointer_base = @history_pointer + 1
|
1598
|
-
history = Reline::HISTORY[(@history_pointer + 1)..-1]
|
1599
|
-
end
|
1600
|
-
else
|
1601
|
-
history_pointer_base = 0
|
1602
|
-
history = Reline::HISTORY
|
1603
|
-
end
|
1604
|
-
elsif @history_pointer
|
1605
|
-
case prev_search_key
|
1585
|
+
if @history_pointer
|
1586
|
+
case search_key
|
1606
1587
|
when "\C-r".ord
|
1607
1588
|
history_pointer_base = 0
|
1608
|
-
history = Reline::HISTORY[0
|
1589
|
+
history = Reline::HISTORY[0..(@history_pointer - 1)]
|
1609
1590
|
when "\C-s".ord
|
1610
|
-
history_pointer_base = @history_pointer
|
1611
|
-
history = Reline::HISTORY[@history_pointer..-1]
|
1591
|
+
history_pointer_base = @history_pointer + 1
|
1592
|
+
history = Reline::HISTORY[(@history_pointer + 1)..-1]
|
1612
1593
|
end
|
1613
1594
|
else
|
1614
1595
|
history_pointer_base = 0
|
1615
1596
|
history = Reline::HISTORY
|
1616
1597
|
end
|
1617
|
-
|
1598
|
+
elsif @history_pointer
|
1599
|
+
case search_key
|
1618
1600
|
when "\C-r".ord
|
1619
|
-
|
1620
|
-
|
1621
|
-
}
|
1601
|
+
history_pointer_base = 0
|
1602
|
+
history = Reline::HISTORY[0..@history_pointer]
|
1622
1603
|
when "\C-s".ord
|
1623
|
-
|
1624
|
-
|
1625
|
-
}
|
1626
|
-
end
|
1627
|
-
if hit_index
|
1628
|
-
@history_pointer = history_pointer_base + hit_index
|
1629
|
-
hit = Reline::HISTORY[@history_pointer]
|
1604
|
+
history_pointer_base = @history_pointer
|
1605
|
+
history = Reline::HISTORY[@history_pointer..-1]
|
1630
1606
|
end
|
1607
|
+
else
|
1608
|
+
history_pointer_base = 0
|
1609
|
+
history = Reline::HISTORY
|
1631
1610
|
end
|
1632
|
-
case
|
1611
|
+
case search_key
|
1633
1612
|
when "\C-r".ord
|
1634
|
-
|
1613
|
+
hit_index = history.rindex { |item|
|
1614
|
+
item.include?(search_word)
|
1615
|
+
}
|
1635
1616
|
when "\C-s".ord
|
1636
|
-
|
1617
|
+
hit_index = history.index { |item|
|
1618
|
+
item.include?(search_word)
|
1619
|
+
}
|
1637
1620
|
end
|
1638
|
-
if
|
1639
|
-
|
1640
|
-
|
1641
|
-
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1642
|
-
@line_index = @buffer_of_lines.size - 1
|
1643
|
-
@byte_pointer = current_line.bytesize
|
1644
|
-
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
|
1645
|
-
else
|
1646
|
-
@buffer_of_lines = [hit]
|
1647
|
-
@byte_pointer = hit.bytesize
|
1648
|
-
@searching_prompt = "(%s)`%s': %s" % [prompt_name, search_word, hit]
|
1649
|
-
end
|
1650
|
-
last_hit = hit
|
1651
|
-
else
|
1652
|
-
if @is_multiline
|
1653
|
-
@searching_prompt = "(failed %s)`%s'" % [prompt_name, search_word]
|
1654
|
-
else
|
1655
|
-
@searching_prompt = "(failed %s)`%s': %s" % [prompt_name, search_word, last_hit]
|
1656
|
-
end
|
1621
|
+
if hit_index
|
1622
|
+
hit_pointer = history_pointer_base + hit_index
|
1623
|
+
hit = Reline::HISTORY[hit_pointer]
|
1657
1624
|
end
|
1658
1625
|
end
|
1626
|
+
case search_key
|
1627
|
+
when "\C-r".ord
|
1628
|
+
prompt_name = 'reverse-i-search'
|
1629
|
+
when "\C-s".ord
|
1630
|
+
prompt_name = 'i-search'
|
1631
|
+
end
|
1632
|
+
prompt_name = "failed #{prompt_name}" unless hit
|
1633
|
+
[search_word, prompt_name, hit_pointer]
|
1659
1634
|
end
|
1660
1635
|
end
|
1661
1636
|
|
1662
1637
|
private def incremental_search_history(key)
|
1663
1638
|
unless @history_pointer
|
1664
|
-
|
1665
|
-
@line_backup_in_history = whole_buffer
|
1666
|
-
else
|
1667
|
-
@line_backup_in_history = current_line
|
1668
|
-
end
|
1639
|
+
@line_backup_in_history = whole_buffer
|
1669
1640
|
end
|
1670
|
-
searcher = generate_searcher
|
1671
|
-
searcher.resume(key)
|
1641
|
+
searcher = generate_searcher(key)
|
1672
1642
|
@searching_prompt = "(reverse-i-search)`': "
|
1673
1643
|
termination_keys = ["\C-j".ord]
|
1674
1644
|
termination_keys.concat(@config.isearch_terminators&.chars&.map(&:ord)) if @config.isearch_terminators
|
@@ -1680,53 +1650,41 @@ class Reline::LineEditor
|
|
1680
1650
|
else
|
1681
1651
|
buffer = @line_backup_in_history
|
1682
1652
|
end
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
@line_index = @buffer_of_lines.size - 1
|
1687
|
-
else
|
1688
|
-
@buffer_of_lines = [buffer]
|
1689
|
-
end
|
1653
|
+
@buffer_of_lines = buffer.split("\n")
|
1654
|
+
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1655
|
+
@line_index = @buffer_of_lines.size - 1
|
1690
1656
|
@searching_prompt = nil
|
1691
1657
|
@waiting_proc = nil
|
1692
1658
|
@byte_pointer = 0
|
1693
|
-
searcher.resume(-1)
|
1694
1659
|
when "\C-g".ord
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
else
|
1700
|
-
@buffer_of_lines = [@line_backup_in_history]
|
1701
|
-
end
|
1702
|
-
@history_pointer = nil
|
1660
|
+
@buffer_of_lines = @line_backup_in_history.split("\n")
|
1661
|
+
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1662
|
+
@line_index = @buffer_of_lines.size - 1
|
1663
|
+
move_history(nil, line: :end, cursor: :end, save_buffer: false)
|
1703
1664
|
@searching_prompt = nil
|
1704
1665
|
@waiting_proc = nil
|
1705
|
-
@line_backup_in_history = nil
|
1706
1666
|
@byte_pointer = 0
|
1707
1667
|
else
|
1708
1668
|
chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
|
1709
1669
|
if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord
|
1710
|
-
searcher.
|
1670
|
+
search_word, prompt_name, hit_pointer = searcher.call(k)
|
1671
|
+
Reline.last_incremental_search = search_word
|
1672
|
+
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
|
1673
|
+
@searching_prompt += ': ' unless @is_multiline
|
1674
|
+
move_history(hit_pointer, line: :end, cursor: :end, save_buffer: false) if hit_pointer
|
1711
1675
|
else
|
1712
1676
|
if @history_pointer
|
1713
1677
|
line = Reline::HISTORY[@history_pointer]
|
1714
1678
|
else
|
1715
1679
|
line = @line_backup_in_history
|
1716
1680
|
end
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
@line_index = @buffer_of_lines.size - 1
|
1722
|
-
else
|
1723
|
-
@line_backup_in_history = current_line
|
1724
|
-
@buffer_of_lines = [line]
|
1725
|
-
end
|
1681
|
+
@line_backup_in_history = whole_buffer
|
1682
|
+
@buffer_of_lines = line.split("\n")
|
1683
|
+
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1684
|
+
@line_index = @buffer_of_lines.size - 1
|
1726
1685
|
@searching_prompt = nil
|
1727
1686
|
@waiting_proc = nil
|
1728
1687
|
@byte_pointer = 0
|
1729
|
-
searcher.resume(-1)
|
1730
1688
|
end
|
1731
1689
|
end
|
1732
1690
|
}
|
@@ -1742,191 +1700,95 @@ class Reline::LineEditor
|
|
1742
1700
|
end
|
1743
1701
|
alias_method :forward_search_history, :vi_search_next
|
1744
1702
|
|
1745
|
-
private def
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
return if not current_line.empty? and substr.empty?
|
1752
|
-
history = Reline::HISTORY
|
1753
|
-
elsif @history_pointer.zero?
|
1754
|
-
history = nil
|
1755
|
-
h_pointer = nil
|
1756
|
-
else
|
1757
|
-
history = Reline::HISTORY.slice(0, @history_pointer)
|
1758
|
-
end
|
1759
|
-
return if history.nil?
|
1760
|
-
if @is_multiline
|
1761
|
-
h_pointer = history.rindex { |h|
|
1762
|
-
h.split("\n").each_with_index { |l, i|
|
1763
|
-
if l.start_with?(substr)
|
1764
|
-
line_no = i
|
1765
|
-
break
|
1766
|
-
end
|
1767
|
-
}
|
1768
|
-
not line_no.nil?
|
1769
|
-
}
|
1770
|
-
else
|
1771
|
-
h_pointer = history.rindex { |l|
|
1772
|
-
l.start_with?(substr)
|
1773
|
-
}
|
1774
|
-
end
|
1775
|
-
return if h_pointer.nil?
|
1776
|
-
@history_pointer = h_pointer
|
1777
|
-
cursor = current_byte_pointer_cursor
|
1778
|
-
if @is_multiline
|
1779
|
-
@buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
|
1780
|
-
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1781
|
-
@line_index = line_no
|
1782
|
-
calculate_nearest_cursor(cursor)
|
1783
|
-
else
|
1784
|
-
@buffer_of_lines = [Reline::HISTORY[@history_pointer]]
|
1785
|
-
calculate_nearest_cursor(cursor)
|
1703
|
+
private def search_history(prefix, pointer_range)
|
1704
|
+
pointer_range.each do |pointer|
|
1705
|
+
lines = Reline::HISTORY[pointer].split("\n")
|
1706
|
+
lines.each_with_index do |line, index|
|
1707
|
+
return [pointer, index] if line.start_with?(prefix)
|
1708
|
+
end
|
1786
1709
|
end
|
1710
|
+
nil
|
1711
|
+
end
|
1712
|
+
|
1713
|
+
private def ed_search_prev_history(key, arg: 1)
|
1714
|
+
substr = current_line.byteslice(0, @byte_pointer)
|
1715
|
+
return if @history_pointer == 0
|
1716
|
+
return if @history_pointer.nil? && substr.empty? && !current_line.empty?
|
1717
|
+
|
1718
|
+
history_range = 0...(@history_pointer || Reline::HISTORY.size)
|
1719
|
+
h_pointer, line_index = search_history(substr, history_range.reverse_each)
|
1720
|
+
return unless h_pointer
|
1721
|
+
move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer)
|
1787
1722
|
arg -= 1
|
1788
1723
|
ed_search_prev_history(key, arg: arg) if arg > 0
|
1789
1724
|
end
|
1790
1725
|
alias_method :history_search_backward, :ed_search_prev_history
|
1791
1726
|
|
1792
1727
|
private def ed_search_next_history(key, arg: 1)
|
1793
|
-
substr = current_line.
|
1794
|
-
if @history_pointer.nil?
|
1795
|
-
|
1796
|
-
|
1797
|
-
|
1798
|
-
end
|
1799
|
-
history = Reline::HISTORY.slice((@history_pointer + 1)..-1)
|
1800
|
-
h_pointer = nil
|
1801
|
-
line_no = nil
|
1802
|
-
if @is_multiline
|
1803
|
-
h_pointer = history.index { |h|
|
1804
|
-
h.split("\n").each_with_index { |l, i|
|
1805
|
-
if l.start_with?(substr)
|
1806
|
-
line_no = i
|
1807
|
-
break
|
1808
|
-
end
|
1809
|
-
}
|
1810
|
-
not line_no.nil?
|
1811
|
-
}
|
1812
|
-
else
|
1813
|
-
h_pointer = history.index { |l|
|
1814
|
-
l.start_with?(substr)
|
1815
|
-
}
|
1816
|
-
end
|
1817
|
-
h_pointer += @history_pointer + 1 if h_pointer and @history_pointer
|
1728
|
+
substr = current_line.byteslice(0, @byte_pointer)
|
1729
|
+
return if @history_pointer.nil?
|
1730
|
+
|
1731
|
+
history_range = @history_pointer + 1...Reline::HISTORY.size
|
1732
|
+
h_pointer, line_index = search_history(substr, history_range)
|
1818
1733
|
return if h_pointer.nil? and not substr.empty?
|
1819
|
-
|
1820
|
-
|
1821
|
-
if @history_pointer.nil? and substr.empty?
|
1822
|
-
@buffer_of_lines = []
|
1823
|
-
@line_index = 0
|
1824
|
-
@byte_pointer = 0
|
1825
|
-
else
|
1826
|
-
cursor = current_byte_pointer_cursor
|
1827
|
-
@buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
|
1828
|
-
@line_index = line_no
|
1829
|
-
calculate_nearest_cursor(cursor)
|
1830
|
-
end
|
1831
|
-
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1832
|
-
else
|
1833
|
-
if @history_pointer.nil? and substr.empty?
|
1834
|
-
set_current_line('', 0)
|
1835
|
-
else
|
1836
|
-
set_current_line(Reline::HISTORY[@history_pointer])
|
1837
|
-
end
|
1838
|
-
end
|
1734
|
+
|
1735
|
+
move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer)
|
1839
1736
|
arg -= 1
|
1840
1737
|
ed_search_next_history(key, arg: arg) if arg > 0
|
1841
1738
|
end
|
1842
1739
|
alias_method :history_search_forward, :ed_search_next_history
|
1843
1740
|
|
1741
|
+
private def move_history(history_pointer, line:, cursor:, save_buffer: true)
|
1742
|
+
history_pointer ||= Reline::HISTORY.size
|
1743
|
+
return if history_pointer < 0 || history_pointer > Reline::HISTORY.size
|
1744
|
+
old_history_pointer = @history_pointer || Reline::HISTORY.size
|
1745
|
+
if old_history_pointer == Reline::HISTORY.size
|
1746
|
+
@line_backup_in_history = save_buffer ? whole_buffer : ''
|
1747
|
+
else
|
1748
|
+
Reline::HISTORY[old_history_pointer] = whole_buffer if save_buffer
|
1749
|
+
end
|
1750
|
+
if history_pointer == Reline::HISTORY.size
|
1751
|
+
buf = @line_backup_in_history
|
1752
|
+
@history_pointer = @line_backup_in_history = nil
|
1753
|
+
else
|
1754
|
+
buf = Reline::HISTORY[history_pointer]
|
1755
|
+
@history_pointer = history_pointer
|
1756
|
+
end
|
1757
|
+
@buffer_of_lines = buf.split("\n")
|
1758
|
+
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1759
|
+
@line_index = line == :start ? 0 : line == :end ? @buffer_of_lines.size - 1 : line
|
1760
|
+
@byte_pointer = cursor == :start ? 0 : cursor == :end ? current_line.bytesize : cursor
|
1761
|
+
end
|
1762
|
+
|
1844
1763
|
private def ed_prev_history(key, arg: 1)
|
1845
|
-
if @
|
1764
|
+
if @line_index > 0
|
1846
1765
|
cursor = current_byte_pointer_cursor
|
1847
1766
|
@line_index -= 1
|
1848
1767
|
calculate_nearest_cursor(cursor)
|
1849
1768
|
return
|
1850
1769
|
end
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
1854
|
-
|
1855
|
-
|
1856
|
-
cursor = current_byte_pointer_cursor
|
1857
|
-
if @is_multiline
|
1858
|
-
@line_backup_in_history = whole_buffer
|
1859
|
-
@buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
|
1860
|
-
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1861
|
-
@line_index = @buffer_of_lines.size - 1
|
1862
|
-
calculate_nearest_cursor(cursor)
|
1863
|
-
else
|
1864
|
-
@line_backup_in_history = whole_buffer
|
1865
|
-
@buffer_of_lines = [Reline::HISTORY[@history_pointer]]
|
1866
|
-
calculate_nearest_cursor(cursor)
|
1867
|
-
end
|
1868
|
-
elsif @history_pointer.zero?
|
1869
|
-
return
|
1870
|
-
else
|
1871
|
-
if @is_multiline
|
1872
|
-
Reline::HISTORY[@history_pointer] = whole_buffer
|
1873
|
-
@history_pointer -= 1
|
1874
|
-
@buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
|
1875
|
-
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1876
|
-
@line_index = @buffer_of_lines.size - 1
|
1877
|
-
else
|
1878
|
-
Reline::HISTORY[@history_pointer] = whole_buffer
|
1879
|
-
@history_pointer -= 1
|
1880
|
-
@buffer_of_lines = [Reline::HISTORY[@history_pointer]]
|
1881
|
-
end
|
1882
|
-
end
|
1883
|
-
if @config.editing_mode_is?(:emacs, :vi_insert)
|
1884
|
-
@byte_pointer = current_line.bytesize
|
1885
|
-
elsif @config.editing_mode_is?(:vi_command)
|
1886
|
-
@byte_pointer = 0
|
1887
|
-
end
|
1770
|
+
move_history(
|
1771
|
+
(@history_pointer || Reline::HISTORY.size) - 1,
|
1772
|
+
line: :end,
|
1773
|
+
cursor: @config.editing_mode_is?(:vi_command) ? :start : :end,
|
1774
|
+
)
|
1888
1775
|
arg -= 1
|
1889
1776
|
ed_prev_history(key, arg: arg) if arg > 0
|
1890
1777
|
end
|
1891
1778
|
alias_method :previous_history, :ed_prev_history
|
1892
1779
|
|
1893
1780
|
private def ed_next_history(key, arg: 1)
|
1894
|
-
if @
|
1781
|
+
if @line_index < (@buffer_of_lines.size - 1)
|
1895
1782
|
cursor = current_byte_pointer_cursor
|
1896
1783
|
@line_index += 1
|
1897
1784
|
calculate_nearest_cursor(cursor)
|
1898
1785
|
return
|
1899
1786
|
end
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
@buffer_of_lines = @line_backup_in_history.split("\n")
|
1906
|
-
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1907
|
-
@line_index = 0
|
1908
|
-
else
|
1909
|
-
@history_pointer = nil
|
1910
|
-
@buffer_of_lines = [@line_backup_in_history]
|
1911
|
-
end
|
1912
|
-
else
|
1913
|
-
if @is_multiline
|
1914
|
-
Reline::HISTORY[@history_pointer] = whole_buffer
|
1915
|
-
@history_pointer += 1
|
1916
|
-
@buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
|
1917
|
-
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1918
|
-
@line_index = 0
|
1919
|
-
else
|
1920
|
-
Reline::HISTORY[@history_pointer] = whole_buffer
|
1921
|
-
@history_pointer += 1
|
1922
|
-
@buffer_of_lines = [Reline::HISTORY[@history_pointer]]
|
1923
|
-
end
|
1924
|
-
end
|
1925
|
-
if @config.editing_mode_is?(:emacs, :vi_insert)
|
1926
|
-
@byte_pointer = current_line.bytesize
|
1927
|
-
elsif @config.editing_mode_is?(:vi_command)
|
1928
|
-
@byte_pointer = 0
|
1929
|
-
end
|
1787
|
+
move_history(
|
1788
|
+
(@history_pointer || Reline::HISTORY.size) + 1,
|
1789
|
+
line: :start,
|
1790
|
+
cursor: @config.editing_mode_is?(:vi_command) ? :start : :end,
|
1791
|
+
)
|
1930
1792
|
arg -= 1
|
1931
1793
|
ed_next_history(key, arg: arg) if arg > 0
|
1932
1794
|
end
|
@@ -1957,17 +1819,13 @@ class Reline::LineEditor
|
|
1957
1819
|
end
|
1958
1820
|
end
|
1959
1821
|
else
|
1960
|
-
if @history_pointer
|
1961
|
-
Reline::HISTORY[@history_pointer] = whole_buffer
|
1962
|
-
@history_pointer = nil
|
1963
|
-
end
|
1964
1822
|
finish
|
1965
1823
|
end
|
1966
1824
|
end
|
1967
1825
|
|
1968
1826
|
private def em_delete_prev_char(key, arg: 1)
|
1969
1827
|
arg.times do
|
1970
|
-
if @
|
1828
|
+
if @byte_pointer == 0 and @line_index > 0
|
1971
1829
|
@byte_pointer = @buffer_of_lines[@line_index - 1].bytesize
|
1972
1830
|
@buffer_of_lines[@line_index - 1] += @buffer_of_lines.delete_at(@line_index)
|
1973
1831
|
@line_index -= 1
|
@@ -1991,7 +1849,7 @@ class Reline::LineEditor
|
|
1991
1849
|
line, deleted = byteslice!(current_line, @byte_pointer, current_line.bytesize - @byte_pointer)
|
1992
1850
|
set_current_line(line, line.bytesize)
|
1993
1851
|
@kill_ring.append(deleted)
|
1994
|
-
elsif @
|
1852
|
+
elsif @byte_pointer == current_line.bytesize and @buffer_of_lines.size > @line_index + 1
|
1995
1853
|
set_current_line(current_line + @buffer_of_lines.delete_at(@line_index + 1), current_line.bytesize)
|
1996
1854
|
end
|
1997
1855
|
end
|
@@ -2031,7 +1889,7 @@ class Reline::LineEditor
|
|
2031
1889
|
alias_method :kill_whole_line, :em_kill_line
|
2032
1890
|
|
2033
1891
|
private def em_delete(key)
|
2034
|
-
if current_line.empty? and
|
1892
|
+
if current_line.empty? and @buffer_of_lines.size == 1 and key == "\C-d".ord
|
2035
1893
|
@eof = true
|
2036
1894
|
finish
|
2037
1895
|
elsif @byte_pointer < current_line.bytesize
|
@@ -2039,7 +1897,7 @@ class Reline::LineEditor
|
|
2039
1897
|
mbchar = splitted_last.grapheme_clusters.first
|
2040
1898
|
line, = byteslice!(current_line, @byte_pointer, mbchar.bytesize)
|
2041
1899
|
set_current_line(line)
|
2042
|
-
elsif @
|
1900
|
+
elsif @byte_pointer == current_line.bytesize and @buffer_of_lines.size > @line_index + 1
|
2043
1901
|
set_current_line(current_line + @buffer_of_lines.delete_at(@line_index + 1), current_line.bytesize)
|
2044
1902
|
end
|
2045
1903
|
end
|
@@ -2282,7 +2140,7 @@ class Reline::LineEditor
|
|
2282
2140
|
end
|
2283
2141
|
|
2284
2142
|
private def vi_delete_prev_char(key)
|
2285
|
-
if @
|
2143
|
+
if @byte_pointer == 0 and @line_index > 0
|
2286
2144
|
@byte_pointer = @buffer_of_lines[@line_index - 1].bytesize
|
2287
2145
|
@buffer_of_lines[@line_index - 1] += @buffer_of_lines.delete_at(@line_index)
|
2288
2146
|
@line_index -= 1
|
@@ -2319,54 +2177,67 @@ class Reline::LineEditor
|
|
2319
2177
|
copy_for_vi(deleted)
|
2320
2178
|
end
|
2321
2179
|
|
2322
|
-
private def
|
2323
|
-
@
|
2180
|
+
private def vi_change_meta(key, arg: nil)
|
2181
|
+
if @vi_waiting_operator
|
2182
|
+
set_current_line('', 0) if @vi_waiting_operator == :vi_change_meta_confirm && arg.nil?
|
2183
|
+
@vi_waiting_operator = nil
|
2184
|
+
@vi_waiting_operator_arg = nil
|
2185
|
+
else
|
2186
|
+
@drop_terminate_spaces = true
|
2187
|
+
@vi_waiting_operator = :vi_change_meta_confirm
|
2188
|
+
@vi_waiting_operator_arg = arg || 1
|
2189
|
+
end
|
2324
2190
|
end
|
2325
2191
|
|
2326
|
-
private def
|
2327
|
-
|
2328
|
-
@
|
2329
|
-
|
2330
|
-
line, cut = byteslice!(current_line, @byte_pointer, byte_pointer_diff)
|
2331
|
-
elsif byte_pointer_diff < 0
|
2332
|
-
line, cut = byteslice!(current_line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff)
|
2333
|
-
end
|
2334
|
-
set_current_line(line)
|
2335
|
-
copy_for_vi(cut)
|
2336
|
-
@byte_pointer += byte_pointer_diff if byte_pointer_diff < 0
|
2337
|
-
@config.editing_mode = :vi_insert
|
2338
|
-
@drop_terminate_spaces = false
|
2339
|
-
}
|
2340
|
-
@waiting_operator_vi_arg = arg
|
2192
|
+
private def vi_change_meta_confirm(byte_pointer_diff)
|
2193
|
+
vi_delete_meta_confirm(byte_pointer_diff)
|
2194
|
+
@config.editing_mode = :vi_insert
|
2195
|
+
@drop_terminate_spaces = false
|
2341
2196
|
end
|
2342
2197
|
|
2343
|
-
private def vi_delete_meta(key, arg:
|
2344
|
-
@
|
2345
|
-
if
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2352
|
-
}
|
2353
|
-
@waiting_operator_vi_arg = arg
|
2198
|
+
private def vi_delete_meta(key, arg: nil)
|
2199
|
+
if @vi_waiting_operator
|
2200
|
+
set_current_line('', 0) if @vi_waiting_operator == :vi_delete_meta_confirm && arg.nil?
|
2201
|
+
@vi_waiting_operator = nil
|
2202
|
+
@vi_waiting_operator_arg = nil
|
2203
|
+
else
|
2204
|
+
@vi_waiting_operator = :vi_delete_meta_confirm
|
2205
|
+
@vi_waiting_operator_arg = arg || 1
|
2206
|
+
end
|
2354
2207
|
end
|
2355
2208
|
|
2356
|
-
private def
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2209
|
+
private def vi_delete_meta_confirm(byte_pointer_diff)
|
2210
|
+
if byte_pointer_diff > 0
|
2211
|
+
line, cut = byteslice!(current_line, @byte_pointer, byte_pointer_diff)
|
2212
|
+
elsif byte_pointer_diff < 0
|
2213
|
+
line, cut = byteslice!(current_line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff)
|
2214
|
+
end
|
2215
|
+
copy_for_vi(cut)
|
2216
|
+
set_current_line(line || '', @byte_pointer + (byte_pointer_diff < 0 ? byte_pointer_diff : 0))
|
2217
|
+
end
|
2218
|
+
|
2219
|
+
private def vi_yank(key, arg: nil)
|
2220
|
+
if @vi_waiting_operator
|
2221
|
+
copy_for_vi(current_line) if @vi_waiting_operator == :vi_yank_confirm && arg.nil?
|
2222
|
+
@vi_waiting_operator = nil
|
2223
|
+
@vi_waiting_operator_arg = nil
|
2224
|
+
else
|
2225
|
+
@vi_waiting_operator = :vi_yank_confirm
|
2226
|
+
@vi_waiting_operator_arg = arg || 1
|
2227
|
+
end
|
2228
|
+
end
|
2229
|
+
|
2230
|
+
private def vi_yank_confirm(byte_pointer_diff)
|
2231
|
+
if byte_pointer_diff > 0
|
2232
|
+
cut = current_line.byteslice(@byte_pointer, byte_pointer_diff)
|
2233
|
+
elsif byte_pointer_diff < 0
|
2234
|
+
cut = current_line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff)
|
2235
|
+
end
|
2236
|
+
copy_for_vi(cut)
|
2366
2237
|
end
|
2367
2238
|
|
2368
2239
|
private def vi_list_or_eof(key)
|
2369
|
-
if
|
2240
|
+
if current_line.empty? and @buffer_of_lines.size == 1
|
2370
2241
|
set_current_line('', 0)
|
2371
2242
|
@eof = true
|
2372
2243
|
finish
|
@@ -2397,36 +2268,18 @@ class Reline::LineEditor
|
|
2397
2268
|
if Reline::HISTORY.empty?
|
2398
2269
|
return
|
2399
2270
|
end
|
2400
|
-
|
2401
|
-
@history_pointer = 0
|
2402
|
-
@line_backup_in_history = current_line
|
2403
|
-
set_current_line(Reline::HISTORY[@history_pointer], 0)
|
2404
|
-
elsif @history_pointer.zero?
|
2405
|
-
return
|
2406
|
-
else
|
2407
|
-
Reline::HISTORY[@history_pointer] = current_line
|
2408
|
-
@history_pointer = 0
|
2409
|
-
set_current_line(Reline::HISTORY[@history_pointer], 0)
|
2410
|
-
end
|
2271
|
+
move_history(0, line: :start, cursor: :start)
|
2411
2272
|
end
|
2412
2273
|
|
2413
2274
|
private def vi_histedit(key)
|
2414
2275
|
path = Tempfile.open { |fp|
|
2415
|
-
|
2416
|
-
fp.write whole_lines.join("\n")
|
2417
|
-
else
|
2418
|
-
fp.write current_line
|
2419
|
-
end
|
2276
|
+
fp.write whole_lines.join("\n")
|
2420
2277
|
fp.path
|
2421
2278
|
}
|
2422
2279
|
system("#{ENV['EDITOR']} #{path}")
|
2423
|
-
|
2424
|
-
|
2425
|
-
|
2426
|
-
@line_index = 0
|
2427
|
-
else
|
2428
|
-
@buffer_of_lines = File.read(path).split("\n")
|
2429
|
-
end
|
2280
|
+
@buffer_of_lines = File.read(path).split("\n")
|
2281
|
+
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
2282
|
+
@line_index = 0
|
2430
2283
|
finish
|
2431
2284
|
end
|
2432
2285
|
|
@@ -2467,18 +2320,11 @@ class Reline::LineEditor
|
|
2467
2320
|
end
|
2468
2321
|
|
2469
2322
|
private def vi_to_column(key, arg: 0)
|
2470
|
-
|
2471
|
-
@byte_pointer, = current_line.grapheme_clusters.inject([0, 0]) { |
|
2472
|
-
# total has [byte_size, cursor]
|
2323
|
+
# Implementing behavior of vi, not Readline's vi-mode.
|
2324
|
+
@byte_pointer, = current_line.grapheme_clusters.inject([0, 0]) { |(total_byte_size, total_width), gc|
|
2473
2325
|
mbchar_width = Reline::Unicode.get_mbchar_width(gc)
|
2474
|
-
if (
|
2475
|
-
|
2476
|
-
elsif (total.last + mbchar_width) >= current_row_width
|
2477
|
-
break total
|
2478
|
-
else
|
2479
|
-
total = [total.first + gc.bytesize, total.last + mbchar_width]
|
2480
|
-
total
|
2481
|
-
end
|
2326
|
+
break [total_byte_size, total_width] if (total_width + mbchar_width) >= arg
|
2327
|
+
[total_byte_size + gc.bytesize, total_width + mbchar_width]
|
2482
2328
|
}
|
2483
2329
|
end
|
2484
2330
|
|
@@ -2605,7 +2451,7 @@ class Reline::LineEditor
|
|
2605
2451
|
end
|
2606
2452
|
|
2607
2453
|
private def vi_join_lines(key, arg: 1)
|
2608
|
-
if @
|
2454
|
+
if @buffer_of_lines.size > @line_index + 1
|
2609
2455
|
next_line = @buffer_of_lines.delete_at(@line_index + 1).lstrip
|
2610
2456
|
set_current_line(current_line + ' ' + next_line, current_line.bytesize)
|
2611
2457
|
end
|
@@ -2626,6 +2472,11 @@ class Reline::LineEditor
|
|
2626
2472
|
end
|
2627
2473
|
alias_method :exchange_point_and_mark, :em_exchange_mark
|
2628
2474
|
|
2629
|
-
private def
|
2475
|
+
private def emacs_editing_mode(key)
|
2476
|
+
@config.editing_mode = :emacs
|
2477
|
+
end
|
2478
|
+
|
2479
|
+
private def vi_editing_mode(key)
|
2480
|
+
@config.editing_mode = :vi_insert
|
2630
2481
|
end
|
2631
2482
|
end
|