reline 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/reline/ansi.rb +1 -1
- data/lib/reline/config.rb +16 -10
- data/lib/reline/general_io.rb +6 -0
- data/lib/reline/line_editor.rb +23 -11
- data/lib/reline/terminfo.rb +6 -3
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +2 -2
- data/lib/reline.rb +41 -27
- metadata +4 -5
- data/lib/reline/sibori.rb +0 -170
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8198104fe3ad27c73acaaffc9c8b1c8b9a5c50069a26a71cd940dd2b5dc13afc
|
4
|
+
data.tar.gz: 171ff8cdf2ae4aebaf4cfb6cea131e2d90e5eb56a2c09dbe19acfa8765522ffc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3411f0086a0445d2d805fc46528a86b947c58b8e61a664dc08b437596702ef1f360cd7e85a1dab64bf159f6f39691b9d5110f951bd5376f4fce0439e9557532
|
7
|
+
data.tar.gz: 968ac4a376ba350590fd37d05525a5a2e5e26c44e159b5fd9b0c7400e260850e91088357c007651373d44b7b7d37c699852014d07258428be86081581baf0229
|
data/lib/reline/ansi.rb
CHANGED
@@ -150,7 +150,7 @@ class Reline::ANSI
|
|
150
150
|
until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
|
151
151
|
Reline.core.line_editor.resize
|
152
152
|
end
|
153
|
-
(c == 0x16 && @@input.raw(min: 0,
|
153
|
+
(c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
|
154
154
|
rescue Errno::EIO
|
155
155
|
# Maybe the I/O has been closed.
|
156
156
|
nil
|
data/lib/reline/config.rb
CHANGED
@@ -45,6 +45,8 @@ class Reline::Config
|
|
45
45
|
attr_accessor v
|
46
46
|
end
|
47
47
|
|
48
|
+
attr_accessor :autocompletion
|
49
|
+
|
48
50
|
def initialize
|
49
51
|
@additional_key_bindings = {} # from inputrc
|
50
52
|
@additional_key_bindings[:emacs] = {}
|
@@ -55,6 +57,7 @@ class Reline::Config
|
|
55
57
|
@if_stack = nil
|
56
58
|
@editing_mode_label = :emacs
|
57
59
|
@keymap_label = :emacs
|
60
|
+
@keymap_prefix = []
|
58
61
|
@key_actors = {}
|
59
62
|
@key_actors[:emacs] = Reline::KeyActor::Emacs.new
|
60
63
|
@key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
|
@@ -93,14 +96,6 @@ class Reline::Config
|
|
93
96
|
(val.respond_to?(:any?) ? val : [val]).any?(@editing_mode_label)
|
94
97
|
end
|
95
98
|
|
96
|
-
def autocompletion=(val)
|
97
|
-
@autocompletion = val
|
98
|
-
end
|
99
|
-
|
100
|
-
def autocompletion
|
101
|
-
@autocompletion
|
102
|
-
end
|
103
|
-
|
104
99
|
def keymap
|
105
100
|
@key_actors[@keymap_label]
|
106
101
|
end
|
@@ -221,7 +216,7 @@ class Reline::Config
|
|
221
216
|
key, func_name = $1, $2
|
222
217
|
keystroke, func = bind_key(key, func_name)
|
223
218
|
next unless keystroke
|
224
|
-
@additional_key_bindings[@keymap_label][keystroke] = func
|
219
|
+
@additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
|
225
220
|
end
|
226
221
|
end
|
227
222
|
unless @if_stack.empty?
|
@@ -292,18 +287,29 @@ class Reline::Config
|
|
292
287
|
when 'emacs'
|
293
288
|
@editing_mode_label = :emacs
|
294
289
|
@keymap_label = :emacs
|
290
|
+
@keymap_prefix = []
|
295
291
|
when 'vi'
|
296
292
|
@editing_mode_label = :vi_insert
|
297
293
|
@keymap_label = :vi_insert
|
294
|
+
@keymap_prefix = []
|
298
295
|
end
|
299
296
|
when 'keymap'
|
300
297
|
case value
|
301
|
-
when 'emacs', 'emacs-standard'
|
298
|
+
when 'emacs', 'emacs-standard'
|
299
|
+
@keymap_label = :emacs
|
300
|
+
@keymap_prefix = []
|
301
|
+
when 'emacs-ctlx'
|
302
|
+
@keymap_label = :emacs
|
303
|
+
@keymap_prefix = [?\C-x.ord]
|
304
|
+
when 'emacs-meta'
|
302
305
|
@keymap_label = :emacs
|
306
|
+
@keymap_prefix = [?\e.ord]
|
303
307
|
when 'vi', 'vi-move', 'vi-command'
|
304
308
|
@keymap_label = :vi_command
|
309
|
+
@keymap_prefix = []
|
305
310
|
when 'vi-insert'
|
306
311
|
@keymap_label = :vi_insert
|
312
|
+
@keymap_prefix = []
|
307
313
|
end
|
308
314
|
when 'keyseq-timeout'
|
309
315
|
@keyseq_timeout = value.to_i
|
data/lib/reline/general_io.rb
CHANGED
data/lib/reline/line_editor.rb
CHANGED
@@ -466,15 +466,17 @@ class Reline::LineEditor
|
|
466
466
|
new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line))
|
467
467
|
rendered = false
|
468
468
|
if @add_newline_to_end_of_buffer
|
469
|
+
clear_dialog_with_content
|
469
470
|
rerender_added_newline(prompt, prompt_width)
|
470
471
|
@add_newline_to_end_of_buffer = false
|
471
472
|
else
|
472
473
|
if @just_cursor_moving and not @rerender_all
|
474
|
+
clear_dialog_with_content
|
473
475
|
rendered = just_move_cursor
|
474
|
-
render_dialog((prompt_width + @cursor) % @screen_size.last)
|
475
476
|
@just_cursor_moving = false
|
476
477
|
return
|
477
478
|
elsif @previous_line_index or new_highest_in_this != @highest_in_this
|
479
|
+
clear_dialog_with_content
|
478
480
|
rerender_changed_current_line
|
479
481
|
@previous_line_index = nil
|
480
482
|
rendered = true
|
@@ -653,7 +655,10 @@ class Reline::LineEditor
|
|
653
655
|
end
|
654
656
|
|
655
657
|
private def padding_space_with_escape_sequences(str, width)
|
656
|
-
|
658
|
+
padding_width = width - calculate_width(str, true)
|
659
|
+
# padding_width should be only positive value. But macOS and Alacritty returns negative value.
|
660
|
+
padding_width = 0 if padding_width < 0
|
661
|
+
str + (' ' * padding_width)
|
657
662
|
end
|
658
663
|
|
659
664
|
private def render_each_dialog(dialog, cursor_column)
|
@@ -741,24 +746,21 @@ class Reline::LineEditor
|
|
741
746
|
Reline::IOGate.move_cursor_column(dialog.column)
|
742
747
|
dialog.contents.each_with_index do |item, i|
|
743
748
|
if i == pointer
|
744
|
-
|
749
|
+
fg_color = dialog_render_info.pointer_fg_color
|
750
|
+
bg_color = dialog_render_info.pointer_bg_color
|
745
751
|
else
|
746
|
-
|
747
|
-
|
748
|
-
else
|
749
|
-
bg_color = '46'
|
750
|
-
end
|
752
|
+
fg_color = dialog_render_info.fg_color
|
753
|
+
bg_color = dialog_render_info.bg_color
|
751
754
|
end
|
752
755
|
str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
|
753
756
|
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
|
754
|
-
@output.write "\e[#{bg_color}m#{str}"
|
757
|
+
@output.write "\e[#{bg_color}m\e[#{fg_color}m#{str}"
|
755
758
|
if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
|
756
759
|
@output.write "\e[37m"
|
757
760
|
if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height)
|
758
761
|
@output.write @full_block
|
759
762
|
elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height)
|
760
763
|
@output.write @upper_half_block
|
761
|
-
str += ''
|
762
764
|
elsif dialog.scrollbar_pos <= (i * 2 + 1) and (i * 2) < (dialog.scrollbar_pos + bar_height)
|
763
765
|
@output.write @lower_half_block
|
764
766
|
else
|
@@ -883,6 +885,14 @@ class Reline::LineEditor
|
|
883
885
|
end
|
884
886
|
end
|
885
887
|
|
888
|
+
private def clear_dialog_with_content
|
889
|
+
@dialogs.each do |dialog|
|
890
|
+
clear_each_dialog(dialog)
|
891
|
+
dialog.contents = nil
|
892
|
+
dialog.trap_key = nil
|
893
|
+
end
|
894
|
+
end
|
895
|
+
|
886
896
|
private def clear_each_dialog(dialog)
|
887
897
|
dialog.trap_key = nil
|
888
898
|
return unless dialog.contents
|
@@ -1420,7 +1430,7 @@ class Reline::LineEditor
|
|
1420
1430
|
if @waiting_operator_proc
|
1421
1431
|
if VI_MOTIONS.include?(method_symbol)
|
1422
1432
|
old_cursor, old_byte_pointer = @cursor, @byte_pointer
|
1423
|
-
@vi_arg = @waiting_operator_vi_arg if @waiting_operator_vi_arg
|
1433
|
+
@vi_arg = @waiting_operator_vi_arg if @waiting_operator_vi_arg&.> 1
|
1424
1434
|
block.(true)
|
1425
1435
|
unless @waiting_proc
|
1426
1436
|
cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer
|
@@ -2223,6 +2233,8 @@ class Reline::LineEditor
|
|
2223
2233
|
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
|
2224
2234
|
@line_index = @buffer_of_lines.size - 1
|
2225
2235
|
@line = @buffer_of_lines.last
|
2236
|
+
@byte_pointer = @line.bytesize
|
2237
|
+
@cursor = @cursor_max = calculate_width(@line)
|
2226
2238
|
@rerender_all = true
|
2227
2239
|
@searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
|
2228
2240
|
else
|
data/lib/reline/terminfo.rb
CHANGED
@@ -35,7 +35,7 @@ module Reline::Terminfo
|
|
35
35
|
# Gem module isn't defined in test-all of the Ruby repository, and
|
36
36
|
# Fiddle in Ruby 3.0.0 or later supports Fiddle::TYPE_VARIADIC.
|
37
37
|
fiddle_supports_variadic = true
|
38
|
-
elsif Fiddle.const_defined?(:VERSION) and Gem::Version.create(Fiddle::VERSION) >= Gem::Version.create('1.0.1')
|
38
|
+
elsif Fiddle.const_defined?(:VERSION,false) and Gem::Version.create(Fiddle::VERSION) >= Gem::Version.create('1.0.1')
|
39
39
|
# Fiddle::TYPE_VARIADIC is supported from Fiddle 1.0.1.
|
40
40
|
fiddle_supports_variadic = true
|
41
41
|
else
|
@@ -92,9 +92,9 @@ module Reline::Terminfo
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def self.setupterm(term, fildes)
|
95
|
-
errret_int =
|
95
|
+
errret_int = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT)
|
96
96
|
ret = @setupterm.(term, fildes, errret_int)
|
97
|
-
errret = errret_int.unpack1('i')
|
97
|
+
errret = errret_int[0, Fiddle::SIZEOF_INT].unpack1('i')
|
98
98
|
case ret
|
99
99
|
when 0 # OK
|
100
100
|
0
|
@@ -121,6 +121,7 @@ module Reline::Terminfo
|
|
121
121
|
end
|
122
122
|
|
123
123
|
def self.tigetstr(capname)
|
124
|
+
raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
|
124
125
|
capability = @tigetstr.(capname)
|
125
126
|
case capability.to_i
|
126
127
|
when 0, -1
|
@@ -138,6 +139,7 @@ module Reline::Terminfo
|
|
138
139
|
end
|
139
140
|
|
140
141
|
def self.tigetflag(capname)
|
142
|
+
raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
|
141
143
|
flag = @tigetflag.(capname).to_i
|
142
144
|
case flag
|
143
145
|
when -1
|
@@ -149,6 +151,7 @@ module Reline::Terminfo
|
|
149
151
|
end
|
150
152
|
|
151
153
|
def self.tigetnum(capname)
|
154
|
+
raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
|
152
155
|
num = @tigetnum.(capname).to_i
|
153
156
|
case num
|
154
157
|
when -2
|
data/lib/reline/version.rb
CHANGED
data/lib/reline/windows.rb
CHANGED
@@ -95,7 +95,7 @@ class Reline::Windows
|
|
95
95
|
end
|
96
96
|
|
97
97
|
VK_RETURN = 0x0D
|
98
|
-
VK_MENU = 0x12
|
98
|
+
VK_MENU = 0x12 # ALT key
|
99
99
|
VK_LMENU = 0xA4
|
100
100
|
VK_CONTROL = 0x11
|
101
101
|
VK_SHIFT = 0x10
|
@@ -249,7 +249,7 @@ class Reline::Windows
|
|
249
249
|
# no char, only control keys
|
250
250
|
return if key.char_code == 0 and key.control_keys.any?
|
251
251
|
|
252
|
-
@@output_buf.push("\e".ord) if key.control_keys.include?(:ALT)
|
252
|
+
@@output_buf.push("\e".ord) if key.control_keys.include?(:ALT) and !key.control_keys.include?(:CTRL)
|
253
253
|
|
254
254
|
@@output_buf.concat(key.char.bytes)
|
255
255
|
end
|
data/lib/reline.rb
CHANGED
@@ -33,7 +33,18 @@ module Reline
|
|
33
33
|
alias_method :==, :match?
|
34
34
|
end
|
35
35
|
CursorPos = Struct.new(:x, :y)
|
36
|
-
DialogRenderInfo = Struct.new(
|
36
|
+
DialogRenderInfo = Struct.new(
|
37
|
+
:pos,
|
38
|
+
:contents,
|
39
|
+
:bg_color,
|
40
|
+
:pointer_bg_color,
|
41
|
+
:fg_color,
|
42
|
+
:pointer_fg_color,
|
43
|
+
:width,
|
44
|
+
:height,
|
45
|
+
:scrollbar,
|
46
|
+
keyword_init: true
|
47
|
+
)
|
37
48
|
|
38
49
|
class Core
|
39
50
|
ATTR_READER_NAMES = %i(
|
@@ -58,6 +69,11 @@ module Reline
|
|
58
69
|
attr_accessor :last_incremental_search
|
59
70
|
attr_reader :output
|
60
71
|
|
72
|
+
extend Forwardable
|
73
|
+
def_delegators :config,
|
74
|
+
:autocompletion,
|
75
|
+
:autocompletion=
|
76
|
+
|
61
77
|
def initialize
|
62
78
|
self.output = STDOUT
|
63
79
|
@dialog_proc_list = {}
|
@@ -123,14 +139,6 @@ module Reline
|
|
123
139
|
@completion_proc = p
|
124
140
|
end
|
125
141
|
|
126
|
-
def autocompletion
|
127
|
-
@config.autocompletion
|
128
|
-
end
|
129
|
-
|
130
|
-
def autocompletion=(val)
|
131
|
-
@config.autocompletion = val
|
132
|
-
end
|
133
|
-
|
134
142
|
def output_modifier_proc=(p)
|
135
143
|
raise ArgumentError unless p.respond_to?(:call) or p.nil?
|
136
144
|
@output_modifier_proc = p
|
@@ -243,7 +251,16 @@ module Reline
|
|
243
251
|
context.push(cursor_pos_to_render, result, pointer, dialog)
|
244
252
|
end
|
245
253
|
dialog.pointer = pointer
|
246
|
-
DialogRenderInfo.new(
|
254
|
+
DialogRenderInfo.new(
|
255
|
+
pos: cursor_pos_to_render,
|
256
|
+
contents: result,
|
257
|
+
scrollbar: true,
|
258
|
+
height: 15,
|
259
|
+
bg_color: 46,
|
260
|
+
pointer_bg_color: 45,
|
261
|
+
fg_color: 37,
|
262
|
+
pointer_fg_color: 37
|
263
|
+
)
|
247
264
|
}
|
248
265
|
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
249
266
|
|
@@ -466,7 +483,7 @@ module Reline
|
|
466
483
|
end
|
467
484
|
|
468
485
|
private def may_req_ambiguous_char_width
|
469
|
-
@ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or STDOUT.
|
486
|
+
@ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or !STDOUT.tty?
|
470
487
|
return if defined? @ambiguous_width
|
471
488
|
Reline::IOGate.move_cursor_column(0)
|
472
489
|
begin
|
@@ -563,24 +580,21 @@ module Reline
|
|
563
580
|
end
|
564
581
|
|
565
582
|
require 'reline/general_io'
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
require 'reline/ansi'
|
573
|
-
Reline::ANSI
|
574
|
-
end
|
583
|
+
io = Reline::GeneralIO
|
584
|
+
unless ENV['TERM'] == 'dumb'
|
585
|
+
case RbConfig::CONFIG['host_os']
|
586
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
587
|
+
require 'reline/windows'
|
588
|
+
tty = (io = Reline::Windows).msys_tty?
|
575
589
|
else
|
576
|
-
|
590
|
+
tty = $stdout.tty?
|
577
591
|
end
|
592
|
+
end
|
593
|
+
Reline::IOGate = if tty
|
594
|
+
require 'reline/ansi'
|
595
|
+
Reline::ANSI
|
578
596
|
else
|
579
|
-
|
580
|
-
require 'reline/ansi'
|
581
|
-
Reline::ANSI
|
582
|
-
else
|
583
|
-
Reline::GeneralIO
|
584
|
-
end
|
597
|
+
io
|
585
598
|
end
|
599
|
+
|
586
600
|
Reline::HISTORY = Reline::History.new(Reline.core.config)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: io-console
|
@@ -47,7 +47,6 @@ files:
|
|
47
47
|
- lib/reline/key_stroke.rb
|
48
48
|
- lib/reline/kill_ring.rb
|
49
49
|
- lib/reline/line_editor.rb
|
50
|
-
- lib/reline/sibori.rb
|
51
50
|
- lib/reline/terminfo.rb
|
52
51
|
- lib/reline/unicode.rb
|
53
52
|
- lib/reline/unicode/east_asian_width.rb
|
@@ -66,14 +65,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
66
65
|
requirements:
|
67
66
|
- - ">="
|
68
67
|
- !ruby/object:Gem::Version
|
69
|
-
version: '2.
|
68
|
+
version: '2.6'
|
70
69
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
70
|
requirements:
|
72
71
|
- - ">="
|
73
72
|
- !ruby/object:Gem::Version
|
74
73
|
version: '0'
|
75
74
|
requirements: []
|
76
|
-
rubygems_version: 3.0.
|
75
|
+
rubygems_version: 3.4.0.dev
|
77
76
|
signing_key:
|
78
77
|
specification_version: 4
|
79
78
|
summary: Alternative GNU Readline or Editline implementation by pure Ruby.
|
data/lib/reline/sibori.rb
DELETED
@@ -1,170 +0,0 @@
|
|
1
|
-
require 'reline/unicode'
|
2
|
-
|
3
|
-
=begin
|
4
|
-
|
5
|
-
\ |
|
6
|
-
\ | <--- whipped cream
|
7
|
-
\ |
|
8
|
-
\ |
|
9
|
-
\-~~|
|
10
|
-
\ | <--- shibori kutigane (piping nozzle in Japanese)
|
11
|
-
\Ml
|
12
|
-
(\ __ __
|
13
|
-
( \--( ) )
|
14
|
-
(__(__)__) <--- compressed whipped cream
|
15
|
-
=end
|
16
|
-
|
17
|
-
class Sibori
|
18
|
-
attr_writer :output
|
19
|
-
|
20
|
-
def initialize(width, height, cursor_pos)
|
21
|
-
@width = width
|
22
|
-
@height = height
|
23
|
-
@cursor_pos = cursor_pos
|
24
|
-
@screen = [String.new]
|
25
|
-
@line_index = 0
|
26
|
-
@byte_pointer_in_line = 0
|
27
|
-
@cleared = false
|
28
|
-
clone_screen
|
29
|
-
end
|
30
|
-
|
31
|
-
def clone_screen
|
32
|
-
@prev_screen = @screen.map { |line|
|
33
|
-
line.dup
|
34
|
-
}
|
35
|
-
@prev_cursor_pos = @cursor_pos.dup
|
36
|
-
@prev_line_index = @line_index
|
37
|
-
end
|
38
|
-
|
39
|
-
def print(str)
|
40
|
-
#$stderr.puts "print #{str.inspect}"
|
41
|
-
line = @screen[@line_index]
|
42
|
-
before = line.byteslice(0, @byte_pointer_in_line)
|
43
|
-
str_width = Reline::Unicode.calculate_width(str, true)
|
44
|
-
after_cursor = line.byteslice(@byte_pointer_in_line..-1)
|
45
|
-
after_cursor_width = Reline::Unicode.calculate_width(after_cursor, true)
|
46
|
-
rest = ''
|
47
|
-
if after_cursor_width > str_width
|
48
|
-
rest_byte_pointer = @byte_pointer_in_line + width_to_bytesize(after_cursor, str_width)
|
49
|
-
rest = line.byteslice(rest_byte_pointer..-1)
|
50
|
-
end
|
51
|
-
@screen[@line_index] = before + str + rest
|
52
|
-
@byte_pointer_in_line += str.bytesize
|
53
|
-
@cursor_pos.x += Reline::Unicode.calculate_width(str, true)
|
54
|
-
end
|
55
|
-
|
56
|
-
def move_cursor_column(col)
|
57
|
-
#$stderr.puts "move_cursor_column(#{col})"
|
58
|
-
@byte_pointer_in_line = width_to_bytesize(@screen[@line_index], col)
|
59
|
-
@cursor_pos.x = col
|
60
|
-
end
|
61
|
-
|
62
|
-
def move_cursor_up(val)
|
63
|
-
#$stderr.puts "move_cursor_up(#{val})"
|
64
|
-
if @line_index.positive?
|
65
|
-
@line_index -= val
|
66
|
-
@byte_pointer_in_line = width_to_bytesize(@screen[@line_index], @cursor_pos.x)
|
67
|
-
@cursor_pos.y -= val
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def move_cursor_down(val)
|
72
|
-
#$stderr.puts "move_cursor_down(#{val})"
|
73
|
-
if @line_index < @height - 1
|
74
|
-
#$stderr.puts "@line_index #{@line_index} @screen.size #{@screen.size} @height #{@height}"
|
75
|
-
#$stderr.puts @screen.inspect
|
76
|
-
@line_index += val
|
77
|
-
@screen[@line_index] = String.new if @line_index == @screen.size
|
78
|
-
@byte_pointer_in_line = width_to_bytesize(@screen[@line_index], @cursor_pos.x)
|
79
|
-
@cursor_pos.y += val
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def scroll_down(val)
|
84
|
-
#$stderr.puts "scroll_down(#{val})"
|
85
|
-
if val >= @height
|
86
|
-
clear_screen
|
87
|
-
@line_index = @screen.size - 1
|
88
|
-
return
|
89
|
-
end
|
90
|
-
@screen.size.times do |n|
|
91
|
-
if n < @screen.size - val
|
92
|
-
#$stderr.puts "A @screen[#{val} + #{n}] (#{@screen[val + n].inspect}) to @screen[#{n}]"
|
93
|
-
@screen[n] = @screen[val + n]
|
94
|
-
else
|
95
|
-
#$stderr.puts "B String.new to @screen[#{n}]"
|
96
|
-
@screen[n] = String.new
|
97
|
-
end
|
98
|
-
end
|
99
|
-
@line_index += val
|
100
|
-
end
|
101
|
-
|
102
|
-
def erase_after_cursor
|
103
|
-
#$stderr.puts "erase_after_cursor"
|
104
|
-
@screen[@line_index] = @screen[@line_index].byteslice(0, @byte_pointer_in_line)
|
105
|
-
end
|
106
|
-
|
107
|
-
def clear_screen
|
108
|
-
#$stderr.puts "clear_screen"
|
109
|
-
@screen = [String.new]
|
110
|
-
@line_index = 0
|
111
|
-
@byte_pointer_in_line = 0
|
112
|
-
@cursor_pos.x = @cursor_pos.y = 0
|
113
|
-
@cleared = true
|
114
|
-
Reline::IOGate.clear_screen
|
115
|
-
end
|
116
|
-
|
117
|
-
private def width_to_bytesize(str, width)
|
118
|
-
lines, _ = Reline::Unicode.split_by_width(str, width)
|
119
|
-
lines.first.bytesize
|
120
|
-
end
|
121
|
-
|
122
|
-
def render
|
123
|
-
#$stderr.puts ?* * 100
|
124
|
-
Reline::IOGate.move_cursor_up(@prev_line_index) if @prev_line_index.positive?
|
125
|
-
#$stderr.puts "! move_cursor_up(#{@prev_line_index})" if @prev_line_index.positive?
|
126
|
-
#$stderr.puts "@prev_line_index #{@prev_line_index} @line_index #{@line_index}"
|
127
|
-
if @screen.size > @prev_screen.size
|
128
|
-
#$stderr.puts ?a * 100
|
129
|
-
down = @screen.size - @prev_screen.size
|
130
|
-
#$stderr.puts "#{@prev_cursor_pos.y} #{down} #{@height}"
|
131
|
-
if @prev_cursor_pos.y + down > (@height - 1)
|
132
|
-
#$stderr.puts ?b * 100
|
133
|
-
scroll = (@prev_cursor_pos.y + down) - (@height - 1)
|
134
|
-
Reline::IOGate.scroll_down(scroll)
|
135
|
-
#$stderr.puts "! scroll_down(#{scroll})"
|
136
|
-
#$stderr.puts "down #{down}"
|
137
|
-
Reline::IOGate.move_cursor_up(@screen.size - 1 - scroll)
|
138
|
-
#$stderr.puts "! move_cursor_up(#{@screen.size - 1})"
|
139
|
-
else
|
140
|
-
#$stderr.puts ?c * 100
|
141
|
-
end
|
142
|
-
end
|
143
|
-
@screen.size.times do |n|
|
144
|
-
Reline::IOGate.move_cursor_column(0)
|
145
|
-
#$stderr.puts "! move_cursor_column(0)"
|
146
|
-
@output.write @screen[n]
|
147
|
-
#$stderr.puts "! print #{@screen[n].inspect}"
|
148
|
-
Reline::IOGate.erase_after_cursor
|
149
|
-
#$stderr.puts "! erase_after_cursor"
|
150
|
-
Reline::IOGate.move_cursor_down(1) if n != (@screen.size - 1)
|
151
|
-
#$stderr.puts "! move_cursor_down(1)" if n != (@screen.size - 1)
|
152
|
-
end
|
153
|
-
up = @screen.size - 1 - @line_index
|
154
|
-
Reline::IOGate.move_cursor_up(up) if up.positive?
|
155
|
-
#$stderr.puts "! move_cursor_up(#{up})" if up.positive?
|
156
|
-
column = Reline::Unicode.calculate_width(@screen[@line_index].byteslice(0, @byte_pointer_in_line), true)
|
157
|
-
Reline::IOGate.move_cursor_column(column)
|
158
|
-
#$stderr.puts "! move_cursor_column(#{column}) #{@byte_pointer_in_line}"
|
159
|
-
clone_screen
|
160
|
-
#$stderr.puts ?- * 10
|
161
|
-
end
|
162
|
-
|
163
|
-
def prep
|
164
|
-
Reline::IOGate.prep
|
165
|
-
end
|
166
|
-
|
167
|
-
def deprep
|
168
|
-
Reline::IOGate.deprep
|
169
|
-
end
|
170
|
-
end
|