reline 0.2.6 → 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/reline.rb +3 -0
- data/lib/reline/ansi.rb +3 -8
- data/lib/reline/config.rb +10 -2
- data/lib/reline/line_editor.rb +11 -3
- data/lib/reline/terminfo.rb +52 -10
- data/lib/reline/version.rb +1 -1
- data/lib/reline/windows.rb +70 -38
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bb2255429504a1beb1a5a9f863f7cba5c4c65781b7cd8b2aa843b0df639fb26
|
4
|
+
data.tar.gz: c9372db87ad831e06d0e99d20981cb14a08e8b15ca3011f4b6df2a05aaeef7b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63e8b6f4a9de8a69a8f22c979b6fee92026143be658b9e928da43dddb868fb6b641b5f140de436c1dd5ed1f3cdbc3c42c7c41084fcc1d811cd713c684aedda8e
|
7
|
+
data.tar.gz: 7a459412f528f43d5e65f4c7c6a5c74055e2c5334f21a65411bc4f187b55b649c15fd612ed27f2dc0032f7fdc5973c7fa57b674b0a323ac2d9537b23fff19664
|
data/lib/reline.rb
CHANGED
@@ -7,12 +7,15 @@ require 'reline/key_actor'
|
|
7
7
|
require 'reline/key_stroke'
|
8
8
|
require 'reline/line_editor'
|
9
9
|
require 'reline/history'
|
10
|
+
require 'reline/terminfo'
|
10
11
|
require 'rbconfig'
|
11
12
|
|
12
13
|
module Reline
|
13
14
|
FILENAME_COMPLETION_PROC = nil
|
14
15
|
USERNAME_COMPLETION_PROC = nil
|
15
16
|
|
17
|
+
class ConfigEncodingConversionError < StandardError; end
|
18
|
+
|
16
19
|
Key = Struct.new('Key', :char, :combined_char, :with_meta)
|
17
20
|
CursorPos = Struct.new(:x, :y)
|
18
21
|
|
data/lib/reline/ansi.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'io/console'
|
2
|
+
require 'io/wait'
|
2
3
|
require 'timeout'
|
3
4
|
require_relative 'terminfo'
|
4
5
|
|
@@ -183,12 +184,7 @@ class Reline::ANSI
|
|
183
184
|
unless @@buf.empty?
|
184
185
|
return false
|
185
186
|
end
|
186
|
-
|
187
|
-
if rs and rs[0]
|
188
|
-
false
|
189
|
-
else
|
190
|
-
true
|
191
|
-
end
|
187
|
+
!@@input.wait_readable(0)
|
192
188
|
end
|
193
189
|
|
194
190
|
def self.ungetc(c)
|
@@ -197,8 +193,7 @@ class Reline::ANSI
|
|
197
193
|
|
198
194
|
def self.retrieve_keybuffer
|
199
195
|
begin
|
200
|
-
|
201
|
-
return if result.nil?
|
196
|
+
return unless @@input.wait_readable(0.001)
|
202
197
|
str = @@input.read_nonblock(1024)
|
203
198
|
str.bytes.each do |c|
|
204
199
|
@@buf.push(c)
|
data/lib/reline/config.rb
CHANGED
@@ -74,6 +74,7 @@ class Reline::Config
|
|
74
74
|
@additional_key_bindings.keys.each do |key|
|
75
75
|
@additional_key_bindings[key].clear
|
76
76
|
end
|
77
|
+
reset_default_key_bindings
|
77
78
|
end
|
78
79
|
|
79
80
|
def editing_mode
|
@@ -157,8 +158,15 @@ class Reline::Config
|
|
157
158
|
end
|
158
159
|
|
159
160
|
def read_lines(lines, file = nil)
|
160
|
-
if lines.first.encoding != Reline.encoding_system_needs
|
161
|
-
|
161
|
+
if not lines.empty? and lines.first.encoding != Reline.encoding_system_needs
|
162
|
+
begin
|
163
|
+
lines = lines.map do |l|
|
164
|
+
l.encode(Reline.encoding_system_needs)
|
165
|
+
rescue Encoding::UndefinedConversionError
|
166
|
+
mes = "The inputrc encoded in #{lines.first.encoding.name} can't be converted to the locale #{Reline.encoding_system_needs.name}."
|
167
|
+
raise Reline::ConfigEncodingConversionError.new(mes)
|
168
|
+
end
|
169
|
+
end
|
162
170
|
end
|
163
171
|
conditions = [@skip_section, @if_stack]
|
164
172
|
@skip_section = nil
|
data/lib/reline/line_editor.rb
CHANGED
@@ -150,7 +150,7 @@ class Reline::LineEditor
|
|
150
150
|
@screen_size = Reline::IOGate.get_screen_size
|
151
151
|
@screen_height = @screen_size.first
|
152
152
|
reset_variables(prompt, encoding: encoding)
|
153
|
-
@old_trap = Signal.trap(
|
153
|
+
@old_trap = Signal.trap(:INT) {
|
154
154
|
if @scroll_partial_screen
|
155
155
|
move_cursor_down(@screen_height - (@line_index - @scroll_partial_screen) - 1)
|
156
156
|
else
|
@@ -158,8 +158,16 @@ class Reline::LineEditor
|
|
158
158
|
end
|
159
159
|
Reline::IOGate.move_cursor_column(0)
|
160
160
|
scroll_down(1)
|
161
|
-
|
162
|
-
|
161
|
+
case @old_trap
|
162
|
+
when 'DEFAULT', 'SYSTEM_DEFAULT'
|
163
|
+
raise Interrupt
|
164
|
+
when 'IGNORE'
|
165
|
+
# Do nothing
|
166
|
+
when 'EXIT'
|
167
|
+
exit
|
168
|
+
else
|
169
|
+
@old_trap.call
|
170
|
+
end
|
163
171
|
}
|
164
172
|
Reline::IOGate.set_winch_handler do
|
165
173
|
@rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
|
data/lib/reline/terminfo.rb
CHANGED
@@ -6,12 +6,39 @@ module Reline::Terminfo
|
|
6
6
|
|
7
7
|
class TerminfoError < StandardError; end
|
8
8
|
|
9
|
-
|
9
|
+
def self.curses_dl_files
|
10
|
+
case RUBY_PLATFORM
|
11
|
+
when /mingw/, /mswin/
|
12
|
+
# aren't supported
|
13
|
+
[]
|
14
|
+
when /cygwin/
|
15
|
+
%w[cygncursesw-10.dll cygncurses-10.dll]
|
16
|
+
when /darwin/
|
17
|
+
%w[libncursesw.dylib libcursesw.dylib libncurses.dylib libcurses.dylib]
|
18
|
+
else
|
19
|
+
%w[libncursesw.so libcursesw.so libncurses.so libcurses.so]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
@curses_dl = false
|
10
24
|
def self.curses_dl
|
11
|
-
return @curses_dl
|
12
|
-
if
|
25
|
+
return @curses_dl unless @curses_dl == false
|
26
|
+
if RUBY_VERSION >= '3.0.0'
|
27
|
+
# Gem module isn't defined in test-all of the Ruby repository, and
|
28
|
+
# Fiddle in Ruby 3.0.0 or later supports Fiddle::TYPE_VARIADIC.
|
29
|
+
fiddle_supports_variadic = true
|
30
|
+
elsif Fiddle.const_defined?(:VERSION) and Gem::Version.create(Fiddle::VERSION) >= Gem::Version.create('1.0.1')
|
13
31
|
# Fiddle::TYPE_VARIADIC is supported from Fiddle 1.0.1.
|
14
|
-
|
32
|
+
fiddle_supports_variadic = true
|
33
|
+
else
|
34
|
+
fiddle_supports_variadic = false
|
35
|
+
end
|
36
|
+
if fiddle_supports_variadic and not Fiddle.const_defined?(:TYPE_VARIADIC)
|
37
|
+
# If the libffi version is not 3.0.5 or higher, there isn't TYPE_VARIADIC.
|
38
|
+
fiddle_supports_variadic = false
|
39
|
+
end
|
40
|
+
if fiddle_supports_variadic
|
41
|
+
curses_dl_files.each do |curses_name|
|
15
42
|
result = Fiddle::Handle.new(curses_name)
|
16
43
|
rescue Fiddle::DLError
|
17
44
|
next
|
@@ -20,6 +47,7 @@ module Reline::Terminfo
|
|
20
47
|
break
|
21
48
|
end
|
22
49
|
end
|
50
|
+
@curses_dl = nil if @curses_dl == false
|
23
51
|
@curses_dl
|
24
52
|
end
|
25
53
|
end
|
@@ -30,8 +58,15 @@ module Reline::Terminfo
|
|
30
58
|
@setupterm = Fiddle::Function.new(curses_dl['setupterm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
31
59
|
#extern 'char *tigetstr(char *capname)'
|
32
60
|
@tigetstr = Fiddle::Function.new(curses_dl['tigetstr'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP)
|
33
|
-
|
34
|
-
|
61
|
+
begin
|
62
|
+
#extern 'char *tiparm(const char *str, ...)'
|
63
|
+
@tiparm = Fiddle::Function.new(curses_dl['tiparm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VARIADIC], Fiddle::TYPE_VOIDP)
|
64
|
+
rescue Fiddle::DLError
|
65
|
+
# OpenBSD lacks tiparm
|
66
|
+
#extern 'char *tparm(const char *str, ...)'
|
67
|
+
@tiparm = Fiddle::Function.new(curses_dl['tparm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VARIADIC], Fiddle::TYPE_VOIDP)
|
68
|
+
end
|
69
|
+
# TODO: add int tigetflag(char *capname) and int tigetnum(char *capname)
|
35
70
|
|
36
71
|
def self.setupterm(term, fildes)
|
37
72
|
errret_int = String.new("\x00" * 8, encoding: 'ASCII-8BIT')
|
@@ -56,12 +91,19 @@ module Reline::Terminfo
|
|
56
91
|
end
|
57
92
|
end
|
58
93
|
|
59
|
-
|
60
|
-
|
61
|
-
def result.tiparm(*args) # for method chain
|
94
|
+
class StringWithTiparm < String
|
95
|
+
def tiparm(*args) # for method chain
|
62
96
|
Reline::Terminfo.tiparm(self, *args)
|
63
97
|
end
|
64
|
-
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.tigetstr(capname)
|
101
|
+
capability = @tigetstr.(capname)
|
102
|
+
case capability.to_i
|
103
|
+
when 0, -1
|
104
|
+
raise TerminfoError, "can't find capability: #{capname}"
|
105
|
+
end
|
106
|
+
StringWithTiparm.new(capability.to_s)
|
65
107
|
end
|
66
108
|
|
67
109
|
def self.tiparm(str, *args)
|
data/lib/reline/version.rb
CHANGED
data/lib/reline/windows.rb
CHANGED
@@ -91,6 +91,7 @@ class Reline::Windows
|
|
91
91
|
VK_LMENU = 0xA4
|
92
92
|
VK_CONTROL = 0x11
|
93
93
|
VK_SHIFT = 0x10
|
94
|
+
VK_DIVIDE = 0x6F
|
94
95
|
|
95
96
|
KEY_EVENT = 0x01
|
96
97
|
WINDOW_BUFFER_SIZE_EVENT = 0x04
|
@@ -180,46 +181,38 @@ class Reline::Windows
|
|
180
181
|
name =~ /(msys-|cygwin-).*-pty/ ? true : false
|
181
182
|
end
|
182
183
|
|
184
|
+
KEY_MAP = [
|
185
|
+
# It's treated as Meta+Enter on Windows.
|
186
|
+
[ { control_keys: :CTRL, virtual_key_code: 0x0D }, "\e\r".bytes ],
|
187
|
+
[ { control_keys: :SHIFT, virtual_key_code: 0x0D }, "\e\r".bytes ],
|
188
|
+
|
189
|
+
# It's treated as Meta+Space on Windows.
|
190
|
+
[ { control_keys: :CTRL, char_code: 0x20 }, "\e ".bytes ],
|
191
|
+
|
192
|
+
# Emulate getwch() key sequences.
|
193
|
+
[ { control_keys: [], virtual_key_code: VK_UP }, [0, 72] ],
|
194
|
+
[ { control_keys: [], virtual_key_code: VK_DOWN }, [0, 80] ],
|
195
|
+
[ { control_keys: [], virtual_key_code: VK_RIGHT }, [0, 77] ],
|
196
|
+
[ { control_keys: [], virtual_key_code: VK_LEFT }, [0, 75] ],
|
197
|
+
[ { control_keys: [], virtual_key_code: VK_DELETE }, [0, 83] ],
|
198
|
+
[ { control_keys: [], virtual_key_code: VK_HOME }, [0, 71] ],
|
199
|
+
[ { control_keys: [], virtual_key_code: VK_END }, [0, 79] ],
|
200
|
+
]
|
201
|
+
|
183
202
|
def self.process_key_event(repeat_count, virtual_key_code, virtual_scan_code, char_code, control_key_state)
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
@@output_buf.push("\e".ord)
|
192
|
-
@@output_buf.push(char_code)
|
193
|
-
elsif control_key_state.anybits?(LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)
|
194
|
-
@@output_buf.push("\e".ord)
|
195
|
-
@@output_buf.concat(char.bytes)
|
196
|
-
elsif control_key_state.anybits?(ENHANCED_KEY)
|
197
|
-
case virtual_key_code # Emulate getwch() key sequences.
|
198
|
-
when VK_END
|
199
|
-
@@output_buf.push(0, 79)
|
200
|
-
when VK_HOME
|
201
|
-
@@output_buf.push(0, 71)
|
202
|
-
when VK_LEFT
|
203
|
-
@@output_buf.push(0, 75)
|
204
|
-
when VK_UP
|
205
|
-
@@output_buf.push(0, 72)
|
206
|
-
when VK_RIGHT
|
207
|
-
@@output_buf.push(0, 77)
|
208
|
-
when VK_DOWN
|
209
|
-
@@output_buf.push(0, 80)
|
210
|
-
when VK_DELETE
|
211
|
-
@@output_buf.push(0, 83)
|
212
|
-
end
|
213
|
-
elsif char_code == 0 and control_key_state != 0
|
214
|
-
# unknown
|
215
|
-
else
|
216
|
-
case virtual_key_code
|
217
|
-
when VK_RETURN
|
218
|
-
@@output_buf.push("\n".ord)
|
219
|
-
else
|
220
|
-
@@output_buf.concat(char.bytes)
|
221
|
-
end
|
203
|
+
|
204
|
+
key = KeyEventRecord.new(virtual_key_code, char_code, control_key_state)
|
205
|
+
|
206
|
+
match = KEY_MAP.find { |args,| key.matches?(**args) }
|
207
|
+
unless match.nil?
|
208
|
+
@@output_buf.concat(match.last)
|
209
|
+
return
|
222
210
|
end
|
211
|
+
|
212
|
+
# no char, only control keys
|
213
|
+
return if key.char_code == 0 and key.control_keys.any?
|
214
|
+
|
215
|
+
@@output_buf.concat(key.char.bytes)
|
223
216
|
end
|
224
217
|
|
225
218
|
def self.check_input_event
|
@@ -360,4 +353,43 @@ class Reline::Windows
|
|
360
353
|
def self.deprep(otio)
|
361
354
|
# do nothing
|
362
355
|
end
|
356
|
+
|
357
|
+
class KeyEventRecord
|
358
|
+
|
359
|
+
attr_reader :virtual_key_code, :char_code, :control_key_state, :control_keys
|
360
|
+
|
361
|
+
def initialize(virtual_key_code, char_code, control_key_state)
|
362
|
+
@virtual_key_code = virtual_key_code
|
363
|
+
@char_code = char_code
|
364
|
+
@control_key_state = control_key_state
|
365
|
+
@enhanced = control_key_state & ENHANCED_KEY != 0
|
366
|
+
|
367
|
+
(@control_keys = []).tap do |control_keys|
|
368
|
+
# symbols must be sorted to make comparison is easier later on
|
369
|
+
control_keys << :ALT if control_key_state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) != 0
|
370
|
+
control_keys << :CTRL if control_key_state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) != 0
|
371
|
+
control_keys << :SHIFT if control_key_state & SHIFT_PRESSED != 0
|
372
|
+
end.freeze
|
373
|
+
end
|
374
|
+
|
375
|
+
def char
|
376
|
+
@char_code.chr(Encoding::UTF_8)
|
377
|
+
end
|
378
|
+
|
379
|
+
def enhanced?
|
380
|
+
@enhanced
|
381
|
+
end
|
382
|
+
|
383
|
+
# Verifies if the arguments match with this key event.
|
384
|
+
# Nil arguments are ignored, but at least one must be passed as non-nil.
|
385
|
+
# To verify that no control keys were pressed, pass an empty array: `control_keys: []`.
|
386
|
+
def matches?(control_keys: nil, virtual_key_code: nil, char_code: nil)
|
387
|
+
raise ArgumentError, 'No argument was passed to match key event' if control_keys.nil? && virtual_key_code.nil? && char_code.nil?
|
388
|
+
|
389
|
+
(control_keys.nil? || [*control_keys].sort == @control_keys) &&
|
390
|
+
(virtual_key_code.nil? || @virtual_key_code == virtual_key_code) &&
|
391
|
+
(char_code.nil? || char_code == @char_code)
|
392
|
+
end
|
393
|
+
|
394
|
+
end
|
363
395
|
end
|
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.2.
|
4
|
+
version: 0.2.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: io-console
|
@@ -73,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '0'
|
75
75
|
requirements: []
|
76
|
-
rubygems_version: 3.2.
|
76
|
+
rubygems_version: 3.2.22
|
77
77
|
signing_key:
|
78
78
|
specification_version: 4
|
79
79
|
summary: Alternative GNU Readline or Editline implementation by pure Ruby.
|