reline 0.5.10 → 0.6.1
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/reline/config.rb +22 -26
- data/lib/reline/history.rb +3 -3
- data/lib/reline/io/ansi.rb +70 -124
- data/lib/reline/io/dumb.rb +16 -2
- data/lib/reline/io/windows.rb +77 -60
- data/lib/reline/io.rb +14 -0
- data/lib/reline/key_actor/base.rb +10 -4
- data/lib/reline/key_actor/emacs.rb +96 -96
- data/lib/reline/key_actor/vi_command.rb +182 -182
- data/lib/reline/key_actor/vi_insert.rb +137 -137
- data/lib/reline/key_stroke.rb +26 -16
- data/lib/reline/line_editor.rb +295 -489
- data/lib/reline/unicode/east_asian_width.rb +41 -15
- data/lib/reline/unicode.rb +141 -397
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +40 -31
- metadata +3 -4
- data/lib/reline/terminfo.rb +0 -158
data/lib/reline.rb
CHANGED
@@ -6,25 +6,26 @@ require 'reline/key_actor'
|
|
6
6
|
require 'reline/key_stroke'
|
7
7
|
require 'reline/line_editor'
|
8
8
|
require 'reline/history'
|
9
|
-
require 'reline/terminfo'
|
10
9
|
require 'reline/io'
|
11
10
|
require 'reline/face'
|
12
11
|
require 'rbconfig'
|
13
12
|
|
14
13
|
module Reline
|
15
14
|
# NOTE: For making compatible with the rb-readline gem
|
16
|
-
FILENAME_COMPLETION_PROC = nil
|
17
|
-
USERNAME_COMPLETION_PROC = nil
|
15
|
+
FILENAME_COMPLETION_PROC = nil # :nodoc:
|
16
|
+
USERNAME_COMPLETION_PROC = nil # :nodoc:
|
18
17
|
|
19
|
-
class ConfigEncodingConversionError < StandardError; end
|
18
|
+
class ConfigEncodingConversionError < StandardError; end # :nodoc:
|
20
19
|
|
21
|
-
|
20
|
+
# EOF key: { char: nil, method_symbol: nil }
|
21
|
+
# Other key: { char: String, method_symbol: Symbol }
|
22
|
+
Key = Struct.new(:char, :method_symbol, :unused_boolean) do
|
22
23
|
# For dialog_proc `key.match?(dialog.name)`
|
23
24
|
def match?(sym)
|
24
|
-
|
25
|
+
method_symbol && method_symbol == sym
|
25
26
|
end
|
26
|
-
end
|
27
|
-
CursorPos = Struct.new(:x, :y)
|
27
|
+
end # :nodoc:
|
28
|
+
CursorPos = Struct.new(:x, :y) # :nodoc:
|
28
29
|
DialogRenderInfo = Struct.new(
|
29
30
|
:pos,
|
30
31
|
:contents,
|
@@ -34,7 +35,7 @@ module Reline
|
|
34
35
|
:height,
|
35
36
|
:scrollbar,
|
36
37
|
keyword_init: true
|
37
|
-
)
|
38
|
+
) # :nodoc:
|
38
39
|
|
39
40
|
class Core
|
40
41
|
ATTR_READER_NAMES = %i(
|
@@ -182,9 +183,7 @@ module Reline
|
|
182
183
|
def output=(val)
|
183
184
|
raise TypeError unless val.respond_to?(:write) or val.nil?
|
184
185
|
@output = val
|
185
|
-
|
186
|
-
io_gate.output = val
|
187
|
-
end
|
186
|
+
io_gate.output = val
|
188
187
|
end
|
189
188
|
|
190
189
|
def vi_editing_mode
|
@@ -245,8 +244,8 @@ module Reline
|
|
245
244
|
height: [15, preferred_dialog_height].min,
|
246
245
|
face: :completion_dialog
|
247
246
|
)
|
248
|
-
}
|
249
|
-
Reline::DEFAULT_DIALOG_CONTEXT = Array.new
|
247
|
+
} # :nodoc:
|
248
|
+
Reline::DEFAULT_DIALOG_CONTEXT = Array.new # :nodoc:
|
250
249
|
|
251
250
|
def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
|
252
251
|
@mutex.synchronize do
|
@@ -308,7 +307,8 @@ module Reline
|
|
308
307
|
otio = io_gate.prep
|
309
308
|
|
310
309
|
may_req_ambiguous_char_width
|
311
|
-
|
310
|
+
key_stroke.encoding = encoding
|
311
|
+
line_editor.reset(prompt)
|
312
312
|
if multiline
|
313
313
|
line_editor.multiline_on
|
314
314
|
if block_given?
|
@@ -317,7 +317,6 @@ module Reline
|
|
317
317
|
else
|
318
318
|
line_editor.multiline_off
|
319
319
|
end
|
320
|
-
line_editor.output = output
|
321
320
|
line_editor.completion_proc = completion_proc
|
322
321
|
line_editor.completion_append_character = completion_append_character
|
323
322
|
line_editor.output_modifier_proc = output_modifier_proc
|
@@ -342,22 +341,22 @@ module Reline
|
|
342
341
|
line_editor.set_signal_handlers
|
343
342
|
loop do
|
344
343
|
read_io(config.keyseq_timeout) { |inputs|
|
345
|
-
line_editor.set_pasting_state(io_gate.in_pasting?)
|
346
344
|
inputs.each do |key|
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
345
|
+
case key.method_symbol
|
346
|
+
when :bracketed_paste_start
|
347
|
+
# io_gate is Reline::ANSI because the key :bracketed_paste_start is only assigned in Reline::ANSI
|
348
|
+
key = Reline::Key.new(io_gate.read_bracketed_paste, :insert_multiline_text)
|
349
|
+
when :quoted_insert, :ed_quoted_insert
|
350
|
+
key = Reline::Key.new(io_gate.read_single_char(config.keyseq_timeout), :insert_raw_char)
|
353
351
|
end
|
352
|
+
line_editor.set_pasting_state(io_gate.in_pasting?)
|
353
|
+
line_editor.update(key)
|
354
354
|
end
|
355
355
|
}
|
356
356
|
if line_editor.finished?
|
357
357
|
line_editor.render_finished
|
358
358
|
break
|
359
359
|
else
|
360
|
-
line_editor.set_pasting_state(io_gate.in_pasting?)
|
361
360
|
line_editor.rerender
|
362
361
|
end
|
363
362
|
end
|
@@ -412,7 +411,7 @@ module Reline
|
|
412
411
|
end
|
413
412
|
|
414
413
|
private def may_req_ambiguous_char_width
|
415
|
-
@ambiguous_width =
|
414
|
+
@ambiguous_width = 1 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
|
416
415
|
return if defined? @ambiguous_width
|
417
416
|
io_gate.move_cursor_column(0)
|
418
417
|
begin
|
@@ -421,7 +420,7 @@ module Reline
|
|
421
420
|
# LANG=C
|
422
421
|
@ambiguous_width = 1
|
423
422
|
else
|
424
|
-
@ambiguous_width = io_gate.cursor_pos.x
|
423
|
+
@ambiguous_width = io_gate.cursor_pos.x == 2 ? 2 : 1
|
425
424
|
end
|
426
425
|
io_gate.move_cursor_column(0)
|
427
426
|
io_gate.erase_after_cursor
|
@@ -440,6 +439,17 @@ module Reline
|
|
440
439
|
}
|
441
440
|
def_single_delegators :core, :input=, :output=
|
442
441
|
def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
|
442
|
+
|
443
|
+
##
|
444
|
+
# :singleton-method: readmultiline
|
445
|
+
# :call-seq:
|
446
|
+
# readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination) -> string or nil
|
447
|
+
def_single_delegators :core, :readmultiline
|
448
|
+
|
449
|
+
##
|
450
|
+
# :singleton-method: readline
|
451
|
+
# :call-seq:
|
452
|
+
# readline(prompt = '', add_hist = false) -> string or nil
|
443
453
|
def_single_delegators :core, :readline
|
444
454
|
def_single_delegators :core, :completion_case_fold, :completion_case_fold=
|
445
455
|
def_single_delegators :core, :completion_quote_character
|
@@ -475,19 +485,18 @@ module Reline
|
|
475
485
|
def_single_delegators :core, :dialog_proc
|
476
486
|
def_single_delegators :core, :autocompletion, :autocompletion=
|
477
487
|
|
478
|
-
def_single_delegators :core, :readmultiline
|
479
488
|
def_instance_delegators self, :readmultiline
|
480
489
|
private :readmultiline
|
481
490
|
|
482
|
-
def self.encoding_system_needs
|
491
|
+
def self.encoding_system_needs # :nodoc:
|
483
492
|
self.core.encoding
|
484
493
|
end
|
485
494
|
|
486
495
|
def self.core
|
487
496
|
@core ||= Core.new { |core|
|
488
497
|
core.config = Reline::Config.new
|
489
|
-
core.key_stroke = Reline::KeyStroke.new(core.config)
|
490
|
-
core.line_editor = Reline::LineEditor.new(core.config
|
498
|
+
core.key_stroke = Reline::KeyStroke.new(core.config, core.encoding)
|
499
|
+
core.line_editor = Reline::LineEditor.new(core.config)
|
491
500
|
|
492
501
|
core.basic_word_break_characters = " \t\n`><=;|&{("
|
493
502
|
core.completer_word_break_characters = " \t\n`><=;|&{("
|
@@ -512,7 +521,7 @@ end
|
|
512
521
|
Reline::IOGate = Reline::IO.decide_io_gate
|
513
522
|
|
514
523
|
# Deprecated
|
515
|
-
Reline::GeneralIO = Reline::Dumb.new
|
524
|
+
Reline::GeneralIO = Reline::Dumb.new # :nodoc:
|
516
525
|
|
517
526
|
Reline::Face.load_initial_configs
|
518
527
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aycabta
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 2025-04-04 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: io-console
|
@@ -50,7 +50,6 @@ files:
|
|
50
50
|
- lib/reline/key_stroke.rb
|
51
51
|
- lib/reline/kill_ring.rb
|
52
52
|
- lib/reline/line_editor.rb
|
53
|
-
- lib/reline/terminfo.rb
|
54
53
|
- lib/reline/unicode.rb
|
55
54
|
- lib/reline/unicode/east_asian_width.rb
|
56
55
|
- lib/reline/version.rb
|
@@ -76,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
75
|
- !ruby/object:Gem::Version
|
77
76
|
version: '0'
|
78
77
|
requirements: []
|
79
|
-
rubygems_version: 3.6.
|
78
|
+
rubygems_version: 3.6.3
|
80
79
|
specification_version: 4
|
81
80
|
summary: Alternative GNU Readline or Editline implementation by pure Ruby.
|
82
81
|
test_files: []
|
data/lib/reline/terminfo.rb
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
# Ignore warning `Add fiddle to your Gemfile or gemspec` in Ruby 3.4.
|
3
|
-
# terminfo.rb and ansi.rb supports fiddle unavailable environment.
|
4
|
-
verbose, $VERBOSE = $VERBOSE, nil
|
5
|
-
require 'fiddle'
|
6
|
-
require 'fiddle/import'
|
7
|
-
rescue LoadError
|
8
|
-
module Reline::Terminfo
|
9
|
-
def self.curses_dl
|
10
|
-
false
|
11
|
-
end
|
12
|
-
end
|
13
|
-
ensure
|
14
|
-
$VERBOSE = verbose
|
15
|
-
end
|
16
|
-
|
17
|
-
module Reline::Terminfo
|
18
|
-
extend Fiddle::Importer
|
19
|
-
|
20
|
-
class TerminfoError < StandardError; end
|
21
|
-
|
22
|
-
def self.curses_dl_files
|
23
|
-
case RUBY_PLATFORM
|
24
|
-
when /mingw/, /mswin/
|
25
|
-
# aren't supported
|
26
|
-
[]
|
27
|
-
when /cygwin/
|
28
|
-
%w[cygncursesw-10.dll cygncurses-10.dll]
|
29
|
-
when /darwin/
|
30
|
-
%w[libncursesw.dylib libcursesw.dylib libncurses.dylib libcurses.dylib]
|
31
|
-
else
|
32
|
-
%w[libncursesw.so libcursesw.so libncurses.so libcurses.so]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
@curses_dl = false
|
37
|
-
def self.curses_dl
|
38
|
-
return @curses_dl unless @curses_dl == false
|
39
|
-
if Fiddle.const_defined?(:TYPE_VARIADIC)
|
40
|
-
curses_dl_files.each do |curses_name|
|
41
|
-
result = Fiddle::Handle.new(curses_name)
|
42
|
-
rescue Fiddle::DLError
|
43
|
-
next
|
44
|
-
else
|
45
|
-
@curses_dl = result
|
46
|
-
break
|
47
|
-
end
|
48
|
-
end
|
49
|
-
@curses_dl = nil if @curses_dl == false
|
50
|
-
@curses_dl
|
51
|
-
end
|
52
|
-
end if not Reline.const_defined?(:Terminfo) or not Reline::Terminfo.respond_to?(:curses_dl)
|
53
|
-
|
54
|
-
module Reline::Terminfo
|
55
|
-
dlload curses_dl
|
56
|
-
#extern 'int setupterm(char *term, int fildes, int *errret)'
|
57
|
-
@setupterm = Fiddle::Function.new(curses_dl['setupterm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
58
|
-
#extern 'char *tigetstr(char *capname)'
|
59
|
-
@tigetstr = Fiddle::Function.new(curses_dl['tigetstr'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP)
|
60
|
-
begin
|
61
|
-
#extern 'char *tiparm(const char *str, ...)'
|
62
|
-
@tiparm = Fiddle::Function.new(curses_dl['tiparm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VARIADIC], Fiddle::TYPE_VOIDP)
|
63
|
-
rescue Fiddle::DLError
|
64
|
-
# OpenBSD lacks tiparm
|
65
|
-
#extern 'char *tparm(const char *str, ...)'
|
66
|
-
@tiparm = Fiddle::Function.new(curses_dl['tparm'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VARIADIC], Fiddle::TYPE_VOIDP)
|
67
|
-
end
|
68
|
-
begin
|
69
|
-
#extern 'int tigetflag(char *str)'
|
70
|
-
@tigetflag = Fiddle::Function.new(curses_dl['tigetflag'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
71
|
-
rescue Fiddle::DLError
|
72
|
-
# OpenBSD lacks tigetflag
|
73
|
-
#extern 'int tgetflag(char *str)'
|
74
|
-
@tigetflag = Fiddle::Function.new(curses_dl['tgetflag'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
75
|
-
end
|
76
|
-
begin
|
77
|
-
#extern 'int tigetnum(char *str)'
|
78
|
-
@tigetnum = Fiddle::Function.new(curses_dl['tigetnum'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
79
|
-
rescue Fiddle::DLError
|
80
|
-
# OpenBSD lacks tigetnum
|
81
|
-
#extern 'int tgetnum(char *str)'
|
82
|
-
@tigetnum = Fiddle::Function.new(curses_dl['tgetnum'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
|
83
|
-
end
|
84
|
-
|
85
|
-
def self.setupterm(term, fildes)
|
86
|
-
errret_int = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT, Fiddle::RUBY_FREE)
|
87
|
-
ret = @setupterm.(term, fildes, errret_int)
|
88
|
-
case ret
|
89
|
-
when 0 # OK
|
90
|
-
@term_supported = true
|
91
|
-
when -1 # ERR
|
92
|
-
@term_supported = false
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
class StringWithTiparm < String
|
97
|
-
def tiparm(*args) # for method chain
|
98
|
-
Reline::Terminfo.tiparm(self, *args)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.tigetstr(capname)
|
103
|
-
raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
|
104
|
-
capability = @tigetstr.(capname)
|
105
|
-
case capability.to_i
|
106
|
-
when 0, -1
|
107
|
-
raise TerminfoError, "can't find capability: #{capname}"
|
108
|
-
end
|
109
|
-
StringWithTiparm.new(capability.to_s)
|
110
|
-
end
|
111
|
-
|
112
|
-
def self.tiparm(str, *args)
|
113
|
-
new_args = []
|
114
|
-
args.each do |a|
|
115
|
-
new_args << Fiddle::TYPE_INT << a
|
116
|
-
end
|
117
|
-
@tiparm.(str, *new_args).to_s
|
118
|
-
end
|
119
|
-
|
120
|
-
def self.tigetflag(capname)
|
121
|
-
raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
|
122
|
-
flag = @tigetflag.(capname).to_i
|
123
|
-
case flag
|
124
|
-
when -1
|
125
|
-
raise TerminfoError, "not boolean capability: #{capname}"
|
126
|
-
when 0
|
127
|
-
raise TerminfoError, "can't find capability: #{capname}"
|
128
|
-
end
|
129
|
-
flag
|
130
|
-
end
|
131
|
-
|
132
|
-
def self.tigetnum(capname)
|
133
|
-
raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
|
134
|
-
num = @tigetnum.(capname).to_i
|
135
|
-
case num
|
136
|
-
when -2
|
137
|
-
raise TerminfoError, "not numeric capability: #{capname}"
|
138
|
-
when -1
|
139
|
-
raise TerminfoError, "can't find capability: #{capname}"
|
140
|
-
end
|
141
|
-
num
|
142
|
-
end
|
143
|
-
|
144
|
-
# NOTE: This means Fiddle and curses are enabled.
|
145
|
-
def self.enabled?
|
146
|
-
true
|
147
|
-
end
|
148
|
-
|
149
|
-
def self.term_supported?
|
150
|
-
@term_supported
|
151
|
-
end
|
152
|
-
end if Reline::Terminfo.curses_dl
|
153
|
-
|
154
|
-
module Reline::Terminfo
|
155
|
-
def self.enabled?
|
156
|
-
false
|
157
|
-
end
|
158
|
-
end unless Reline::Terminfo.curses_dl
|