reline 0.6.0 → 0.6.2
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 -17
- 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 +86 -112
- data/lib/reline/unicode/east_asian_width.rb +48 -23
- data/lib/reline/unicode.rb +23 -17
- 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: ec7aa526103ceb5eff3fa7dbbfff8c33f296f9cfb28ec4cc925b28e649dc18c8
|
4
|
+
data.tar.gz: 5c86a58b7769f390a81e9f6ca19a1e64eefad4ad05091544e5a01ef752b21983
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4e586ed0f631e402d0b4b58fb05f0eec016f1290624021e957de1ced06c15e8638dac34e91c72d4b53a83e2c6b5eb5aadec2b749271d47201773dd220c63827
|
7
|
+
data.tar.gz: 6dcd53d5a30722bb4884f79eb9c70f49ab267b5e285b231237d339a52efdaa597377d308a264ed2cef23802b27aabb38d5ccbfd0c2dce40d631e15a6da5ede68
|
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.
|
@@ -192,14 +184,14 @@ class Reline::ANSI < Reline::IO
|
|
192
184
|
s = [ENV["LINES"].to_i, ENV["COLUMNS"].to_i]
|
193
185
|
return s if s[0] > 0 && s[1] > 0
|
194
186
|
[24, 80]
|
195
|
-
rescue
|
187
|
+
rescue SystemCallError
|
196
188
|
[24, 80]
|
197
189
|
end
|
198
190
|
|
199
191
|
def set_screen_size(rows, columns)
|
200
192
|
@input.winsize = [rows, columns]
|
201
193
|
self
|
202
|
-
rescue
|
194
|
+
rescue SystemCallError
|
203
195
|
self
|
204
196
|
end
|
205
197
|
|
@@ -217,9 +209,7 @@ class Reline::ANSI < Reline::IO
|
|
217
209
|
break
|
218
210
|
end
|
219
211
|
end
|
220
|
-
buf.
|
221
|
-
stdin.ungetc ch
|
222
|
-
end
|
212
|
+
@buf.concat buf.bytes
|
223
213
|
end
|
224
214
|
[match[:column].to_i - 1, match[:row].to_i - 1] if match
|
225
215
|
end
|
@@ -309,6 +299,13 @@ class Reline::ANSI < Reline::IO
|
|
309
299
|
# Signal.trap may raise an ArgumentError if the platform doesn't support the signal.
|
310
300
|
end
|
311
301
|
|
302
|
+
def read_single_char(timeout_second)
|
303
|
+
# Disable intr to read `C-c` `C-z` `C-\` for quoted insert
|
304
|
+
@input.raw(intr: false) do
|
305
|
+
super
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
312
309
|
def prep
|
313
310
|
# Enable bracketed paste
|
314
311
|
write "\e[?2004h" if Reline.core.config.enable_bracketed_paste && both_tty?
|
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)
|
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,7 +1420,14 @@ 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
|
@@ -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
|
@@ -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,12 +28,12 @@ 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"
|
@@ -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.2
|
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: []
|