reline 0.6.0 → 0.6.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/config.rb +5 -0
- data/lib/reline/io/ansi.rb +14 -29
- data/lib/reline/io.rb +2 -2
- data/lib/reline/key_actor/emacs.rb +2 -2
- data/lib/reline/key_stroke.rb +2 -2
- data/lib/reline/line_editor.rb +121 -147
- data/lib/reline/unicode/east_asian_width.rb +48 -23
- data/lib/reline/unicode.rb +24 -18
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +24 -16
- metadata +3 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cac4dc95dc3a9106a6f332d3503a62502f09205161a21157222e2dcd985ab706
|
|
4
|
+
data.tar.gz: 586f28ad1d6e68eefe7e5b4a15a4ee69f9d55d5469c144b686b72084b0abebe8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6f2e8fc8a404e1e8a0491c083e5ce524c5a5e465fceebcfa6eb7c0a5df20b98e07d337bb2c8703806f54e055efbeeba9c5d1f3171bd8e0faf6a611e30bbbf5da
|
|
7
|
+
data.tar.gz: a73fe51d441f70a4bb84ecfac2172251e6db0abf9f3007cbadf4f0374e5772b3ee62f71c753f10e88aa460278d1c0611b32ebca2e6f59fc6e42894377b56eb34
|
data/lib/reline/config.rb
CHANGED
|
@@ -177,6 +177,11 @@ class Reline::Config
|
|
|
177
177
|
if_stack = []
|
|
178
178
|
|
|
179
179
|
lines.each_with_index do |line, no|
|
|
180
|
+
# Even after encoding conversion, we need to verify the encoding is valid
|
|
181
|
+
# as some invalid byte sequences might pass through the conversion.
|
|
182
|
+
unless line.valid_encoding?
|
|
183
|
+
raise InvalidInputrc, "#{file}:#{no + 1}: can't be converted to the locale #{Reline.encoding_system_needs.name}"
|
|
184
|
+
end
|
|
180
185
|
next if line.match(/\A\s*#/)
|
|
181
186
|
|
|
182
187
|
no += 1
|
data/lib/reline/io/ansi.rb
CHANGED
|
@@ -2,18 +2,6 @@ require 'io/console'
|
|
|
2
2
|
require 'io/wait'
|
|
3
3
|
|
|
4
4
|
class Reline::ANSI < Reline::IO
|
|
5
|
-
CAPNAME_KEY_BINDINGS = {
|
|
6
|
-
'khome' => :ed_move_to_beg,
|
|
7
|
-
'kend' => :ed_move_to_end,
|
|
8
|
-
'kdch1' => :key_delete,
|
|
9
|
-
'kpp' => :ed_search_prev_history,
|
|
10
|
-
'knp' => :ed_search_next_history,
|
|
11
|
-
'kcuu1' => :ed_prev_history,
|
|
12
|
-
'kcud1' => :ed_next_history,
|
|
13
|
-
'kcuf1' => :ed_next_char,
|
|
14
|
-
'kcub1' => :ed_prev_char,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
5
|
ANSI_CURSOR_KEY_BINDINGS = {
|
|
18
6
|
# Up
|
|
19
7
|
'A' => [:ed_prev_history, {}],
|
|
@@ -136,6 +124,10 @@ class Reline::ANSI < Reline::IO
|
|
|
136
124
|
Reline.core.line_editor.handle_signal
|
|
137
125
|
end
|
|
138
126
|
c = @input.getbyte
|
|
127
|
+
|
|
128
|
+
# When "Escape non-ASCII Input with Control-V" is enabled in macOS Terminal.app,
|
|
129
|
+
# all non-ascii bytes are automatically escaped with `C-v`.
|
|
130
|
+
# "\xE3\x81\x82" (U+3042) becomes "\x16\xE3\x16\x81\x16\x82".
|
|
139
131
|
(c == 0x16 && @input.tty? && @input.raw(min: 0, time: 0, &:getbyte)) || c
|
|
140
132
|
rescue Errno::EIO
|
|
141
133
|
# Maybe the I/O has been closed.
|
|
@@ -175,31 +167,20 @@ class Reline::ANSI < Reline::IO
|
|
|
175
167
|
@buf.unshift(c)
|
|
176
168
|
end
|
|
177
169
|
|
|
178
|
-
def retrieve_keybuffer
|
|
179
|
-
begin
|
|
180
|
-
return unless @input.wait_readable(0.001)
|
|
181
|
-
str = @input.read_nonblock(1024)
|
|
182
|
-
str.bytes.each do |c|
|
|
183
|
-
@buf.push(c)
|
|
184
|
-
end
|
|
185
|
-
rescue EOFError
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
170
|
def get_screen_size
|
|
190
171
|
s = @input.winsize
|
|
191
172
|
return s if s[0] > 0 && s[1] > 0
|
|
192
173
|
s = [ENV["LINES"].to_i, ENV["COLUMNS"].to_i]
|
|
193
174
|
return s if s[0] > 0 && s[1] > 0
|
|
194
175
|
[24, 80]
|
|
195
|
-
rescue
|
|
176
|
+
rescue SystemCallError
|
|
196
177
|
[24, 80]
|
|
197
178
|
end
|
|
198
179
|
|
|
199
180
|
def set_screen_size(rows, columns)
|
|
200
181
|
@input.winsize = [rows, columns]
|
|
201
182
|
self
|
|
202
|
-
rescue
|
|
183
|
+
rescue SystemCallError
|
|
203
184
|
self
|
|
204
185
|
end
|
|
205
186
|
|
|
@@ -217,9 +198,7 @@ class Reline::ANSI < Reline::IO
|
|
|
217
198
|
break
|
|
218
199
|
end
|
|
219
200
|
end
|
|
220
|
-
buf.
|
|
221
|
-
stdin.ungetc ch
|
|
222
|
-
end
|
|
201
|
+
@buf.concat buf.bytes
|
|
223
202
|
end
|
|
224
203
|
[match[:column].to_i - 1, match[:row].to_i - 1] if match
|
|
225
204
|
end
|
|
@@ -309,10 +288,16 @@ class Reline::ANSI < Reline::IO
|
|
|
309
288
|
# Signal.trap may raise an ArgumentError if the platform doesn't support the signal.
|
|
310
289
|
end
|
|
311
290
|
|
|
291
|
+
def read_single_char(timeout_second)
|
|
292
|
+
# Disable intr to read `C-c` `C-z` `C-\` for quoted insert
|
|
293
|
+
@input.raw(intr: false) do
|
|
294
|
+
super
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
312
298
|
def prep
|
|
313
299
|
# Enable bracketed paste
|
|
314
300
|
write "\e[?2004h" if Reline.core.config.enable_bracketed_paste && both_tty?
|
|
315
|
-
retrieve_keybuffer
|
|
316
301
|
nil
|
|
317
302
|
end
|
|
318
303
|
|
data/lib/reline/io.rb
CHANGED
|
@@ -37,10 +37,10 @@ module Reline
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
# Read a single encoding valid character from the input.
|
|
40
|
-
def read_single_char(
|
|
40
|
+
def read_single_char(timeout_second)
|
|
41
41
|
buffer = String.new(encoding: Encoding::ASCII_8BIT)
|
|
42
42
|
loop do
|
|
43
|
-
timeout = buffer.empty? ? Float::INFINITY :
|
|
43
|
+
timeout = buffer.empty? ? Float::INFINITY : timeout_second
|
|
44
44
|
c = getc(timeout)
|
|
45
45
|
return unless c
|
|
46
46
|
|
data/lib/reline/key_stroke.rb
CHANGED
|
@@ -56,8 +56,8 @@ class Reline::KeyStroke
|
|
|
56
56
|
if func.is_a?(Array)
|
|
57
57
|
# Perform simple macro expansion for single byte key bindings.
|
|
58
58
|
# Multibyte key bindings and recursive macro expansion are not supported yet.
|
|
59
|
-
|
|
60
|
-
keys =
|
|
59
|
+
macro = func.pack('c*').force_encoding(@encoding)
|
|
60
|
+
keys = macro.chars.map do |c|
|
|
61
61
|
f = key_mapping.get(c.bytes)
|
|
62
62
|
Reline::Key.new(c, f.is_a?(Symbol) ? f : :ed_insert, false)
|
|
63
63
|
end
|
data/lib/reline/line_editor.rb
CHANGED
|
@@ -250,8 +250,8 @@ class Reline::LineEditor
|
|
|
250
250
|
@resized = false
|
|
251
251
|
@cache = {}
|
|
252
252
|
@rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0)
|
|
253
|
-
@
|
|
254
|
-
@
|
|
253
|
+
@undo_redo_history = [[[""], 0, 0]]
|
|
254
|
+
@undo_redo_index = 0
|
|
255
255
|
@restoring = false
|
|
256
256
|
@prev_action_state = NullActionState
|
|
257
257
|
@next_action_state = NullActionState
|
|
@@ -470,14 +470,6 @@ class Reline::LineEditor
|
|
|
470
470
|
end
|
|
471
471
|
end
|
|
472
472
|
|
|
473
|
-
def print_nomultiline_prompt
|
|
474
|
-
Reline::IOGate.disable_auto_linewrap(true) if Reline::IOGate.win?
|
|
475
|
-
# Readline's test `TestRelineAsReadline#test_readline` requires first output to be prompt, not cursor reset escape sequence.
|
|
476
|
-
Reline::IOGate.write Reline::Unicode.strip_non_printing_start_end(@prompt) if @prompt && !@is_multiline
|
|
477
|
-
ensure
|
|
478
|
-
Reline::IOGate.disable_auto_linewrap(false) if Reline::IOGate.win?
|
|
479
|
-
end
|
|
480
|
-
|
|
481
473
|
def render
|
|
482
474
|
wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
|
|
483
475
|
new_lines = wrapped_prompt_and_input_lines.flatten(1)[screen_scroll_top, screen_height].map do |prompt, line|
|
|
@@ -542,6 +534,7 @@ class Reline::LineEditor
|
|
|
542
534
|
Reline::IOGate.show_cursor
|
|
543
535
|
end
|
|
544
536
|
Reline::IOGate.move_cursor_column new_cursor_x
|
|
537
|
+
new_cursor_y = new_cursor_y.clamp(0, screen_height - 1)
|
|
545
538
|
Reline::IOGate.move_cursor_down new_cursor_y - cursor_y
|
|
546
539
|
@rendered_screen.cursor_y = new_cursor_y
|
|
547
540
|
ensure
|
|
@@ -911,28 +904,36 @@ class Reline::LineEditor
|
|
|
911
904
|
)
|
|
912
905
|
end
|
|
913
906
|
|
|
914
|
-
private def run_for_operators(key, method_symbol
|
|
907
|
+
private def run_for_operators(key, method_symbol)
|
|
908
|
+
# Reject multibyte input (converted to ed_insert) in vi_command mode
|
|
909
|
+
return if method_symbol == :ed_insert && @config.editing_mode_is?(:vi_command) && !@waiting_proc
|
|
910
|
+
|
|
911
|
+
if ARGUMENT_DIGIT_METHODS.include?(method_symbol) && !@waiting_proc
|
|
912
|
+
wrap_method_call(method_symbol, key, false)
|
|
913
|
+
return
|
|
914
|
+
end
|
|
915
|
+
|
|
915
916
|
if @vi_waiting_operator
|
|
916
|
-
if VI_MOTIONS.include?(method_symbol)
|
|
917
|
+
if @waiting_proc || VI_MOTIONS.include?(method_symbol)
|
|
917
918
|
old_byte_pointer = @byte_pointer
|
|
918
919
|
@vi_arg = (@vi_arg || 1) * @vi_waiting_operator_arg
|
|
919
|
-
|
|
920
|
+
wrap_method_call(method_symbol, key, true)
|
|
920
921
|
unless @waiting_proc
|
|
921
922
|
byte_pointer_diff = @byte_pointer - old_byte_pointer
|
|
922
923
|
@byte_pointer = old_byte_pointer
|
|
923
|
-
|
|
924
|
-
wrap_method_call(@vi_waiting_operator, method_obj, byte_pointer_diff)
|
|
924
|
+
__send__(@vi_waiting_operator, byte_pointer_diff)
|
|
925
925
|
cleanup_waiting
|
|
926
926
|
end
|
|
927
927
|
else
|
|
928
928
|
# Ignores operator when not motion is given.
|
|
929
|
-
|
|
929
|
+
wrap_method_call(method_symbol, key, false)
|
|
930
930
|
cleanup_waiting
|
|
931
931
|
end
|
|
932
|
-
@vi_arg = nil
|
|
933
932
|
else
|
|
934
|
-
|
|
933
|
+
wrap_method_call(method_symbol, key, false)
|
|
935
934
|
end
|
|
935
|
+
@vi_arg = nil
|
|
936
|
+
@kill_ring.process
|
|
936
937
|
end
|
|
937
938
|
|
|
938
939
|
private def argumentable?(method_obj)
|
|
@@ -945,20 +946,23 @@ class Reline::LineEditor
|
|
|
945
946
|
method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :inclusive }
|
|
946
947
|
end
|
|
947
948
|
|
|
948
|
-
def wrap_method_call(method_symbol,
|
|
949
|
-
if @
|
|
950
|
-
|
|
951
|
-
|
|
949
|
+
def wrap_method_call(method_symbol, key, with_operator)
|
|
950
|
+
if @waiting_proc
|
|
951
|
+
@waiting_proc.call(key, method_symbol)
|
|
952
|
+
return
|
|
952
953
|
end
|
|
954
|
+
|
|
955
|
+
return unless respond_to?(method_symbol, true)
|
|
956
|
+
method_obj = method(method_symbol)
|
|
953
957
|
if @vi_arg and argumentable?(method_obj)
|
|
954
|
-
if
|
|
955
|
-
method_obj.(key, arg: @vi_arg, inclusive:
|
|
958
|
+
if inclusive?(method_obj)
|
|
959
|
+
method_obj.(key, arg: @vi_arg, inclusive: with_operator)
|
|
956
960
|
else
|
|
957
961
|
method_obj.(key, arg: @vi_arg)
|
|
958
962
|
end
|
|
959
963
|
else
|
|
960
|
-
if
|
|
961
|
-
method_obj.(key, inclusive:
|
|
964
|
+
if inclusive?(method_obj)
|
|
965
|
+
method_obj.(key, inclusive: with_operator)
|
|
962
966
|
else
|
|
963
967
|
method_obj.(key)
|
|
964
968
|
end
|
|
@@ -984,50 +988,9 @@ class Reline::LineEditor
|
|
|
984
988
|
cleanup_waiting unless VI_WAITING_ACCEPT_METHODS.include?(method_symbol) || VI_MOTIONS.include?(method_symbol)
|
|
985
989
|
end
|
|
986
990
|
|
|
987
|
-
|
|
988
|
-
old_byte_pointer = @byte_pointer
|
|
989
|
-
@waiting_proc.call(key)
|
|
990
|
-
if @vi_waiting_operator
|
|
991
|
-
byte_pointer_diff = @byte_pointer - old_byte_pointer
|
|
992
|
-
@byte_pointer = old_byte_pointer
|
|
993
|
-
method_obj = method(@vi_waiting_operator)
|
|
994
|
-
wrap_method_call(@vi_waiting_operator, method_obj, byte_pointer_diff)
|
|
995
|
-
cleanup_waiting
|
|
996
|
-
end
|
|
997
|
-
@kill_ring.process
|
|
998
|
-
return
|
|
999
|
-
end
|
|
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)
|
|
991
|
+
process_insert(force: method_symbol != :ed_insert)
|
|
1003
992
|
|
|
1004
|
-
|
|
1005
|
-
method_obj = method(method_symbol)
|
|
1006
|
-
end
|
|
1007
|
-
if @vi_arg
|
|
1008
|
-
if ARGUMENT_DIGIT_METHODS.include?(method_symbol)
|
|
1009
|
-
ed_argument_digit(key)
|
|
1010
|
-
else
|
|
1011
|
-
if argumentable?(method_obj)
|
|
1012
|
-
run_for_operators(key, method_symbol) do |with_operator|
|
|
1013
|
-
wrap_method_call(method_symbol, method_obj, key, with_operator)
|
|
1014
|
-
end
|
|
1015
|
-
elsif method_obj
|
|
1016
|
-
wrap_method_call(method_symbol, method_obj, key)
|
|
1017
|
-
end
|
|
1018
|
-
@kill_ring.process
|
|
1019
|
-
@vi_arg = nil
|
|
1020
|
-
end
|
|
1021
|
-
elsif method_obj
|
|
1022
|
-
if method_symbol == :ed_argument_digit
|
|
1023
|
-
wrap_method_call(method_symbol, method_obj, key)
|
|
1024
|
-
else
|
|
1025
|
-
run_for_operators(key, method_symbol) do |with_operator|
|
|
1026
|
-
wrap_method_call(method_symbol, method_obj, key, with_operator)
|
|
1027
|
-
end
|
|
1028
|
-
end
|
|
1029
|
-
@kill_ring.process
|
|
1030
|
-
end
|
|
993
|
+
run_for_operators(key, method_symbol)
|
|
1031
994
|
end
|
|
1032
995
|
|
|
1033
996
|
def update(key)
|
|
@@ -1041,7 +1004,7 @@ class Reline::LineEditor
|
|
|
1041
1004
|
end
|
|
1042
1005
|
|
|
1043
1006
|
def input_key(key)
|
|
1044
|
-
|
|
1007
|
+
old_buffer_of_lines = @buffer_of_lines.dup
|
|
1045
1008
|
@config.reset_oneshot_key_bindings
|
|
1046
1009
|
if key.char.nil?
|
|
1047
1010
|
process_insert(force: true)
|
|
@@ -1049,11 +1012,8 @@ class Reline::LineEditor
|
|
|
1049
1012
|
finish
|
|
1050
1013
|
return
|
|
1051
1014
|
end
|
|
1052
|
-
@dialogs.
|
|
1053
|
-
|
|
1054
|
-
return
|
|
1055
|
-
end
|
|
1056
|
-
end
|
|
1015
|
+
return if @dialogs.any? { |dialog| dialog.name == key.method_symbol }
|
|
1016
|
+
|
|
1057
1017
|
@completion_occurs = false
|
|
1058
1018
|
|
|
1059
1019
|
process_key(key.char, key.method_symbol)
|
|
@@ -1069,7 +1029,9 @@ class Reline::LineEditor
|
|
|
1069
1029
|
@completion_journey_state = nil
|
|
1070
1030
|
end
|
|
1071
1031
|
|
|
1072
|
-
|
|
1032
|
+
modified = old_buffer_of_lines != @buffer_of_lines
|
|
1033
|
+
|
|
1034
|
+
push_undo_redo(modified) unless @restoring
|
|
1073
1035
|
@restoring = false
|
|
1074
1036
|
|
|
1075
1037
|
if @in_pasting
|
|
@@ -1077,7 +1039,6 @@ class Reline::LineEditor
|
|
|
1077
1039
|
return
|
|
1078
1040
|
end
|
|
1079
1041
|
|
|
1080
|
-
modified = @old_buffer_of_lines != @buffer_of_lines
|
|
1081
1042
|
if !@completion_occurs && modified && !@config.disable_completion && @config.autocompletion
|
|
1082
1043
|
# Auto complete starts only when edited
|
|
1083
1044
|
process_insert(force: true)
|
|
@@ -1086,26 +1047,17 @@ class Reline::LineEditor
|
|
|
1086
1047
|
modified
|
|
1087
1048
|
end
|
|
1088
1049
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1050
|
+
MAX_UNDO_REDO_HISTORY_SIZE = 100
|
|
1051
|
+
def push_undo_redo(modified)
|
|
1052
|
+
if modified
|
|
1053
|
+
@undo_redo_history = @undo_redo_history[0..@undo_redo_index]
|
|
1054
|
+
@undo_redo_history.push([@buffer_of_lines.dup, @byte_pointer, @line_index])
|
|
1055
|
+
if @undo_redo_history.size > MAX_UNDO_REDO_HISTORY_SIZE
|
|
1056
|
+
@undo_redo_history.shift
|
|
1057
|
+
end
|
|
1058
|
+
@undo_redo_index = @undo_redo_history.size - 1
|
|
1096
1059
|
else
|
|
1097
|
-
@
|
|
1098
|
-
@input_lines_position += 1
|
|
1099
|
-
@input_lines.push([@buffer_of_lines.dup, @byte_pointer, @line_index])
|
|
1100
|
-
end
|
|
1101
|
-
trim_input_lines
|
|
1102
|
-
end
|
|
1103
|
-
|
|
1104
|
-
MAX_INPUT_LINES = 100
|
|
1105
|
-
def trim_input_lines
|
|
1106
|
-
if @input_lines.size > MAX_INPUT_LINES
|
|
1107
|
-
@input_lines.shift
|
|
1108
|
-
@input_lines_position -= 1
|
|
1060
|
+
@undo_redo_history[@undo_redo_index] = [@buffer_of_lines.dup, @byte_pointer, @line_index]
|
|
1109
1061
|
end
|
|
1110
1062
|
end
|
|
1111
1063
|
|
|
@@ -1188,7 +1140,7 @@ class Reline::LineEditor
|
|
|
1188
1140
|
quote_characters = Reline.completer_quote_characters
|
|
1189
1141
|
before = current_line.byteslice(0, @byte_pointer).grapheme_clusters
|
|
1190
1142
|
quote = nil
|
|
1191
|
-
#
|
|
1143
|
+
# Calculate closing quote when cursor is at the end of the line
|
|
1192
1144
|
if current_line.bytesize == @byte_pointer && !quote_characters.empty?
|
|
1193
1145
|
escaped = false
|
|
1194
1146
|
before.each do |c|
|
|
@@ -1413,9 +1365,16 @@ class Reline::LineEditor
|
|
|
1413
1365
|
|
|
1414
1366
|
insert_text(str)
|
|
1415
1367
|
end
|
|
1416
|
-
alias_method :ed_digit, :ed_insert
|
|
1417
1368
|
alias_method :self_insert, :ed_insert
|
|
1418
1369
|
|
|
1370
|
+
private def ed_digit(key)
|
|
1371
|
+
if @vi_arg
|
|
1372
|
+
ed_argument_digit(key)
|
|
1373
|
+
else
|
|
1374
|
+
ed_insert(key)
|
|
1375
|
+
end
|
|
1376
|
+
end
|
|
1377
|
+
|
|
1419
1378
|
private def insert_raw_char(str, arg: 1)
|
|
1420
1379
|
arg.times do
|
|
1421
1380
|
if str == "\C-j" or str == "\C-m"
|
|
@@ -1461,28 +1420,38 @@ class Reline::LineEditor
|
|
|
1461
1420
|
@byte_pointer = 0
|
|
1462
1421
|
end
|
|
1463
1422
|
alias_method :beginning_of_line, :ed_move_to_beg
|
|
1464
|
-
|
|
1423
|
+
|
|
1424
|
+
private def vi_zero(key)
|
|
1425
|
+
if @vi_arg
|
|
1426
|
+
ed_argument_digit(key)
|
|
1427
|
+
else
|
|
1428
|
+
ed_move_to_beg(key)
|
|
1429
|
+
end
|
|
1430
|
+
end
|
|
1465
1431
|
|
|
1466
1432
|
private def ed_move_to_end(key)
|
|
1467
1433
|
@byte_pointer = current_line.bytesize
|
|
1468
1434
|
end
|
|
1469
1435
|
alias_method :end_of_line, :ed_move_to_end
|
|
1470
1436
|
|
|
1471
|
-
private def generate_searcher(
|
|
1437
|
+
private def generate_searcher(direction)
|
|
1472
1438
|
search_word = String.new(encoding: encoding)
|
|
1473
1439
|
hit_pointer = nil
|
|
1474
|
-
lambda do |key|
|
|
1440
|
+
lambda do |key, key_symbol|
|
|
1475
1441
|
search_again = false
|
|
1476
|
-
case
|
|
1477
|
-
when
|
|
1442
|
+
case key_symbol
|
|
1443
|
+
when :em_delete_prev_char, :backward_delete_char
|
|
1478
1444
|
grapheme_clusters = search_word.grapheme_clusters
|
|
1479
1445
|
if grapheme_clusters.size > 0
|
|
1480
1446
|
grapheme_clusters.pop
|
|
1481
1447
|
search_word = grapheme_clusters.join
|
|
1482
1448
|
end
|
|
1483
|
-
when
|
|
1484
|
-
search_again =
|
|
1485
|
-
|
|
1449
|
+
when :reverse_search_history, :vi_search_prev
|
|
1450
|
+
search_again = direction == :reverse
|
|
1451
|
+
direction = :reverse
|
|
1452
|
+
when :forward_search_history, :vi_search_next
|
|
1453
|
+
search_again = direction == :forward
|
|
1454
|
+
direction = :forward
|
|
1486
1455
|
else
|
|
1487
1456
|
search_word << key
|
|
1488
1457
|
end
|
|
@@ -1496,11 +1465,11 @@ class Reline::LineEditor
|
|
|
1496
1465
|
search_word = Reline.last_incremental_search
|
|
1497
1466
|
end
|
|
1498
1467
|
if @history_pointer
|
|
1499
|
-
case
|
|
1500
|
-
when
|
|
1468
|
+
case direction
|
|
1469
|
+
when :reverse
|
|
1501
1470
|
history_pointer_base = 0
|
|
1502
1471
|
history = Reline::HISTORY[0..(@history_pointer - 1)]
|
|
1503
|
-
when
|
|
1472
|
+
when :forward
|
|
1504
1473
|
history_pointer_base = @history_pointer + 1
|
|
1505
1474
|
history = Reline::HISTORY[(@history_pointer + 1)..-1]
|
|
1506
1475
|
end
|
|
@@ -1509,11 +1478,11 @@ class Reline::LineEditor
|
|
|
1509
1478
|
history = Reline::HISTORY
|
|
1510
1479
|
end
|
|
1511
1480
|
elsif @history_pointer
|
|
1512
|
-
case
|
|
1513
|
-
when
|
|
1481
|
+
case direction
|
|
1482
|
+
when :reverse
|
|
1514
1483
|
history_pointer_base = 0
|
|
1515
1484
|
history = Reline::HISTORY[0..@history_pointer]
|
|
1516
|
-
when
|
|
1485
|
+
when :forward
|
|
1517
1486
|
history_pointer_base = @history_pointer
|
|
1518
1487
|
history = Reline::HISTORY[@history_pointer..-1]
|
|
1519
1488
|
end
|
|
@@ -1521,12 +1490,12 @@ class Reline::LineEditor
|
|
|
1521
1490
|
history_pointer_base = 0
|
|
1522
1491
|
history = Reline::HISTORY
|
|
1523
1492
|
end
|
|
1524
|
-
case
|
|
1525
|
-
when
|
|
1493
|
+
case direction
|
|
1494
|
+
when :reverse
|
|
1526
1495
|
hit_index = history.rindex { |item|
|
|
1527
1496
|
item.include?(search_word)
|
|
1528
1497
|
}
|
|
1529
|
-
when
|
|
1498
|
+
when :forward
|
|
1530
1499
|
hit_index = history.index { |item|
|
|
1531
1500
|
item.include?(search_word)
|
|
1532
1501
|
}
|
|
@@ -1536,31 +1505,28 @@ class Reline::LineEditor
|
|
|
1536
1505
|
hit = Reline::HISTORY[hit_pointer]
|
|
1537
1506
|
end
|
|
1538
1507
|
end
|
|
1539
|
-
|
|
1540
|
-
when "\C-r"
|
|
1541
|
-
prompt_name = 'reverse-i-search'
|
|
1542
|
-
when "\C-s"
|
|
1543
|
-
prompt_name = 'i-search'
|
|
1544
|
-
end
|
|
1508
|
+
prompt_name = direction == :forward ? 'i-search' : 'reverse-i-search'
|
|
1545
1509
|
prompt_name = "failed #{prompt_name}" unless hit
|
|
1546
1510
|
[search_word, prompt_name, hit_pointer]
|
|
1547
1511
|
end
|
|
1548
1512
|
end
|
|
1549
1513
|
|
|
1550
|
-
private def incremental_search_history(
|
|
1514
|
+
private def incremental_search_history(direction)
|
|
1551
1515
|
backup = @buffer_of_lines.dup, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history
|
|
1552
|
-
searcher = generate_searcher(
|
|
1553
|
-
|
|
1516
|
+
searcher = generate_searcher(direction)
|
|
1517
|
+
prompt_name = direction == :forward ? 'i-search' : 'reverse-i-search'
|
|
1518
|
+
@searching_prompt = "(#{prompt_name})`': "
|
|
1554
1519
|
termination_keys = ["\C-j"]
|
|
1555
1520
|
termination_keys.concat(@config.isearch_terminators.chars) if @config.isearch_terminators
|
|
1556
|
-
|
|
1521
|
+
accept_key_syms = [:em_delete_prev_char, :backward_delete_char, :vi_search_prev, :vi_search_next, :reverse_search_history, :forward_search_history]
|
|
1522
|
+
@waiting_proc = ->(k, key_symbol) {
|
|
1557
1523
|
if k == "\C-g"
|
|
1558
1524
|
# cancel search and restore buffer
|
|
1559
1525
|
@buffer_of_lines, @line_index, @byte_pointer, @history_pointer, @line_backup_in_history = backup
|
|
1560
1526
|
@searching_prompt = nil
|
|
1561
1527
|
@waiting_proc = nil
|
|
1562
|
-
elsif !termination_keys.include?(k) && (k.match?(/[[:print:]]/) ||
|
|
1563
|
-
search_word, prompt_name, hit_pointer = searcher.call(k)
|
|
1528
|
+
elsif !termination_keys.include?(k) && (k.match?(/[[:print:]]/) || accept_key_syms.include?(key_symbol))
|
|
1529
|
+
search_word, prompt_name, hit_pointer = searcher.call(k, key_symbol)
|
|
1564
1530
|
Reline.last_incremental_search = search_word
|
|
1565
1531
|
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
|
|
1566
1532
|
@searching_prompt += ': ' unless @is_multiline
|
|
@@ -1575,12 +1541,12 @@ class Reline::LineEditor
|
|
|
1575
1541
|
end
|
|
1576
1542
|
|
|
1577
1543
|
private def vi_search_prev(key)
|
|
1578
|
-
incremental_search_history(
|
|
1544
|
+
incremental_search_history(:reverse)
|
|
1579
1545
|
end
|
|
1580
1546
|
alias_method :reverse_search_history, :vi_search_prev
|
|
1581
1547
|
|
|
1582
1548
|
private def vi_search_next(key)
|
|
1583
|
-
incremental_search_history(
|
|
1549
|
+
incremental_search_history(:forward)
|
|
1584
1550
|
end
|
|
1585
1551
|
alias_method :forward_search_history, :vi_search_next
|
|
1586
1552
|
|
|
@@ -1680,6 +1646,16 @@ class Reline::LineEditor
|
|
|
1680
1646
|
end
|
|
1681
1647
|
alias_method :next_history, :ed_next_history
|
|
1682
1648
|
|
|
1649
|
+
private def ed_beginning_of_history(key)
|
|
1650
|
+
move_history(0, line: :end, cursor: :end)
|
|
1651
|
+
end
|
|
1652
|
+
alias_method :beginning_of_history, :ed_beginning_of_history
|
|
1653
|
+
|
|
1654
|
+
private def ed_end_of_history(key)
|
|
1655
|
+
move_history(Reline::HISTORY.size, line: :end, cursor: :end)
|
|
1656
|
+
end
|
|
1657
|
+
alias_method :end_of_history, :ed_end_of_history
|
|
1658
|
+
|
|
1683
1659
|
private def ed_newline(key)
|
|
1684
1660
|
process_insert(force: true)
|
|
1685
1661
|
if @is_multiline
|
|
@@ -1691,17 +1667,10 @@ class Reline::LineEditor
|
|
|
1691
1667
|
finish
|
|
1692
1668
|
end
|
|
1693
1669
|
else
|
|
1694
|
-
if @line_index ==
|
|
1695
|
-
if confirm_multiline_termination
|
|
1696
|
-
finish
|
|
1697
|
-
else
|
|
1698
|
-
key_newline(key)
|
|
1699
|
-
end
|
|
1700
|
-
else
|
|
1701
|
-
# should check confirm_multiline_termination to finish?
|
|
1702
|
-
@line_index = @buffer_of_lines.size - 1
|
|
1703
|
-
@byte_pointer = current_line.bytesize
|
|
1670
|
+
if @line_index == @buffer_of_lines.size - 1 && confirm_multiline_termination
|
|
1704
1671
|
finish
|
|
1672
|
+
else
|
|
1673
|
+
key_newline(key)
|
|
1705
1674
|
end
|
|
1706
1675
|
end
|
|
1707
1676
|
else
|
|
@@ -1709,6 +1678,11 @@ class Reline::LineEditor
|
|
|
1709
1678
|
end
|
|
1710
1679
|
end
|
|
1711
1680
|
|
|
1681
|
+
private def ed_force_submit(_key)
|
|
1682
|
+
process_insert(force: true)
|
|
1683
|
+
finish
|
|
1684
|
+
end
|
|
1685
|
+
|
|
1712
1686
|
private def em_delete_prev_char(key, arg: 1)
|
|
1713
1687
|
arg.times do
|
|
1714
1688
|
if @byte_pointer == 0 and @line_index > 0
|
|
@@ -2208,7 +2182,7 @@ class Reline::LineEditor
|
|
|
2208
2182
|
end
|
|
2209
2183
|
|
|
2210
2184
|
private def vi_replace_char(key, arg: 1)
|
|
2211
|
-
@waiting_proc = ->(k) {
|
|
2185
|
+
@waiting_proc = ->(k, _sym) {
|
|
2212
2186
|
if arg == 1
|
|
2213
2187
|
byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
|
|
2214
2188
|
before = current_line.byteslice(0, @byte_pointer)
|
|
@@ -2232,11 +2206,11 @@ class Reline::LineEditor
|
|
|
2232
2206
|
end
|
|
2233
2207
|
|
|
2234
2208
|
private def vi_next_char(key, arg: 1, inclusive: false)
|
|
2235
|
-
@waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, inclusive: inclusive) }
|
|
2209
|
+
@waiting_proc = ->(key_for_proc, _sym) { search_next_char(key_for_proc, arg, inclusive: inclusive) }
|
|
2236
2210
|
end
|
|
2237
2211
|
|
|
2238
2212
|
private def vi_to_next_char(key, arg: 1, inclusive: false)
|
|
2239
|
-
@waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, need_prev_char: true, inclusive: inclusive) }
|
|
2213
|
+
@waiting_proc = ->(key_for_proc, _sym) { search_next_char(key_for_proc, arg, need_prev_char: true, inclusive: inclusive) }
|
|
2240
2214
|
end
|
|
2241
2215
|
|
|
2242
2216
|
private def search_next_char(key, arg, need_prev_char: false, inclusive: false)
|
|
@@ -2279,11 +2253,11 @@ class Reline::LineEditor
|
|
|
2279
2253
|
end
|
|
2280
2254
|
|
|
2281
2255
|
private def vi_prev_char(key, arg: 1)
|
|
2282
|
-
@waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg) }
|
|
2256
|
+
@waiting_proc = ->(key_for_proc, _sym) { search_prev_char(key_for_proc, arg) }
|
|
2283
2257
|
end
|
|
2284
2258
|
|
|
2285
2259
|
private def vi_to_prev_char(key, arg: 1)
|
|
2286
|
-
@waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg, true) }
|
|
2260
|
+
@waiting_proc = ->(key_for_proc, _sym) { search_prev_char(key_for_proc, arg, true) }
|
|
2287
2261
|
end
|
|
2288
2262
|
|
|
2289
2263
|
private def search_prev_char(key, arg, need_next_char = false)
|
|
@@ -2351,10 +2325,10 @@ class Reline::LineEditor
|
|
|
2351
2325
|
|
|
2352
2326
|
private def move_undo_redo(direction)
|
|
2353
2327
|
@restoring = true
|
|
2354
|
-
return unless (0..@
|
|
2328
|
+
return unless (0..@undo_redo_history.size - 1).cover?(@undo_redo_index + direction)
|
|
2355
2329
|
|
|
2356
|
-
@
|
|
2357
|
-
buffer_of_lines, byte_pointer, line_index = @
|
|
2330
|
+
@undo_redo_index += direction
|
|
2331
|
+
buffer_of_lines, byte_pointer, line_index = @undo_redo_history[@undo_redo_index]
|
|
2358
2332
|
@buffer_of_lines = buffer_of_lines.dup
|
|
2359
2333
|
@line_index = line_index
|
|
2360
2334
|
@byte_pointer = byte_pointer
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class Reline::Unicode::EastAsianWidth
|
|
2
2
|
# This is based on EastAsianWidth.txt
|
|
3
|
-
# UNICODE_VERSION = '
|
|
3
|
+
# UNICODE_VERSION = '16.0.0'
|
|
4
4
|
|
|
5
5
|
CHUNK_LAST, CHUNK_WIDTH = [
|
|
6
6
|
[0x1f, 2],
|
|
@@ -129,7 +129,7 @@ class Reline::Unicode::EastAsianWidth
|
|
|
129
129
|
[0x450, 1],
|
|
130
130
|
[0x451, -1],
|
|
131
131
|
[0x482, 1],
|
|
132
|
-
[
|
|
132
|
+
[0x489, 0],
|
|
133
133
|
[0x590, 1],
|
|
134
134
|
[0x5bd, 0],
|
|
135
135
|
[0x5be, 1],
|
|
@@ -174,7 +174,7 @@ class Reline::Unicode::EastAsianWidth
|
|
|
174
174
|
[0x82d, 0],
|
|
175
175
|
[0x858, 1],
|
|
176
176
|
[0x85b, 0],
|
|
177
|
-
[
|
|
177
|
+
[0x896, 1],
|
|
178
178
|
[0x89f, 0],
|
|
179
179
|
[0x8c9, 1],
|
|
180
180
|
[0x8e1, 0],
|
|
@@ -356,6 +356,7 @@ class Reline::Unicode::EastAsianWidth
|
|
|
356
356
|
[0x109d, 0],
|
|
357
357
|
[0x10ff, 1],
|
|
358
358
|
[0x115f, 2],
|
|
359
|
+
[0x11ff, 0],
|
|
359
360
|
[0x135c, 1],
|
|
360
361
|
[0x135f, 0],
|
|
361
362
|
[0x1711, 1],
|
|
@@ -411,8 +412,6 @@ class Reline::Unicode::EastAsianWidth
|
|
|
411
412
|
[0x1a7e, 1],
|
|
412
413
|
[0x1a7f, 0],
|
|
413
414
|
[0x1aaf, 1],
|
|
414
|
-
[0x1abd, 0],
|
|
415
|
-
[0x1abe, 1],
|
|
416
415
|
[0x1ace, 0],
|
|
417
416
|
[0x1aff, 1],
|
|
418
417
|
[0x1b03, 0],
|
|
@@ -491,10 +490,6 @@ class Reline::Unicode::EastAsianWidth
|
|
|
491
490
|
[0x20ab, 1],
|
|
492
491
|
[0x20ac, -1],
|
|
493
492
|
[0x20cf, 1],
|
|
494
|
-
[0x20dc, 0],
|
|
495
|
-
[0x20e0, 1],
|
|
496
|
-
[0x20e1, 0],
|
|
497
|
-
[0x20e4, 1],
|
|
498
493
|
[0x20f0, 0],
|
|
499
494
|
[0x2102, 1],
|
|
500
495
|
[0x2103, -1],
|
|
@@ -646,6 +641,8 @@ class Reline::Unicode::EastAsianWidth
|
|
|
646
641
|
[0x261c, -1],
|
|
647
642
|
[0x261d, 1],
|
|
648
643
|
[0x261e, -1],
|
|
644
|
+
[0x262f, 1],
|
|
645
|
+
[0x2637, 2],
|
|
649
646
|
[0x263f, 1],
|
|
650
647
|
[0x2640, -1],
|
|
651
648
|
[0x2641, 1],
|
|
@@ -664,6 +661,8 @@ class Reline::Unicode::EastAsianWidth
|
|
|
664
661
|
[0x266f, -1],
|
|
665
662
|
[0x267e, 1],
|
|
666
663
|
[0x267f, 2],
|
|
664
|
+
[0x2689, 1],
|
|
665
|
+
[0x268f, 2],
|
|
667
666
|
[0x2692, 1],
|
|
668
667
|
[0x2693, 2],
|
|
669
668
|
[0x269d, 1],
|
|
@@ -753,19 +752,17 @@ class Reline::Unicode::EastAsianWidth
|
|
|
753
752
|
[0x3130, 1],
|
|
754
753
|
[0x318e, 2],
|
|
755
754
|
[0x318f, 1],
|
|
756
|
-
[
|
|
755
|
+
[0x31e5, 2],
|
|
757
756
|
[0x31ee, 1],
|
|
758
757
|
[0x321e, 2],
|
|
759
758
|
[0x321f, 1],
|
|
760
759
|
[0x3247, 2],
|
|
761
760
|
[0x324f, -1],
|
|
762
|
-
[0x4dbf, 2],
|
|
763
|
-
[0x4dff, 1],
|
|
764
761
|
[0xa48c, 2],
|
|
765
762
|
[0xa48f, 1],
|
|
766
763
|
[0xa4c6, 2],
|
|
767
764
|
[0xa66e, 1],
|
|
768
|
-
[
|
|
765
|
+
[0xa672, 0],
|
|
769
766
|
[0xa673, 1],
|
|
770
767
|
[0xa67d, 0],
|
|
771
768
|
[0xa69d, 1],
|
|
@@ -838,6 +835,10 @@ class Reline::Unicode::EastAsianWidth
|
|
|
838
835
|
[0xabed, 0],
|
|
839
836
|
[0xabff, 1],
|
|
840
837
|
[0xd7a3, 2],
|
|
838
|
+
[0xd7af, 1],
|
|
839
|
+
[0xd7c6, 0],
|
|
840
|
+
[0xd7ca, 1],
|
|
841
|
+
[0xd7fb, 0],
|
|
841
842
|
[0xdfff, 1],
|
|
842
843
|
[0xf8ff, -1],
|
|
843
844
|
[0xfaff, 2],
|
|
@@ -879,9 +880,11 @@ class Reline::Unicode::EastAsianWidth
|
|
|
879
880
|
[0x10ae6, 0],
|
|
880
881
|
[0x10d23, 1],
|
|
881
882
|
[0x10d27, 0],
|
|
883
|
+
[0x10d68, 1],
|
|
884
|
+
[0x10d6d, 0],
|
|
882
885
|
[0x10eaa, 1],
|
|
883
886
|
[0x10eac, 0],
|
|
884
|
-
[
|
|
887
|
+
[0x10efb, 1],
|
|
885
888
|
[0x10eff, 0],
|
|
886
889
|
[0x10f45, 1],
|
|
887
890
|
[0x10f50, 0],
|
|
@@ -943,6 +946,16 @@ class Reline::Unicode::EastAsianWidth
|
|
|
943
946
|
[0x1136c, 0],
|
|
944
947
|
[0x1136f, 1],
|
|
945
948
|
[0x11374, 0],
|
|
949
|
+
[0x113ba, 1],
|
|
950
|
+
[0x113c0, 0],
|
|
951
|
+
[0x113cd, 1],
|
|
952
|
+
[0x113ce, 0],
|
|
953
|
+
[0x113cf, 1],
|
|
954
|
+
[0x113d0, 0],
|
|
955
|
+
[0x113d1, 1],
|
|
956
|
+
[0x113d2, 0],
|
|
957
|
+
[0x113e0, 1],
|
|
958
|
+
[0x113e2, 0],
|
|
946
959
|
[0x11437, 1],
|
|
947
960
|
[0x1143f, 0],
|
|
948
961
|
[0x11441, 1],
|
|
@@ -982,6 +995,8 @@ class Reline::Unicode::EastAsianWidth
|
|
|
982
995
|
[0x116b6, 1],
|
|
983
996
|
[0x116b7, 0],
|
|
984
997
|
[0x1171c, 1],
|
|
998
|
+
[0x1171d, 0],
|
|
999
|
+
[0x1171e, 1],
|
|
985
1000
|
[0x1171f, 0],
|
|
986
1001
|
[0x11721, 1],
|
|
987
1002
|
[0x11725, 0],
|
|
@@ -1059,10 +1074,16 @@ class Reline::Unicode::EastAsianWidth
|
|
|
1059
1074
|
[0x11f40, 0],
|
|
1060
1075
|
[0x11f41, 1],
|
|
1061
1076
|
[0x11f42, 0],
|
|
1077
|
+
[0x11f59, 1],
|
|
1078
|
+
[0x11f5a, 0],
|
|
1062
1079
|
[0x1343f, 1],
|
|
1063
1080
|
[0x13440, 0],
|
|
1064
1081
|
[0x13446, 1],
|
|
1065
1082
|
[0x13455, 0],
|
|
1083
|
+
[0x1611d, 1],
|
|
1084
|
+
[0x16129, 0],
|
|
1085
|
+
[0x1612c, 1],
|
|
1086
|
+
[0x1612f, 0],
|
|
1066
1087
|
[0x16aef, 1],
|
|
1067
1088
|
[0x16af4, 0],
|
|
1068
1089
|
[0x16b2f, 1],
|
|
@@ -1080,7 +1101,7 @@ class Reline::Unicode::EastAsianWidth
|
|
|
1080
1101
|
[0x187f7, 2],
|
|
1081
1102
|
[0x187ff, 1],
|
|
1082
1103
|
[0x18cd5, 2],
|
|
1083
|
-
[
|
|
1104
|
+
[0x18cfe, 1],
|
|
1084
1105
|
[0x18d08, 2],
|
|
1085
1106
|
[0x1afef, 1],
|
|
1086
1107
|
[0x1aff3, 2],
|
|
@@ -1116,6 +1137,10 @@ class Reline::Unicode::EastAsianWidth
|
|
|
1116
1137
|
[0x1d1ad, 0],
|
|
1117
1138
|
[0x1d241, 1],
|
|
1118
1139
|
[0x1d244, 0],
|
|
1140
|
+
[0x1d2ff, 1],
|
|
1141
|
+
[0x1d356, 2],
|
|
1142
|
+
[0x1d35f, 1],
|
|
1143
|
+
[0x1d376, 2],
|
|
1119
1144
|
[0x1d9ff, 1],
|
|
1120
1145
|
[0x1da36, 0],
|
|
1121
1146
|
[0x1da3a, 1],
|
|
@@ -1148,6 +1173,8 @@ class Reline::Unicode::EastAsianWidth
|
|
|
1148
1173
|
[0x1e2ef, 0],
|
|
1149
1174
|
[0x1e4eb, 1],
|
|
1150
1175
|
[0x1e4ef, 0],
|
|
1176
|
+
[0x1e5ed, 1],
|
|
1177
|
+
[0x1e5ef, 0],
|
|
1151
1178
|
[0x1e8cf, 1],
|
|
1152
1179
|
[0x1e8d6, 0],
|
|
1153
1180
|
[0x1e943, 1],
|
|
@@ -1241,15 +1268,13 @@ class Reline::Unicode::EastAsianWidth
|
|
|
1241
1268
|
[0x1fa6f, 1],
|
|
1242
1269
|
[0x1fa7c, 2],
|
|
1243
1270
|
[0x1fa7f, 1],
|
|
1244
|
-
[
|
|
1245
|
-
[
|
|
1246
|
-
[
|
|
1247
|
-
[0x1fabe, 1],
|
|
1248
|
-
[0x1fac5, 2],
|
|
1271
|
+
[0x1fa89, 2],
|
|
1272
|
+
[0x1fa8e, 1],
|
|
1273
|
+
[0x1fac6, 2],
|
|
1249
1274
|
[0x1facd, 1],
|
|
1250
|
-
[
|
|
1251
|
-
[
|
|
1252
|
-
[
|
|
1275
|
+
[0x1fadc, 2],
|
|
1276
|
+
[0x1fade, 1],
|
|
1277
|
+
[0x1fae9, 2],
|
|
1253
1278
|
[0x1faef, 1],
|
|
1254
1279
|
[0x1faf8, 2],
|
|
1255
1280
|
[0x1ffff, 1],
|
data/lib/reline/unicode.rb
CHANGED
|
@@ -28,16 +28,16 @@ class Reline::Unicode
|
|
|
28
28
|
0x19 => '^Y',
|
|
29
29
|
0x1A => '^Z', # C-z
|
|
30
30
|
0x1B => '^[', # C-[ C-3
|
|
31
|
+
0x1C => '^\\', # C-\
|
|
31
32
|
0x1D => '^]', # C-]
|
|
32
33
|
0x1E => '^^', # C-~ C-6
|
|
33
34
|
0x1F => '^_', # C-_ C-7
|
|
34
35
|
0x7F => '^?', # C-? C-8
|
|
35
36
|
}
|
|
36
|
-
EscapedChars = EscapedPairs.keys.map(&:chr)
|
|
37
37
|
|
|
38
38
|
NON_PRINTING_START = "\1"
|
|
39
39
|
NON_PRINTING_END = "\2"
|
|
40
|
-
CSI_REGEXP = /\e\[[\
|
|
40
|
+
CSI_REGEXP = /\e\[[\x30-\x3f]*[\x20-\x2f]*[a-zA-Z]/
|
|
41
41
|
OSC_REGEXP = /\e\]\d+(?:;[^;\a\e]+)*(?:\a|\e\\)/
|
|
42
42
|
WIDTH_SCANNER = /\G(?:(#{NON_PRINTING_START})|(#{NON_PRINTING_END})|(#{CSI_REGEXP})|(#{OSC_REGEXP})|(\X))/o
|
|
43
43
|
|
|
@@ -61,7 +61,7 @@ class Reline::Unicode
|
|
|
61
61
|
|
|
62
62
|
# This code is essentially doing the same thing as
|
|
63
63
|
# `str.encode(utf8, **replace_options).encode(encoding, **replace_options)`
|
|
64
|
-
# but also avoids
|
|
64
|
+
# but also avoids unnecessary irreversible encoding conversion.
|
|
65
65
|
converted.gsub(/\X/) do |c|
|
|
66
66
|
c.encode(Encoding::UTF_8)
|
|
67
67
|
c
|
|
@@ -72,26 +72,32 @@ class Reline::Unicode
|
|
|
72
72
|
|
|
73
73
|
require 'reline/unicode/east_asian_width'
|
|
74
74
|
|
|
75
|
+
def self.east_asian_width(ord)
|
|
76
|
+
chunk_index = EastAsianWidth::CHUNK_LAST.bsearch_index { |o| ord <= o }
|
|
77
|
+
size = EastAsianWidth::CHUNK_WIDTH[chunk_index]
|
|
78
|
+
size == -1 ? Reline.ambiguous_width : size
|
|
79
|
+
end
|
|
80
|
+
|
|
75
81
|
def self.get_mbchar_width(mbchar)
|
|
76
82
|
ord = mbchar.ord
|
|
77
83
|
if ord <= 0x1F # in EscapedPairs
|
|
78
84
|
return 2
|
|
79
|
-
elsif ord <= 0x7E # printable ASCII chars
|
|
85
|
+
elsif mbchar.length == 1 && ord <= 0x7E # printable ASCII chars
|
|
80
86
|
return 1
|
|
81
87
|
end
|
|
88
|
+
|
|
82
89
|
utf8_mbchar = mbchar.encode(Encoding::UTF_8)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
size
|
|
90
|
+
zwj = false
|
|
91
|
+
utf8_mbchar.chars.sum do |c|
|
|
92
|
+
if zwj
|
|
93
|
+
zwj = false
|
|
94
|
+
0
|
|
95
|
+
elsif c.ord == 0x200D # Zero Width Joiner
|
|
96
|
+
zwj = true
|
|
97
|
+
0
|
|
98
|
+
else
|
|
99
|
+
east_asian_width(c.ord)
|
|
100
|
+
end
|
|
95
101
|
end
|
|
96
102
|
end
|
|
97
103
|
|
|
@@ -214,7 +220,7 @@ class Reline::Unicode
|
|
|
214
220
|
next
|
|
215
221
|
elsif padding && !cover_begin && prev_width < start_col && start_col < total_width
|
|
216
222
|
# Add preceding padding. This padding might have background color.
|
|
217
|
-
chunk << ' '
|
|
223
|
+
chunk << ' ' * (total_width - start_col)
|
|
218
224
|
chunk_start_col ||= start_col
|
|
219
225
|
chunk_end_col = total_width
|
|
220
226
|
next
|
|
@@ -228,7 +234,7 @@ class Reline::Unicode
|
|
|
228
234
|
# Current character exceeds end_col
|
|
229
235
|
if padding && end_col < total_width
|
|
230
236
|
# Add succeeding padding. This padding might have background color.
|
|
231
|
-
chunk << ' '
|
|
237
|
+
chunk << ' ' * (end_col - prev_width)
|
|
232
238
|
chunk_start_col ||= prev_width
|
|
233
239
|
chunk_end_col = end_col
|
|
234
240
|
end
|
data/lib/reline/version.rb
CHANGED
data/lib/reline.rb
CHANGED
|
@@ -12,10 +12,10 @@ require 'rbconfig'
|
|
|
12
12
|
|
|
13
13
|
module Reline
|
|
14
14
|
# NOTE: For making compatible with the rb-readline gem
|
|
15
|
-
FILENAME_COMPLETION_PROC = nil
|
|
16
|
-
USERNAME_COMPLETION_PROC = nil
|
|
15
|
+
FILENAME_COMPLETION_PROC = nil # :nodoc:
|
|
16
|
+
USERNAME_COMPLETION_PROC = nil # :nodoc:
|
|
17
17
|
|
|
18
|
-
class ConfigEncodingConversionError < StandardError; end
|
|
18
|
+
class ConfigEncodingConversionError < StandardError; end # :nodoc:
|
|
19
19
|
|
|
20
20
|
# EOF key: { char: nil, method_symbol: nil }
|
|
21
21
|
# Other key: { char: String, method_symbol: Symbol }
|
|
@@ -24,8 +24,8 @@ module Reline
|
|
|
24
24
|
def match?(sym)
|
|
25
25
|
method_symbol && method_symbol == sym
|
|
26
26
|
end
|
|
27
|
-
end
|
|
28
|
-
CursorPos = Struct.new(:x, :y)
|
|
27
|
+
end # :nodoc:
|
|
28
|
+
CursorPos = Struct.new(:x, :y) # :nodoc:
|
|
29
29
|
DialogRenderInfo = Struct.new(
|
|
30
30
|
:pos,
|
|
31
31
|
:contents,
|
|
@@ -35,7 +35,7 @@ module Reline
|
|
|
35
35
|
:height,
|
|
36
36
|
:scrollbar,
|
|
37
37
|
keyword_init: true
|
|
38
|
-
)
|
|
38
|
+
) # :nodoc:
|
|
39
39
|
|
|
40
40
|
class Core
|
|
41
41
|
ATTR_READER_NAMES = %i(
|
|
@@ -244,8 +244,8 @@ module Reline
|
|
|
244
244
|
height: [15, preferred_dialog_height].min,
|
|
245
245
|
face: :completion_dialog
|
|
246
246
|
)
|
|
247
|
-
}
|
|
248
|
-
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
|
247
|
+
} # :nodoc:
|
|
248
|
+
Reline::DEFAULT_DIALOG_CONTEXT = Array.new # :nodoc:
|
|
249
249
|
|
|
250
250
|
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
|
|
251
251
|
@mutex.synchronize do
|
|
@@ -324,8 +324,6 @@ module Reline
|
|
|
324
324
|
line_editor.auto_indent_proc = auto_indent_proc
|
|
325
325
|
line_editor.dig_perfect_match_proc = dig_perfect_match_proc
|
|
326
326
|
|
|
327
|
-
# Readline calls pre_input_hook just after printing the first prompt.
|
|
328
|
-
line_editor.print_nomultiline_prompt
|
|
329
327
|
pre_input_hook&.call
|
|
330
328
|
|
|
331
329
|
unless Reline::IOGate.dumb?
|
|
@@ -341,15 +339,16 @@ module Reline
|
|
|
341
339
|
line_editor.set_signal_handlers
|
|
342
340
|
loop do
|
|
343
341
|
read_io(config.keyseq_timeout) { |inputs|
|
|
344
|
-
line_editor.set_pasting_state(io_gate.in_pasting?)
|
|
345
342
|
inputs.each do |key|
|
|
346
343
|
case key.method_symbol
|
|
347
344
|
when :bracketed_paste_start
|
|
348
345
|
# io_gate is Reline::ANSI because the key :bracketed_paste_start is only assigned in Reline::ANSI
|
|
349
346
|
key = Reline::Key.new(io_gate.read_bracketed_paste, :insert_multiline_text)
|
|
350
347
|
when :quoted_insert, :ed_quoted_insert
|
|
351
|
-
|
|
348
|
+
char = io_gate.read_single_char(config.keyseq_timeout.fdiv(1000))
|
|
349
|
+
key = Reline::Key.new(char || '', :insert_raw_char)
|
|
352
350
|
end
|
|
351
|
+
line_editor.set_pasting_state(io_gate.in_pasting?)
|
|
353
352
|
line_editor.update(key)
|
|
354
353
|
end
|
|
355
354
|
}
|
|
@@ -357,7 +356,6 @@ module Reline
|
|
|
357
356
|
line_editor.render_finished
|
|
358
357
|
break
|
|
359
358
|
else
|
|
360
|
-
line_editor.set_pasting_state(io_gate.in_pasting?)
|
|
361
359
|
line_editor.rerender
|
|
362
360
|
end
|
|
363
361
|
end
|
|
@@ -440,6 +438,17 @@ module Reline
|
|
|
440
438
|
}
|
|
441
439
|
def_single_delegators :core, :input=, :output=
|
|
442
440
|
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
|
|
441
|
+
|
|
442
|
+
##
|
|
443
|
+
# :singleton-method: readmultiline
|
|
444
|
+
# :call-seq:
|
|
445
|
+
# readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination) -> string or nil
|
|
446
|
+
def_single_delegators :core, :readmultiline
|
|
447
|
+
|
|
448
|
+
##
|
|
449
|
+
# :singleton-method: readline
|
|
450
|
+
# :call-seq:
|
|
451
|
+
# readline(prompt = '', add_hist = false) -> string or nil
|
|
443
452
|
def_single_delegators :core, :readline
|
|
444
453
|
def_single_delegators :core, :completion_case_fold, :completion_case_fold=
|
|
445
454
|
def_single_delegators :core, :completion_quote_character
|
|
@@ -475,11 +484,10 @@ module Reline
|
|
|
475
484
|
def_single_delegators :core, :dialog_proc
|
|
476
485
|
def_single_delegators :core, :autocompletion, :autocompletion=
|
|
477
486
|
|
|
478
|
-
def_single_delegators :core, :readmultiline
|
|
479
487
|
def_instance_delegators self, :readmultiline
|
|
480
488
|
private :readmultiline
|
|
481
489
|
|
|
482
|
-
def self.encoding_system_needs
|
|
490
|
+
def self.encoding_system_needs # :nodoc:
|
|
483
491
|
self.core.encoding
|
|
484
492
|
end
|
|
485
493
|
|
|
@@ -512,7 +520,7 @@ end
|
|
|
512
520
|
Reline::IOGate = Reline::IO.decide_io_gate
|
|
513
521
|
|
|
514
522
|
# Deprecated
|
|
515
|
-
Reline::GeneralIO = Reline::Dumb.new
|
|
523
|
+
Reline::GeneralIO = Reline::Dumb.new # :nodoc:
|
|
516
524
|
|
|
517
525
|
Reline::Face.load_initial_configs
|
|
518
526
|
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: reline
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- aycabta
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: io-console
|
|
@@ -62,7 +61,6 @@ metadata:
|
|
|
62
61
|
bug_tracker_uri: https://github.com/ruby/reline/issues
|
|
63
62
|
changelog_uri: https://github.com/ruby/reline/releases
|
|
64
63
|
source_code_uri: https://github.com/ruby/reline
|
|
65
|
-
post_install_message:
|
|
66
64
|
rdoc_options: []
|
|
67
65
|
require_paths:
|
|
68
66
|
- lib
|
|
@@ -77,8 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
77
75
|
- !ruby/object:Gem::Version
|
|
78
76
|
version: '0'
|
|
79
77
|
requirements: []
|
|
80
|
-
rubygems_version: 3.
|
|
81
|
-
signing_key:
|
|
78
|
+
rubygems_version: 3.6.7
|
|
82
79
|
specification_version: 4
|
|
83
80
|
summary: Alternative GNU Readline or Editline implementation by pure Ruby.
|
|
84
81
|
test_files: []
|