reline 0.5.9 → 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 +41 -50
- data/lib/reline/face.rb +1 -1
- data/lib/reline/history.rb +3 -3
- data/lib/reline/io/ansi.rb +77 -123
- data/lib/reline/io/dumb.rb +16 -2
- data/lib/reline/io/windows.rb +94 -67
- 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 +331 -534
- data/lib/reline/unicode/east_asian_width.rb +1289 -1192
- data/lib/reline/unicode.rb +155 -436
- data/lib/reline/version.rb +1 -1
- data/lib/reline.rb +46 -34
- metadata +3 -7
- data/lib/reline/terminfo.rb +0 -158
data/lib/reline/version.rb
CHANGED
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,21 +317,23 @@ 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
|
324
323
|
line_editor.prompt_proc = prompt_proc
|
325
324
|
line_editor.auto_indent_proc = auto_indent_proc
|
326
325
|
line_editor.dig_perfect_match_proc = dig_perfect_match_proc
|
326
|
+
|
327
|
+
# Readline calls pre_input_hook just after printing the first prompt.
|
328
|
+
line_editor.print_nomultiline_prompt
|
327
329
|
pre_input_hook&.call
|
330
|
+
|
328
331
|
unless Reline::IOGate.dumb?
|
329
332
|
@dialog_proc_list.each_pair do |name_sym, d|
|
330
333
|
line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
|
331
334
|
end
|
332
335
|
end
|
333
336
|
|
334
|
-
line_editor.print_nomultiline_prompt(prompt)
|
335
337
|
line_editor.update_dialogs
|
336
338
|
line_editor.rerender
|
337
339
|
|
@@ -339,22 +341,22 @@ module Reline
|
|
339
341
|
line_editor.set_signal_handlers
|
340
342
|
loop do
|
341
343
|
read_io(config.keyseq_timeout) { |inputs|
|
342
|
-
line_editor.set_pasting_state(io_gate.in_pasting?)
|
343
344
|
inputs.each do |key|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
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)
|
350
351
|
end
|
352
|
+
line_editor.set_pasting_state(io_gate.in_pasting?)
|
353
|
+
line_editor.update(key)
|
351
354
|
end
|
352
355
|
}
|
353
356
|
if line_editor.finished?
|
354
357
|
line_editor.render_finished
|
355
358
|
break
|
356
359
|
else
|
357
|
-
line_editor.set_pasting_state(io_gate.in_pasting?)
|
358
360
|
line_editor.rerender
|
359
361
|
end
|
360
362
|
end
|
@@ -409,7 +411,7 @@ module Reline
|
|
409
411
|
end
|
410
412
|
|
411
413
|
private def may_req_ambiguous_char_width
|
412
|
-
@ambiguous_width =
|
414
|
+
@ambiguous_width = 1 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
|
413
415
|
return if defined? @ambiguous_width
|
414
416
|
io_gate.move_cursor_column(0)
|
415
417
|
begin
|
@@ -418,7 +420,7 @@ module Reline
|
|
418
420
|
# LANG=C
|
419
421
|
@ambiguous_width = 1
|
420
422
|
else
|
421
|
-
@ambiguous_width = io_gate.cursor_pos.x
|
423
|
+
@ambiguous_width = io_gate.cursor_pos.x == 2 ? 2 : 1
|
422
424
|
end
|
423
425
|
io_gate.move_cursor_column(0)
|
424
426
|
io_gate.erase_after_cursor
|
@@ -437,6 +439,17 @@ module Reline
|
|
437
439
|
}
|
438
440
|
def_single_delegators :core, :input=, :output=
|
439
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
|
440
453
|
def_single_delegators :core, :readline
|
441
454
|
def_single_delegators :core, :completion_case_fold, :completion_case_fold=
|
442
455
|
def_single_delegators :core, :completion_quote_character
|
@@ -457,8 +470,8 @@ module Reline
|
|
457
470
|
def_single_delegator :line_editor, :byte_pointer, :point
|
458
471
|
def_single_delegator :line_editor, :byte_pointer=, :point=
|
459
472
|
|
460
|
-
def self.insert_text(
|
461
|
-
line_editor.
|
473
|
+
def self.insert_text(text)
|
474
|
+
line_editor.insert_multiline_text(text)
|
462
475
|
self
|
463
476
|
end
|
464
477
|
|
@@ -472,19 +485,18 @@ module Reline
|
|
472
485
|
def_single_delegators :core, :dialog_proc
|
473
486
|
def_single_delegators :core, :autocompletion, :autocompletion=
|
474
487
|
|
475
|
-
def_single_delegators :core, :readmultiline
|
476
488
|
def_instance_delegators self, :readmultiline
|
477
489
|
private :readmultiline
|
478
490
|
|
479
|
-
def self.encoding_system_needs
|
491
|
+
def self.encoding_system_needs # :nodoc:
|
480
492
|
self.core.encoding
|
481
493
|
end
|
482
494
|
|
483
495
|
def self.core
|
484
496
|
@core ||= Core.new { |core|
|
485
497
|
core.config = Reline::Config.new
|
486
|
-
core.key_stroke = Reline::KeyStroke.new(core.config)
|
487
|
-
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)
|
488
500
|
|
489
501
|
core.basic_word_break_characters = " \t\n`><=;|&{("
|
490
502
|
core.completer_word_break_characters = " \t\n`><=;|&{("
|
@@ -509,7 +521,7 @@ end
|
|
509
521
|
Reline::IOGate = Reline::IO.decide_io_gate
|
510
522
|
|
511
523
|
# Deprecated
|
512
|
-
Reline::GeneralIO = Reline::Dumb.new
|
524
|
+
Reline::GeneralIO = Reline::Dumb.new # :nodoc:
|
513
525
|
|
514
526
|
Reline::Face.load_initial_configs
|
515
527
|
|
metadata
CHANGED
@@ -1,14 +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
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-04-04 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: io-console
|
@@ -51,7 +50,6 @@ files:
|
|
51
50
|
- lib/reline/key_stroke.rb
|
52
51
|
- lib/reline/kill_ring.rb
|
53
52
|
- lib/reline/line_editor.rb
|
54
|
-
- lib/reline/terminfo.rb
|
55
53
|
- lib/reline/unicode.rb
|
56
54
|
- lib/reline/unicode/east_asian_width.rb
|
57
55
|
- lib/reline/version.rb
|
@@ -63,7 +61,6 @@ metadata:
|
|
63
61
|
bug_tracker_uri: https://github.com/ruby/reline/issues
|
64
62
|
changelog_uri: https://github.com/ruby/reline/releases
|
65
63
|
source_code_uri: https://github.com/ruby/reline
|
66
|
-
post_install_message:
|
67
64
|
rdoc_options: []
|
68
65
|
require_paths:
|
69
66
|
- lib
|
@@ -78,8 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
75
|
- !ruby/object:Gem::Version
|
79
76
|
version: '0'
|
80
77
|
requirements: []
|
81
|
-
rubygems_version: 3.
|
82
|
-
signing_key:
|
78
|
+
rubygems_version: 3.6.3
|
83
79
|
specification_version: 4
|
84
80
|
summary: Alternative GNU Readline or Editline implementation by pure Ruby.
|
85
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)
|
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
|