yap-rawline 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|