yap-rawline 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/examples/rawline_shell.rb +1 -1
- data/lib/rawline/editor.rb +11 -10
- data/lib/rawline/history_buffer.rb +28 -7
- data/lib/rawline/line.rb +5 -1
- data/lib/rawline/line_editor.rb +4 -3
- data/lib/rawline/version.rb +1 -1
- data/spec/editor_spec.rb +3 -1
- data/spec/history_buffer_spec.rb +83 -5
- data/spec/keycode_parser_spec.rb +16 -21
- data/spec/line_spec.rb +14 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: faf5249796b514e5aeed4e79a1de38d1559bf431
|
4
|
+
data.tar.gz: 893634b11c7c908ab2e983c51b5dac5996f46e58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1309021069574aba5c5b597342c9602caa858b1c211c88f79375d17380b7ab57a75f63198d151db981d2ffb90fb6805b606d6eb0a9007695c31f4baf2558fb37
|
7
|
+
data.tar.gz: 63ff4a40b302a64c1017a3b00993ce08750305e950109506f3a7a08b277ee9d40b8bb299ffe1fded63d034c8976e071a0c684f82b29b02a16e111fae4435138d
|
data/examples/rawline_shell.rb
CHANGED
@@ -74,7 +74,7 @@ editor.bind(:ctrl_w){
|
|
74
74
|
# History forward, but if at the end of the history then give user a
|
75
75
|
# blank line rather than remain on the last command
|
76
76
|
editor.bind(:down_arrow) {
|
77
|
-
if editor.history
|
77
|
+
if editor.history && !editor.history.end?
|
78
78
|
editor.history_forward
|
79
79
|
else
|
80
80
|
editor.overwrite_line ""
|
data/lib/rawline/editor.rb
CHANGED
@@ -90,13 +90,14 @@ module RawLine
|
|
90
90
|
class Environment
|
91
91
|
attr_accessor :keys, :completion_class, :history, :word_separator
|
92
92
|
attr_accessor :keyboard_input_processors
|
93
|
+
attr_accessor :terminal
|
93
94
|
|
94
95
|
# * <tt>@history_size</tt> - the size of the editor history buffer (30).
|
95
96
|
# * <tt>@keys</tt> - the keys (arrays of character codes) bound to specific actions.
|
96
97
|
# * <tt>@line_history_size</tt> - the size of the editor line history buffer (50).
|
97
|
-
def initialize(env: nil)
|
98
|
+
def initialize(env: nil, terminal: nil)
|
98
99
|
@env = env
|
99
|
-
@keys = KeyBindings.new
|
100
|
+
@keys = KeyBindings.new(terminal: terminal)
|
100
101
|
@keyboard_input_processors = []
|
101
102
|
|
102
103
|
@completion_class = Completer
|
@@ -133,7 +134,7 @@ module RawLine
|
|
133
134
|
@renderer = renderer
|
134
135
|
@terminal = terminal
|
135
136
|
|
136
|
-
@env_stack = [Environment.new]
|
137
|
+
@env_stack = [Environment.new(terminal: terminal)]
|
137
138
|
|
138
139
|
@word_break_characters = " \t\n\"'@><=;|&{()}"
|
139
140
|
@mode = :insert
|
@@ -537,9 +538,9 @@ module RawLine
|
|
537
538
|
# with <tt>new_line</tt>, and optionally reset the cursor position to
|
538
539
|
# <tt>position</tt>.
|
539
540
|
#
|
540
|
-
def overwrite_line(new_line, position
|
541
|
-
Treefell['editor'].puts "overwrite_line new_line=#{new_line} position=#{position}
|
542
|
-
if @line_editor.overwrite_line(new_line, position,
|
541
|
+
def overwrite_line(new_line, position: nil, highlight_up_to: nil)
|
542
|
+
Treefell['editor'].puts "overwrite_line new_line=#{new_line} position=#{position} highlight_up_to=#{highlight_up_to}"
|
543
|
+
if @line_editor.overwrite_line(new_line, position: position, highlight_up_to: highlight_up_to)
|
543
544
|
@event_loop.add_event name: "render", source: focused_input_box
|
544
545
|
end
|
545
546
|
end
|
@@ -722,7 +723,7 @@ module RawLine
|
|
722
723
|
@terminal.puts sprintf("%-#{max_index_width}d %s\n", i+1, item)
|
723
724
|
end
|
724
725
|
render(reset: true)
|
725
|
-
overwrite_line(text, pos)
|
726
|
+
overwrite_line(text, position: pos)
|
726
727
|
end
|
727
728
|
|
728
729
|
#
|
@@ -813,7 +814,7 @@ module RawLine
|
|
813
814
|
# terminal.puts "Character at Position: [#{text[pos].chr}] (#{text[pos]})" unless pos >= @line.length
|
814
815
|
# terminal.puts "Current Word: [#{word[:text]}] (#{word[:start]} -- #{word[:end]})"
|
815
816
|
clear_line
|
816
|
-
overwrite_line(text, pos)
|
817
|
+
overwrite_line(text, position: pos)
|
817
818
|
end
|
818
819
|
|
819
820
|
def focus_input_box(box)
|
@@ -893,7 +894,7 @@ module RawLine
|
|
893
894
|
return unless line
|
894
895
|
|
895
896
|
cursor_position = nil
|
896
|
-
overwrite_line(line, cursor_position, highlight_up_to: cursor_position)
|
897
|
+
overwrite_line(line, position: cursor_position, highlight_up_to: cursor_position)
|
897
898
|
end
|
898
899
|
end
|
899
900
|
|
@@ -904,7 +905,7 @@ module RawLine
|
|
904
905
|
return unless line
|
905
906
|
|
906
907
|
cursor_position = nil
|
907
|
-
overwrite_line(line, cursor_position, highlight_up_to: cursor_position)
|
908
|
+
overwrite_line(line, position: cursor_position, highlight_up_to: cursor_position)
|
908
909
|
end
|
909
910
|
end
|
910
911
|
|
@@ -46,10 +46,6 @@ module RawLine
|
|
46
46
|
@position = nil
|
47
47
|
end
|
48
48
|
|
49
|
-
def searching?
|
50
|
-
!!@position
|
51
|
-
end
|
52
|
-
|
53
49
|
#
|
54
50
|
# Resize the buffer, resetting <tt>@position</tt> to nil.
|
55
51
|
#
|
@@ -61,6 +57,26 @@ module RawLine
|
|
61
57
|
@position = nil
|
62
58
|
end
|
63
59
|
|
60
|
+
def find_match_backward(text)
|
61
|
+
regex = to_regex(text)
|
62
|
+
offset = @position ? length - position : 0
|
63
|
+
reverse[offset..-1].detect.with_index do |item, index|
|
64
|
+
if item.match(regex)
|
65
|
+
@position = length - index - (offset + 1)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def find_match_forward(text)
|
71
|
+
regex = to_regex(text)
|
72
|
+
offset = @position ? @position + 1 : 0
|
73
|
+
self[offset..-1].detect.with_index do |item, index|
|
74
|
+
if item.match(regex)
|
75
|
+
@position = index + offset
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
64
80
|
#
|
65
81
|
# Clear the content of the buffer and reset <tt>@position</tt> to nil.
|
66
82
|
#
|
@@ -74,7 +90,7 @@ module RawLine
|
|
74
90
|
#
|
75
91
|
def get
|
76
92
|
return nil unless length > 0
|
77
|
-
|
93
|
+
@position = length-1 unless @position
|
78
94
|
at(@position).dup
|
79
95
|
end
|
80
96
|
|
@@ -148,8 +164,7 @@ module RawLine
|
|
148
164
|
# Add a new item to the buffer.
|
149
165
|
#
|
150
166
|
def push(item)
|
151
|
-
|
152
|
-
if !@duplicates && self[-1] == item
|
167
|
+
if !@duplicates && include?(item)
|
153
168
|
# skip adding this line
|
154
169
|
return
|
155
170
|
end
|
@@ -168,6 +183,12 @@ module RawLine
|
|
168
183
|
|
169
184
|
alias << push
|
170
185
|
|
186
|
+
private
|
187
|
+
|
188
|
+
def to_regex(text)
|
189
|
+
return text if text.is_a?(Regexp)
|
190
|
+
/#{Regexp.escape(text)}/
|
191
|
+
end
|
171
192
|
end
|
172
193
|
|
173
194
|
end
|
data/lib/rawline/line.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'ansi_string'
|
2
2
|
|
3
3
|
#
|
4
4
|
# line.rb
|
@@ -56,6 +56,10 @@ module RawLine
|
|
56
56
|
@text = ANSIString.new(val)
|
57
57
|
end
|
58
58
|
|
59
|
+
def text_up_to_position
|
60
|
+
text[0...position]
|
61
|
+
end
|
62
|
+
|
59
63
|
#
|
60
64
|
# Return information about the current word, as a Hash composed by the following
|
61
65
|
# elements:
|
data/lib/rawline/line_editor.rb
CHANGED
@@ -144,13 +144,14 @@ module RawLine
|
|
144
144
|
# with <tt>new_line</tt>, and optionally reset the cursor position to
|
145
145
|
# <tt>position</tt>.
|
146
146
|
#
|
147
|
-
def overwrite_line(new_line, position
|
147
|
+
def overwrite_line(new_line, position: nil, highlight_up_to: nil)
|
148
|
+
position = @line.position if position == :preserve
|
148
149
|
text = @line.text
|
149
150
|
@highlighting = false
|
150
151
|
|
151
|
-
if
|
152
|
+
if highlight_up_to
|
152
153
|
@highlighting = true
|
153
|
-
new_line = highlight_text_up_to(new_line,
|
154
|
+
new_line = highlight_text_up_to(new_line, highlight_up_to)
|
154
155
|
end
|
155
156
|
|
156
157
|
@line.position = position || new_line.length
|
data/lib/rawline/version.rb
CHANGED
data/spec/editor_spec.rb
CHANGED
@@ -38,6 +38,8 @@ describe RawLine::Editor do
|
|
38
38
|
let(:dom) { RawLine::DomTree.new }
|
39
39
|
let(:renderer) do
|
40
40
|
instance_double(RawLine::Renderer,
|
41
|
+
pause: nil,
|
42
|
+
unpause: nil,
|
41
43
|
render_cursor: nil,
|
42
44
|
render: nil
|
43
45
|
)
|
@@ -335,7 +337,7 @@ describe RawLine::Editor do
|
|
335
337
|
input << "test #8a"
|
336
338
|
input.rewind
|
337
339
|
@editor.event_loop.tick
|
338
|
-
@editor.overwrite_line("test #8b", 2)
|
340
|
+
@editor.overwrite_line("test #8b", position: 2)
|
339
341
|
expect(@editor.line.text).to eq("test #8b")
|
340
342
|
expect(@editor.line.position).to eq(2)
|
341
343
|
end
|
data/spec/history_buffer_spec.rb
CHANGED
@@ -3,8 +3,7 @@
|
|
3
3
|
require_relative "../lib/rawline/history_buffer.rb"
|
4
4
|
|
5
5
|
describe RawLine::HistoryBuffer do
|
6
|
-
|
7
|
-
before :each do
|
6
|
+
before do
|
8
7
|
@history = RawLine::HistoryBuffer.new(5)
|
9
8
|
end
|
10
9
|
|
@@ -18,15 +17,15 @@ describe RawLine::HistoryBuffer do
|
|
18
17
|
@history << "line #2"
|
19
18
|
@history << "line #3"
|
20
19
|
@history << "line #2"
|
21
|
-
expect(@history).to eq(["line #1",
|
20
|
+
expect(@history).to eq(["line #1", "line #2", "line #3"])
|
22
21
|
@history.duplicates = true
|
23
22
|
@history << "line #3"
|
24
|
-
expect(@history).to eq(["line #1", "line #
|
23
|
+
expect(@history).to eq(["line #1", "line #2", "line #3", "line #3"])
|
25
24
|
@history.exclude = lambda { |i| i.match(/line #[456]/) }
|
26
25
|
@history << "line #4"
|
27
26
|
@history << "line #5"
|
28
27
|
@history << "line #6"
|
29
|
-
expect(@history).to eq(["line #1", "line #
|
28
|
+
expect(@history).to eq(["line #1", "line #2", "line #3", "line #3"])
|
30
29
|
end
|
31
30
|
|
32
31
|
it "does not overflow" do
|
@@ -103,4 +102,83 @@ describe RawLine::HistoryBuffer do
|
|
103
102
|
expect(@history.size).to eq(6)
|
104
103
|
expect(@history.position).to eq(nil)
|
105
104
|
end
|
105
|
+
|
106
|
+
describe 'finding matches in history, forward and backward' do
|
107
|
+
before do
|
108
|
+
@history.resize(100)
|
109
|
+
@history << 'echo foo'
|
110
|
+
@history << 'echo bar'
|
111
|
+
@history << 'echo baz'
|
112
|
+
@history << 'echo food'
|
113
|
+
@history << 'echo bark'
|
114
|
+
@history << 'echo bonanza'
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#find_match_backward' do
|
118
|
+
context 'when the position starts as nil' do
|
119
|
+
it 'finds the first item back that matches' do
|
120
|
+
@history.clear_position
|
121
|
+
expect(@history.find_match_backward('bonanza')).to eq 'echo bonanza'
|
122
|
+
|
123
|
+
@history.clear_position
|
124
|
+
expect(@history.find_match_backward('foo')).to eq 'echo food'
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'can find consecutive matches, skipping unmatched items' do
|
128
|
+
@history.clear_position
|
129
|
+
expect(@history.find_match_backward('foo')).to eq 'echo food'
|
130
|
+
$z = true
|
131
|
+
expect(@history.find_match_backward('foo')).to eq 'echo foo'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when the position starts as non-nil' do
|
136
|
+
it 'finds the first item back that matches from the current position' do
|
137
|
+
3.times { @history.back }
|
138
|
+
expect(@history.find_match_backward('bar')).to eq 'echo bar'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#find_match_forward' do
|
144
|
+
context 'when the position starts as nil' do
|
145
|
+
it 'finds the first item from the beginning that matches' do
|
146
|
+
@history.clear_position
|
147
|
+
expect(@history.find_match_forward('bar')).to eq 'echo bar'
|
148
|
+
expect(@history.position).to eq @history.index('echo bar')
|
149
|
+
|
150
|
+
@history.clear_position
|
151
|
+
expect(@history.find_match_forward('foo')).to eq 'echo foo'
|
152
|
+
expect(@history.position).to eq @history.index('echo foo')
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'can find consecutive matches, skipping unmatched items' do
|
156
|
+
@history.clear_position
|
157
|
+
expect(@history.find_match_forward('foo')).to eq 'echo foo'
|
158
|
+
expect(@history.position).to eq @history.index('echo foo')
|
159
|
+
|
160
|
+
expect(@history.find_match_forward('foo')).to eq 'echo food'
|
161
|
+
expect(@history.position).to eq @history.index('echo food')
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'when the position starts as non-nil' do
|
166
|
+
it 'finds the first item back that matches from the current position' do
|
167
|
+
3.times { @history.back }
|
168
|
+
expect(@history.find_match_forward('bar')).to eq 'echo bark'
|
169
|
+
expect(@history.position).to eq @history.index('echo bark')
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'when its gone all the way back, and we want to go forward' do
|
174
|
+
it 'd' do
|
175
|
+
@history.length.times do
|
176
|
+
@history.find_match_backward('bar')
|
177
|
+
end
|
178
|
+
expect(@history.find_match_forward('bar')).to eq 'echo bark'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
106
184
|
end
|
data/spec/keycode_parser_spec.rb
CHANGED
@@ -6,32 +6,23 @@ describe RawLine::KeycodeParser do
|
|
6
6
|
subject(:keycode_parser) { described_class.new(keymap) }
|
7
7
|
let(:keymap) { {} }
|
8
8
|
|
9
|
-
describe "#
|
10
|
-
|
11
|
-
keycode_parser.
|
9
|
+
describe "#parse_bytes_into_sequences" do
|
10
|
+
let(:parse) do
|
11
|
+
keycode_parser.parse_bytes_into_sequences(bytes)
|
12
12
|
end
|
13
|
+
let(:bytes){ fail 'Implement :bytes in context/describe for relevant example' }
|
13
14
|
|
14
15
|
context "given a char that isn't in the keymap" do
|
16
|
+
let(:bytes){ "a".bytes }
|
15
17
|
it "returns the byte as a keycode" do
|
16
|
-
expect(
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context "given a char that isn't in the keymap" do
|
21
|
-
it "returns the byte as a keycode" do
|
22
|
-
expect(parse_bytes([97])).to eq ["a".ord]
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context "given multiple characters that aren't in the keymap" do
|
27
|
-
it "returns the bytes as individual keycodes" do
|
28
|
-
expect(parse_bytes(["a", "b", "C"])).to eq ["a", "b", "C"].map(&:ord)
|
18
|
+
expect(parse).to eq ["a"]
|
29
19
|
end
|
30
20
|
end
|
31
21
|
|
32
22
|
context "given multiple characters that aren't in the keymap" do
|
23
|
+
let(:bytes){ "abC".bytes }
|
33
24
|
it "returns the bytes as individual keycodes" do
|
34
|
-
expect(
|
25
|
+
expect(parse).to eq ["abC"]
|
35
26
|
end
|
36
27
|
end
|
37
28
|
|
@@ -39,9 +30,10 @@ describe RawLine::KeycodeParser do
|
|
39
30
|
let(:keymap) do
|
40
31
|
{ backspace: [?\C-?.ord] }
|
41
32
|
end
|
33
|
+
let(:bytes){ [127] }
|
42
34
|
|
43
35
|
it "returns the bytes as a single key code" do
|
44
|
-
expect(
|
36
|
+
expect(parse).to eq ["", [127]]
|
45
37
|
end
|
46
38
|
end
|
47
39
|
|
@@ -49,9 +41,10 @@ describe RawLine::KeycodeParser do
|
|
49
41
|
let(:keymap) do
|
50
42
|
{ backspace: [?\C-?.ord] }
|
51
43
|
end
|
44
|
+
let(:bytes) { [97, 127, 67] }
|
52
45
|
|
53
46
|
it "returns the key codes appropriately" do
|
54
|
-
expect(
|
47
|
+
expect(parse).to eq ["a", [127], "C"]
|
55
48
|
end
|
56
49
|
end
|
57
50
|
|
@@ -59,9 +52,10 @@ describe RawLine::KeycodeParser do
|
|
59
52
|
let(:keymap) do
|
60
53
|
{ left_arrow: [?\e.ord, ?[.ord, ?D.ord] }
|
61
54
|
end
|
55
|
+
let(:bytes) { [?\e.ord, ?[.ord, ?D.ord] }
|
62
56
|
|
63
57
|
it "returns a single key code" do
|
64
|
-
expect(
|
58
|
+
expect(parse).to eq ["", [27, 91, 68]]
|
65
59
|
end
|
66
60
|
end
|
67
61
|
|
@@ -69,9 +63,10 @@ describe RawLine::KeycodeParser do
|
|
69
63
|
let(:keymap) do
|
70
64
|
{ left_arrow: [?\e.ord, ?[.ord, ?D.ord] }
|
71
65
|
end
|
66
|
+
let(:bytes) { ["a".ord, ?\e.ord, ?[.ord, ?D.ord, "C".ord] }
|
72
67
|
|
73
68
|
it "returns a keycodes appropriately" do
|
74
|
-
expect(
|
69
|
+
expect(parse).to eq ["a", [?\e.ord, ?[.ord, ?D.ord], "C"]
|
75
70
|
end
|
76
71
|
end
|
77
72
|
|
data/spec/line_spec.rb
CHANGED
@@ -8,7 +8,7 @@ require_relative "../lib/rawline/line.rb"
|
|
8
8
|
|
9
9
|
describe RawLine::Line do
|
10
10
|
|
11
|
-
before
|
11
|
+
before do
|
12
12
|
@line = RawLine::Line.new(5) {|l| l.prompt = "=>" }
|
13
13
|
end
|
14
14
|
|
@@ -55,4 +55,17 @@ describe RawLine::Line do
|
|
55
55
|
expect(@line.word).to eq({:start => 5, :end => 6, :text => "is"})
|
56
56
|
end
|
57
57
|
|
58
|
+
describe '#text_up_to_position' do
|
59
|
+
subject(:line) { described_class.new }
|
60
|
+
|
61
|
+
it 'returns the text up to, but not including the current position' do
|
62
|
+
line << 'abcdefghij'
|
63
|
+
line.position = 1
|
64
|
+
expect(line.text_up_to_position).to eq('a')
|
65
|
+
|
66
|
+
line.position = 7
|
67
|
+
expect(line.text_up_to_position).to eq('abcdefg')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
58
71
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yap-rawline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fabio Cevasco
|
@@ -148,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
148
|
version: '0'
|
149
149
|
requirements: []
|
150
150
|
rubyforge_project:
|
151
|
-
rubygems_version: 2.
|
151
|
+
rubygems_version: 2.5.1
|
152
152
|
signing_key:
|
153
153
|
specification_version: 4
|
154
154
|
summary: A library for defining custom key bindings and perform line editing operations
|