reline 0.2.8.pre.8 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|