reline 0.0.7 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/reline.rb +20 -5
- data/lib/reline/ansi.rb +12 -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/line_editor.rb +223 -75
- 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: 7612855f90bdd7b5602c7d9e7b2b4de200d6986c45ff64b5a356380c1211b83e
|
4
|
+
data.tar.gz: 58406022787d706f400e828e31fde79b3e90c09a106b82a84218e5b748725db4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcd02ec0e09c6dafa6cf3e9e1dbbeab9befabe033a1ae581628ff01fb4435fce3bb4cbe4cccb5890761e1a58a6637379a5f154ed67f28edaf46a71ba6a00d5c1
|
7
|
+
data.tar.gz: 55a61bcab1c41d35002462c80f11d4406426a815bc84ddb680f73c023139fea95e89bc5cc3d1a9e25f1b77ed0986923e5152cfdd489b9e484bd2e459a6602256
|
data/lib/reline.rb
CHANGED
@@ -32,19 +32,17 @@ module Reline
|
|
32
32
|
dig_perfect_match_proc
|
33
33
|
).each(&method(:attr_reader))
|
34
34
|
|
35
|
-
ATTR_ACCESSOR_NAMES = %i(
|
36
|
-
completion_case_fold
|
37
|
-
).each(&method(:attr_accessor))
|
38
|
-
|
39
35
|
attr_accessor :config
|
40
36
|
attr_accessor :key_stroke
|
41
37
|
attr_accessor :line_editor
|
42
38
|
attr_accessor :ambiguous_width
|
39
|
+
attr_accessor :last_incremental_search
|
43
40
|
attr_reader :output
|
44
41
|
|
45
42
|
def initialize
|
46
43
|
self.output = STDOUT
|
47
44
|
yield self
|
45
|
+
@completion_quote_character = nil
|
48
46
|
end
|
49
47
|
|
50
48
|
def completion_append_character=(val)
|
@@ -83,6 +81,18 @@ module Reline
|
|
83
81
|
@special_prefixes = v.encode(Encoding::default_external)
|
84
82
|
end
|
85
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
|
+
|
86
96
|
def completion_proc=(p)
|
87
97
|
raise ArgumentError unless p.respond_to?(:call)
|
88
98
|
@completion_proc = p
|
@@ -202,6 +212,7 @@ module Reline
|
|
202
212
|
end
|
203
213
|
line_editor.output = output
|
204
214
|
line_editor.completion_proc = completion_proc
|
215
|
+
line_editor.completion_append_character = completion_append_character
|
205
216
|
line_editor.output_modifier_proc = output_modifier_proc
|
206
217
|
line_editor.prompt_proc = prompt_proc
|
207
218
|
line_editor.auto_indent_proc = auto_indent_proc
|
@@ -335,12 +346,14 @@ 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
|
345
358
|
private :readline
|
346
359
|
|
@@ -367,6 +380,8 @@ module Reline
|
|
367
380
|
def_single_delegator :line_editor, :rerender, :redisplay
|
368
381
|
def_single_delegators :core, :vi_editing_mode?, :emacs_editing_mode?
|
369
382
|
def_single_delegators :core, :ambiguous_width
|
383
|
+
def_single_delegators :core, :last_incremental_search
|
384
|
+
def_single_delegators :core, :last_incremental_search=
|
370
385
|
|
371
386
|
def_single_delegators :core, :readmultiline
|
372
387
|
def_instance_delegators self, :readmultiline
|
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, # ↑
|
@@ -11,6 +13,8 @@ class Reline::ANSI
|
|
11
13
|
[27, 91, 70] => :ed_move_to_end, # End
|
12
14
|
[27, 32] => :em_set_mark, # M-<space>
|
13
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+←
|
14
18
|
}
|
15
19
|
|
16
20
|
@@input = STDIN
|
@@ -28,7 +32,8 @@ class Reline::ANSI
|
|
28
32
|
unless @@buf.empty?
|
29
33
|
return @@buf.shift
|
30
34
|
end
|
31
|
-
@@input.getbyte
|
35
|
+
c = @@input.raw(intr: true, &:getbyte)
|
36
|
+
(c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
|
32
37
|
end
|
33
38
|
|
34
39
|
def self.ungetc(c)
|
@@ -60,14 +65,18 @@ class Reline::ANSI
|
|
60
65
|
def self.cursor_pos
|
61
66
|
begin
|
62
67
|
res = ''
|
68
|
+
m = nil
|
63
69
|
@@input.raw do |stdin|
|
64
70
|
@@output << "\e[6n"
|
65
71
|
@@output.flush
|
66
72
|
while (c = stdin.getc) != 'R'
|
67
73
|
res << c if c
|
68
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
|
69
79
|
end
|
70
|
-
m = res.match(/(?<row>\d+);(?<column>\d+)/)
|
71
80
|
column = m[:column].to_i - 1
|
72
81
|
row = m[:row].to_i - 1
|
73
82
|
rescue Errno::ENOTTY
|
@@ -120,24 +129,12 @@ class Reline::ANSI
|
|
120
129
|
def self.prep
|
121
130
|
retrieve_keybuffer
|
122
131
|
int_handle = Signal.trap('INT', 'IGNORE')
|
123
|
-
otio = `stty -g`.chomp
|
124
|
-
setting = ' -echo -icrnl cbreak'
|
125
|
-
stty = `stty -a`
|
126
|
-
if /-parenb\b/ =~ stty
|
127
|
-
setting << ' pass8'
|
128
|
-
end
|
129
|
-
if /\bdsusp *=/ =~ stty
|
130
|
-
setting << ' dsusp undef'
|
131
|
-
end
|
132
|
-
setting << ' -ixoff'
|
133
|
-
`stty #{setting}`
|
134
132
|
Signal.trap('INT', int_handle)
|
135
|
-
|
133
|
+
nil
|
136
134
|
end
|
137
135
|
|
138
136
|
def self.deprep(otio)
|
139
137
|
int_handle = Signal.trap('INT', 'IGNORE')
|
140
|
-
system("stty #{otio}", err: File::NULL)
|
141
138
|
Signal.trap('INT', int_handle)
|
142
139
|
Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
|
143
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/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
|
|
@@ -549,10 +552,14 @@ class Reline::LineEditor
|
|
549
552
|
private def complete_internal_proc(list, is_menu)
|
550
553
|
preposing, target, postposing = retrieve_completion_block
|
551
554
|
list = list.select { |i|
|
552
|
-
if i and
|
553
|
-
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)
|
554
562
|
end
|
555
|
-
i&.start_with?(target)
|
556
563
|
}
|
557
564
|
if is_menu
|
558
565
|
menu(target, list)
|
@@ -569,10 +576,18 @@ class Reline::LineEditor
|
|
569
576
|
size = [memo_mbchars.size, item_mbchars.size].min
|
570
577
|
result = ''
|
571
578
|
size.times do |i|
|
572
|
-
if
|
573
|
-
|
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
|
574
585
|
else
|
575
|
-
|
586
|
+
if memo_mbchars[i] == item_mbchars[i]
|
587
|
+
result << memo_mbchars[i]
|
588
|
+
else
|
589
|
+
break
|
590
|
+
end
|
576
591
|
end
|
577
592
|
end
|
578
593
|
result
|
@@ -580,27 +595,43 @@ class Reline::LineEditor
|
|
580
595
|
[target, preposing, completed, postposing]
|
581
596
|
end
|
582
597
|
|
583
|
-
private def complete(list)
|
598
|
+
private def complete(list, just_show_list = false)
|
584
599
|
case @completion_state
|
585
600
|
when CompletionState::NORMAL, CompletionState::JOURNEY
|
586
601
|
@completion_state = CompletionState::COMPLETION
|
587
602
|
when CompletionState::PERFECT_MATCH
|
588
603
|
@dig_perfect_match_proc&.(@perfect_matched)
|
589
604
|
end
|
590
|
-
|
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
|
591
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
|
592
618
|
return if result.nil?
|
593
619
|
target, preposing, completed, postposing = result
|
594
620
|
return if completed.nil?
|
595
|
-
if target <= completed and (@completion_state == CompletionState::COMPLETION
|
596
|
-
@completion_state = CompletionState::MENU
|
621
|
+
if target <= completed and (@completion_state == CompletionState::COMPLETION)
|
597
622
|
if list.include?(completed)
|
598
|
-
|
623
|
+
if list.one?
|
624
|
+
@completion_state = CompletionState::PERFECT_MATCH
|
625
|
+
else
|
626
|
+
@completion_state = CompletionState::MENU_WITH_PERFECT_MATCH
|
627
|
+
end
|
599
628
|
@perfect_matched = completed
|
629
|
+
else
|
630
|
+
@completion_state = CompletionState::MENU
|
600
631
|
end
|
601
|
-
if target < completed
|
602
|
-
@line = preposing + completed + postposing
|
603
|
-
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
|
604
635
|
@cursor_max = calculate_width(@line)
|
605
636
|
@cursor = calculate_width(line_to_pointer)
|
606
637
|
@byte_pointer = line_to_pointer.bytesize
|
@@ -610,7 +641,8 @@ class Reline::LineEditor
|
|
610
641
|
|
611
642
|
private def move_completed_list(list, direction)
|
612
643
|
case @completion_state
|
613
|
-
when CompletionState::NORMAL, CompletionState::COMPLETION,
|
644
|
+
when CompletionState::NORMAL, CompletionState::COMPLETION,
|
645
|
+
CompletionState::MENU, CompletionState::MENU_WITH_PERFECT_MATCH
|
614
646
|
@completion_state = CompletionState::JOURNEY
|
615
647
|
result = retrieve_completion_block
|
616
648
|
return if result.nil?
|
@@ -776,20 +808,20 @@ class Reline::LineEditor
|
|
776
808
|
@first_char = false
|
777
809
|
completion_occurs = false
|
778
810
|
if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
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
|
785
817
|
end
|
786
|
-
elsif @config.editing_mode_is?(:vi_insert) and ["\C-p".ord, "\C-n".ord].include?(key.char)
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
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
|
793
825
|
end
|
794
826
|
elsif Symbol === key.char and respond_to?(key.char, true)
|
795
827
|
process_key(key.char, key.char)
|
@@ -804,6 +836,14 @@ class Reline::LineEditor
|
|
804
836
|
end
|
805
837
|
end
|
806
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
|
+
|
807
847
|
private def process_auto_indent
|
808
848
|
return if not @check_new_auto_indent and @previous_line_index # move cursor up or down
|
809
849
|
if @check_new_auto_indent and @previous_line_index and @previous_line_index > 0 and @line_index > @previous_line_index
|
@@ -815,12 +855,9 @@ class Reline::LineEditor
|
|
815
855
|
@line = ' ' * new_indent + @line.lstrip
|
816
856
|
|
817
857
|
new_indent = nil
|
818
|
-
(new_lines[-2].size + 1)
|
819
|
-
|
820
|
-
|
821
|
-
new_indent = result
|
822
|
-
break
|
823
|
-
end
|
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
|
824
861
|
end
|
825
862
|
if new_indent&.>= 0
|
826
863
|
@line = ' ' * new_indent + @line.lstrip
|
@@ -848,7 +885,7 @@ class Reline::LineEditor
|
|
848
885
|
@check_new_auto_indent = false
|
849
886
|
end
|
850
887
|
|
851
|
-
def retrieve_completion_block
|
888
|
+
def retrieve_completion_block(set_completion_quote_character = false)
|
852
889
|
word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/
|
853
890
|
quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/
|
854
891
|
before = @line.byteslice(0, @byte_pointer)
|
@@ -867,31 +904,42 @@ class Reline::LineEditor
|
|
867
904
|
if quote and slice.start_with?(closing_quote)
|
868
905
|
quote = nil
|
869
906
|
i += 1
|
907
|
+
rest = nil
|
908
|
+
break_pointer = nil
|
870
909
|
elsif quote and slice.start_with?(escaped_quote)
|
871
910
|
# skip
|
872
911
|
i += 2
|
873
912
|
elsif slice =~ quote_characters_regexp # find new "
|
913
|
+
rest = $'
|
874
914
|
quote = $&
|
875
915
|
closing_quote = /(?!\\)#{Regexp.escape(quote)}/
|
876
916
|
escaped_quote = /\\#{Regexp.escape(quote)}/
|
877
917
|
i += 1
|
918
|
+
break_pointer = i
|
878
919
|
elsif not quote and slice =~ word_break_regexp
|
879
920
|
rest = $'
|
880
921
|
i += 1
|
922
|
+
before = @line.byteslice(i, @byte_pointer - i)
|
881
923
|
break_pointer = i
|
882
924
|
else
|
883
925
|
i += 1
|
884
926
|
end
|
885
927
|
end
|
928
|
+
postposing = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer)
|
886
929
|
if rest
|
887
930
|
preposing = @line.byteslice(0, break_pointer)
|
888
931
|
target = rest
|
932
|
+
if set_completion_quote_character and quote
|
933
|
+
Reline.core.instance_variable_set(:@completion_quote_character, quote)
|
934
|
+
if postposing !~ /(?!\\)#{Regexp.escape(quote)}/ # closing quote
|
935
|
+
insert_text(quote)
|
936
|
+
end
|
937
|
+
end
|
889
938
|
else
|
890
939
|
preposing = ''
|
891
940
|
target = before
|
892
941
|
end
|
893
|
-
|
894
|
-
[preposing, target, postposing]
|
942
|
+
[preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
|
895
943
|
end
|
896
944
|
|
897
945
|
def confirm_multiline_termination
|
@@ -1144,25 +1192,34 @@ class Reline::LineEditor
|
|
1144
1192
|
end
|
1145
1193
|
alias_method :end_of_line, :ed_move_to_end
|
1146
1194
|
|
1147
|
-
private def
|
1148
|
-
|
1149
|
-
|
1150
|
-
else
|
1151
|
-
@line_backup_in_history = @line
|
1152
|
-
end
|
1153
|
-
searcher = Fiber.new do
|
1195
|
+
private def generate_searcher
|
1196
|
+
Fiber.new do |first_key|
|
1197
|
+
prev_search_key = first_key
|
1154
1198
|
search_word = String.new(encoding: @encoding)
|
1155
1199
|
multibyte_buf = String.new(encoding: 'ASCII-8BIT')
|
1156
1200
|
last_hit = nil
|
1201
|
+
case first_key
|
1202
|
+
when "\C-r".ord
|
1203
|
+
prompt_name = 'reverse-i-search'
|
1204
|
+
when "\C-s".ord
|
1205
|
+
prompt_name = 'i-search'
|
1206
|
+
end
|
1157
1207
|
loop do
|
1158
1208
|
key = Fiber.yield(search_word)
|
1209
|
+
search_again = false
|
1159
1210
|
case key
|
1160
|
-
when
|
1211
|
+
when -1 # determined
|
1212
|
+
Reline.last_incremental_search = search_word
|
1213
|
+
break
|
1214
|
+
when "\C-h".ord, "\C-?".ord
|
1161
1215
|
grapheme_clusters = search_word.grapheme_clusters
|
1162
1216
|
if grapheme_clusters.size > 0
|
1163
1217
|
grapheme_clusters.pop
|
1164
1218
|
search_word = grapheme_clusters.join
|
1165
1219
|
end
|
1220
|
+
when "\C-r".ord, "\C-s".ord
|
1221
|
+
search_again = true if prev_search_key == key
|
1222
|
+
prev_search_key = key
|
1166
1223
|
else
|
1167
1224
|
multibyte_buf << key
|
1168
1225
|
if multibyte_buf.dup.force_encoding(@encoding).valid_encoding?
|
@@ -1171,18 +1228,61 @@ class Reline::LineEditor
|
|
1171
1228
|
end
|
1172
1229
|
end
|
1173
1230
|
hit = nil
|
1174
|
-
if @line_backup_in_history
|
1231
|
+
if not search_word.empty? and @line_backup_in_history&.include?(search_word)
|
1175
1232
|
@history_pointer = nil
|
1176
1233
|
hit = @line_backup_in_history
|
1177
1234
|
else
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1235
|
+
if search_again
|
1236
|
+
if search_word.empty? and Reline.last_incremental_search
|
1237
|
+
search_word = Reline.last_incremental_search
|
1238
|
+
end
|
1239
|
+
if @history_pointer # TODO
|
1240
|
+
case prev_search_key
|
1241
|
+
when "\C-r".ord
|
1242
|
+
history_pointer_base = 0
|
1243
|
+
history = Reline::HISTORY[0..(@history_pointer - 1)]
|
1244
|
+
when "\C-s".ord
|
1245
|
+
history_pointer_base = @history_pointer + 1
|
1246
|
+
history = Reline::HISTORY[(@history_pointer + 1)..-1]
|
1247
|
+
end
|
1248
|
+
else
|
1249
|
+
history_pointer_base = 0
|
1250
|
+
history = Reline::HISTORY
|
1251
|
+
end
|
1252
|
+
elsif @history_pointer
|
1253
|
+
case prev_search_key
|
1254
|
+
when "\C-r".ord
|
1255
|
+
history_pointer_base = 0
|
1256
|
+
history = Reline::HISTORY[0..@history_pointer]
|
1257
|
+
when "\C-s".ord
|
1258
|
+
history_pointer_base = @history_pointer
|
1259
|
+
history = Reline::HISTORY[@history_pointer..-1]
|
1260
|
+
end
|
1261
|
+
else
|
1262
|
+
history_pointer_base = 0
|
1263
|
+
history = Reline::HISTORY
|
1264
|
+
end
|
1265
|
+
case prev_search_key
|
1266
|
+
when "\C-r".ord
|
1267
|
+
hit_index = history.rindex { |item|
|
1268
|
+
item.include?(search_word)
|
1269
|
+
}
|
1270
|
+
when "\C-s".ord
|
1271
|
+
hit_index = history.index { |item|
|
1272
|
+
item.include?(search_word)
|
1273
|
+
}
|
1274
|
+
end
|
1181
1275
|
if hit_index
|
1182
|
-
@history_pointer = hit_index
|
1276
|
+
@history_pointer = history_pointer_base + hit_index
|
1183
1277
|
hit = Reline::HISTORY[@history_pointer]
|
1184
1278
|
end
|
1185
1279
|
end
|
1280
|
+
case prev_search_key
|
1281
|
+
when "\C-r".ord
|
1282
|
+
prompt_name = 'reverse-i-search'
|
1283
|
+
when "\C-s".ord
|
1284
|
+
prompt_name = 'i-search'
|
1285
|
+
end
|
1186
1286
|
if hit
|
1187
1287
|
if @is_multiline
|
1188
1288
|
@buffer_of_lines = hit.split("\n")
|
@@ -1190,47 +1290,77 @@ class Reline::LineEditor
|
|
1190
1290
|
@line_index = @buffer_of_lines.size - 1
|
1191
1291
|
@line = @buffer_of_lines.last
|
1192
1292
|
@rerender_all = true
|
1193
|
-
@searching_prompt = "(
|
1293
|
+
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
|
1194
1294
|
else
|
1195
1295
|
@line = hit
|
1196
|
-
@searching_prompt = "(
|
1296
|
+
@searching_prompt = "(%s)`%s': %s" % [prompt_name, search_word, hit]
|
1197
1297
|
end
|
1198
1298
|
last_hit = hit
|
1199
1299
|
else
|
1200
1300
|
if @is_multiline
|
1201
1301
|
@rerender_all = true
|
1202
|
-
@searching_prompt = "(failed
|
1302
|
+
@searching_prompt = "(failed %s)`%s'" % [prompt_name, search_word]
|
1203
1303
|
else
|
1204
|
-
@searching_prompt = "(failed
|
1304
|
+
@searching_prompt = "(failed %s)`%s': %s" % [prompt_name, search_word, last_hit]
|
1205
1305
|
end
|
1206
1306
|
end
|
1207
1307
|
end
|
1208
1308
|
end
|
1209
|
-
|
1309
|
+
end
|
1310
|
+
|
1311
|
+
private def search_history(key)
|
1312
|
+
unless @history_pointer
|
1313
|
+
if @is_multiline
|
1314
|
+
@line_backup_in_history = whole_buffer
|
1315
|
+
else
|
1316
|
+
@line_backup_in_history = @line
|
1317
|
+
end
|
1318
|
+
end
|
1319
|
+
searcher = generate_searcher
|
1320
|
+
searcher.resume(key)
|
1210
1321
|
@searching_prompt = "(reverse-i-search)`': "
|
1211
1322
|
@waiting_proc = ->(k) {
|
1212
1323
|
case k
|
1213
|
-
when "\C-j".ord
|
1324
|
+
when "\C-j".ord
|
1214
1325
|
if @history_pointer
|
1215
|
-
|
1326
|
+
buffer = Reline::HISTORY[@history_pointer]
|
1216
1327
|
else
|
1217
|
-
|
1328
|
+
buffer = @line_backup_in_history
|
1329
|
+
end
|
1330
|
+
if @is_multiline
|
1331
|
+
@buffer_of_lines = buffer.split("\n")
|
1332
|
+
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1333
|
+
@line_index = @buffer_of_lines.size - 1
|
1334
|
+
@line = @buffer_of_lines.last
|
1335
|
+
@rerender_all = true
|
1336
|
+
else
|
1337
|
+
@line = buffer
|
1218
1338
|
end
|
1219
1339
|
@searching_prompt = nil
|
1220
1340
|
@waiting_proc = nil
|
1221
1341
|
@cursor_max = calculate_width(@line)
|
1222
1342
|
@cursor = @byte_pointer = 0
|
1343
|
+
searcher.resume(-1)
|
1223
1344
|
when "\C-g".ord
|
1224
|
-
|
1345
|
+
if @is_multiline
|
1346
|
+
@buffer_of_lines = @line_backup_in_history.split("\n")
|
1347
|
+
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
1348
|
+
@line_index = @buffer_of_lines.size - 1
|
1349
|
+
@line = @buffer_of_lines.last
|
1350
|
+
@rerender_all = true
|
1351
|
+
else
|
1352
|
+
@line = @line_backup_in_history
|
1353
|
+
end
|
1225
1354
|
@history_pointer = nil
|
1226
1355
|
@searching_prompt = nil
|
1227
1356
|
@waiting_proc = nil
|
1228
1357
|
@line_backup_in_history = nil
|
1229
1358
|
@cursor_max = calculate_width(@line)
|
1230
1359
|
@cursor = @byte_pointer = 0
|
1360
|
+
@rerender_all = true
|
1231
1361
|
else
|
1232
1362
|
chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
|
1233
|
-
if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k ==
|
1363
|
+
if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord
|
1234
1364
|
searcher.resume(k)
|
1235
1365
|
else
|
1236
1366
|
if @history_pointer
|
@@ -1253,13 +1383,21 @@ class Reline::LineEditor
|
|
1253
1383
|
@waiting_proc = nil
|
1254
1384
|
@cursor_max = calculate_width(@line)
|
1255
1385
|
@cursor = @byte_pointer = 0
|
1386
|
+
searcher.resume(-1)
|
1256
1387
|
end
|
1257
1388
|
end
|
1258
1389
|
}
|
1259
1390
|
end
|
1260
1391
|
|
1392
|
+
private def ed_search_prev_history(key)
|
1393
|
+
search_history(key)
|
1394
|
+
end
|
1395
|
+
alias_method :reverse_search_history, :ed_search_prev_history
|
1396
|
+
|
1261
1397
|
private def ed_search_next_history(key)
|
1398
|
+
search_history(key)
|
1262
1399
|
end
|
1400
|
+
alias_method :forward_search_history, :ed_search_next_history
|
1263
1401
|
|
1264
1402
|
private def ed_prev_history(key, arg: 1)
|
1265
1403
|
if @is_multiline and @line_index > 0
|
@@ -1417,6 +1555,14 @@ class Reline::LineEditor
|
|
1417
1555
|
@byte_pointer = @line.bytesize
|
1418
1556
|
@cursor = @cursor_max = calculate_width(@line)
|
1419
1557
|
@kill_ring.append(deleted)
|
1558
|
+
elsif @is_multiline and @byte_pointer == @line.bytesize and @buffer_of_lines.size > @line_index + 1
|
1559
|
+
@cursor = calculate_width(@line)
|
1560
|
+
@byte_pointer = @line.bytesize
|
1561
|
+
@line += @buffer_of_lines.delete_at(@line_index + 1)
|
1562
|
+
@cursor_max = calculate_width(@line)
|
1563
|
+
@buffer_of_lines[@line_index] = @line
|
1564
|
+
@rerender_all = true
|
1565
|
+
@rest_height += 1
|
1420
1566
|
end
|
1421
1567
|
end
|
1422
1568
|
|
@@ -1430,7 +1576,7 @@ class Reline::LineEditor
|
|
1430
1576
|
end
|
1431
1577
|
end
|
1432
1578
|
|
1433
|
-
private def
|
1579
|
+
private def em_delete(key)
|
1434
1580
|
if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
|
1435
1581
|
@line = nil
|
1436
1582
|
if @buffer_of_lines.size > 1
|
@@ -1455,7 +1601,19 @@ class Reline::LineEditor
|
|
1455
1601
|
@rest_height += 1
|
1456
1602
|
end
|
1457
1603
|
end
|
1458
|
-
alias_method :delete_char, :
|
1604
|
+
alias_method :delete_char, :em_delete
|
1605
|
+
|
1606
|
+
private def em_delete_or_list(key)
|
1607
|
+
if @line.empty? or @byte_pointer < @line.bytesize
|
1608
|
+
em_delete(key)
|
1609
|
+
else # show completed list
|
1610
|
+
result = call_completion_proc
|
1611
|
+
if result.is_a?(Array)
|
1612
|
+
complete(result, true)
|
1613
|
+
end
|
1614
|
+
end
|
1615
|
+
end
|
1616
|
+
alias_method :delete_char_or_list, :em_delete_or_list
|
1459
1617
|
|
1460
1618
|
private def em_yank(key)
|
1461
1619
|
yanked = @kill_ring.yank
|
@@ -1759,18 +1917,6 @@ class Reline::LineEditor
|
|
1759
1917
|
private def vi_yank(key)
|
1760
1918
|
end
|
1761
1919
|
|
1762
|
-
private def vi_end_of_transmission(key)
|
1763
|
-
if @line.empty?
|
1764
|
-
@line = nil
|
1765
|
-
if @buffer_of_lines.size > 1
|
1766
|
-
scroll_down(@highest_in_all - @first_line_started_from)
|
1767
|
-
end
|
1768
|
-
Reline::IOGate.move_cursor_column(0)
|
1769
|
-
@eof = true
|
1770
|
-
finish
|
1771
|
-
end
|
1772
|
-
end
|
1773
|
-
|
1774
1920
|
private def vi_list_or_eof(key)
|
1775
1921
|
if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
|
1776
1922
|
@line = nil
|
@@ -1781,9 +1927,11 @@ class Reline::LineEditor
|
|
1781
1927
|
@eof = true
|
1782
1928
|
finish
|
1783
1929
|
else
|
1784
|
-
|
1930
|
+
ed_newline(key)
|
1785
1931
|
end
|
1786
1932
|
end
|
1933
|
+
alias_method :vi_end_of_transmission, :vi_list_or_eof
|
1934
|
+
alias_method :vi_eof_maybe, :vi_list_or_eof
|
1787
1935
|
|
1788
1936
|
private def ed_delete_next_char(key, arg: 1)
|
1789
1937
|
byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
|
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.2
|
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.
|
115
|
+
rubygems_version: 3.1.2
|
102
116
|
signing_key:
|
103
117
|
specification_version: 4
|
104
118
|
summary: Alternative GNU Readline or Editline implementation by pure Ruby.
|