reline 0.2.8.pre.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/reline/ansi.rb +50 -23
- data/lib/reline/config.rb +10 -2
- data/lib/reline/general_io.rb +2 -1
- data/lib/reline/key_actor/emacs.rb +1 -1
- data/lib/reline/key_stroke.rb +60 -62
- data/lib/reline/line_editor.rb +239 -110
- data/lib/reline/terminfo.rb +12 -4
- data/lib/reline/unicode.rb +9 -1
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +121 -50
- data/lib/reline.rb +31 -23
- metadata +4 -5
- data/lib/reline/line_editor.rb.orig +0 -3199
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e8c2181e5eb21934546d6b768715cb47eab6e1ea1edb2fd2300f43af62dc2b1
|
4
|
+
data.tar.gz: 99a61e2729d4b5d150f6f59d99d6de235ea4f1aab6ac262c92fff6a77101b85f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96ceefe0bf71e7e44ccd2a5970b35fc44019af9d7da4d2e04ac1d827eb6bc6a201e679a5e40c4db976554159286f16e39cdeac68bcf69c2c5abeb00a2045e563
|
7
|
+
data.tar.gz: 251c2029df6b3073010ad6a591fb216990124ed4f9e00f533e79461be66c6a2383ea56c1554dd273e4af3cfc9358dee37b76a1b4bff25a1867972201bfebace3
|
data/lib/reline/ansi.rb
CHANGED
@@ -4,6 +4,19 @@ require 'timeout'
|
|
4
4
|
require_relative 'terminfo'
|
5
5
|
|
6
6
|
class Reline::ANSI
|
7
|
+
CAPNAME_KEY_BINDINGS = {
|
8
|
+
'khome' => :ed_move_to_beg,
|
9
|
+
'kend' => :ed_move_to_end,
|
10
|
+
'kcuu1' => :ed_prev_history,
|
11
|
+
'kcud1' => :ed_next_history,
|
12
|
+
'kcuf1' => :ed_next_char,
|
13
|
+
'kcub1' => :ed_prev_char,
|
14
|
+
'cuu' => :ed_prev_history,
|
15
|
+
'cud' => :ed_next_history,
|
16
|
+
'cuf' => :ed_next_char,
|
17
|
+
'cub' => :ed_prev_char,
|
18
|
+
}
|
19
|
+
|
7
20
|
if Reline::Terminfo.enabled?
|
8
21
|
Reline::Terminfo.setupterm(0, 2)
|
9
22
|
end
|
@@ -33,31 +46,39 @@ class Reline::ANSI
|
|
33
46
|
config.add_default_key_binding_by_keymap(:vi_insert, key, func)
|
34
47
|
config.add_default_key_binding_by_keymap(:vi_command, key, func)
|
35
48
|
end
|
49
|
+
{
|
50
|
+
[27, 91, 90] => :completion_journey_up, # S-Tab
|
51
|
+
}.each_pair do |key, func|
|
52
|
+
config.add_default_key_binding_by_keymap(:emacs, key, func)
|
53
|
+
config.add_default_key_binding_by_keymap(:vi_insert, key, func)
|
54
|
+
end
|
36
55
|
{
|
37
56
|
# default bindings
|
38
57
|
[27, 32] => :em_set_mark, # M-<space>
|
39
58
|
[24, 24] => :em_exchange_mark, # C-x C-x
|
40
|
-
[27, 91, 90] => :completion_journey_up, # S-Tab
|
41
59
|
}.each_pair do |key, func|
|
42
60
|
config.add_default_key_binding_by_keymap(:emacs, key, func)
|
43
61
|
end
|
44
62
|
end
|
45
63
|
|
46
64
|
def self.set_default_key_bindings_terminfo(config)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
Reline::Terminfo
|
59
|
-
|
60
|
-
|
65
|
+
key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding|
|
66
|
+
begin
|
67
|
+
key_code = Reline::Terminfo.tigetstr(capname)
|
68
|
+
case capname
|
69
|
+
# Escape sequences that omit the move distance and are set to defaults
|
70
|
+
# value 1 may be sometimes sent by pressing the arrow-key.
|
71
|
+
when 'cuu', 'cud', 'cuf', 'cub'
|
72
|
+
[ key_code.sub(/%p1%d/, '').bytes, key_binding ]
|
73
|
+
else
|
74
|
+
[ key_code.bytes, key_binding ]
|
75
|
+
end
|
76
|
+
rescue Reline::Terminfo::TerminfoError
|
77
|
+
# capname is undefined
|
78
|
+
end
|
79
|
+
end.compact.to_h
|
80
|
+
|
81
|
+
key_bindings.each_pair do |key, func|
|
61
82
|
config.add_default_key_binding_by_keymap(:emacs, key, func)
|
62
83
|
config.add_default_key_binding_by_keymap(:vi_insert, key, func)
|
63
84
|
config.add_default_key_binding_by_keymap(:vi_command, key, func)
|
@@ -126,8 +147,8 @@ class Reline::ANSI
|
|
126
147
|
unless @@buf.empty?
|
127
148
|
return @@buf.shift
|
128
149
|
end
|
129
|
-
until c = @@input.raw(intr: true
|
130
|
-
|
150
|
+
until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
|
151
|
+
Reline.core.line_editor.resize
|
131
152
|
end
|
132
153
|
(c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
|
133
154
|
rescue Errno::EIO
|
@@ -261,7 +282,7 @@ class Reline::ANSI
|
|
261
282
|
|
262
283
|
def self.move_cursor_up(x)
|
263
284
|
if x > 0
|
264
|
-
@@output.write "\e[#{x}A"
|
285
|
+
@@output.write "\e[#{x}A"
|
265
286
|
elsif x < 0
|
266
287
|
move_cursor_down(-x)
|
267
288
|
end
|
@@ -269,7 +290,7 @@ class Reline::ANSI
|
|
269
290
|
|
270
291
|
def self.move_cursor_down(x)
|
271
292
|
if x > 0
|
272
|
-
@@output.write "\e[#{x}B"
|
293
|
+
@@output.write "\e[#{x}B"
|
273
294
|
elsif x < 0
|
274
295
|
move_cursor_up(-x)
|
275
296
|
end
|
@@ -277,7 +298,11 @@ class Reline::ANSI
|
|
277
298
|
|
278
299
|
def self.hide_cursor
|
279
300
|
if Reline::Terminfo.enabled?
|
280
|
-
|
301
|
+
begin
|
302
|
+
@@output.write Reline::Terminfo.tigetstr('civis')
|
303
|
+
rescue Reline::Terminfo::TerminfoError
|
304
|
+
# civis is undefined
|
305
|
+
end
|
281
306
|
else
|
282
307
|
# ignored
|
283
308
|
end
|
@@ -285,7 +310,11 @@ class Reline::ANSI
|
|
285
310
|
|
286
311
|
def self.show_cursor
|
287
312
|
if Reline::Terminfo.enabled?
|
288
|
-
|
313
|
+
begin
|
314
|
+
@@output.write Reline::Terminfo.tigetstr('cnorm')
|
315
|
+
rescue Reline::Terminfo::TerminfoError
|
316
|
+
# cnorm is undefined
|
317
|
+
end
|
289
318
|
else
|
290
319
|
# ignored
|
291
320
|
end
|
@@ -316,8 +345,6 @@ class Reline::ANSI
|
|
316
345
|
end
|
317
346
|
|
318
347
|
def self.deprep(otio)
|
319
|
-
int_handle = Signal.trap('INT', 'IGNORE')
|
320
|
-
Signal.trap('INT', int_handle)
|
321
348
|
Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
|
322
349
|
end
|
323
350
|
end
|
data/lib/reline/config.rb
CHANGED
@@ -67,6 +67,7 @@ class Reline::Config
|
|
67
67
|
@keyseq_timeout = 500
|
68
68
|
@test_mode = false
|
69
69
|
@autocompletion = false
|
70
|
+
@convert_meta = true if seven_bit_encoding?(Reline::IOGate.encoding)
|
70
71
|
end
|
71
72
|
|
72
73
|
def reset
|
@@ -154,8 +155,11 @@ class Reline::Config
|
|
154
155
|
end
|
155
156
|
|
156
157
|
def key_bindings
|
157
|
-
#
|
158
|
-
@key_actors[@editing_mode_label].default_key_bindings.
|
158
|
+
# The key bindings for each editing mode will be overwritten by the user-defined ones.
|
159
|
+
kb = @key_actors[@editing_mode_label].default_key_bindings.dup
|
160
|
+
kb.merge!(@additional_key_bindings[@editing_mode_label])
|
161
|
+
kb.merge!(@oneshot_key_bindings)
|
162
|
+
kb
|
159
163
|
end
|
160
164
|
|
161
165
|
def add_oneshot_key_binding(keystroke, target)
|
@@ -384,4 +388,8 @@ class Reline::Config
|
|
384
388
|
end
|
385
389
|
ret
|
386
390
|
end
|
391
|
+
|
392
|
+
private def seven_bit_encoding?(encoding)
|
393
|
+
encoding == Encoding::US_ASCII
|
394
|
+
end
|
387
395
|
end
|
data/lib/reline/general_io.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'timeout'
|
2
|
+
require 'io/wait'
|
2
3
|
|
3
4
|
class Reline::GeneralIO
|
4
5
|
def self.reset(encoding: nil)
|
@@ -36,7 +37,7 @@ class Reline::GeneralIO
|
|
36
37
|
end
|
37
38
|
c = nil
|
38
39
|
loop do
|
39
|
-
result =
|
40
|
+
result = @@input.wait_readable(0.1)
|
40
41
|
next if result.nil?
|
41
42
|
c = @@input.read(1)
|
42
43
|
break
|
data/lib/reline/key_stroke.rb
CHANGED
@@ -1,90 +1,88 @@
|
|
1
1
|
class Reline::KeyStroke
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
2
|
+
def initialize(config)
|
3
|
+
@config = config
|
4
|
+
end
|
5
|
+
|
6
|
+
def compress_meta_key(ary)
|
7
|
+
return ary unless @config.convert_meta
|
8
|
+
ary.inject([]) { |result, key|
|
9
|
+
if result.size > 0 and result.last == "\e".ord
|
10
|
+
result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
|
11
|
+
else
|
12
|
+
result << key
|
13
|
+
end
|
14
|
+
result
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def start_with?(me, other)
|
19
|
+
compressed_me = compress_meta_key(me)
|
20
|
+
compressed_other = compress_meta_key(other)
|
21
|
+
i = 0
|
22
|
+
loop do
|
23
|
+
my_c = compressed_me[i]
|
24
|
+
other_c = compressed_other[i]
|
25
|
+
other_is_last = (i + 1) == compressed_other.size
|
26
|
+
me_is_last = (i + 1) == compressed_me.size
|
27
|
+
if my_c != other_c
|
28
|
+
if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
|
29
|
+
return true
|
11
30
|
else
|
12
|
-
|
31
|
+
return false
|
13
32
|
end
|
33
|
+
elsif other_is_last
|
34
|
+
return true
|
35
|
+
elsif me_is_last
|
36
|
+
return false
|
14
37
|
end
|
38
|
+
i += 1
|
15
39
|
end
|
40
|
+
end
|
16
41
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
return true
|
30
|
-
else
|
31
|
-
return false
|
32
|
-
end
|
33
|
-
elsif other_is_last
|
34
|
-
return true
|
35
|
-
elsif me_is_last
|
36
|
-
return false
|
37
|
-
end
|
38
|
-
i += 1
|
42
|
+
def equal?(me, other)
|
43
|
+
case me
|
44
|
+
when Array
|
45
|
+
compressed_me = compress_meta_key(me)
|
46
|
+
compressed_other = compress_meta_key(other)
|
47
|
+
compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| equal?(i[0], i[1]) }
|
48
|
+
when Integer
|
49
|
+
if other.is_a?(Reline::Key)
|
50
|
+
if other.combined_char == "\e".ord
|
51
|
+
false
|
52
|
+
else
|
53
|
+
other.combined_char == me
|
39
54
|
end
|
55
|
+
else
|
56
|
+
me == other
|
40
57
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
def compress_meta_key
|
49
|
-
inject([]) { |result, key|
|
50
|
-
if result.size > 0 and result.last == "\e".ord
|
51
|
-
result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
|
52
|
-
else
|
53
|
-
result << key
|
54
|
-
end
|
55
|
-
result
|
56
|
-
}
|
57
|
-
end
|
58
|
-
|
59
|
-
def bytes
|
60
|
-
self
|
58
|
+
when Reline::Key
|
59
|
+
if other.is_a?(Integer)
|
60
|
+
me.combined_char == other
|
61
|
+
else
|
62
|
+
me == other
|
61
63
|
end
|
62
64
|
end
|
63
|
-
}
|
64
|
-
|
65
|
-
def initialize(config)
|
66
|
-
@config = config
|
67
65
|
end
|
68
66
|
|
69
67
|
def match_status(input)
|
70
68
|
key_mapping.keys.select { |lhs|
|
71
|
-
|
69
|
+
start_with?(lhs, input)
|
72
70
|
}.tap { |it|
|
73
|
-
return :matched if it.size == 1 && (it[0]
|
74
|
-
return :matching if it.size == 1 && (it[0]
|
71
|
+
return :matched if it.size == 1 && equal?(it[0], input)
|
72
|
+
return :matching if it.size == 1 && !equal?(it[0], input)
|
75
73
|
return :matched if it.max_by(&:size)&.size&.< input.size
|
76
74
|
return :matching if it.size > 1
|
77
75
|
}
|
78
76
|
key_mapping.keys.select { |lhs|
|
79
|
-
|
77
|
+
start_with?(input, lhs)
|
80
78
|
}.tap { |it|
|
81
79
|
return it.size > 0 ? :matched : :unmatched
|
82
80
|
}
|
83
81
|
end
|
84
82
|
|
85
83
|
def expand(input)
|
86
|
-
input = input
|
87
|
-
lhs = key_mapping.keys.select { |item|
|
84
|
+
input = compress_meta_key(input)
|
85
|
+
lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
|
88
86
|
return input unless lhs
|
89
87
|
rhs = key_mapping[lhs]
|
90
88
|
|