reline 0.2.8.pre.6 → 0.2.8.pre.10
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 +8 -3
- data/lib/reline/config.rb +20 -3
- data/lib/reline/key_actor/emacs.rb +1 -1
- data/lib/reline/key_stroke.rb +63 -14
- data/lib/reline/line_editor.rb +219 -73
- data/lib/reline/terminfo.rb +1 -1
- data/lib/reline/unicode.rb +3 -3
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +17 -14
- data/lib/reline.rb +57 -25
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdcb3b1edc046520bc5be9cbddb21a4ba498fd1111319c90b05f76b066155eaa
|
4
|
+
data.tar.gz: f5a5af7fb221dc0fb21aac67baa20af7c159f22ee792b5f9264badb1ff8b6ba4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a40a42eb7fe33b39dbf8d56eae76708caee116462bbe35b537e36b39e0edb8263cd5854f48b8c7ef440b686c5dabb7e34c72ec844c2ab79661797c23a28a9f0f
|
7
|
+
data.tar.gz: 9937033c4b7509a3ef39522bc82e574cd6049cfa6204463625bf89ad427ff7c21e36ca3e0a94b11e3b36dfb1cacb2b3a357a3a115e80b13e94eb9512697aea1e
|
data/lib/reline/ansi.rb
CHANGED
@@ -33,11 +33,16 @@ class Reline::ANSI
|
|
33
33
|
config.add_default_key_binding_by_keymap(:vi_insert, key, func)
|
34
34
|
config.add_default_key_binding_by_keymap(:vi_command, key, func)
|
35
35
|
end
|
36
|
+
{
|
37
|
+
[27, 91, 90] => :completion_journey_up, # S-Tab
|
38
|
+
}.each_pair do |key, func|
|
39
|
+
config.add_default_key_binding_by_keymap(:emacs, key, func)
|
40
|
+
config.add_default_key_binding_by_keymap(:vi_insert, key, func)
|
41
|
+
end
|
36
42
|
{
|
37
43
|
# default bindings
|
38
44
|
[27, 32] => :em_set_mark, # M-<space>
|
39
45
|
[24, 24] => :em_exchange_mark, # C-x C-x
|
40
|
-
[27, 91, 90] => :completion_journey_up, # S-Tab
|
41
46
|
}.each_pair do |key, func|
|
42
47
|
config.add_default_key_binding_by_keymap(:emacs, key, func)
|
43
48
|
end
|
@@ -126,8 +131,8 @@ class Reline::ANSI
|
|
126
131
|
unless @@buf.empty?
|
127
132
|
return @@buf.shift
|
128
133
|
end
|
129
|
-
until c = @@input.raw(intr: true,
|
130
|
-
|
134
|
+
until c = @@input.raw(intr: true) { select([@@input], [], [], 0.1) && @@input.getbyte }
|
135
|
+
Reline.core.line_editor.resize
|
131
136
|
end
|
132
137
|
(c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
|
133
138
|
rescue Errno::EIO
|
data/lib/reline/config.rb
CHANGED
@@ -50,6 +50,7 @@ class Reline::Config
|
|
50
50
|
@additional_key_bindings[:emacs] = {}
|
51
51
|
@additional_key_bindings[:vi_insert] = {}
|
52
52
|
@additional_key_bindings[:vi_command] = {}
|
53
|
+
@oneshot_key_bindings = {}
|
53
54
|
@skip_section = nil
|
54
55
|
@if_stack = nil
|
55
56
|
@editing_mode_label = :emacs
|
@@ -75,6 +76,7 @@ class Reline::Config
|
|
75
76
|
@additional_key_bindings.keys.each do |key|
|
76
77
|
@additional_key_bindings[key].clear
|
77
78
|
end
|
79
|
+
@oneshot_key_bindings.clear
|
78
80
|
reset_default_key_bindings
|
79
81
|
end
|
80
82
|
|
@@ -128,8 +130,12 @@ class Reline::Config
|
|
128
130
|
return home_rc_path
|
129
131
|
end
|
130
132
|
|
133
|
+
private def default_inputrc_path
|
134
|
+
@default_inputrc_path ||= inputrc_path
|
135
|
+
end
|
136
|
+
|
131
137
|
def read(file = nil)
|
132
|
-
file ||=
|
138
|
+
file ||= default_inputrc_path
|
133
139
|
begin
|
134
140
|
if file.respond_to?(:readlines)
|
135
141
|
lines = file.readlines
|
@@ -148,8 +154,19 @@ class Reline::Config
|
|
148
154
|
end
|
149
155
|
|
150
156
|
def key_bindings
|
151
|
-
#
|
152
|
-
@key_actors[@editing_mode_label].default_key_bindings.
|
157
|
+
# The key bindings for each editing mode will be overwritten by the user-defined ones.
|
158
|
+
kb = @key_actors[@editing_mode_label].default_key_bindings.dup
|
159
|
+
kb.merge!(@additional_key_bindings[@editing_mode_label])
|
160
|
+
kb.merge!(@oneshot_key_bindings)
|
161
|
+
kb
|
162
|
+
end
|
163
|
+
|
164
|
+
def add_oneshot_key_binding(keystroke, target)
|
165
|
+
@oneshot_key_bindings[keystroke] = target
|
166
|
+
end
|
167
|
+
|
168
|
+
def reset_oneshot_key_bindings
|
169
|
+
@oneshot_key_bindings.clear
|
153
170
|
end
|
154
171
|
|
155
172
|
def add_default_key_binding_by_keymap(keymap, keystroke, target)
|
data/lib/reline/key_stroke.rb
CHANGED
@@ -1,38 +1,87 @@
|
|
1
1
|
class Reline::KeyStroke
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
def initialize(config)
|
3
|
+
@config = config
|
4
|
+
end
|
5
|
+
|
6
|
+
def compress_meta_key(ary)
|
7
|
+
ary.inject([]) { |result, key|
|
8
|
+
if result.size > 0 and result.last == "\e".ord
|
9
|
+
result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
|
10
|
+
else
|
11
|
+
result << key
|
6
12
|
end
|
13
|
+
result
|
14
|
+
}
|
15
|
+
end
|
7
16
|
|
8
|
-
|
9
|
-
|
17
|
+
def start_with?(me, other)
|
18
|
+
compressed_me = compress_meta_key(me)
|
19
|
+
compressed_other = compress_meta_key(other)
|
20
|
+
i = 0
|
21
|
+
loop do
|
22
|
+
my_c = compressed_me[i]
|
23
|
+
other_c = compressed_other[i]
|
24
|
+
other_is_last = (i + 1) == compressed_other.size
|
25
|
+
me_is_last = (i + 1) == compressed_me.size
|
26
|
+
if my_c != other_c
|
27
|
+
if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
|
28
|
+
return true
|
29
|
+
else
|
30
|
+
return false
|
31
|
+
end
|
32
|
+
elsif other_is_last
|
33
|
+
return true
|
34
|
+
elsif me_is_last
|
35
|
+
return false
|
10
36
|
end
|
37
|
+
i += 1
|
11
38
|
end
|
12
|
-
|
39
|
+
end
|
13
40
|
|
14
|
-
def
|
15
|
-
|
41
|
+
def equal?(me, other)
|
42
|
+
case me
|
43
|
+
when Array
|
44
|
+
compressed_me = compress_meta_key(me)
|
45
|
+
compressed_other = compress_meta_key(other)
|
46
|
+
compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| equal?(i[0], i[1]) }
|
47
|
+
when Integer
|
48
|
+
if other.is_a?(Reline::Key)
|
49
|
+
if other.combined_char == "\e".ord
|
50
|
+
false
|
51
|
+
else
|
52
|
+
other.combined_char == me
|
53
|
+
end
|
54
|
+
else
|
55
|
+
me == other
|
56
|
+
end
|
57
|
+
when Reline::Key
|
58
|
+
if other.is_a?(Integer)
|
59
|
+
me.combined_char == other
|
60
|
+
else
|
61
|
+
me == other
|
62
|
+
end
|
63
|
+
end
|
16
64
|
end
|
17
65
|
|
18
66
|
def match_status(input)
|
19
67
|
key_mapping.keys.select { |lhs|
|
20
|
-
|
68
|
+
start_with?(lhs, input)
|
21
69
|
}.tap { |it|
|
22
|
-
return :matched if it.size == 1 && (it
|
23
|
-
return :matching if it.size == 1 && (it
|
70
|
+
return :matched if it.size == 1 && equal?(it[0], input)
|
71
|
+
return :matching if it.size == 1 && !equal?(it[0], input)
|
24
72
|
return :matched if it.max_by(&:size)&.size&.< input.size
|
25
73
|
return :matching if it.size > 1
|
26
74
|
}
|
27
75
|
key_mapping.keys.select { |lhs|
|
28
|
-
|
76
|
+
start_with?(input, lhs)
|
29
77
|
}.tap { |it|
|
30
78
|
return it.size > 0 ? :matched : :unmatched
|
31
79
|
}
|
32
80
|
end
|
33
81
|
|
34
82
|
def expand(input)
|
35
|
-
|
83
|
+
input = compress_meta_key(input)
|
84
|
+
lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
|
36
85
|
return input unless lhs
|
37
86
|
rhs = key_mapping[lhs]
|
38
87
|
|
data/lib/reline/line_editor.rb
CHANGED
@@ -5,6 +5,7 @@ require 'tempfile'
|
|
5
5
|
|
6
6
|
class Reline::LineEditor
|
7
7
|
# TODO: undo
|
8
|
+
# TODO: Use "private alias_method" idiom after drop Ruby 2.5.
|
8
9
|
attr_reader :line
|
9
10
|
attr_reader :byte_pointer
|
10
11
|
attr_accessor :confirm_multiline_termination_proc
|
@@ -150,7 +151,7 @@ class Reline::LineEditor
|
|
150
151
|
@screen_size = Reline::IOGate.get_screen_size
|
151
152
|
@screen_height = @screen_size.first
|
152
153
|
reset_variables(prompt, encoding: encoding)
|
153
|
-
@old_trap = Signal.trap(
|
154
|
+
@old_trap = Signal.trap('INT') {
|
154
155
|
clear_dialog
|
155
156
|
if @scroll_partial_screen
|
156
157
|
move_cursor_down(@screen_height - (@line_index - @scroll_partial_screen) - 1)
|
@@ -170,47 +171,65 @@ class Reline::LineEditor
|
|
170
171
|
@old_trap.call
|
171
172
|
end
|
172
173
|
}
|
174
|
+
begin
|
175
|
+
@old_tstp_trap = Signal.trap('TSTP') {
|
176
|
+
Reline::IOGate.ungetc("\C-z".ord)
|
177
|
+
@old_tstp_trap.call if @old_tstp_trap.respond_to?(:call)
|
178
|
+
}
|
179
|
+
rescue ArgumentError
|
180
|
+
end
|
173
181
|
Reline::IOGate.set_winch_handler do
|
174
|
-
@
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
182
|
+
@resized = true
|
183
|
+
end
|
184
|
+
@block_elem_width = Reline::Unicode.calculate_width('█')
|
185
|
+
end
|
186
|
+
|
187
|
+
def resize
|
188
|
+
return unless @resized
|
189
|
+
@resized = false
|
190
|
+
@rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
|
191
|
+
old_screen_size = @screen_size
|
192
|
+
@screen_size = Reline::IOGate.get_screen_size
|
193
|
+
@screen_height = @screen_size.first
|
194
|
+
if old_screen_size.last < @screen_size.last # columns increase
|
195
|
+
@rerender_all = true
|
196
|
+
rerender
|
197
|
+
else
|
198
|
+
back = 0
|
199
|
+
new_buffer = whole_lines
|
200
|
+
prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt)
|
201
|
+
new_buffer.each_with_index do |line, index|
|
202
|
+
prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
|
203
|
+
width = prompt_width + calculate_width(line)
|
204
|
+
height = calculate_height_by_width(width)
|
205
|
+
back += height
|
206
|
+
end
|
207
|
+
@highest_in_all = back
|
208
|
+
@highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
|
209
|
+
@first_line_started_from =
|
210
|
+
if @line_index.zero?
|
211
|
+
0
|
212
|
+
else
|
213
|
+
calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
|
202
214
|
end
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
@highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
|
207
|
-
@rerender_all = true
|
215
|
+
if @prompt_proc
|
216
|
+
prompt = prompt_list[@line_index]
|
217
|
+
prompt_width = calculate_width(prompt, true)
|
208
218
|
end
|
219
|
+
calculate_nearest_cursor
|
220
|
+
@started_from = calculate_height_by_width(prompt_width + @cursor) - 1
|
221
|
+
Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
|
222
|
+
@highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
|
223
|
+
@rerender_all = true
|
209
224
|
end
|
210
225
|
end
|
211
226
|
|
212
227
|
def finalize
|
213
|
-
Signal.trap('
|
228
|
+
Signal.trap('INT', @old_trap)
|
229
|
+
begin
|
230
|
+
Signal.trap('TSTP', @old_tstp_trap)
|
231
|
+
rescue ArgumentError
|
232
|
+
end
|
214
233
|
end
|
215
234
|
|
216
235
|
def eof?
|
@@ -251,6 +270,8 @@ class Reline::LineEditor
|
|
251
270
|
@in_pasting = false
|
252
271
|
@auto_indent_proc = nil
|
253
272
|
@dialogs = []
|
273
|
+
@last_key = nil
|
274
|
+
@resized = false
|
254
275
|
reset_line
|
255
276
|
end
|
256
277
|
|
@@ -512,6 +533,14 @@ class Reline::LineEditor
|
|
512
533
|
@cursor_pos.y = row
|
513
534
|
end
|
514
535
|
|
536
|
+
def set_key(key)
|
537
|
+
@key = key
|
538
|
+
end
|
539
|
+
|
540
|
+
def key
|
541
|
+
@key
|
542
|
+
end
|
543
|
+
|
515
544
|
def cursor_pos
|
516
545
|
@cursor_pos
|
517
546
|
end
|
@@ -539,13 +568,15 @@ class Reline::LineEditor
|
|
539
568
|
|
540
569
|
class Dialog
|
541
570
|
attr_reader :name, :contents, :width
|
542
|
-
attr_accessor :scroll_top, :column, :vertical_offset, :lines_backup
|
571
|
+
attr_accessor :scroll_top, :scrollbar_pos, :pointer, :column, :vertical_offset, :lines_backup, :trap_key
|
543
572
|
|
544
|
-
def initialize(name, proc_scope)
|
573
|
+
def initialize(name, config, proc_scope)
|
545
574
|
@name = name
|
575
|
+
@config = config
|
546
576
|
@proc_scope = proc_scope
|
547
577
|
@width = nil
|
548
578
|
@scroll_top = 0
|
579
|
+
@trap_key = nil
|
549
580
|
end
|
550
581
|
|
551
582
|
def set_cursor_pos(col, row)
|
@@ -563,15 +594,28 @@ class Reline::LineEditor
|
|
563
594
|
end
|
564
595
|
end
|
565
596
|
|
566
|
-
def call
|
597
|
+
def call(key)
|
567
598
|
@proc_scope.set_dialog(self)
|
568
|
-
@proc_scope.
|
599
|
+
@proc_scope.set_key(key)
|
600
|
+
dialog_render_info = @proc_scope.call
|
601
|
+
if @trap_key
|
602
|
+
if @trap_key.any?{ |i| i.is_a?(Array) } # multiple trap
|
603
|
+
@trap_key.each do |t|
|
604
|
+
@config.add_oneshot_key_binding(t, @name)
|
605
|
+
end
|
606
|
+
elsif @trap_key.is_a?(Array)
|
607
|
+
@config.add_oneshot_key_binding(@trap_key, @name)
|
608
|
+
elsif @trap_key.is_a?(Integer) or @trap_key.is_a?(Reline::Key)
|
609
|
+
@config.add_oneshot_key_binding([@trap_key], @name)
|
610
|
+
end
|
611
|
+
end
|
612
|
+
dialog_render_info
|
569
613
|
end
|
570
614
|
end
|
571
615
|
|
572
616
|
def add_dialog_proc(name, p, context = nil)
|
573
617
|
return if @dialogs.any? { |d| d.name == name }
|
574
|
-
@dialogs << Dialog.new(name, DialogProcScope.new(self, @config, p, context))
|
618
|
+
@dialogs << Dialog.new(name, @config, DialogProcScope.new(self, @config, p, context))
|
575
619
|
end
|
576
620
|
|
577
621
|
DIALOG_HEIGHT = 20
|
@@ -588,10 +632,11 @@ class Reline::LineEditor
|
|
588
632
|
private def render_each_dialog(dialog, cursor_column)
|
589
633
|
if @in_pasting
|
590
634
|
dialog.contents = nil
|
635
|
+
dialog.trap_key = nil
|
591
636
|
return
|
592
637
|
end
|
593
638
|
dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from)
|
594
|
-
dialog_render_info = dialog.call
|
639
|
+
dialog_render_info = dialog.call(@last_key)
|
595
640
|
if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
|
596
641
|
dialog.lines_backup = {
|
597
642
|
lines: modify_lines(whole_lines),
|
@@ -602,27 +647,41 @@ class Reline::LineEditor
|
|
602
647
|
}
|
603
648
|
clear_each_dialog(dialog)
|
604
649
|
dialog.contents = nil
|
650
|
+
dialog.trap_key = nil
|
605
651
|
return
|
606
652
|
end
|
607
653
|
old_dialog = dialog.clone
|
608
|
-
dialog.width = dialog_render_info.width if dialog_render_info.width
|
609
|
-
height = dialog_render_info.height || DIALOG_HEIGHT
|
610
|
-
pointer = dialog_render_info.pointer
|
611
654
|
dialog.contents = dialog_render_info.contents
|
655
|
+
pointer = dialog.pointer
|
656
|
+
if dialog_render_info.width
|
657
|
+
dialog.width = dialog_render_info.width
|
658
|
+
else
|
659
|
+
dialog.width = dialog.contents.map { |l| calculate_width(l, true) }.max
|
660
|
+
end
|
661
|
+
height = dialog_render_info.height || DIALOG_HEIGHT
|
612
662
|
height = dialog.contents.size if dialog.contents.size < height
|
613
663
|
if dialog.contents.size > height
|
614
|
-
if
|
615
|
-
if
|
664
|
+
if dialog.pointer
|
665
|
+
if dialog.pointer < 0
|
616
666
|
dialog.scroll_top = 0
|
617
|
-
elsif (
|
618
|
-
dialog.scroll_top =
|
619
|
-
elsif (
|
620
|
-
dialog.scroll_top =
|
667
|
+
elsif (dialog.pointer - dialog.scroll_top) >= (height - 1)
|
668
|
+
dialog.scroll_top = dialog.pointer - (height - 1)
|
669
|
+
elsif (dialog.pointer - dialog.scroll_top) < 0
|
670
|
+
dialog.scroll_top = dialog.pointer
|
621
671
|
end
|
622
|
-
pointer =
|
672
|
+
pointer = dialog.pointer - dialog.scroll_top
|
623
673
|
end
|
624
674
|
dialog.contents = dialog.contents[dialog.scroll_top, height]
|
625
675
|
end
|
676
|
+
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
|
677
|
+
bar_max_height = height * 2
|
678
|
+
moving_distance = (dialog_render_info.contents.size - height) * 2
|
679
|
+
position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
|
680
|
+
bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
|
681
|
+
dialog.scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
|
682
|
+
else
|
683
|
+
dialog.scrollbar_pos = nil
|
684
|
+
end
|
626
685
|
upper_space = @first_line_started_from - @started_from
|
627
686
|
lower_space = @highest_in_all - @first_line_started_from - @started_from - 1
|
628
687
|
dialog.column = dialog_render_info.pos.x
|
@@ -642,6 +701,7 @@ class Reline::LineEditor
|
|
642
701
|
dialog.vertical_offset = dialog_render_info.pos.y + 1
|
643
702
|
end
|
644
703
|
Reline::IOGate.hide_cursor
|
704
|
+
dialog.width += @block_elem_width if dialog.scrollbar_pos
|
645
705
|
reset_dialog(dialog, old_dialog)
|
646
706
|
move_cursor_down(dialog.vertical_offset)
|
647
707
|
Reline::IOGate.move_cursor_column(dialog.column)
|
@@ -655,8 +715,23 @@ class Reline::LineEditor
|
|
655
715
|
bg_color = '46'
|
656
716
|
end
|
657
717
|
end
|
658
|
-
|
659
|
-
|
718
|
+
str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
|
719
|
+
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
|
720
|
+
@output.write "\e[#{bg_color}m#{str}"
|
721
|
+
if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
|
722
|
+
@output.write "\e[37m"
|
723
|
+
if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height)
|
724
|
+
@output.write '█'
|
725
|
+
elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height)
|
726
|
+
@output.write '▀'
|
727
|
+
str += ''
|
728
|
+
elsif dialog.scrollbar_pos <= (i * 2 + 1) and (i * 2) < (dialog.scrollbar_pos + bar_height)
|
729
|
+
@output.write '▄'
|
730
|
+
else
|
731
|
+
@output.write ' ' * @block_elem_width
|
732
|
+
end
|
733
|
+
end
|
734
|
+
@output.write "\e[0m"
|
660
735
|
Reline::IOGate.move_cursor_column(dialog.column)
|
661
736
|
move_cursor_down(1) if i < (dialog.contents.size - 1)
|
662
737
|
end
|
@@ -697,12 +772,12 @@ class Reline::LineEditor
|
|
697
772
|
line_num.times do |i|
|
698
773
|
Reline::IOGate.move_cursor_column(old_dialog.column)
|
699
774
|
if visual_lines[start + i].nil?
|
700
|
-
s = ' ' *
|
775
|
+
s = ' ' * old_dialog.width
|
701
776
|
else
|
702
|
-
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column,
|
703
|
-
s = padding_space_with_escape_sequences(s,
|
777
|
+
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
|
778
|
+
s = padding_space_with_escape_sequences(s, old_dialog.width)
|
704
779
|
end
|
705
|
-
@output.write "\e[
|
780
|
+
@output.write "\e[0m#{s}\e[0m"
|
706
781
|
move_cursor_down(1) if i < (line_num - 1)
|
707
782
|
end
|
708
783
|
move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
|
@@ -715,12 +790,12 @@ class Reline::LineEditor
|
|
715
790
|
line_num.times do |i|
|
716
791
|
Reline::IOGate.move_cursor_column(old_dialog.column)
|
717
792
|
if visual_lines[start + i].nil?
|
718
|
-
s = ' ' *
|
793
|
+
s = ' ' * old_dialog.width
|
719
794
|
else
|
720
|
-
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column,
|
721
|
-
s = padding_space_with_escape_sequences(s,
|
795
|
+
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, old_dialog.width)
|
796
|
+
s = padding_space_with_escape_sequences(s, old_dialog.width)
|
722
797
|
end
|
723
|
-
@output.write "\e[
|
798
|
+
@output.write "\e[0m#{s}\e[0m"
|
724
799
|
move_cursor_down(1) if i < (line_num - 1)
|
725
800
|
end
|
726
801
|
move_cursor_up(dialog.vertical_offset + dialog.contents.size + line_num - 1 - y_diff)
|
@@ -739,7 +814,7 @@ class Reline::LineEditor
|
|
739
814
|
s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, width)
|
740
815
|
s = padding_space_with_escape_sequences(s, dialog.width)
|
741
816
|
end
|
742
|
-
@output.write "\e[
|
817
|
+
@output.write "\e[0m#{s}\e[0m"
|
743
818
|
move_cursor_down(1) if i < (line_num - 1)
|
744
819
|
end
|
745
820
|
move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
|
@@ -759,7 +834,7 @@ class Reline::LineEditor
|
|
759
834
|
s = padding_space_with_escape_sequences(s, dialog.width)
|
760
835
|
end
|
761
836
|
Reline::IOGate.move_cursor_column(dialog.column + dialog.width)
|
762
|
-
@output.write "\e[
|
837
|
+
@output.write "\e[0m#{s}\e[0m"
|
763
838
|
move_cursor_down(1) if i < (line_num - 1)
|
764
839
|
end
|
765
840
|
move_cursor_up(old_dialog.vertical_offset + line_num - 1 + y_diff)
|
@@ -774,6 +849,7 @@ class Reline::LineEditor
|
|
774
849
|
end
|
775
850
|
|
776
851
|
private def clear_each_dialog(dialog)
|
852
|
+
dialog.trap_key = nil
|
777
853
|
return unless dialog.contents
|
778
854
|
prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines], prompt)
|
779
855
|
visual_lines = []
|
@@ -798,10 +874,10 @@ class Reline::LineEditor
|
|
798
874
|
Reline::IOGate.move_cursor_column(dialog.column)
|
799
875
|
str = Reline::Unicode.take_range(visual_lines_under_dialog[i], dialog.column, dialog.width)
|
800
876
|
str = padding_space_with_escape_sequences(str, dialog.width)
|
801
|
-
@output.write "\e[
|
877
|
+
@output.write "\e[0m#{str}\e[0m"
|
802
878
|
else
|
803
879
|
Reline::IOGate.move_cursor_column(dialog.column)
|
804
|
-
@output.write "\e[
|
880
|
+
@output.write "\e[0m#{' ' * dialog.width}\e[0m"
|
805
881
|
end
|
806
882
|
move_cursor_down(1) if i < (dialog_vertical_size - 1)
|
807
883
|
end
|
@@ -1151,7 +1227,7 @@ class Reline::LineEditor
|
|
1151
1227
|
height = render_partial(prompt, prompt_width, line, back, with_control: false)
|
1152
1228
|
end
|
1153
1229
|
if index < (@buffer_of_lines.size - 1)
|
1154
|
-
move_cursor_down(
|
1230
|
+
move_cursor_down(1)
|
1155
1231
|
back += height
|
1156
1232
|
end
|
1157
1233
|
end
|
@@ -1334,7 +1410,10 @@ class Reline::LineEditor
|
|
1334
1410
|
end
|
1335
1411
|
@waiting_operator_proc = nil
|
1336
1412
|
@waiting_operator_vi_arg = nil
|
1337
|
-
@vi_arg
|
1413
|
+
if @vi_arg
|
1414
|
+
@rerender_all = true
|
1415
|
+
@vi_arg = nil
|
1416
|
+
end
|
1338
1417
|
else
|
1339
1418
|
block.(false)
|
1340
1419
|
end
|
@@ -1385,7 +1464,10 @@ class Reline::LineEditor
|
|
1385
1464
|
wrap_method_call(method_symbol, method_obj, key) if method_obj
|
1386
1465
|
end
|
1387
1466
|
@kill_ring.process
|
1388
|
-
@vi_arg
|
1467
|
+
if @vi_arg
|
1468
|
+
@rerender_al = true
|
1469
|
+
@vi_arg = nil
|
1470
|
+
end
|
1389
1471
|
elsif @vi_arg
|
1390
1472
|
if key.chr =~ /[0-9]/
|
1391
1473
|
ed_argument_digit(key)
|
@@ -1402,7 +1484,10 @@ class Reline::LineEditor
|
|
1402
1484
|
ed_insert(key) unless @config.editing_mode_is?(:vi_command)
|
1403
1485
|
end
|
1404
1486
|
@kill_ring.process
|
1405
|
-
@vi_arg
|
1487
|
+
if @vi_arg
|
1488
|
+
@rerender_all = true
|
1489
|
+
@vi_arg = nil
|
1490
|
+
end
|
1406
1491
|
end
|
1407
1492
|
elsif @waiting_proc
|
1408
1493
|
@waiting_proc.(key)
|
@@ -1460,6 +1545,13 @@ class Reline::LineEditor
|
|
1460
1545
|
end
|
1461
1546
|
|
1462
1547
|
def input_key(key)
|
1548
|
+
@last_key = key
|
1549
|
+
@config.reset_oneshot_key_bindings
|
1550
|
+
@dialogs.each do |dialog|
|
1551
|
+
if key.char.instance_of?(Symbol) and key.char == dialog.name
|
1552
|
+
return
|
1553
|
+
end
|
1554
|
+
end
|
1463
1555
|
@just_cursor_moving = nil
|
1464
1556
|
if key.char.nil?
|
1465
1557
|
if @first_char
|
@@ -1834,6 +1926,8 @@ class Reline::LineEditor
|
|
1834
1926
|
end
|
1835
1927
|
end
|
1836
1928
|
|
1929
|
+
# Editline:: +ed-unassigned+ This editor command always results in an error.
|
1930
|
+
# GNU Readline:: There is no corresponding macro.
|
1837
1931
|
private def ed_unassigned(key) end # do nothing
|
1838
1932
|
|
1839
1933
|
private def process_insert(force: false)
|
@@ -1851,6 +1945,19 @@ class Reline::LineEditor
|
|
1851
1945
|
@continuous_insertion_buffer.clear
|
1852
1946
|
end
|
1853
1947
|
|
1948
|
+
# Editline:: +ed-insert+ (vi input: almost all; emacs: printable characters)
|
1949
|
+
# In insert mode, insert the input character left of the cursor
|
1950
|
+
# position. In replace mode, overwrite the character at the
|
1951
|
+
# cursor and move the cursor to the right by one character
|
1952
|
+
# position. Accept an argument to do this repeatedly. It is an
|
1953
|
+
# error if the input character is the NUL character (+Ctrl-@+).
|
1954
|
+
# Failure to enlarge the edit buffer also results in an error.
|
1955
|
+
# Editline:: +ed-digit+ (emacs: 0 to 9) If in argument input mode, append
|
1956
|
+
# the input digit to the argument being read. Otherwise, call
|
1957
|
+
# +ed-insert+. It is an error if the input character is not a
|
1958
|
+
# digit or if the existing argument is already greater than a
|
1959
|
+
# million.
|
1960
|
+
# GNU Readline:: +self-insert+ (a, b, A, 1, !, …) Insert yourself.
|
1854
1961
|
private def ed_insert(key)
|
1855
1962
|
str = nil
|
1856
1963
|
width = nil
|
@@ -1901,6 +2008,8 @@ class Reline::LineEditor
|
|
1901
2008
|
arg.times do
|
1902
2009
|
if key == "\C-j".ord or key == "\C-m".ord
|
1903
2010
|
key_newline(key)
|
2011
|
+
elsif key == 0
|
2012
|
+
# Ignore NUL.
|
1904
2013
|
else
|
1905
2014
|
ed_insert(key)
|
1906
2015
|
end
|
@@ -2335,6 +2444,7 @@ class Reline::LineEditor
|
|
2335
2444
|
arg -= 1
|
2336
2445
|
ed_prev_history(key, arg: arg) if arg > 0
|
2337
2446
|
end
|
2447
|
+
alias_method :previous_history, :ed_prev_history
|
2338
2448
|
|
2339
2449
|
private def ed_next_history(key, arg: 1)
|
2340
2450
|
if @is_multiline and @line_index < (@buffer_of_lines.size - 1)
|
@@ -2382,6 +2492,7 @@ class Reline::LineEditor
|
|
2382
2492
|
arg -= 1
|
2383
2493
|
ed_next_history(key, arg: arg) if arg > 0
|
2384
2494
|
end
|
2495
|
+
alias_method :next_history, :ed_next_history
|
2385
2496
|
|
2386
2497
|
private def ed_newline(key)
|
2387
2498
|
process_insert(force: true)
|
@@ -2416,7 +2527,7 @@ class Reline::LineEditor
|
|
2416
2527
|
end
|
2417
2528
|
end
|
2418
2529
|
|
2419
|
-
private def em_delete_prev_char(key)
|
2530
|
+
private def em_delete_prev_char(key, arg: 1)
|
2420
2531
|
if @is_multiline and @cursor == 0 and @line_index > 0
|
2421
2532
|
@buffer_of_lines[@line_index] = @line
|
2422
2533
|
@cursor = calculate_width(@buffer_of_lines[@line_index - 1])
|
@@ -2434,9 +2545,16 @@ class Reline::LineEditor
|
|
2434
2545
|
@cursor -= width
|
2435
2546
|
@cursor_max -= width
|
2436
2547
|
end
|
2548
|
+
arg -= 1
|
2549
|
+
em_delete_prev_char(key, arg: arg) if arg > 0
|
2437
2550
|
end
|
2438
2551
|
alias_method :backward_delete_char, :em_delete_prev_char
|
2439
2552
|
|
2553
|
+
# Editline:: +ed-kill-line+ (vi command: +D+, +Ctrl-K+; emacs: +Ctrl-K+,
|
2554
|
+
# +Ctrl-U+) + Kill from the cursor to the end of the line.
|
2555
|
+
# GNU Readline:: +kill-line+ (+C-k+) Kill the text from point to the end of
|
2556
|
+
# the line. With a negative numeric argument, kill backward
|
2557
|
+
# from the cursor to the beginning of the current line.
|
2440
2558
|
private def ed_kill_line(key)
|
2441
2559
|
if @line.bytesize > @byte_pointer
|
2442
2560
|
@line, deleted = byteslice!(@line, @byte_pointer, @line.bytesize - @byte_pointer)
|
@@ -2453,8 +2571,14 @@ class Reline::LineEditor
|
|
2453
2571
|
@rest_height += 1
|
2454
2572
|
end
|
2455
2573
|
end
|
2574
|
+
alias_method :kill_line, :ed_kill_line
|
2456
2575
|
|
2457
|
-
|
2576
|
+
# Editline:: +vi-kill-line-prev+ (vi: +Ctrl-U+) Delete the string from the
|
2577
|
+
# beginning of the edit buffer to the cursor and save it to the
|
2578
|
+
# cut buffer.
|
2579
|
+
# GNU Readline:: +unix-line-discard+ (+C-u+) Kill backward from the cursor
|
2580
|
+
# to the beginning of the current line.
|
2581
|
+
private def vi_kill_line_prev(key)
|
2458
2582
|
if @byte_pointer > 0
|
2459
2583
|
@line, deleted = byteslice!(@line, 0, @byte_pointer)
|
2460
2584
|
@byte_pointer = 0
|
@@ -2463,7 +2587,22 @@ class Reline::LineEditor
|
|
2463
2587
|
@cursor = 0
|
2464
2588
|
end
|
2465
2589
|
end
|
2466
|
-
alias_method :
|
2590
|
+
alias_method :unix_line_discard, :vi_kill_line_prev
|
2591
|
+
|
2592
|
+
# Editline:: +em-kill-line+ (not bound) Delete the entire contents of the
|
2593
|
+
# edit buffer and save it to the cut buffer. +vi-kill-line-prev+
|
2594
|
+
# GNU Readline:: +kill-whole-line+ (not bound) Kill all characters on the
|
2595
|
+
# current line, no matter where point is.
|
2596
|
+
private def em_kill_line(key)
|
2597
|
+
if @line.size > 0
|
2598
|
+
@kill_ring.append(@line.dup, true)
|
2599
|
+
@line.clear
|
2600
|
+
@byte_pointer = 0
|
2601
|
+
@cursor_max = 0
|
2602
|
+
@cursor = 0
|
2603
|
+
end
|
2604
|
+
end
|
2605
|
+
alias_method :kill_whole_line, :em_kill_line
|
2467
2606
|
|
2468
2607
|
private def em_delete(key)
|
2469
2608
|
if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
|
@@ -2968,7 +3107,14 @@ class Reline::LineEditor
|
|
2968
3107
|
|
2969
3108
|
private def ed_argument_digit(key)
|
2970
3109
|
if @vi_arg.nil?
|
2971
|
-
|
3110
|
+
if key.chr.to_i.zero?
|
3111
|
+
if key.anybits?(0b10000000)
|
3112
|
+
unescaped_key = key ^ 0b10000000
|
3113
|
+
unless unescaped_key.chr.to_i.zero?
|
3114
|
+
@vi_arg = unescaped_key.chr.to_i
|
3115
|
+
end
|
3116
|
+
end
|
3117
|
+
else
|
2972
3118
|
@vi_arg = key.chr.to_i
|
2973
3119
|
end
|
2974
3120
|
else
|
data/lib/reline/terminfo.rb
CHANGED
@@ -71,7 +71,7 @@ module Reline::Terminfo
|
|
71
71
|
def self.setupterm(term, fildes)
|
72
72
|
errret_int = String.new("\x00" * 8, encoding: 'ASCII-8BIT')
|
73
73
|
ret = @setupterm.(term, fildes, errret_int)
|
74
|
-
errret = errret_int.
|
74
|
+
errret = errret_int.unpack1('i')
|
75
75
|
case ret
|
76
76
|
when 0 # OK
|
77
77
|
0
|
data/lib/reline/unicode.rb
CHANGED
@@ -101,9 +101,9 @@ class Reline::Unicode
|
|
101
101
|
|
102
102
|
def self.get_mbchar_width(mbchar)
|
103
103
|
ord = mbchar.ord
|
104
|
-
if (0x00 <= ord and ord <= 0x1F)
|
104
|
+
if (0x00 <= ord and ord <= 0x1F) # in EscapedPairs
|
105
105
|
return 2
|
106
|
-
elsif (0x20 <= ord and ord <= 0x7E)
|
106
|
+
elsif (0x20 <= ord and ord <= 0x7E) # printable ASCII chars
|
107
107
|
return 1
|
108
108
|
end
|
109
109
|
m = mbchar.encode(Encoding::UTF_8).match(MBCharWidthRE)
|
@@ -185,7 +185,7 @@ class Reline::Unicode
|
|
185
185
|
[lines, height]
|
186
186
|
end
|
187
187
|
|
188
|
-
# Take a chunk of a String with escape sequences.
|
188
|
+
# Take a chunk of a String cut by width with escape sequences.
|
189
189
|
def self.take_range(str, start_col, max_width, encoding = str.encoding)
|
190
190
|
chunk = String.new(encoding: encoding)
|
191
191
|
total_width = 0
|
data/lib/reline/version.rb
CHANGED
data/lib/reline/windows.rb
CHANGED
@@ -184,7 +184,7 @@ class Reline::Windows
|
|
184
184
|
# DWORD FileNameLength;
|
185
185
|
# WCHAR FileName[1];
|
186
186
|
# } FILE_NAME_INFO
|
187
|
-
len = p_buffer[0, 4].
|
187
|
+
len = p_buffer[0, 4].unpack1("L")
|
188
188
|
name = p_buffer[4, len].encode(Encoding::UTF_8, Encoding::UTF_16LE, invalid: :replace)
|
189
189
|
|
190
190
|
# Check if this could be a MSYS2 pty pipe ('\msys-XXXX-ptyN-XX')
|
@@ -226,28 +226,31 @@ class Reline::Windows
|
|
226
226
|
# no char, only control keys
|
227
227
|
return if key.char_code == 0 and key.control_keys.any?
|
228
228
|
|
229
|
+
@@output_buf.push("\e".ord) if key.control_keys.include?(:ALT)
|
230
|
+
|
229
231
|
@@output_buf.concat(key.char.bytes)
|
230
232
|
end
|
231
233
|
|
232
234
|
def self.check_input_event
|
233
235
|
num_of_events = 0.chr * 8
|
234
236
|
while @@output_buf.empty? #or true
|
237
|
+
Reline.core.line_editor.resize
|
235
238
|
next if @@WaitForSingleObject.(@@hConsoleInputHandle, 100) != 0 # max 0.1 sec
|
236
|
-
next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.
|
239
|
+
next if @@GetNumberOfConsoleInputEvents.(@@hConsoleInputHandle, num_of_events) == 0 or num_of_events.unpack1('L') == 0
|
237
240
|
input_record = 0.chr * 18
|
238
241
|
read_event = 0.chr * 4
|
239
242
|
if @@ReadConsoleInputW.(@@hConsoleInputHandle, input_record, 1, read_event) != 0
|
240
|
-
event = input_record[0, 2].
|
243
|
+
event = input_record[0, 2].unpack1('s*')
|
241
244
|
case event
|
242
245
|
when WINDOW_BUFFER_SIZE_EVENT
|
243
246
|
@@winch_handler.()
|
244
247
|
when KEY_EVENT
|
245
|
-
key_down = input_record[4, 4].
|
246
|
-
repeat_count = input_record[8, 2].
|
247
|
-
virtual_key_code = input_record[10, 2].
|
248
|
-
virtual_scan_code = input_record[12, 2].
|
249
|
-
char_code = input_record[14, 2].
|
250
|
-
control_key_state = input_record[16, 2].
|
248
|
+
key_down = input_record[4, 4].unpack1('l*')
|
249
|
+
repeat_count = input_record[8, 2].unpack1('s*')
|
250
|
+
virtual_key_code = input_record[10, 2].unpack1('s*')
|
251
|
+
virtual_scan_code = input_record[12, 2].unpack1('s*')
|
252
|
+
char_code = input_record[14, 2].unpack1('S*')
|
253
|
+
control_key_state = input_record[16, 2].unpack1('S*')
|
251
254
|
is_key_down = key_down.zero? ? false : true
|
252
255
|
if is_key_down
|
253
256
|
process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
|
@@ -289,8 +292,8 @@ class Reline::Windows
|
|
289
292
|
def self.cursor_pos
|
290
293
|
csbi = 0.chr * 22
|
291
294
|
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
|
292
|
-
x = csbi[4, 2].
|
293
|
-
y = csbi[6, 2].
|
295
|
+
x = csbi[4, 2].unpack1('s*')
|
296
|
+
y = csbi[6, 2].unpack1('s*')
|
294
297
|
Reline::CursorPos.new(x, y)
|
295
298
|
end
|
296
299
|
|
@@ -322,7 +325,7 @@ class Reline::Windows
|
|
322
325
|
def self.erase_after_cursor
|
323
326
|
csbi = 0.chr * 24
|
324
327
|
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
|
325
|
-
cursor = csbi[4, 4].
|
328
|
+
cursor = csbi[4, 4].unpack1('L')
|
326
329
|
written = 0.chr * 4
|
327
330
|
@@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
|
328
331
|
@@FillConsoleOutputAttribute.call(@@hConsoleHandle, 0, get_screen_size.last - cursor_pos.x, cursor, written)
|
@@ -341,8 +344,8 @@ class Reline::Windows
|
|
341
344
|
def self.clear_screen
|
342
345
|
csbi = 0.chr * 22
|
343
346
|
return if @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) == 0
|
344
|
-
buffer_width = csbi[0, 2].
|
345
|
-
attributes = csbi[8, 2].
|
347
|
+
buffer_width = csbi[0, 2].unpack1('S')
|
348
|
+
attributes = csbi[8, 2].unpack1('S')
|
346
349
|
_window_left, window_top, _window_right, window_bottom = *csbi[10,8].unpack('S*')
|
347
350
|
fill_length = buffer_width * (window_bottom - window_top + 1)
|
348
351
|
screen_topleft = window_top * 65536
|
data/lib/reline.rb
CHANGED
@@ -16,9 +16,24 @@ module Reline
|
|
16
16
|
|
17
17
|
class ConfigEncodingConversionError < StandardError; end
|
18
18
|
|
19
|
-
Key = Struct.new('Key', :char, :combined_char, :with_meta)
|
19
|
+
Key = Struct.new('Key', :char, :combined_char, :with_meta) do
|
20
|
+
def match?(other)
|
21
|
+
case other
|
22
|
+
when Reline::Key
|
23
|
+
(other.char.nil? or char.nil? or char == other.char) and
|
24
|
+
(other.combined_char.nil? or combined_char.nil? or combined_char == other.combined_char) and
|
25
|
+
(other.with_meta.nil? or with_meta.nil? or with_meta == other.with_meta)
|
26
|
+
when Integer, Symbol
|
27
|
+
(combined_char and combined_char == other) or
|
28
|
+
(combined_char.nil? and char and char == other)
|
29
|
+
else
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
alias_method :==, :match?
|
34
|
+
end
|
20
35
|
CursorPos = Struct.new(:x, :y)
|
21
|
-
DialogRenderInfo = Struct.new(:pos, :contents, :
|
36
|
+
DialogRenderInfo = Struct.new(:pos, :contents, :bg_color, :width, :height, :scrollbar, keyword_init: true)
|
22
37
|
|
23
38
|
class Core
|
24
39
|
ATTR_READER_NAMES = %i(
|
@@ -195,7 +210,7 @@ module Reline
|
|
195
210
|
return nil
|
196
211
|
end
|
197
212
|
pre, target, post = retrieve_completion_block(true)
|
198
|
-
if target.nil? or target.empty
|
213
|
+
if target.nil? or target.empty? or (completion_journey_data&.pointer == -1 and target.size <= 3)
|
199
214
|
return nil
|
200
215
|
end
|
201
216
|
if completion_journey_data and completion_journey_data.list
|
@@ -206,7 +221,7 @@ module Reline
|
|
206
221
|
result = call_completion_proc_with_checking_args(pre, target, post)
|
207
222
|
pointer = nil
|
208
223
|
end
|
209
|
-
if result and result.size == 1 and result[0] == target
|
224
|
+
if result and result.size == 1 and result[0] == target and pointer != 0
|
210
225
|
result = nil
|
211
226
|
end
|
212
227
|
target_width = Reline::Unicode.calculate_width(target)
|
@@ -222,7 +237,8 @@ module Reline
|
|
222
237
|
context.clear
|
223
238
|
context.push(cursor_pos_to_render, result, pointer, dialog)
|
224
239
|
end
|
225
|
-
|
240
|
+
dialog.pointer = pointer
|
241
|
+
DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, scrollbar: true, height: 15)
|
226
242
|
}
|
227
243
|
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
228
244
|
|
@@ -362,25 +378,9 @@ module Reline
|
|
362
378
|
break
|
363
379
|
when :matching
|
364
380
|
if buffer.size == 1
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
succ_c = Reline::IOGate.getc
|
369
|
-
}
|
370
|
-
rescue Timeout::Error # cancel matching only when first byte
|
371
|
-
block.([Reline::Key.new(c, c, false)])
|
372
|
-
break
|
373
|
-
else
|
374
|
-
if key_stroke.match_status(buffer.dup.push(succ_c)) == :unmatched
|
375
|
-
if c == "\e".ord
|
376
|
-
block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
|
377
|
-
else
|
378
|
-
block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
|
379
|
-
end
|
380
|
-
break
|
381
|
-
else
|
382
|
-
Reline::IOGate.ungetc(succ_c)
|
383
|
-
end
|
381
|
+
case read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
|
382
|
+
when :break then break
|
383
|
+
when :next then next
|
384
384
|
end
|
385
385
|
end
|
386
386
|
when :unmatched
|
@@ -397,6 +397,38 @@ module Reline
|
|
397
397
|
end
|
398
398
|
end
|
399
399
|
|
400
|
+
private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
|
401
|
+
begin
|
402
|
+
succ_c = nil
|
403
|
+
Timeout.timeout(keyseq_timeout / 1000.0) {
|
404
|
+
succ_c = Reline::IOGate.getc
|
405
|
+
}
|
406
|
+
rescue Timeout::Error # cancel matching only when first byte
|
407
|
+
block.([Reline::Key.new(c, c, false)])
|
408
|
+
return :break
|
409
|
+
else
|
410
|
+
case key_stroke.match_status(buffer.dup.push(succ_c))
|
411
|
+
when :unmatched
|
412
|
+
if c == "\e".ord
|
413
|
+
block.([Reline::Key.new(succ_c, succ_c | 0b10000000, true)])
|
414
|
+
else
|
415
|
+
block.([Reline::Key.new(c, c, false), Reline::Key.new(succ_c, succ_c, false)])
|
416
|
+
end
|
417
|
+
return :break
|
418
|
+
when :matching
|
419
|
+
Reline::IOGate.ungetc(succ_c)
|
420
|
+
return :next
|
421
|
+
when :matched
|
422
|
+
buffer << succ_c
|
423
|
+
expanded = key_stroke.expand(buffer).map{ |expanded_c|
|
424
|
+
Reline::Key.new(expanded_c, expanded_c, false)
|
425
|
+
}
|
426
|
+
block.(expanded)
|
427
|
+
return :break
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
400
432
|
private def read_escaped_key(keyseq_timeout, c, block)
|
401
433
|
begin
|
402
434
|
escaped_c = nil
|
@@ -448,7 +480,7 @@ module Reline
|
|
448
480
|
#--------------------------------------------------------
|
449
481
|
|
450
482
|
(Core::ATTR_READER_NAMES).each { |name|
|
451
|
-
def_single_delegators :core, "#{name}", "#{name}="
|
483
|
+
def_single_delegators :core, :"#{name}", :"#{name}="
|
452
484
|
}
|
453
485
|
def_single_delegators :core, :input=, :output=
|
454
486
|
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.8.pre.
|
4
|
+
version: 0.2.8.pre.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: io-console
|