reline 0.0.4 → 0.1.1
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.rb +46 -23
- data/lib/reline/ansi.rb +16 -15
- data/lib/reline/config.rb +2 -2
- data/lib/reline/history.rb +1 -1
- data/lib/reline/key_actor/emacs.rb +2 -2
- data/lib/reline/key_actor/vi_command.rb +1 -1
- data/lib/reline/key_actor/vi_insert.rb +1 -1
- data/lib/reline/key_stroke.rb +1 -1
- data/lib/reline/line_editor.rb +279 -93
- data/lib/reline/version.rb +1 -1
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb3a343a202a2c043257a432f50eb05eeb58b5638a88c24eb095c96a40b03fea
|
4
|
+
data.tar.gz: e9c8aec5f70fe3897fb8f835d0d5b228a93a5444b0a7ce804290c19ae44c6c55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0e2a92e1e007d23542313783108250c66ad81b90389c306a9f413b8426ce14a39e14731f974aa8fcabcddaeceae529a70388e6e1a3db6ec7a511278b0c568d7
|
7
|
+
data.tar.gz: 0f86f497938921154a475f4b63059a4cda560b44b5b6f9fb63b3b4afcae9de3ea351c1226640eb074546a765b2f51ff5a62bd1af20142a6211c8e74a06f16a57
|
data/lib/reline.rb
CHANGED
@@ -16,12 +16,6 @@ module Reline
|
|
16
16
|
CursorPos = Struct.new(:x, :y)
|
17
17
|
|
18
18
|
class Core
|
19
|
-
if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
20
|
-
IS_WINDOWS = true
|
21
|
-
else
|
22
|
-
IS_WINDOWS = false
|
23
|
-
end
|
24
|
-
|
25
19
|
ATTR_READER_NAMES = %i(
|
26
20
|
completion_append_character
|
27
21
|
basic_word_break_characters
|
@@ -38,19 +32,17 @@ module Reline
|
|
38
32
|
dig_perfect_match_proc
|
39
33
|
).each(&method(:attr_reader))
|
40
34
|
|
41
|
-
ATTR_ACCESSOR_NAMES = %i(
|
42
|
-
completion_case_fold
|
43
|
-
).each(&method(:attr_accessor))
|
44
|
-
|
45
35
|
attr_accessor :config
|
46
36
|
attr_accessor :key_stroke
|
47
37
|
attr_accessor :line_editor
|
48
38
|
attr_accessor :ambiguous_width
|
39
|
+
attr_accessor :last_incremental_search
|
49
40
|
attr_reader :output
|
50
41
|
|
51
42
|
def initialize
|
52
43
|
self.output = STDOUT
|
53
44
|
yield self
|
45
|
+
@completion_quote_character = nil
|
54
46
|
end
|
55
47
|
|
56
48
|
def completion_append_character=(val)
|
@@ -89,23 +81,35 @@ module Reline
|
|
89
81
|
@special_prefixes = v.encode(Encoding::default_external)
|
90
82
|
end
|
91
83
|
|
84
|
+
def completion_case_fold=(v)
|
85
|
+
@config.completion_ignore_case = v
|
86
|
+
end
|
87
|
+
|
88
|
+
def completion_case_fold
|
89
|
+
@config.completion_ignore_case
|
90
|
+
end
|
91
|
+
|
92
|
+
def completion_quote_character
|
93
|
+
@completion_quote_character
|
94
|
+
end
|
95
|
+
|
92
96
|
def completion_proc=(p)
|
93
|
-
raise ArgumentError unless p.
|
97
|
+
raise ArgumentError unless p.respond_to?(:call)
|
94
98
|
@completion_proc = p
|
95
99
|
end
|
96
100
|
|
97
101
|
def output_modifier_proc=(p)
|
98
|
-
raise ArgumentError unless p.
|
102
|
+
raise ArgumentError unless p.respond_to?(:call)
|
99
103
|
@output_modifier_proc = p
|
100
104
|
end
|
101
105
|
|
102
106
|
def prompt_proc=(p)
|
103
|
-
raise ArgumentError unless p.
|
107
|
+
raise ArgumentError unless p.respond_to?(:call)
|
104
108
|
@prompt_proc = p
|
105
109
|
end
|
106
110
|
|
107
111
|
def auto_indent_proc=(p)
|
108
|
-
raise ArgumentError unless p.
|
112
|
+
raise ArgumentError unless p.respond_to?(:call)
|
109
113
|
@auto_indent_proc = p
|
110
114
|
end
|
111
115
|
|
@@ -114,7 +118,7 @@ module Reline
|
|
114
118
|
end
|
115
119
|
|
116
120
|
def dig_perfect_match_proc=(p)
|
117
|
-
raise ArgumentError unless p.
|
121
|
+
raise ArgumentError unless p.respond_to?(:call)
|
118
122
|
@dig_perfect_match_proc = p
|
119
123
|
end
|
120
124
|
|
@@ -166,7 +170,7 @@ module Reline
|
|
166
170
|
inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
|
167
171
|
|
168
172
|
whole_buffer = line_editor.whole_buffer.dup
|
169
|
-
whole_buffer.taint
|
173
|
+
whole_buffer.taint if RUBY_VERSION < '2.7'
|
170
174
|
if add_hist and whole_buffer and whole_buffer.chomp.size > 0
|
171
175
|
Reline::HISTORY << whole_buffer
|
172
176
|
end
|
@@ -179,7 +183,7 @@ module Reline
|
|
179
183
|
inner_readline(prompt, add_hist, false)
|
180
184
|
|
181
185
|
line = line_editor.line.dup
|
182
|
-
line.taint
|
186
|
+
line.taint if RUBY_VERSION < '2.7'
|
183
187
|
if add_hist and line and line.chomp.size > 0
|
184
188
|
Reline::HISTORY << line.chomp
|
185
189
|
end
|
@@ -208,6 +212,7 @@ module Reline
|
|
208
212
|
end
|
209
213
|
line_editor.output = output
|
210
214
|
line_editor.completion_proc = completion_proc
|
215
|
+
line_editor.completion_append_character = completion_append_character
|
211
216
|
line_editor.output_modifier_proc = output_modifier_proc
|
212
217
|
line_editor.prompt_proc = prompt_proc
|
213
218
|
line_editor.auto_indent_proc = auto_indent_proc
|
@@ -260,7 +265,10 @@ module Reline
|
|
260
265
|
result = key_stroke.match_status(buffer)
|
261
266
|
case result
|
262
267
|
when :matched
|
263
|
-
|
268
|
+
expanded = key_stroke.expand(buffer).map{ |expanded_c|
|
269
|
+
Reline::Key.new(expanded_c, expanded_c, false)
|
270
|
+
}
|
271
|
+
block.(expanded)
|
264
272
|
break
|
265
273
|
when :matching
|
266
274
|
if buffer.size == 1
|
@@ -289,7 +297,10 @@ module Reline
|
|
289
297
|
if buffer.size == 1 and c == "\e".ord
|
290
298
|
read_escaped_key(keyseq_timeout, c, block)
|
291
299
|
else
|
292
|
-
|
300
|
+
expanded = buffer.map{ |expanded_c|
|
301
|
+
Reline::Key.new(expanded_c, expanded_c, false)
|
302
|
+
}
|
303
|
+
block.(expanded)
|
293
304
|
end
|
294
305
|
break
|
295
306
|
end
|
@@ -319,7 +330,7 @@ module Reline
|
|
319
330
|
|
320
331
|
private def may_req_ambiguous_char_width
|
321
332
|
@ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or STDOUT.is_a?(File)
|
322
|
-
return if
|
333
|
+
return if ambiguous_width
|
323
334
|
Reline::IOGate.move_cursor_column(0)
|
324
335
|
print "\u{25bd}"
|
325
336
|
@ambiguous_width = Reline::IOGate.cursor_pos.x
|
@@ -335,13 +346,16 @@ module Reline
|
|
335
346
|
# Documented API
|
336
347
|
#--------------------------------------------------------
|
337
348
|
|
338
|
-
(Core::ATTR_READER_NAMES
|
349
|
+
(Core::ATTR_READER_NAMES).each { |name|
|
339
350
|
def_single_delegators :core, "#{name}", "#{name}="
|
340
351
|
}
|
341
352
|
def_single_delegators :core, :input=, :output=
|
342
353
|
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
|
343
354
|
def_single_delegators :core, :readline
|
355
|
+
def_single_delegators :core, :completion_case_fold, :completion_case_fold=
|
356
|
+
def_single_delegators :core, :completion_quote_character
|
344
357
|
def_instance_delegators self, :readline
|
358
|
+
private :readline
|
345
359
|
|
346
360
|
|
347
361
|
#--------------------------------------------------------
|
@@ -366,9 +380,12 @@ module Reline
|
|
366
380
|
def_single_delegator :line_editor, :rerender, :redisplay
|
367
381
|
def_single_delegators :core, :vi_editing_mode?, :emacs_editing_mode?
|
368
382
|
def_single_delegators :core, :ambiguous_width
|
383
|
+
def_single_delegators :core, :last_incremental_search
|
384
|
+
def_single_delegators :core, :last_incremental_search=
|
369
385
|
|
370
386
|
def_single_delegators :core, :readmultiline
|
371
387
|
def_instance_delegators self, :readmultiline
|
388
|
+
private :readmultiline
|
372
389
|
|
373
390
|
def self.core
|
374
391
|
@core ||= Core.new { |core|
|
@@ -392,9 +409,15 @@ module Reline
|
|
392
409
|
HISTORY = History.new(core.config)
|
393
410
|
end
|
394
411
|
|
395
|
-
if
|
412
|
+
if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
396
413
|
require 'reline/windows'
|
397
|
-
Reline::
|
414
|
+
if Reline::Windows.get_screen_size == [0, 0]
|
415
|
+
# Maybe Mintty on Cygwin
|
416
|
+
require 'reline/ansi'
|
417
|
+
Reline::IOGate = Reline::ANSI
|
418
|
+
else
|
419
|
+
Reline::IOGate = Reline::Windows
|
420
|
+
end
|
398
421
|
else
|
399
422
|
require 'reline/ansi'
|
400
423
|
Reline::IOGate = Reline::ANSI
|
data/lib/reline/ansi.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'io/console'
|
2
|
+
|
1
3
|
class Reline::ANSI
|
2
4
|
RAW_KEYSTROKE_CONFIG = {
|
3
5
|
[27, 91, 65] => :ed_prev_history, # ↑
|
@@ -7,6 +9,12 @@ class Reline::ANSI
|
|
7
9
|
[27, 91, 51, 126] => :key_delete, # Del
|
8
10
|
[27, 91, 49, 126] => :ed_move_to_beg, # Home
|
9
11
|
[27, 91, 52, 126] => :ed_move_to_end, # End
|
12
|
+
[27, 91, 72] => :ed_move_to_beg, # Home
|
13
|
+
[27, 91, 70] => :ed_move_to_end, # End
|
14
|
+
[27, 32] => :em_set_mark, # M-<space>
|
15
|
+
[24, 24] => :em_exchange_mark, # C-x C-x TODO also add Windows
|
16
|
+
[27, 91, 49, 59, 53, 67] => :em_next_word, # Ctrl+→
|
17
|
+
[27, 91, 49, 59, 53, 68] => :ed_prev_word, # Ctrl+←
|
10
18
|
}
|
11
19
|
|
12
20
|
@@input = STDIN
|
@@ -24,7 +32,8 @@ class Reline::ANSI
|
|
24
32
|
unless @@buf.empty?
|
25
33
|
return @@buf.shift
|
26
34
|
end
|
27
|
-
@@input.getbyte
|
35
|
+
c = @@input.raw(intr: true, &:getbyte)
|
36
|
+
(c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
|
28
37
|
end
|
29
38
|
|
30
39
|
def self.ungetc(c)
|
@@ -56,14 +65,18 @@ class Reline::ANSI
|
|
56
65
|
def self.cursor_pos
|
57
66
|
begin
|
58
67
|
res = ''
|
68
|
+
m = nil
|
59
69
|
@@input.raw do |stdin|
|
60
70
|
@@output << "\e[6n"
|
61
71
|
@@output.flush
|
62
72
|
while (c = stdin.getc) != 'R'
|
63
73
|
res << c if c
|
64
74
|
end
|
75
|
+
m = res.match(/\e\[(?<row>\d+);(?<column>\d+)/)
|
76
|
+
(m.pre_match + m.post_match).chars.reverse_each do |ch|
|
77
|
+
stdin.ungetc ch
|
78
|
+
end
|
65
79
|
end
|
66
|
-
m = res.match(/(?<row>\d+);(?<column>\d+)/)
|
67
80
|
column = m[:column].to_i - 1
|
68
81
|
row = m[:row].to_i - 1
|
69
82
|
rescue Errno::ENOTTY
|
@@ -116,24 +129,12 @@ class Reline::ANSI
|
|
116
129
|
def self.prep
|
117
130
|
retrieve_keybuffer
|
118
131
|
int_handle = Signal.trap('INT', 'IGNORE')
|
119
|
-
otio = `stty -g`.chomp
|
120
|
-
setting = ' -echo -icrnl cbreak'
|
121
|
-
stty = `stty -a`
|
122
|
-
if /-parenb\b/ =~ stty
|
123
|
-
setting << ' pass8'
|
124
|
-
end
|
125
|
-
if /\bdsusp *=/ =~ stty
|
126
|
-
setting << ' dsusp undef'
|
127
|
-
end
|
128
|
-
setting << ' -ixoff'
|
129
|
-
`stty #{setting}`
|
130
132
|
Signal.trap('INT', int_handle)
|
131
|
-
|
133
|
+
nil
|
132
134
|
end
|
133
135
|
|
134
136
|
def self.deprep(otio)
|
135
137
|
int_handle = Signal.trap('INT', 'IGNORE')
|
136
|
-
`stty #{otio}`
|
137
138
|
Signal.trap('INT', int_handle)
|
138
139
|
Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
|
139
140
|
end
|
data/lib/reline/config.rb
CHANGED
@@ -157,7 +157,7 @@ class Reline::Config
|
|
157
157
|
case directive
|
158
158
|
when 'if'
|
159
159
|
condition = false
|
160
|
-
case args
|
160
|
+
case args
|
161
161
|
when 'mode'
|
162
162
|
when 'term'
|
163
163
|
when 'version'
|
@@ -184,7 +184,7 @@ class Reline::Config
|
|
184
184
|
|
185
185
|
def bind_variable(name, value)
|
186
186
|
case name
|
187
|
-
when VARIABLE_NAMES then
|
187
|
+
when *VARIABLE_NAMES then
|
188
188
|
variable_name = :"@#{name.tr(?-, ?_)}"
|
189
189
|
instance_variable_set(variable_name, value.nil? || value == '1' || value == 'on')
|
190
190
|
when 'bell-style'
|
data/lib/reline/history.rb
CHANGED
@@ -9,7 +9,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
|
|
9
9
|
# 3 ^C
|
10
10
|
:ed_ignore,
|
11
11
|
# 4 ^D
|
12
|
-
:
|
12
|
+
:em_delete,
|
13
13
|
# 5 ^E
|
14
14
|
:ed_move_to_end,
|
15
15
|
# 6 ^F
|
@@ -39,7 +39,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
|
|
39
39
|
# 18 ^R
|
40
40
|
:ed_search_prev_history,
|
41
41
|
# 19 ^S
|
42
|
-
:
|
42
|
+
:ed_search_next_history,
|
43
43
|
# 20 ^T
|
44
44
|
:ed_transpose_chars,
|
45
45
|
# 21 ^U
|
data/lib/reline/key_stroke.rb
CHANGED
@@ -32,7 +32,7 @@ class Reline::KeyStroke
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def expand(input)
|
35
|
-
lhs = key_mapping.keys.select { |
|
35
|
+
lhs = key_mapping.keys.select { |item| input.start_with? item }.sort_by(&:size).reverse.first
|
36
36
|
return input unless lhs
|
37
37
|
rhs = key_mapping[lhs]
|
38
38
|
|
data/lib/reline/line_editor.rb
CHANGED
@@ -10,6 +10,7 @@ class Reline::LineEditor
|
|
10
10
|
attr_reader :byte_pointer
|
11
11
|
attr_accessor :confirm_multiline_termination_proc
|
12
12
|
attr_accessor :completion_proc
|
13
|
+
attr_accessor :completion_append_character
|
13
14
|
attr_accessor :output_modifier_proc
|
14
15
|
attr_accessor :prompt_proc
|
15
16
|
attr_accessor :auto_indent_proc
|
@@ -43,6 +44,7 @@ class Reline::LineEditor
|
|
43
44
|
COMPLETION = :completion
|
44
45
|
MENU = :menu
|
45
46
|
JOURNEY = :journey
|
47
|
+
MENU_WITH_PERFECT_MATCH = :menu_with_perfect_match
|
46
48
|
PERFECT_MATCH = :perfect_match
|
47
49
|
end
|
48
50
|
|
@@ -57,6 +59,7 @@ class Reline::LineEditor
|
|
57
59
|
|
58
60
|
def initialize(config)
|
59
61
|
@config = config
|
62
|
+
@completion_append_character = ''
|
60
63
|
reset_variables
|
61
64
|
end
|
62
65
|
|
@@ -113,9 +116,7 @@ class Reline::LineEditor
|
|
113
116
|
if @line_index.zero?
|
114
117
|
0
|
115
118
|
else
|
116
|
-
@buffer_of_lines[0..(@line_index - 1)]
|
117
|
-
result + calculate_height_by_width(prompt_width + calculate_width(line)) # TODO prompt_list
|
118
|
-
}
|
119
|
+
calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list)
|
119
120
|
end
|
120
121
|
if @prompt_proc
|
121
122
|
prompt = prompt_list[@line_index]
|
@@ -140,6 +141,7 @@ class Reline::LineEditor
|
|
140
141
|
|
141
142
|
def reset_variables(prompt = '', encoding = Encoding.default_external)
|
142
143
|
@prompt = prompt
|
144
|
+
@mark_pointer = nil
|
143
145
|
@encoding = encoding
|
144
146
|
@is_multiline = false
|
145
147
|
@finished = false
|
@@ -188,6 +190,16 @@ class Reline::LineEditor
|
|
188
190
|
@is_multiline = false
|
189
191
|
end
|
190
192
|
|
193
|
+
private def calculate_height_by_lines(lines, prompt_list)
|
194
|
+
result = 0
|
195
|
+
lines.each_with_index { |line, i|
|
196
|
+
prompt = ''
|
197
|
+
prompt = prompt_list[i] if prompt_list and prompt_list[i]
|
198
|
+
result += calculate_height_by_width(calculate_width(prompt, true) + calculate_width(line))
|
199
|
+
}
|
200
|
+
result
|
201
|
+
end
|
202
|
+
|
191
203
|
private def insert_new_line(cursor_line, next_line)
|
192
204
|
@line = cursor_line
|
193
205
|
@buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: @encoding))
|
@@ -346,9 +358,7 @@ class Reline::LineEditor
|
|
346
358
|
new_lines = whole_lines
|
347
359
|
end
|
348
360
|
prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines, prompt)
|
349
|
-
all_height = new_lines
|
350
|
-
result + calculate_height_by_width(prompt_width + calculate_width(line)) # TODO prompt_list
|
351
|
-
}
|
361
|
+
all_height = calculate_height_by_lines(new_lines, prompt_list)
|
352
362
|
diff = all_height - @highest_in_all
|
353
363
|
move_cursor_down(@highest_in_all - @first_line_started_from - @started_from - 1)
|
354
364
|
if diff > 0
|
@@ -388,9 +398,7 @@ class Reline::LineEditor
|
|
388
398
|
if @line_index.zero?
|
389
399
|
0
|
390
400
|
else
|
391
|
-
@buffer_of_lines[0..(@line_index - 1)]
|
392
|
-
result + calculate_height_by_width(prompt_width + calculate_width(line)) # TODO prompt_list
|
393
|
-
}
|
401
|
+
calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list)
|
394
402
|
end
|
395
403
|
if @prompt_proc
|
396
404
|
prompt = prompt_list[@line_index]
|
@@ -449,9 +457,7 @@ class Reline::LineEditor
|
|
449
457
|
if @line_index.zero?
|
450
458
|
0
|
451
459
|
else
|
452
|
-
new_buffer[0..(@line_index - 1)]
|
453
|
-
result + calculate_height_by_width(prompt_width + calculate_width(line)) # TODO prompt_list
|
454
|
-
}
|
460
|
+
calculate_height_by_lines(new_buffer[0..(@line_index - 1)], prompt_list)
|
455
461
|
end
|
456
462
|
@started_from = calculate_height_by_width(prompt_width + @cursor) - 1
|
457
463
|
move_cursor_down(@first_line_started_from + @started_from)
|
@@ -546,10 +552,14 @@ class Reline::LineEditor
|
|
546
552
|
private def complete_internal_proc(list, is_menu)
|
547
553
|
preposing, target, postposing = retrieve_completion_block
|
548
554
|
list = list.select { |i|
|
549
|
-
if i and
|
550
|
-
raise Encoding::CompatibilityError
|
555
|
+
if i and not Encoding.compatible?(target.encoding, i.encoding)
|
556
|
+
raise Encoding::CompatibilityError, "#{target.encoding.name} is not compatible with #{i.encoding.name}"
|
557
|
+
end
|
558
|
+
if @config.completion_ignore_case
|
559
|
+
i&.downcase&.start_with?(target.downcase)
|
560
|
+
else
|
561
|
+
i&.start_with?(target)
|
551
562
|
end
|
552
|
-
i&.start_with?(target)
|
553
563
|
}
|
554
564
|
if is_menu
|
555
565
|
menu(target, list)
|
@@ -566,10 +576,18 @@ class Reline::LineEditor
|
|
566
576
|
size = [memo_mbchars.size, item_mbchars.size].min
|
567
577
|
result = ''
|
568
578
|
size.times do |i|
|
569
|
-
if
|
570
|
-
|
579
|
+
if @config.completion_ignore_case
|
580
|
+
if memo_mbchars[i].casecmp?(item_mbchars[i])
|
581
|
+
result << memo_mbchars[i]
|
582
|
+
else
|
583
|
+
break
|
584
|
+
end
|
571
585
|
else
|
572
|
-
|
586
|
+
if memo_mbchars[i] == item_mbchars[i]
|
587
|
+
result << memo_mbchars[i]
|
588
|
+
else
|
589
|
+
break
|
590
|
+
end
|
573
591
|
end
|
574
592
|
end
|
575
593
|
result
|
@@ -577,27 +595,43 @@ class Reline::LineEditor
|
|
577
595
|
[target, preposing, completed, postposing]
|
578
596
|
end
|
579
597
|
|
580
|
-
private def complete(list)
|
598
|
+
private def complete(list, just_show_list = false)
|
581
599
|
case @completion_state
|
582
600
|
when CompletionState::NORMAL, CompletionState::JOURNEY
|
583
601
|
@completion_state = CompletionState::COMPLETION
|
584
602
|
when CompletionState::PERFECT_MATCH
|
585
603
|
@dig_perfect_match_proc&.(@perfect_matched)
|
586
604
|
end
|
587
|
-
|
605
|
+
if just_show_list
|
606
|
+
is_menu = true
|
607
|
+
elsif @completion_state == CompletionState::MENU
|
608
|
+
is_menu = true
|
609
|
+
elsif @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH
|
610
|
+
is_menu = true
|
611
|
+
else
|
612
|
+
is_menu = false
|
613
|
+
end
|
588
614
|
result = complete_internal_proc(list, is_menu)
|
615
|
+
if @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH
|
616
|
+
@completion_state = CompletionState::PERFECT_MATCH
|
617
|
+
end
|
589
618
|
return if result.nil?
|
590
619
|
target, preposing, completed, postposing = result
|
591
620
|
return if completed.nil?
|
592
|
-
if target <= completed and (@completion_state == CompletionState::COMPLETION
|
593
|
-
@completion_state = CompletionState::MENU
|
621
|
+
if target <= completed and (@completion_state == CompletionState::COMPLETION)
|
594
622
|
if list.include?(completed)
|
595
|
-
|
623
|
+
if list.one?
|
624
|
+
@completion_state = CompletionState::PERFECT_MATCH
|
625
|
+
else
|
626
|
+
@completion_state = CompletionState::MENU_WITH_PERFECT_MATCH
|
627
|
+
end
|
596
628
|
@perfect_matched = completed
|
629
|
+
else
|
630
|
+
@completion_state = CompletionState::MENU
|
597
631
|
end
|
598
|
-
if target < completed
|
599
|
-
@line = preposing + completed + postposing
|
600
|
-
line_to_pointer = preposing + completed
|
632
|
+
if not just_show_list and target < completed
|
633
|
+
@line = preposing + completed + completion_append_character.to_s + postposing
|
634
|
+
line_to_pointer = preposing + completed + completion_append_character.to_s
|
601
635
|
@cursor_max = calculate_width(@line)
|
602
636
|
@cursor = calculate_width(line_to_pointer)
|
603
637
|
@byte_pointer = line_to_pointer.bytesize
|
@@ -607,7 +641,8 @@ class Reline::LineEditor
|
|
607
641
|
|
608
642
|
private def move_completed_list(list, direction)
|
609
643
|
case @completion_state
|
610
|
-
when CompletionState::NORMAL, CompletionState::COMPLETION,
|
644
|
+
when CompletionState::NORMAL, CompletionState::COMPLETION,
|
645
|
+
CompletionState::MENU, CompletionState::MENU_WITH_PERFECT_MATCH
|
611
646
|
@completion_state = CompletionState::JOURNEY
|
612
647
|
result = retrieve_completion_block
|
613
648
|
return if result.nil?
|
@@ -650,9 +685,9 @@ class Reline::LineEditor
|
|
650
685
|
else
|
651
686
|
old_waiting_proc = @waiting_proc
|
652
687
|
old_waiting_operator_proc = @waiting_operator_proc
|
653
|
-
@waiting_proc = proc { |
|
688
|
+
@waiting_proc = proc { |k|
|
654
689
|
old_cursor, old_byte_pointer = @cursor, @byte_pointer
|
655
|
-
old_waiting_proc.(
|
690
|
+
old_waiting_proc.(k)
|
656
691
|
cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer
|
657
692
|
@cursor, @byte_pointer = old_cursor, old_byte_pointer
|
658
693
|
@waiting_operator_proc.(cursor_diff, byte_pointer_diff)
|
@@ -763,7 +798,7 @@ class Reline::LineEditor
|
|
763
798
|
end
|
764
799
|
|
765
800
|
def input_key(key)
|
766
|
-
if key.
|
801
|
+
if key.char.nil?
|
767
802
|
if @first_char
|
768
803
|
@line = nil
|
769
804
|
end
|
@@ -773,20 +808,20 @@ class Reline::LineEditor
|
|
773
808
|
@first_char = false
|
774
809
|
completion_occurs = false
|
775
810
|
if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
811
|
+
unless @config.disable_completion
|
812
|
+
result = call_completion_proc
|
813
|
+
if result.is_a?(Array)
|
814
|
+
completion_occurs = true
|
815
|
+
complete(result)
|
816
|
+
end
|
782
817
|
end
|
783
|
-
elsif @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char)
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
818
|
+
elsif not @config.disable_completion and @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char)
|
819
|
+
unless @config.disable_completion
|
820
|
+
result = call_completion_proc
|
821
|
+
if result.is_a?(Array)
|
822
|
+
completion_occurs = true
|
823
|
+
move_completed_list(result, "\C-p".ord == key.char ? :up : :down)
|
824
|
+
end
|
790
825
|
end
|
791
826
|
elsif Symbol === key.char and respond_to?(key.char, true)
|
792
827
|
process_key(key.char, key.char)
|
@@ -801,8 +836,33 @@ class Reline::LineEditor
|
|
801
836
|
end
|
802
837
|
end
|
803
838
|
|
839
|
+
def call_completion_proc
|
840
|
+
result = retrieve_completion_block(true)
|
841
|
+
slice = result[1]
|
842
|
+
result = @completion_proc.(slice) if @completion_proc and slice
|
843
|
+
Reline.core.instance_variable_set(:@completion_quote_character, nil)
|
844
|
+
result
|
845
|
+
end
|
846
|
+
|
804
847
|
private def process_auto_indent
|
805
848
|
return if not @check_new_auto_indent and @previous_line_index # move cursor up or down
|
849
|
+
if @check_new_auto_indent and @previous_line_index and @previous_line_index > 0 and @line_index > @previous_line_index
|
850
|
+
# Fix indent of a line when a newline is inserted to the next
|
851
|
+
new_lines = whole_lines(index: @previous_line_index, line: @line)
|
852
|
+
new_indent = @auto_indent_proc.(new_lines[0..-3].push(''), @line_index - 1, 0, true)
|
853
|
+
md = @line.match(/\A */)
|
854
|
+
prev_indent = md[0].count(' ')
|
855
|
+
@line = ' ' * new_indent + @line.lstrip
|
856
|
+
|
857
|
+
new_indent = nil
|
858
|
+
result = @auto_indent_proc.(new_lines[0..-2], @line_index - 1, (new_lines[-2].size + 1), false)
|
859
|
+
if result
|
860
|
+
new_indent = result
|
861
|
+
end
|
862
|
+
if new_indent&.>= 0
|
863
|
+
@line = ' ' * new_indent + @line.lstrip
|
864
|
+
end
|
865
|
+
end
|
806
866
|
if @previous_line_index
|
807
867
|
new_lines = whole_lines(index: @previous_line_index, line: @line)
|
808
868
|
else
|
@@ -825,7 +885,7 @@ class Reline::LineEditor
|
|
825
885
|
@check_new_auto_indent = false
|
826
886
|
end
|
827
887
|
|
828
|
-
def retrieve_completion_block
|
888
|
+
def retrieve_completion_block(set_completion_quote_character = false)
|
829
889
|
word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/
|
830
890
|
quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/
|
831
891
|
before = @line.byteslice(0, @byte_pointer)
|
@@ -844,14 +904,18 @@ class Reline::LineEditor
|
|
844
904
|
if quote and slice.start_with?(closing_quote)
|
845
905
|
quote = nil
|
846
906
|
i += 1
|
907
|
+
rest = nil
|
908
|
+
break_pointer = nil
|
847
909
|
elsif quote and slice.start_with?(escaped_quote)
|
848
910
|
# skip
|
849
911
|
i += 2
|
850
912
|
elsif slice =~ quote_characters_regexp # find new "
|
913
|
+
rest = $'
|
851
914
|
quote = $&
|
852
915
|
closing_quote = /(?!\\)#{Regexp.escape(quote)}/
|
853
916
|
escaped_quote = /\\#{Regexp.escape(quote)}/
|
854
917
|
i += 1
|
918
|
+
break_pointer = i
|
855
919
|
elsif not quote and slice =~ word_break_regexp
|
856
920
|
rest = $'
|
857
921
|
i += 1
|
@@ -860,15 +924,21 @@ class Reline::LineEditor
|
|
860
924
|
i += 1
|
861
925
|
end
|
862
926
|
end
|
927
|
+
postposing = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer)
|
863
928
|
if rest
|
864
929
|
preposing = @line.byteslice(0, break_pointer)
|
865
930
|
target = rest
|
931
|
+
if set_completion_quote_character and quote
|
932
|
+
Reline.core.instance_variable_set(:@completion_quote_character, quote)
|
933
|
+
if postposing !~ /(?!\\)#{Regexp.escape(quote)}/ # closing quote
|
934
|
+
insert_text(quote)
|
935
|
+
end
|
936
|
+
end
|
866
937
|
else
|
867
938
|
preposing = ''
|
868
939
|
target = before
|
869
940
|
end
|
870
|
-
|
871
|
-
[preposing, target, postposing]
|
941
|
+
[preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
|
872
942
|
end
|
873
943
|
|
874
944
|
def confirm_multiline_termination
|
@@ -994,8 +1064,8 @@ class Reline::LineEditor
|
|
994
1064
|
end
|
995
1065
|
width
|
996
1066
|
else
|
997
|
-
str.encode(Encoding::UTF_8).grapheme_clusters.inject(0) { |
|
998
|
-
|
1067
|
+
str.encode(Encoding::UTF_8).grapheme_clusters.inject(0) { |w, gc|
|
1068
|
+
w + Reline::Unicode.get_mbchar_width(gc)
|
999
1069
|
}
|
1000
1070
|
end
|
1001
1071
|
end
|
@@ -1121,25 +1191,34 @@ class Reline::LineEditor
|
|
1121
1191
|
end
|
1122
1192
|
alias_method :end_of_line, :ed_move_to_end
|
1123
1193
|
|
1124
|
-
private def
|
1125
|
-
|
1126
|
-
|
1127
|
-
else
|
1128
|
-
@line_backup_in_history = @line
|
1129
|
-
end
|
1130
|
-
searcher = Fiber.new do
|
1194
|
+
private def generate_searcher
|
1195
|
+
Fiber.new do |first_key|
|
1196
|
+
prev_search_key = first_key
|
1131
1197
|
search_word = String.new(encoding: @encoding)
|
1132
1198
|
multibyte_buf = String.new(encoding: 'ASCII-8BIT')
|
1133
1199
|
last_hit = nil
|
1200
|
+
case first_key
|
1201
|
+
when "\C-r".ord
|
1202
|
+
prompt_name = 'reverse-i-search'
|
1203
|
+
when "\C-s".ord
|
1204
|
+
prompt_name = 'i-search'
|
1205
|
+
end
|
1134
1206
|
loop do
|
1135
1207
|
key = Fiber.yield(search_word)
|
1208
|
+
search_again = false
|
1136
1209
|
case key
|
1137
|
-
when
|
1210
|
+
when -1 # determined
|
1211
|
+
Reline.last_incremental_search = search_word
|
1212
|
+
break
|
1213
|
+
when "\C-h".ord, "\C-?".ord
|
1138
1214
|
grapheme_clusters = search_word.grapheme_clusters
|
1139
1215
|
if grapheme_clusters.size > 0
|
1140
1216
|
grapheme_clusters.pop
|
1141
1217
|
search_word = grapheme_clusters.join
|
1142
1218
|
end
|
1219
|
+
when "\C-r".ord, "\C-s".ord
|
1220
|
+
search_again = true if prev_search_key == key
|
1221
|
+
prev_search_key = key
|
1143
1222
|
else
|
1144
1223
|
multibyte_buf << key
|
1145
1224
|
if multibyte_buf.dup.force_encoding(@encoding).valid_encoding?
|
@@ -1148,18 +1227,61 @@ class Reline::LineEditor
|
|
1148
1227
|
end
|
1149
1228
|
end
|
1150
1229
|
hit = nil
|
1151
|
-
if @line_backup_in_history
|
1230
|
+
if not search_word.empty? and @line_backup_in_history&.include?(search_word)
|
1152
1231
|
@history_pointer = nil
|
1153
1232
|
hit = @line_backup_in_history
|
1154
1233
|
else
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1234
|
+
if search_again
|
1235
|
+
if search_word.empty? and Reline.last_incremental_search
|
1236
|
+
search_word = Reline.last_incremental_search
|
1237
|
+
end
|
1238
|
+
if @history_pointer # TODO
|
1239
|
+
case prev_search_key
|
1240
|
+
when "\C-r".ord
|
1241
|
+
history_pointer_base = 0
|
1242
|
+
history = Reline::HISTORY[0..(@history_pointer - 1)]
|
1243
|
+
when "\C-s".ord
|
1244
|
+
history_pointer_base = @history_pointer + 1
|
1245
|
+
history = Reline::HISTORY[(@history_pointer + 1)..-1]
|
1246
|
+
end
|
1247
|
+
else
|
1248
|
+
history_pointer_base = 0
|
1249
|
+
history = Reline::HISTORY
|
1250
|
+
end
|
1251
|
+
elsif @history_pointer
|
1252
|
+
case prev_search_key
|
1253
|
+
when "\C-r".ord
|
1254
|
+
history_pointer_base = 0
|
1255
|
+
history = Reline::HISTORY[0..@history_pointer]
|
1256
|
+
when "\C-s".ord
|
1257
|
+
history_pointer_base = @history_pointer
|
1258
|
+
history = Reline::HISTORY[@history_pointer..-1]
|
1259
|
+
end
|
1260
|
+
else
|
1261
|
+
history_pointer_base = 0
|
1262
|
+
history = Reline::HISTORY
|
1263
|
+
end
|
1264
|
+
case prev_search_key
|
1265
|
+
when "\C-r".ord
|
1266
|
+
hit_index = history.rindex { |item|
|
1267
|
+
item.include?(search_word)
|
1268
|
+
}
|
1269
|
+
when "\C-s".ord
|
1270
|
+
hit_index = history.index { |item|
|
1271
|
+
item.include?(search_word)
|
1272
|
+
}
|
1273
|
+
end
|
1158
1274
|
if hit_index
|
1159
|
-
@history_pointer = hit_index
|
1275
|
+
@history_pointer = history_pointer_base + hit_index
|
1160
1276
|
hit = Reline::HISTORY[@history_pointer]
|
1161
1277
|
end
|
1162
1278
|
end
|
1279
|
+
case prev_search_key
|
1280
|
+
when "\C-r".ord
|
1281
|
+
prompt_name = 'reverse-i-search'
|
1282
|
+
when "\C-s".ord
|
1283
|
+
prompt_name = 'i-search'
|
1284
|
+
end
|
1163
1285
|
if hit
|
1164
1286
|
if @is_multiline
|
1165
1287
|
@buffer_of_lines = hit.split("\n")
|
@@ -1167,48 +1289,78 @@ class Reline::LineEditor
|
|
1167
1289
|
@line_index = @buffer_of_lines.size - 1
|
1168
1290
|
@line = @buffer_of_lines.last
|
1169
1291
|
@rerender_all = true
|
1170
|
-
@searching_prompt = "(
|
1292
|
+
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
|
1171
1293
|
else
|
1172
1294
|
@line = hit
|
1173
|
-
@searching_prompt = "(
|
1295
|
+
@searching_prompt = "(%s)`%s': %s" % [prompt_name, search_word, hit]
|
1174
1296
|
end
|
1175
1297
|
last_hit = hit
|
1176
1298
|
else
|
1177
1299
|
if @is_multiline
|
1178
1300
|
@rerender_all = true
|
1179
|
-
@searching_prompt = "(failed
|
1301
|
+
@searching_prompt = "(failed %s)`%s'" % [prompt_name, search_word]
|
1180
1302
|
else
|
1181
|
-
@searching_prompt = "(failed
|
1303
|
+
@searching_prompt = "(failed %s)`%s': %s" % [prompt_name, search_word, last_hit]
|
1182
1304
|
end
|
1183
1305
|
end
|
1184
1306
|
end
|
1185
1307
|
end
|
1186
|
-
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
private def search_history(key)
|
1311
|
+
unless @history_pointer
|
1312
|
+
if @is_multiline
|
1313
|
+
@line_backup_in_history = whole_buffer
|
1314
|
+
else
|
1315
|
+
@line_backup_in_history = @line
|
1316
|
+
end
|
1317
|
+
end
|
1318
|
+
searcher = generate_searcher
|
1319
|
+
searcher.resume(key)
|
1187
1320
|
@searching_prompt = "(reverse-i-search)`': "
|
1188
|
-
@waiting_proc = ->(
|
1189
|
-
case
|
1190
|
-
when "\C-j".ord
|
1321
|
+
@waiting_proc = ->(k) {
|
1322
|
+
case k
|
1323
|
+
when "\C-j".ord
|
1191
1324
|
if @history_pointer
|
1192
|
-
|
1325
|
+
buffer = Reline::HISTORY[@history_pointer]
|
1193
1326
|
else
|
1194
|
-
|
1327
|
+
buffer = @line_backup_in_history
|
1328
|
+
end
|
1329
|
+
if @is_multiline
|
1330
|
+
@buffer_of_lines = buffer.split("\n")
|
1331
|
+
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1332
|
+
@line_index = @buffer_of_lines.size - 1
|
1333
|
+
@line = @buffer_of_lines.last
|
1334
|
+
@rerender_all = true
|
1335
|
+
else
|
1336
|
+
@line = buffer
|
1195
1337
|
end
|
1196
1338
|
@searching_prompt = nil
|
1197
1339
|
@waiting_proc = nil
|
1198
1340
|
@cursor_max = calculate_width(@line)
|
1199
1341
|
@cursor = @byte_pointer = 0
|
1342
|
+
searcher.resume(-1)
|
1200
1343
|
when "\C-g".ord
|
1201
|
-
|
1344
|
+
if @is_multiline
|
1345
|
+
@buffer_of_lines = @line_backup_in_history.split("\n")
|
1346
|
+
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1347
|
+
@line_index = @buffer_of_lines.size - 1
|
1348
|
+
@line = @buffer_of_lines.last
|
1349
|
+
@rerender_all = true
|
1350
|
+
else
|
1351
|
+
@line = @line_backup_in_history
|
1352
|
+
end
|
1202
1353
|
@history_pointer = nil
|
1203
1354
|
@searching_prompt = nil
|
1204
1355
|
@waiting_proc = nil
|
1205
1356
|
@line_backup_in_history = nil
|
1206
1357
|
@cursor_max = calculate_width(@line)
|
1207
1358
|
@cursor = @byte_pointer = 0
|
1359
|
+
@rerender_all = true
|
1208
1360
|
else
|
1209
|
-
chr =
|
1210
|
-
if chr.match?(/[[:print:]]/) or
|
1211
|
-
searcher.resume(
|
1361
|
+
chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
|
1362
|
+
if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord
|
1363
|
+
searcher.resume(k)
|
1212
1364
|
else
|
1213
1365
|
if @history_pointer
|
1214
1366
|
line = Reline::HISTORY[@history_pointer]
|
@@ -1230,13 +1382,21 @@ class Reline::LineEditor
|
|
1230
1382
|
@waiting_proc = nil
|
1231
1383
|
@cursor_max = calculate_width(@line)
|
1232
1384
|
@cursor = @byte_pointer = 0
|
1385
|
+
searcher.resume(-1)
|
1233
1386
|
end
|
1234
1387
|
end
|
1235
1388
|
}
|
1236
1389
|
end
|
1237
1390
|
|
1391
|
+
private def ed_search_prev_history(key)
|
1392
|
+
search_history(key)
|
1393
|
+
end
|
1394
|
+
alias_method :reverse_search_history, :ed_search_prev_history
|
1395
|
+
|
1238
1396
|
private def ed_search_next_history(key)
|
1397
|
+
search_history(key)
|
1239
1398
|
end
|
1399
|
+
alias_method :forward_search_history, :ed_search_next_history
|
1240
1400
|
|
1241
1401
|
private def ed_prev_history(key, arg: 1)
|
1242
1402
|
if @is_multiline and @line_index > 0
|
@@ -1394,6 +1554,14 @@ class Reline::LineEditor
|
|
1394
1554
|
@byte_pointer = @line.bytesize
|
1395
1555
|
@cursor = @cursor_max = calculate_width(@line)
|
1396
1556
|
@kill_ring.append(deleted)
|
1557
|
+
elsif @is_multiline and @byte_pointer == @line.bytesize and @buffer_of_lines.size > @line_index + 1
|
1558
|
+
@cursor = calculate_width(@line)
|
1559
|
+
@byte_pointer = @line.bytesize
|
1560
|
+
@line += @buffer_of_lines.delete_at(@line_index + 1)
|
1561
|
+
@cursor_max = calculate_width(@line)
|
1562
|
+
@buffer_of_lines[@line_index] = @line
|
1563
|
+
@rerender_all = true
|
1564
|
+
@rest_height += 1
|
1397
1565
|
end
|
1398
1566
|
end
|
1399
1567
|
|
@@ -1407,7 +1575,7 @@ class Reline::LineEditor
|
|
1407
1575
|
end
|
1408
1576
|
end
|
1409
1577
|
|
1410
|
-
private def
|
1578
|
+
private def em_delete(key)
|
1411
1579
|
if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
|
1412
1580
|
@line = nil
|
1413
1581
|
if @buffer_of_lines.size > 1
|
@@ -1432,7 +1600,19 @@ class Reline::LineEditor
|
|
1432
1600
|
@rest_height += 1
|
1433
1601
|
end
|
1434
1602
|
end
|
1435
|
-
alias_method :delete_char, :
|
1603
|
+
alias_method :delete_char, :em_delete
|
1604
|
+
|
1605
|
+
private def em_delete_or_list(key)
|
1606
|
+
if @line.empty? or @byte_pointer < @line.bytesize
|
1607
|
+
em_delete(key)
|
1608
|
+
else # show completed list
|
1609
|
+
result = call_completion_proc
|
1610
|
+
if result.is_a?(Array)
|
1611
|
+
complete(result, true)
|
1612
|
+
end
|
1613
|
+
end
|
1614
|
+
end
|
1615
|
+
alias_method :delete_char_or_list, :em_delete_or_list
|
1436
1616
|
|
1437
1617
|
private def em_yank(key)
|
1438
1618
|
yanked = @kill_ring.yank
|
@@ -1736,18 +1916,6 @@ class Reline::LineEditor
|
|
1736
1916
|
private def vi_yank(key)
|
1737
1917
|
end
|
1738
1918
|
|
1739
|
-
private def vi_end_of_transmission(key)
|
1740
|
-
if @line.empty?
|
1741
|
-
@line = nil
|
1742
|
-
if @buffer_of_lines.size > 1
|
1743
|
-
scroll_down(@highest_in_all - @first_line_started_from)
|
1744
|
-
end
|
1745
|
-
Reline::IOGate.move_cursor_column(0)
|
1746
|
-
@eof = true
|
1747
|
-
finish
|
1748
|
-
end
|
1749
|
-
end
|
1750
|
-
|
1751
1919
|
private def vi_list_or_eof(key)
|
1752
1920
|
if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
|
1753
1921
|
@line = nil
|
@@ -1758,9 +1926,11 @@ class Reline::LineEditor
|
|
1758
1926
|
@eof = true
|
1759
1927
|
finish
|
1760
1928
|
else
|
1761
|
-
|
1929
|
+
ed_newline(key)
|
1762
1930
|
end
|
1763
1931
|
end
|
1932
|
+
alias_method :vi_end_of_transmission, :vi_list_or_eof
|
1933
|
+
alias_method :vi_eof_maybe, :vi_list_or_eof
|
1764
1934
|
|
1765
1935
|
private def ed_delete_next_char(key, arg: 1)
|
1766
1936
|
byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
|
@@ -1861,13 +2031,13 @@ class Reline::LineEditor
|
|
1861
2031
|
end
|
1862
2032
|
|
1863
2033
|
private def vi_replace_char(key, arg: 1)
|
1864
|
-
@waiting_proc = ->(
|
2034
|
+
@waiting_proc = ->(k) {
|
1865
2035
|
if arg == 1
|
1866
2036
|
byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
|
1867
2037
|
before = @line.byteslice(0, @byte_pointer)
|
1868
2038
|
remaining_point = @byte_pointer + byte_size
|
1869
2039
|
after = @line.byteslice(remaining_point, @line.size - remaining_point)
|
1870
|
-
@line = before +
|
2040
|
+
@line = before + k.chr + after
|
1871
2041
|
@cursor_max = calculate_width(@line)
|
1872
2042
|
@waiting_proc = nil
|
1873
2043
|
elsif arg > 1
|
@@ -1878,7 +2048,7 @@ class Reline::LineEditor
|
|
1878
2048
|
before = @line.byteslice(0, @byte_pointer)
|
1879
2049
|
remaining_point = @byte_pointer + byte_size
|
1880
2050
|
after = @line.byteslice(remaining_point, @line.size - remaining_point)
|
1881
|
-
replaced =
|
2051
|
+
replaced = k.chr * arg
|
1882
2052
|
@line = before + replaced + after
|
1883
2053
|
@byte_pointer += replaced.bytesize
|
1884
2054
|
@cursor += calculate_width(replaced)
|
@@ -1939,4 +2109,20 @@ class Reline::LineEditor
|
|
1939
2109
|
arg -= 1
|
1940
2110
|
vi_join_lines(key, arg: arg) if arg > 0
|
1941
2111
|
end
|
2112
|
+
|
2113
|
+
private def em_set_mark(key)
|
2114
|
+
@mark_pointer = [@byte_pointer, @line_index]
|
2115
|
+
end
|
2116
|
+
alias_method :set_mark, :em_set_mark
|
2117
|
+
|
2118
|
+
private def em_exchange_mark(key)
|
2119
|
+
new_pointer = [@byte_pointer, @line_index]
|
2120
|
+
@previous_line_index = @line_index
|
2121
|
+
@byte_pointer, @line_index = @mark_pointer
|
2122
|
+
@byte_pointer, @line_index = @mark_pointer
|
2123
|
+
@cursor = calculate_width(@line.byteslice(0, @byte_pointer))
|
2124
|
+
@cursor_max = calculate_width(@line)
|
2125
|
+
@mark_pointer = new_pointer
|
2126
|
+
end
|
2127
|
+
alias_method :exchange_point_and_mark, :em_exchange_mark
|
1942
2128
|
end
|
data/lib/reline/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-12-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: io-console
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.5'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -91,14 +105,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
105
|
requirements:
|
92
106
|
- - ">="
|
93
107
|
- !ruby/object:Gem::Version
|
94
|
-
version: '
|
108
|
+
version: '2.5'
|
95
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
110
|
requirements:
|
97
111
|
- - ">="
|
98
112
|
- !ruby/object:Gem::Version
|
99
113
|
version: '0'
|
100
114
|
requirements: []
|
101
|
-
rubygems_version: 3.0.
|
115
|
+
rubygems_version: 3.1.0.pre3
|
102
116
|
signing_key:
|
103
117
|
specification_version: 4
|
104
118
|
summary: Alternative GNU Readline or Editline implementation by pure Ruby.
|