yap-rawline 0.2.0 → 0.3.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/lib/rawline/completer.rb +12 -7
- data/lib/rawline/editor.rb +102 -121
- data/lib/rawline/history_buffer.rb +0 -4
- data/lib/rawline/keycode_parser.rb +36 -0
- data/lib/rawline/line.rb +2 -2
- data/lib/rawline/terminal/vt220_terminal.rb +4 -0
- data/lib/rawline/terminal.rb +1 -0
- data/lib/rawline/version.rb +3 -0
- data/lib/rawline.rb +1 -4
- data/lib/tasks/gem.rake +62 -0
- data/spec/editor_spec.rb +70 -5
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be73e6267c8fe5f9ae5dd481a01bace695822a39
|
4
|
+
data.tar.gz: bc7d6f138c08f9fa7c182ddf4fad243a529992dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e32e2906e69dd93fa0a68f10025f1e7396dbb4dbef59134459e8348c534390e71a3e6634331a3264517c71466f44035ec09aff0bbd6bf9867ff1dd9af22f0942
|
7
|
+
data.tar.gz: 935126f5ff9486c6a3bd4ac98b8a98313e4fc0de4817cb403276415fb9aba2130186c0d57891bcb9909c43f5fbed6f4df3f21edaa2963550190d10002b86ee02
|
data/lib/rawline/completer.rb
CHANGED
@@ -38,7 +38,18 @@ module RawLine
|
|
38
38
|
elsif bytes.map(&:ord) != @completion_char
|
39
39
|
@done_proc.call(bytes)
|
40
40
|
elsif @first_time
|
41
|
-
|
41
|
+
unless !@completion_proc || @completion_proc == []
|
42
|
+
word = @line.text[@line.word[:start]..@line.position-1] || ""
|
43
|
+
words = @line.text
|
44
|
+
.split(/\s+/)
|
45
|
+
.delete_if(&:empty?)
|
46
|
+
word_index = words.index(word)
|
47
|
+
matches = @completion_proc.call(
|
48
|
+
word,
|
49
|
+
words,
|
50
|
+
word_index
|
51
|
+
)
|
52
|
+
end
|
42
53
|
matches = matches.to_a.compact.sort.reverse
|
43
54
|
|
44
55
|
if matches.any?
|
@@ -64,12 +75,6 @@ module RawLine
|
|
64
75
|
@completion_found_proc.call(completion: match, possible_completions: @completion_matches.reverse)
|
65
76
|
end
|
66
77
|
end
|
67
|
-
|
68
|
-
private
|
69
|
-
|
70
|
-
def sub_word
|
71
|
-
@line.text[@line.word[:start]..@line.position-1] || ""
|
72
|
-
end
|
73
78
|
end
|
74
79
|
|
75
80
|
end
|
data/lib/rawline/editor.rb
CHANGED
@@ -41,9 +41,9 @@ module RawLine
|
|
41
41
|
extend Forwardable
|
42
42
|
include HighLine::SystemExtensions
|
43
43
|
|
44
|
-
attr_accessor :char
|
45
|
-
attr_accessor :terminal, :
|
46
|
-
attr_accessor :
|
44
|
+
attr_accessor :char
|
45
|
+
attr_accessor :terminal, :mode
|
46
|
+
attr_accessor :completion_proc, :line, :history
|
47
47
|
attr_accessor :match_hidden_files
|
48
48
|
attr_accessor :word_break_characters
|
49
49
|
attr_accessor :dom
|
@@ -85,18 +85,42 @@ module RawLine
|
|
85
85
|
)
|
86
86
|
end
|
87
87
|
|
88
|
+
class Environment
|
89
|
+
attr_accessor :keys, :completion_class, :history, :word_separator
|
90
|
+
|
91
|
+
# * <tt>@history_size</tt> - the size of the editor history buffer (30).
|
92
|
+
# * <tt>@keys</tt> - the keys (arrays of character codes) bound to specific actions.
|
93
|
+
# * <tt>@line_history_size</tt> - the size of the editor line history buffer (50).
|
94
|
+
def initialize(env: nil)
|
95
|
+
@env = env
|
96
|
+
@keys = {}
|
97
|
+
|
98
|
+
@completion_class = Completer
|
99
|
+
|
100
|
+
@line_history_size = 50
|
101
|
+
@history_size = 30
|
102
|
+
|
103
|
+
@history = HistoryBuffer.new(@history_size) do |h|
|
104
|
+
h.duplicates = false;
|
105
|
+
h.exclude = lambda { |item| item.strip == "" }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def initialize_line(&blk)
|
110
|
+
Line.new(@line_history_size) do |line|
|
111
|
+
blk.call(line) if blk
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
88
116
|
#
|
89
117
|
# Create an instance of RawLine::Editor which can be used
|
90
118
|
# to read from input and perform line-editing operations.
|
91
119
|
# This method takes an optional block used to override the
|
92
120
|
# following instance attributes:
|
93
|
-
# * <tt>@history_size</tt> - the size of the editor history buffer (30).
|
94
|
-
# * <tt>@line_history_size</tt> - the size of the editor line history buffer (50).
|
95
|
-
# * <tt>@keys</tt> - the keys (arrays of character codes) bound to specific actions.
|
96
121
|
# * <tt>@word_break_characters</tt> - a regex used for word separation, default inclues: " \t\n\"\\'`@$><=;|&{("
|
97
122
|
# * <tt>@mode</tt> - The editor's character insertion mode (:insert).
|
98
123
|
# * <tt>@completion_proc</tt> - a Proc object used to perform word completion.
|
99
|
-
# * <tt>@completion_append_string</tt> - a string to append to completed words ('').
|
100
124
|
# * <tt>@terminal</tt> - a RawLine::Terminal containing character key codes.
|
101
125
|
#
|
102
126
|
def initialize(dom:, input:, renderer:, terminal:)
|
@@ -105,24 +129,17 @@ module RawLine
|
|
105
129
|
@renderer = renderer
|
106
130
|
@terminal = terminal
|
107
131
|
|
108
|
-
@
|
109
|
-
|
110
|
-
@
|
111
|
-
@word_break_characters = " \t\n\"'@\$><=;|&{("
|
132
|
+
@env_stack = [Environment.new]
|
133
|
+
|
134
|
+
@word_break_characters = " \t\n\"'@><=;|&{("
|
112
135
|
@mode = :insert
|
113
|
-
|
136
|
+
|
114
137
|
@completion_proc = filename_completion_proc
|
115
|
-
|
138
|
+
|
116
139
|
@match_hidden_files = false
|
117
140
|
set_default_keys
|
118
141
|
@add_history = false
|
119
|
-
@highlight_history_matching_text = true
|
120
|
-
@history = HistoryBuffer.new(@history_size) do |h|
|
121
|
-
h.duplicates = false;
|
122
|
-
h.exclude = lambda { |item| item.strip == "" }
|
123
|
-
end
|
124
142
|
@keyboard_input_processors = [self]
|
125
|
-
# @allow_prompt_updates = true
|
126
143
|
yield self if block_given?
|
127
144
|
update_word_separator
|
128
145
|
@char = nil
|
@@ -134,11 +151,17 @@ module RawLine
|
|
134
151
|
attr_reader :dom, :event_loop, :input
|
135
152
|
attr_reader :keyboard_input_processors
|
136
153
|
|
154
|
+
def env ; @env_stack.last ; end
|
155
|
+
|
156
|
+
def completion_class ; env.completion_class ; end
|
157
|
+
def history ; env.history ; end
|
158
|
+
def keys ; env.keys ; end
|
159
|
+
|
137
160
|
#
|
138
161
|
# Return the current RawLine version
|
139
162
|
#
|
140
163
|
def library_version
|
141
|
-
"RawLine v#{RawLine
|
164
|
+
"RawLine v#{RawLine::VERSION}"
|
142
165
|
end
|
143
166
|
|
144
167
|
def prompt
|
@@ -214,18 +237,14 @@ module RawLine
|
|
214
237
|
def read_bytes(bytes)
|
215
238
|
return unless bytes.any?
|
216
239
|
old_position = @line.position
|
217
|
-
|
218
|
-
|
219
|
-
|
240
|
+
|
241
|
+
key_code_sequences = parse_key_code_sequences(bytes)
|
242
|
+
key_code_sequences.each do |sequence|
|
243
|
+
@char = sequence
|
220
244
|
process_character
|
221
245
|
|
222
246
|
new_position = @line.position
|
223
247
|
|
224
|
-
if !@ignore_position_change && new_position != old_position
|
225
|
-
@matching_text = @line.text[0...@line.position]
|
226
|
-
end
|
227
|
-
|
228
|
-
@ignore_position_change = false
|
229
248
|
if @char == @terminal.keys[:enter] || !@char
|
230
249
|
process_line
|
231
250
|
end
|
@@ -252,11 +271,10 @@ module RawLine
|
|
252
271
|
# This method is called automatically by <tt>read</tt>
|
253
272
|
#
|
254
273
|
def process_character
|
255
|
-
|
256
|
-
when 'Fixnum' then
|
257
|
-
default_action
|
258
|
-
when 'Array'
|
274
|
+
if @char.is_a?(Array)
|
259
275
|
press_key if key_bound?
|
276
|
+
else
|
277
|
+
default_action
|
260
278
|
end
|
261
279
|
end
|
262
280
|
|
@@ -281,16 +299,16 @@ module RawLine
|
|
281
299
|
case key.class.to_s
|
282
300
|
when 'Symbol' then
|
283
301
|
raise BindingException, "Unknown key or key sequence '#{key.to_s}' (#{key.class.to_s})" unless @terminal.keys[key]
|
284
|
-
|
302
|
+
keys[@terminal.keys[key]] = block
|
285
303
|
when 'Array' then
|
286
304
|
raise BindingException, "Unknown key or key sequence '#{key.join(", ")}' (#{key.class.to_s})" unless @terminal.keys.has_value? key
|
287
|
-
|
305
|
+
keys[key] = block
|
288
306
|
when 'Fixnum' then
|
289
307
|
raise BindingException, "Unknown key or key sequence '#{key.to_s}' (#{key.class.to_s})" unless @terminal.keys.has_value? [key]
|
290
|
-
|
308
|
+
keys[[key]] = block
|
291
309
|
when 'String' then
|
292
310
|
if key.length == 1 then
|
293
|
-
|
311
|
+
keys[[key.ord]] = block
|
294
312
|
else
|
295
313
|
bind_hash({:"#{key}" => key}, block)
|
296
314
|
end
|
@@ -306,14 +324,14 @@ module RawLine
|
|
306
324
|
def unbind(key)
|
307
325
|
block = case key.class.to_s
|
308
326
|
when 'Symbol' then
|
309
|
-
|
327
|
+
keys.delete @terminal.keys[key]
|
310
328
|
when 'Array' then
|
311
|
-
|
329
|
+
keys.delete keys[key]
|
312
330
|
when 'Fixnum' then
|
313
|
-
|
331
|
+
keys.delete[[key]]
|
314
332
|
when 'String' then
|
315
333
|
if key.length == 1 then
|
316
|
-
|
334
|
+
keys.delete([key.ord])
|
317
335
|
else
|
318
336
|
raise NotImplementedError, "This is no implemented yet. It needs to return the previously bound block"
|
319
337
|
bind_hash({:"#{key}" => key}, block)
|
@@ -330,7 +348,7 @@ module RawLine
|
|
330
348
|
# Return true if the last character read via <tt>read</tt> is bound to an action.
|
331
349
|
#
|
332
350
|
def key_bound?
|
333
|
-
|
351
|
+
keys[@char] ? true : false
|
334
352
|
end
|
335
353
|
|
336
354
|
#
|
@@ -338,24 +356,23 @@ module RawLine
|
|
338
356
|
# This method is called automatically by <tt>process_character</tt>.
|
339
357
|
#
|
340
358
|
def press_key
|
341
|
-
|
359
|
+
keys[@char].call
|
342
360
|
end
|
343
361
|
|
344
362
|
#
|
345
363
|
# Execute the default action for the last character read via <tt>read</tt>.
|
346
|
-
# By default it prints the character to the screen via <tt>
|
364
|
+
# By default it prints the character to the screen via <tt>write</tt>.
|
347
365
|
# This method is called automatically by <tt>process_character</tt>.
|
348
366
|
#
|
349
367
|
def default_action
|
350
|
-
@
|
351
|
-
print_character
|
368
|
+
insert(@char)
|
352
369
|
end
|
353
370
|
|
354
371
|
#
|
355
372
|
# Parse a key or key sequence into the corresponding codes.
|
356
373
|
#
|
357
|
-
def
|
358
|
-
KeycodeParser.new(@terminal.keys).
|
374
|
+
def parse_key_code_sequences(bytes)
|
375
|
+
KeycodeParser.new(@terminal.keys).parse_bytes_into_sequences(bytes)
|
359
376
|
end
|
360
377
|
|
361
378
|
#
|
@@ -364,7 +381,7 @@ module RawLine
|
|
364
381
|
#
|
365
382
|
def newline
|
366
383
|
add_to_history
|
367
|
-
|
384
|
+
history.clear_position
|
368
385
|
end
|
369
386
|
|
370
387
|
def on_read_line(&blk)
|
@@ -387,7 +404,7 @@ module RawLine
|
|
387
404
|
@line.text = ""
|
388
405
|
@line.position = 0
|
389
406
|
@dom.input_box.position = @line.position
|
390
|
-
|
407
|
+
history.clear_position
|
391
408
|
end
|
392
409
|
|
393
410
|
def clear_screen
|
@@ -416,7 +433,7 @@ module RawLine
|
|
416
433
|
@dom.input_box.position = @line.position
|
417
434
|
@dom.input_box.content = @line.text
|
418
435
|
add_to_line_history unless no_line_history
|
419
|
-
|
436
|
+
history.clear_position
|
420
437
|
end
|
421
438
|
|
422
439
|
#
|
@@ -434,7 +451,7 @@ module RawLine
|
|
434
451
|
@dom.input_box.content = @line.text
|
435
452
|
@dom.input_box.position = @line.position
|
436
453
|
add_to_line_history unless no_line_history
|
437
|
-
|
454
|
+
history.clear_position
|
438
455
|
end
|
439
456
|
end
|
440
457
|
|
@@ -447,7 +464,7 @@ module RawLine
|
|
447
464
|
@line.text[@line.position..-1] = ANSIString.new("")
|
448
465
|
@dom.input_box.content = line.text
|
449
466
|
@dom.input_box.position = @line.position
|
450
|
-
|
467
|
+
history.clear_position
|
451
468
|
killed_text
|
452
469
|
end
|
453
470
|
|
@@ -456,7 +473,7 @@ module RawLine
|
|
456
473
|
@line.position = line.position + text.length
|
457
474
|
@dom.input_box.content = line.text
|
458
475
|
@dom.input_box.position = @line.position
|
459
|
-
|
476
|
+
history.clear_position
|
460
477
|
end
|
461
478
|
|
462
479
|
#
|
@@ -543,7 +560,6 @@ module RawLine
|
|
543
560
|
new_line = highlight_text_up_to(new_line, options[:highlight_up_to])
|
544
561
|
end
|
545
562
|
|
546
|
-
@ignore_position_change = true
|
547
563
|
@line.position = position || new_line.length
|
548
564
|
@line.text = new_line
|
549
565
|
@dom.input_box.content = @line.text
|
@@ -572,30 +588,6 @@ module RawLine
|
|
572
588
|
#
|
573
589
|
############################################################################
|
574
590
|
|
575
|
-
#
|
576
|
-
# Write a character to <tt>output</tt> at cursor position,
|
577
|
-
# shifting characters as appropriate.
|
578
|
-
# If <tt>no_line_history</tt> is set to <tt>true</tt>, the updated
|
579
|
-
# won't be saved in the history of the current line.
|
580
|
-
#
|
581
|
-
def print_character(char=@char, no_line_history = false)
|
582
|
-
if @line.position < @line.length then
|
583
|
-
chars = select_characters_from_cursor if @mode == :insert
|
584
|
-
@line.text[@line.position] = (@mode == :insert) ? "#{char.chr}#{@line.text[@line.position]}" : "#{char.chr}"
|
585
|
-
@line.right
|
586
|
-
@dom.input_box.position = @line.position
|
587
|
-
# if @mode == :insert then
|
588
|
-
# chars.length.times { @line.left } # move cursor back
|
589
|
-
# end
|
590
|
-
else
|
591
|
-
@line.right
|
592
|
-
@line << char
|
593
|
-
end
|
594
|
-
@dom.input_box.content = @line.text
|
595
|
-
@dom.input_box.position = @line.position
|
596
|
-
add_to_line_history unless no_line_history
|
597
|
-
end
|
598
|
-
|
599
591
|
#
|
600
592
|
# Write to <tt>output</tt> and then immediately re-render.
|
601
593
|
#
|
@@ -605,15 +597,29 @@ module RawLine
|
|
605
597
|
end
|
606
598
|
|
607
599
|
#
|
608
|
-
#
|
600
|
+
# Inserts a string at the current line position, shifting characters
|
601
|
+
# to right if necessary.
|
602
|
+
#
|
603
|
+
def insert(string, add_to_line_history: true)
|
604
|
+
@line.text.insert @line.position, string
|
605
|
+
string.length.times { @line.right }
|
606
|
+
@dom.input_box.position = @line.position
|
607
|
+
@dom.input_box.content = @line.text
|
608
|
+
|
609
|
+
self.add_to_line_history if add_to_line_history
|
610
|
+
end
|
611
|
+
|
612
|
+
#
|
613
|
+
# Write a string starting from the cursor position ovewriting any character
|
614
|
+
# at the current position if necessary.
|
609
615
|
#
|
610
|
-
def write(string)
|
616
|
+
def write(string, add_to_line_history: true)
|
611
617
|
@line.text[@line.position] = string
|
612
618
|
string.length.times { @line.right }
|
613
619
|
@dom.input_box.position = @line.position
|
614
620
|
@dom.input_box.content = @line.text
|
615
621
|
|
616
|
-
add_to_line_history
|
622
|
+
self.add_to_line_history if add_to_line_history
|
617
623
|
end
|
618
624
|
|
619
625
|
############################################################################
|
@@ -635,7 +641,7 @@ module RawLine
|
|
635
641
|
#
|
636
642
|
def complete
|
637
643
|
@dom.input_box.cursor_off
|
638
|
-
completer =
|
644
|
+
completer = completion_class.new(
|
639
645
|
char: @char,
|
640
646
|
line: @line,
|
641
647
|
completion: @completion_proc,
|
@@ -669,7 +675,7 @@ module RawLine
|
|
669
675
|
|
670
676
|
move_to_position @line.word[:end]
|
671
677
|
delete_n_characters(@line.word[:end] - @line.word[:start], true)
|
672
|
-
write completion.to_s
|
678
|
+
write completion.to_s
|
673
679
|
end
|
674
680
|
|
675
681
|
def completion_not_found
|
@@ -729,7 +735,7 @@ module RawLine
|
|
729
735
|
def show_history
|
730
736
|
pos = @line.position
|
731
737
|
text = @line.text
|
732
|
-
|
738
|
+
history.each {|l| puts "- [#{l}]"}
|
733
739
|
overwrite_line(text, pos)
|
734
740
|
end
|
735
741
|
|
@@ -737,7 +743,7 @@ module RawLine
|
|
737
743
|
# Clear the editor history.
|
738
744
|
#
|
739
745
|
def clear_history
|
740
|
-
|
746
|
+
history.empty
|
741
747
|
end
|
742
748
|
|
743
749
|
#
|
@@ -764,7 +770,7 @@ module RawLine
|
|
764
770
|
# This action is bound to the up arrow key by default.
|
765
771
|
#
|
766
772
|
def history_back
|
767
|
-
generic_history_back(
|
773
|
+
generic_history_back(history)
|
768
774
|
add_to_line_history
|
769
775
|
end
|
770
776
|
|
@@ -774,7 +780,7 @@ module RawLine
|
|
774
780
|
# This action is bound to down arrow key by default.
|
775
781
|
#
|
776
782
|
def history_forward
|
777
|
-
generic_history_forward(
|
783
|
+
generic_history_forward(history)
|
778
784
|
add_to_line_history
|
779
785
|
end
|
780
786
|
|
@@ -791,7 +797,7 @@ module RawLine
|
|
791
797
|
# Add the current line (<tt>@line.text</tt>) to the editor history.
|
792
798
|
#
|
793
799
|
def add_to_history
|
794
|
-
|
800
|
+
history << @line.text.dup if @add_history && @line.text != ""
|
795
801
|
end
|
796
802
|
|
797
803
|
############################################################################
|
@@ -831,7 +837,7 @@ module RawLine
|
|
831
837
|
@event_loop.add_event name: "render", source: @dom#, target: event[:target]
|
832
838
|
end
|
833
839
|
|
834
|
-
@dom.on :
|
840
|
+
@dom.on :position_changed do |*args|
|
835
841
|
@renderer.render_cursor(@dom.input_box)
|
836
842
|
end
|
837
843
|
|
@@ -846,8 +852,8 @@ module RawLine
|
|
846
852
|
def initialize_line
|
847
853
|
@dom.input_box.content = ""
|
848
854
|
update_word_separator
|
849
|
-
@add_history = true
|
850
|
-
@line =
|
855
|
+
@add_history = true
|
856
|
+
@line = env.initialize_line do |l|
|
851
857
|
l.prompt = @dom.prompt_box.content
|
852
858
|
l.word_separator = @word_separator
|
853
859
|
end
|
@@ -881,7 +887,7 @@ module RawLine
|
|
881
887
|
raise BindingException, "Unable to bind '#{k.to_s}' (#{k.class.to_s})"
|
882
888
|
end
|
883
889
|
@terminal.keys[j] = code
|
884
|
-
|
890
|
+
keys[code] = block
|
885
891
|
end
|
886
892
|
end
|
887
893
|
|
@@ -891,36 +897,21 @@ module RawLine
|
|
891
897
|
|
892
898
|
def generic_history_back(history)
|
893
899
|
unless history.empty?
|
894
|
-
history.back
|
900
|
+
history.back
|
895
901
|
line = history.get
|
896
902
|
return unless line
|
897
903
|
|
898
904
|
cursor_position = nil
|
899
|
-
if supports_partial_text_matching? && highlight_history_matching_text
|
900
|
-
if line && matching_text
|
901
|
-
cursor_position = [line.length, matching_text.length].min
|
902
|
-
elsif matching_text
|
903
|
-
cursor_position = matching_text.length
|
904
|
-
end
|
905
|
-
end
|
906
|
-
|
907
905
|
overwrite_line(line, cursor_position, highlight_up_to: cursor_position)
|
908
906
|
end
|
909
907
|
end
|
910
908
|
|
911
|
-
def supports_partial_text_matching?
|
912
|
-
history.supports_partial_text_matching?
|
913
|
-
end
|
914
|
-
|
915
909
|
def generic_history_forward(history)
|
916
|
-
if history.forward
|
910
|
+
if history.forward
|
917
911
|
line = history.get
|
918
912
|
return unless line
|
919
913
|
|
920
|
-
cursor_position =
|
921
|
-
[line.length, matching_text.length].min
|
922
|
-
end
|
923
|
-
|
914
|
+
cursor_position = nil
|
924
915
|
overwrite_line(line, cursor_position, highlight_up_to: cursor_position)
|
925
916
|
end
|
926
917
|
end
|
@@ -934,7 +925,7 @@ module RawLine
|
|
934
925
|
end
|
935
926
|
|
936
927
|
def set_default_keys
|
937
|
-
bind(:space) {
|
928
|
+
bind(:space) { insert(' ') }
|
938
929
|
bind(:enter) { newline }
|
939
930
|
bind(:tab) { complete }
|
940
931
|
bind(:backspace) { delete_left_character }
|
@@ -950,16 +941,6 @@ module RawLine
|
|
950
941
|
bind(:insert) { toggle_mode }
|
951
942
|
end
|
952
943
|
|
953
|
-
def matching_text
|
954
|
-
return nil unless @line
|
955
|
-
return nil if @line.text == ""
|
956
|
-
if @history.searching?
|
957
|
-
@matching_text
|
958
|
-
else
|
959
|
-
@matching_text = @line[0...@line.position]
|
960
|
-
end
|
961
|
-
end
|
962
|
-
|
963
944
|
def terminal_row_for_line_position(line_position)
|
964
945
|
((@line.prompt.length + line_position) / terminal_width.to_f).ceil
|
965
946
|
end
|
@@ -5,6 +5,42 @@ module RawLine
|
|
5
5
|
@escape_code = keymap[:escape]
|
6
6
|
end
|
7
7
|
|
8
|
+
# Parses a collection of bytes into key code sequences. All
|
9
|
+
# multi-byte sequences (e.g. [27, 91, 67]) will be left alone where-as
|
10
|
+
# all other byte sequences will be converted to UTF-8.
|
11
|
+
#
|
12
|
+
# E.g.
|
13
|
+
# parse_bytes_into_sequences [97, 98, [27, 91, 67], 99, 198, 146]
|
14
|
+
# # => ["a", "b", [27, 91, 67], "c", "ƒ"]
|
15
|
+
#
|
16
|
+
def parse_bytes_into_sequences(bytes)
|
17
|
+
key_codes = parse_bytes(bytes)
|
18
|
+
|
19
|
+
byte_buffer = []
|
20
|
+
sequences = key_codes.each_with_object([]) do |val, arr|
|
21
|
+
if val.is_a?(Array)
|
22
|
+
arr.push *convert_bytes_to_utf8(byte_buffer)
|
23
|
+
arr << val
|
24
|
+
byte_buffer = []
|
25
|
+
else
|
26
|
+
byte_buffer << val
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# don't forget about remaining bytes in the buffer
|
31
|
+
if byte_buffer.any?
|
32
|
+
sequences.push *convert_bytes_to_utf8(byte_buffer)
|
33
|
+
end
|
34
|
+
|
35
|
+
sequences
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def convert_bytes_to_utf8(bytes)
|
41
|
+
bytes.pack('C*').force_encoding('UTF-8')
|
42
|
+
end
|
43
|
+
|
8
44
|
def parse_bytes(bytes)
|
9
45
|
i = 0
|
10
46
|
results = []
|
data/lib/rawline/line.rb
CHANGED
@@ -22,6 +22,10 @@ module RawLine
|
|
22
22
|
@escape_codes = [?\e.ord]
|
23
23
|
@keys.merge!(
|
24
24
|
{
|
25
|
+
:alt_up_arrow => [?\e.ord, ?\e.ord, ?[.ord, ?A.ord],
|
26
|
+
:alt_down_arrow => [?\e.ord, ?\e.ord, ?[.ord, ?B.ord],
|
27
|
+
:alt_right_arrow => [?\e.ord, ?\e.ord, ?[.ord, ?C.ord],
|
28
|
+
:alt_left_arrow => [?\e.ord, ?\e.ord, ?[.ord, ?D.ord],
|
25
29
|
:up_arrow => [?\e.ord, ?[.ord, ?A.ord],
|
26
30
|
:down_arrow => [?\e.ord, ?[.ord, ?B.ord],
|
27
31
|
:right_arrow => [?\e.ord, ?[.ord, ?C.ord],
|
data/lib/rawline/terminal.rb
CHANGED
data/lib/rawline.rb
CHANGED
data/lib/tasks/gem.rake
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
namespace :bump do
|
2
|
+
namespace :version do
|
3
|
+
class ProjectVersion
|
4
|
+
FILE = File.dirname(__FILE__) + '/../rawline/version.rb'
|
5
|
+
PATTERN = /VERSION\s*=\s*"(\d+)\.(\d+)\.(\d+)"/m
|
6
|
+
|
7
|
+
def initialize(file=FILE, pattern=PATTERN)
|
8
|
+
@file = file
|
9
|
+
@pattern = pattern
|
10
|
+
end
|
11
|
+
|
12
|
+
def bump(major:nil, minor:nil, patch:nil)
|
13
|
+
version = nil
|
14
|
+
contents.sub!(@pattern) do
|
15
|
+
_major = major.call($1) if major
|
16
|
+
_minor = minor.call($2) if minor
|
17
|
+
_patch = patch.call($3) if patch
|
18
|
+
version = "#{_major}.#{_minor}.#{_patch}"
|
19
|
+
results = %|VERSION = "#{version}"|
|
20
|
+
end
|
21
|
+
File.write(@file, contents)
|
22
|
+
system "bundle"
|
23
|
+
system "git add #{ProjectVersion::FILE} && git commit -m 'Bumping version to #{version}'"
|
24
|
+
system "git tag v#{version}"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def contents
|
30
|
+
@contents ||= File.read(@file)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Increments the patch number by 1 for the project"
|
35
|
+
task :patch do
|
36
|
+
ProjectVersion.new.bump(
|
37
|
+
major: ->(major){ major },
|
38
|
+
minor: ->(minor){ minor },
|
39
|
+
patch: ->(patch){ patch.succ }
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "Increments the minor number by 1 for the project"
|
44
|
+
task :minor do
|
45
|
+
ProjectVersion.new.bump(
|
46
|
+
major: ->(major){ major },
|
47
|
+
minor: ->(minor){ minor.succ },
|
48
|
+
patch: ->(patch){ 0 }
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Increments the major number by 1 for the project"
|
53
|
+
task :major do
|
54
|
+
ProjectVersion.new.bump(
|
55
|
+
major: ->(major){ major.succ },
|
56
|
+
minor: ->(minor){ 0 },
|
57
|
+
patch: ->(patch){ 0 }
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/spec/editor_spec.rb
CHANGED
@@ -132,7 +132,7 @@ describe RawLine::Editor do
|
|
132
132
|
it "moves the line and cursor position to left by 1 character" do
|
133
133
|
@editor.event_loop.tick
|
134
134
|
expect(@editor.line.position).to eq(3)
|
135
|
-
expect(@editor.input_box.
|
135
|
+
expect(@editor.input_box.position).to eq(3)
|
136
136
|
|
137
137
|
input.clear
|
138
138
|
input << arrow_key_left_ansi
|
@@ -142,7 +142,7 @@ describe RawLine::Editor do
|
|
142
142
|
@editor.event_loop.tick
|
143
143
|
|
144
144
|
expect(@editor.line.position).to eq(2)
|
145
|
-
expect(@editor.input_box.
|
145
|
+
expect(@editor.input_box.position).to eq(2)
|
146
146
|
end
|
147
147
|
end
|
148
148
|
|
@@ -150,7 +150,7 @@ describe RawLine::Editor do
|
|
150
150
|
it "doesnt move the line and cursor position" do
|
151
151
|
@editor.event_loop.tick
|
152
152
|
expect(@editor.line.position).to eq(3)
|
153
|
-
expect(@editor.input_box.
|
153
|
+
expect(@editor.input_box.position).to eq(3)
|
154
154
|
|
155
155
|
input.clear
|
156
156
|
input << arrow_key_right_ansi
|
@@ -160,7 +160,7 @@ describe RawLine::Editor do
|
|
160
160
|
@editor.event_loop.tick
|
161
161
|
|
162
162
|
expect(@editor.line.position).to eq(3)
|
163
|
-
expect(@editor.input_box.
|
163
|
+
expect(@editor.input_box.position).to eq(3)
|
164
164
|
end
|
165
165
|
end
|
166
166
|
|
@@ -204,12 +204,77 @@ describe RawLine::Editor do
|
|
204
204
|
|
205
205
|
it "correctly sets the line and cursor position" do
|
206
206
|
expect(@editor.line.position).to eq(3)
|
207
|
-
expect(@editor.input_box.
|
207
|
+
expect(@editor.input_box.position).to eq(3)
|
208
208
|
end
|
209
209
|
end
|
210
210
|
end
|
211
211
|
end
|
212
212
|
|
213
|
+
describe "#insert" do
|
214
|
+
before do
|
215
|
+
input << "test #5"
|
216
|
+
input.rewind
|
217
|
+
@editor.event_loop.tick
|
218
|
+
expect(@editor.line.position).to eq(7)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "inserts the given string at the current line position" do
|
222
|
+
@editor.insert "ABC"
|
223
|
+
expect(@editor.line.text).to eq("test #5ABC")
|
224
|
+
end
|
225
|
+
|
226
|
+
it "increments the line position the length of the inserted string" do
|
227
|
+
@editor.insert "ABC"
|
228
|
+
expect(@editor.line.position).to eq(10)
|
229
|
+
end
|
230
|
+
|
231
|
+
it "shifts characters not at the end of the string" do
|
232
|
+
@editor.move_left
|
233
|
+
@editor.insert "931"
|
234
|
+
expect(@editor.line.text).to eq("test #9315")
|
235
|
+
expect(@editor.line.position).to eq(9)
|
236
|
+
end
|
237
|
+
|
238
|
+
it "updates the DOM's input_box and position" do
|
239
|
+
@editor.insert "hello"
|
240
|
+
expect(dom.input_box.content).to eq("test #5hello")
|
241
|
+
expect(dom.input_box.position).to eq(12)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe "#write" do
|
246
|
+
before do
|
247
|
+
input << "test #5"
|
248
|
+
input.rewind
|
249
|
+
@editor.event_loop.tick
|
250
|
+
expect(@editor.line.position).to eq(7)
|
251
|
+
end
|
252
|
+
|
253
|
+
it "writes the given string at the current line position" do
|
254
|
+
@editor.write "ABC"
|
255
|
+
expect(@editor.line.text).to eq("test #5ABC")
|
256
|
+
end
|
257
|
+
|
258
|
+
it "increments the line position the length of the written string" do
|
259
|
+
@editor.write "ABC"
|
260
|
+
expect(@editor.line.position).to eq(10)
|
261
|
+
end
|
262
|
+
|
263
|
+
it "overwrites any character at the current position" do
|
264
|
+
@editor.move_left
|
265
|
+
@editor.write "931"
|
266
|
+
expect(@editor.line.text).to eq("test #931")
|
267
|
+
expect(@editor.line.position).to eq(9)
|
268
|
+
end
|
269
|
+
|
270
|
+
it "updates the DOM's input_box and position" do
|
271
|
+
@editor.move_left
|
272
|
+
@editor.write "hello"
|
273
|
+
expect(dom.input_box.content).to eq("test #hello")
|
274
|
+
expect(dom.input_box.position).to eq(11)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
213
278
|
it "can delete characters" do
|
214
279
|
input << "test #5"
|
215
280
|
input.rewind
|
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.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fabio Cevasco
|
@@ -104,6 +104,8 @@ files:
|
|
104
104
|
- lib/rawline/terminal.rb
|
105
105
|
- lib/rawline/terminal/vt220_terminal.rb
|
106
106
|
- lib/rawline/terminal/windows_terminal.rb
|
107
|
+
- lib/rawline/version.rb
|
108
|
+
- lib/tasks/gem.rake
|
107
109
|
- spec/editor_spec.rb
|
108
110
|
- spec/history_buffer_spec.rb
|
109
111
|
- spec/keycode_parser_spec.rb
|