reline 0.5.8 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bcccc644594f9c2e4b9ae0eb743c2ae293ef084e96a8d9bd032b76825111c01b
4
- data.tar.gz: b5ab239a3d20925d4fbd8fb827908fa3e4fa70298a172e32e9b2b4de59dc767e
3
+ metadata.gz: 28ee53a9963a33e9eb1159bea507695d94cc4f67b05ce005175808b7ec2d5175
4
+ data.tar.gz: c165de2edcc223bc4e3e149208fe29994063445ea0cf02b93658010a245df5e4
5
5
  SHA512:
6
- metadata.gz: 9bce894711da0253bf9b3f0eb192ff64947d591edd00f9094430431eb470fade4d02f3f8b529d364cdd7124d7f5a5203ea755be41dbfda890e37654aca430706
7
- data.tar.gz: eed500ad148a1f83e3de03e6d7daaf5d250ba3ea25d47d24070e749dfd44a7d900b83474dd0b427faee74bad883dab97b7af1984a7fb7209e1819fd416d4381b
6
+ metadata.gz: af0f93e54d3a414c63dfb369746f00e8fa9cac609c646c0a48ad5f87275e7b6f5c88c47d4c30218075d3774fd41ba7978f49a0ffbfa070ee42921ba0e500c06e
7
+ data.tar.gz: 5b0a45b7ae2cfb0e23c9d3b4a863e381f4d9ba5d6298f864c261e408cb5c366031d6137d623d0d46e3729b7bbe086fc5da5c5e636163bce230ae0f297441e016
data/lib/reline/config.rb CHANGED
@@ -29,18 +29,20 @@ class Reline::Config
29
29
  attr_accessor :autocompletion
30
30
 
31
31
  def initialize
32
- @additional_key_bindings = {} # from inputrc
33
- @additional_key_bindings[:emacs] = {}
34
- @additional_key_bindings[:vi_insert] = {}
35
- @additional_key_bindings[:vi_command] = {}
36
- @oneshot_key_bindings = {}
32
+ @additional_key_bindings = { # from inputrc
33
+ emacs: Reline::KeyActor::Base.new,
34
+ vi_insert: Reline::KeyActor::Base.new,
35
+ vi_command: Reline::KeyActor::Base.new
36
+ }
37
+ @oneshot_key_bindings = Reline::KeyActor::Base.new
37
38
  @editing_mode_label = :emacs
38
39
  @keymap_label = :emacs
39
40
  @keymap_prefix = []
40
- @key_actors = {}
41
- @key_actors[:emacs] = Reline::KeyActor::Emacs.new
42
- @key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
43
- @key_actors[:vi_command] = Reline::KeyActor::ViCommand.new
41
+ @default_key_bindings = {
42
+ emacs: Reline::KeyActor::Base.new(Reline::KeyActor::EMACS_MAPPING),
43
+ vi_insert: Reline::KeyActor::Base.new(Reline::KeyActor::VI_INSERT_MAPPING),
44
+ vi_command: Reline::KeyActor::Base.new(Reline::KeyActor::VI_COMMAND_MAPPING)
45
+ }
44
46
  @vi_cmd_mode_string = '(cmd)'
45
47
  @vi_ins_mode_string = '(ins)'
46
48
  @emacs_mode_string = '@'
@@ -62,7 +64,7 @@ class Reline::Config
62
64
  end
63
65
 
64
66
  def editing_mode
65
- @key_actors[@editing_mode_label]
67
+ @default_key_bindings[@editing_mode_label]
66
68
  end
67
69
 
68
70
  def editing_mode=(val)
@@ -74,7 +76,7 @@ class Reline::Config
74
76
  end
75
77
 
76
78
  def keymap
77
- @key_actors[@keymap_label]
79
+ @default_key_bindings[@keymap_label]
78
80
  end
79
81
 
80
82
  def loaded?
@@ -133,14 +135,14 @@ class Reline::Config
133
135
 
134
136
  def key_bindings
135
137
  # The key bindings for each editing mode will be overwritten by the user-defined ones.
136
- kb = @key_actors[@editing_mode_label].default_key_bindings.dup
137
- kb.merge!(@additional_key_bindings[@editing_mode_label])
138
- kb.merge!(@oneshot_key_bindings)
139
- kb
138
+ Reline::KeyActor::Composite.new([@oneshot_key_bindings, @additional_key_bindings[@editing_mode_label], @default_key_bindings[@editing_mode_label]])
140
139
  end
141
140
 
142
141
  def add_oneshot_key_binding(keystroke, target)
143
- @oneshot_key_bindings[keystroke] = target
142
+ # IRB sets invalid keystroke [Reline::Key]. We should ignore it.
143
+ return unless keystroke.all? { |c| c.is_a?(Integer) }
144
+
145
+ @oneshot_key_bindings.add(keystroke, target)
144
146
  end
145
147
 
146
148
  def reset_oneshot_key_bindings
@@ -148,11 +150,11 @@ class Reline::Config
148
150
  end
149
151
 
150
152
  def add_default_key_binding_by_keymap(keymap, keystroke, target)
151
- @key_actors[keymap].default_key_bindings[keystroke] = target
153
+ @default_key_bindings[keymap].add(keystroke, target)
152
154
  end
153
155
 
154
156
  def add_default_key_binding(keystroke, target)
155
- @key_actors[@keymap_label].default_key_bindings[keystroke] = target
157
+ add_default_key_binding_by_keymap(@keymap_label, keystroke, target)
156
158
  end
157
159
 
158
160
  def read_lines(lines, file = nil)
@@ -192,7 +194,7 @@ class Reline::Config
192
194
  func_name = func_name.split.first
193
195
  keystroke, func = bind_key(key, func_name)
194
196
  next unless keystroke
195
- @additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
197
+ @additional_key_bindings[@keymap_label].add(@keymap_prefix + keystroke, func)
196
198
  end
197
199
  end
198
200
  unless if_stack.empty?
@@ -1,10 +1,7 @@
1
1
  require 'io/console'
2
2
  require 'io/wait'
3
- require_relative 'terminfo'
4
-
5
- class Reline::ANSI
6
- RESET_COLOR = "\e[0m"
7
3
 
4
+ class Reline::ANSI < Reline::IO
8
5
  CAPNAME_KEY_BINDINGS = {
9
6
  'khome' => :ed_move_to_beg,
10
7
  'kend' => :ed_move_to_end,
@@ -36,15 +33,18 @@ class Reline::ANSI
36
33
  Reline::Terminfo.setupterm(0, 2)
37
34
  end
38
35
 
39
- def self.encoding
40
- Encoding.default_external
36
+ def initialize
37
+ @input = STDIN
38
+ @output = STDOUT
39
+ @buf = []
40
+ @old_winch_handler = nil
41
41
  end
42
42
 
43
- def self.win?
44
- false
43
+ def encoding
44
+ Encoding.default_external
45
45
  end
46
46
 
47
- def self.set_default_key_bindings(config, allow_terminfo: true)
47
+ def set_default_key_bindings(config, allow_terminfo: true)
48
48
  set_bracketed_paste_key_bindings(config)
49
49
  set_default_key_bindings_ansi_cursor(config)
50
50
  if allow_terminfo && Reline::Terminfo.enabled?
@@ -67,13 +67,13 @@ class Reline::ANSI
67
67
  end
68
68
  end
69
69
 
70
- def self.set_bracketed_paste_key_bindings(config)
70
+ def set_bracketed_paste_key_bindings(config)
71
71
  [:emacs, :vi_insert, :vi_command].each do |keymap|
72
72
  config.add_default_key_binding_by_keymap(keymap, START_BRACKETED_PASTE.bytes, :bracketed_paste_start)
73
73
  end
74
74
  end
75
75
 
76
- def self.set_default_key_bindings_ansi_cursor(config)
76
+ def set_default_key_bindings_ansi_cursor(config)
77
77
  ANSI_CURSOR_KEY_BINDINGS.each do |char, (default_func, modifiers)|
78
78
  bindings = [["\e[#{char}", default_func]] # CSI + char
79
79
  if modifiers[:ctrl]
@@ -95,7 +95,7 @@ class Reline::ANSI
95
95
  end
96
96
  end
97
97
 
98
- def self.set_default_key_bindings_terminfo(config)
98
+ def set_default_key_bindings_terminfo(config)
99
99
  key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding|
100
100
  begin
101
101
  key_code = Reline::Terminfo.tigetstr(capname)
@@ -112,12 +112,16 @@ class Reline::ANSI
112
112
  end
113
113
  end
114
114
 
115
- def self.set_default_key_bindings_comprehensive_list(config)
115
+ def set_default_key_bindings_comprehensive_list(config)
116
116
  {
117
+ # xterm
118
+ [27, 91, 51, 126] => :key_delete, # kdch1
119
+ [27, 91, 53, 126] => :ed_search_prev_history, # kpp
120
+ [27, 91, 54, 126] => :ed_search_next_history, # knp
121
+
117
122
  # Console (80x25)
118
123
  [27, 91, 49, 126] => :ed_move_to_beg, # Home
119
124
  [27, 91, 52, 126] => :ed_move_to_end, # End
120
- [27, 91, 51, 126] => :key_delete, # Del
121
125
 
122
126
  # KDE
123
127
  # Del is 0x08
@@ -147,47 +151,42 @@ class Reline::ANSI
147
151
  end
148
152
  end
149
153
 
150
- @@input = STDIN
151
- def self.input=(val)
152
- @@input = val
154
+ def input=(val)
155
+ @input = val
153
156
  end
154
157
 
155
- @@output = STDOUT
156
- def self.output=(val)
157
- @@output = val
158
+ def output=(val)
159
+ @output = val
158
160
  end
159
161
 
160
- def self.with_raw_input
161
- if @@input.tty?
162
- @@input.raw(intr: true) { yield }
162
+ def with_raw_input
163
+ if @input.tty?
164
+ @input.raw(intr: true) { yield }
163
165
  else
164
166
  yield
165
167
  end
166
168
  end
167
169
 
168
- @@buf = []
169
- def self.inner_getc(timeout_second)
170
- unless @@buf.empty?
171
- return @@buf.shift
170
+ def inner_getc(timeout_second)
171
+ unless @buf.empty?
172
+ return @buf.shift
172
173
  end
173
- until @@input.wait_readable(0.01)
174
+ until @input.wait_readable(0.01)
174
175
  timeout_second -= 0.01
175
176
  return nil if timeout_second <= 0
176
177
 
177
178
  Reline.core.line_editor.handle_signal
178
179
  end
179
- c = @@input.getbyte
180
- (c == 0x16 && @@input.raw(min: 0, time: 0, &:getbyte)) || c
180
+ c = @input.getbyte
181
+ (c == 0x16 && @input.tty? && @input.raw(min: 0, time: 0, &:getbyte)) || c
181
182
  rescue Errno::EIO
182
183
  # Maybe the I/O has been closed.
183
184
  nil
184
- rescue Errno::ENOTTY
185
- nil
186
185
  end
187
186
 
188
187
  START_BRACKETED_PASTE = String.new("\e[200~", encoding: Encoding::ASCII_8BIT)
189
188
  END_BRACKETED_PASTE = String.new("\e[201~", encoding: Encoding::ASCII_8BIT)
190
- def self.read_bracketed_paste
189
+ def read_bracketed_paste
191
190
  buffer = String.new(encoding: Encoding::ASCII_8BIT)
192
191
  until buffer.end_with?(END_BRACKETED_PASTE)
193
192
  c = inner_getc(Float::INFINITY)
@@ -199,38 +198,38 @@ class Reline::ANSI
199
198
  end
200
199
 
201
200
  # if the usage expects to wait indefinitely, use Float::INFINITY for timeout_second
202
- def self.getc(timeout_second)
201
+ def getc(timeout_second)
203
202
  inner_getc(timeout_second)
204
203
  end
205
204
 
206
- def self.in_pasting?
205
+ def in_pasting?
207
206
  not empty_buffer?
208
207
  end
209
208
 
210
- def self.empty_buffer?
211
- unless @@buf.empty?
209
+ def empty_buffer?
210
+ unless @buf.empty?
212
211
  return false
213
212
  end
214
- !@@input.wait_readable(0)
213
+ !@input.wait_readable(0)
215
214
  end
216
215
 
217
- def self.ungetc(c)
218
- @@buf.unshift(c)
216
+ def ungetc(c)
217
+ @buf.unshift(c)
219
218
  end
220
219
 
221
- def self.retrieve_keybuffer
220
+ def retrieve_keybuffer
222
221
  begin
223
- return unless @@input.wait_readable(0.001)
224
- str = @@input.read_nonblock(1024)
222
+ return unless @input.wait_readable(0.001)
223
+ str = @input.read_nonblock(1024)
225
224
  str.bytes.each do |c|
226
- @@buf.push(c)
225
+ @buf.push(c)
227
226
  end
228
227
  rescue EOFError
229
228
  end
230
229
  end
231
230
 
232
- def self.get_screen_size
233
- s = @@input.winsize
231
+ def get_screen_size
232
+ s = @input.winsize
234
233
  return s if s[0] > 0 && s[1] > 0
235
234
  s = [ENV["LINES"].to_i, ENV["COLUMNS"].to_i]
236
235
  return s if s[0] > 0 && s[1] > 0
@@ -239,20 +238,20 @@ class Reline::ANSI
239
238
  [24, 80]
240
239
  end
241
240
 
242
- def self.set_screen_size(rows, columns)
243
- @@input.winsize = [rows, columns]
241
+ def set_screen_size(rows, columns)
242
+ @input.winsize = [rows, columns]
244
243
  self
245
- rescue Errno::ENOTTY
244
+ rescue Errno::ENOTTY, Errno::ENODEV
246
245
  self
247
246
  end
248
247
 
249
- def self.cursor_pos
250
- begin
248
+ def cursor_pos
249
+ if both_tty?
251
250
  res = +''
252
251
  m = nil
253
- @@input.raw do |stdin|
254
- @@output << "\e[6n"
255
- @@output.flush
252
+ @input.raw do |stdin|
253
+ @output << "\e[6n"
254
+ @output.flush
256
255
  loop do
257
256
  c = stdin.getc
258
257
  next if c.nil?
@@ -266,9 +265,9 @@ class Reline::ANSI
266
265
  end
267
266
  column = m[:column].to_i - 1
268
267
  row = m[:row].to_i - 1
269
- rescue Errno::ENOTTY
268
+ else
270
269
  begin
271
- buf = @@output.pread(@@output.pos, 0)
270
+ buf = @output.pread(@output.pos, 0)
272
271
  row = buf.count("\n")
273
272
  column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0
274
273
  rescue Errno::ESPIPE, IOError
@@ -281,82 +280,85 @@ class Reline::ANSI
281
280
  Reline::CursorPos.new(column, row)
282
281
  end
283
282
 
284
- def self.move_cursor_column(x)
285
- @@output.write "\e[#{x + 1}G"
283
+ def both_tty?
284
+ @input.tty? && @output.tty?
285
+ end
286
+
287
+ def move_cursor_column(x)
288
+ @output.write "\e[#{x + 1}G"
286
289
  end
287
290
 
288
- def self.move_cursor_up(x)
291
+ def move_cursor_up(x)
289
292
  if x > 0
290
- @@output.write "\e[#{x}A"
293
+ @output.write "\e[#{x}A"
291
294
  elsif x < 0
292
295
  move_cursor_down(-x)
293
296
  end
294
297
  end
295
298
 
296
- def self.move_cursor_down(x)
299
+ def move_cursor_down(x)
297
300
  if x > 0
298
- @@output.write "\e[#{x}B"
301
+ @output.write "\e[#{x}B"
299
302
  elsif x < 0
300
303
  move_cursor_up(-x)
301
304
  end
302
305
  end
303
306
 
304
- def self.hide_cursor
307
+ def hide_cursor
308
+ seq = "\e[?25l"
305
309
  if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
306
310
  begin
307
- @@output.write Reline::Terminfo.tigetstr('civis')
311
+ seq = Reline::Terminfo.tigetstr('civis')
308
312
  rescue Reline::Terminfo::TerminfoError
309
313
  # civis is undefined
310
314
  end
311
- else
312
- # ignored
313
315
  end
316
+ @output.write seq
314
317
  end
315
318
 
316
- def self.show_cursor
319
+ def show_cursor
320
+ seq = "\e[?25h"
317
321
  if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
318
322
  begin
319
- @@output.write Reline::Terminfo.tigetstr('cnorm')
323
+ seq = Reline::Terminfo.tigetstr('cnorm')
320
324
  rescue Reline::Terminfo::TerminfoError
321
325
  # cnorm is undefined
322
326
  end
323
- else
324
- # ignored
325
327
  end
328
+ @output.write seq
326
329
  end
327
330
 
328
- def self.erase_after_cursor
329
- @@output.write "\e[K"
331
+ def erase_after_cursor
332
+ @output.write "\e[K"
330
333
  end
331
334
 
332
335
  # This only works when the cursor is at the bottom of the scroll range
333
336
  # For more details, see https://github.com/ruby/reline/pull/577#issuecomment-1646679623
334
- def self.scroll_down(x)
337
+ def scroll_down(x)
335
338
  return if x.zero?
336
339
  # We use `\n` instead of CSI + S because CSI + S would cause https://github.com/ruby/reline/issues/576
337
- @@output.write "\n" * x
340
+ @output.write "\n" * x
338
341
  end
339
342
 
340
- def self.clear_screen
341
- @@output.write "\e[2J"
342
- @@output.write "\e[1;1H"
343
+ def clear_screen
344
+ @output.write "\e[2J"
345
+ @output.write "\e[1;1H"
343
346
  end
344
347
 
345
- @@old_winch_handler = nil
346
- def self.set_winch_handler(&handler)
347
- @@old_winch_handler = Signal.trap('WINCH', &handler)
348
+ def set_winch_handler(&handler)
349
+ @old_winch_handler = Signal.trap('WINCH', &handler)
348
350
  end
349
351
 
350
- def self.prep
352
+ def prep
351
353
  # Enable bracketed paste
352
- @@output.write "\e[?2004h" if Reline.core.config.enable_bracketed_paste
354
+ @output.write "\e[?2004h" if Reline.core.config.enable_bracketed_paste && both_tty?
353
355
  retrieve_keybuffer
354
356
  nil
355
357
  end
356
358
 
357
- def self.deprep(otio)
359
+ def deprep(otio)
358
360
  # Disable bracketed paste
359
- @@output.write "\e[?2004l" if Reline.core.config.enable_bracketed_paste
360
- Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
361
+ @output.write "\e[?2004l" if Reline.core.config.enable_bracketed_paste && both_tty?
362
+ Signal.trap('WINCH', @old_winch_handler) if @old_winch_handler
361
363
  end
362
364
  end
@@ -0,0 +1,106 @@
1
+ require 'io/wait'
2
+
3
+ class Reline::Dumb < Reline::IO
4
+ RESET_COLOR = '' # Do not send color reset sequence
5
+
6
+ def initialize(encoding: nil)
7
+ @input = STDIN
8
+ @buf = []
9
+ @pasting = false
10
+ @encoding = encoding
11
+ @screen_size = [24, 80]
12
+ end
13
+
14
+ def dumb?
15
+ true
16
+ end
17
+
18
+ def encoding
19
+ if @encoding
20
+ @encoding
21
+ elsif RUBY_PLATFORM =~ /mswin|mingw/
22
+ Encoding::UTF_8
23
+ else
24
+ Encoding::default_external
25
+ end
26
+ end
27
+
28
+ def set_default_key_bindings(_)
29
+ end
30
+
31
+ def input=(val)
32
+ @input = val
33
+ end
34
+
35
+ def with_raw_input
36
+ yield
37
+ end
38
+
39
+ def getc(_timeout_second)
40
+ unless @buf.empty?
41
+ return @buf.shift
42
+ end
43
+ c = nil
44
+ loop do
45
+ Reline.core.line_editor.handle_signal
46
+ result = @input.wait_readable(0.1)
47
+ next if result.nil?
48
+ c = @input.read(1)
49
+ break
50
+ end
51
+ c&.ord
52
+ end
53
+
54
+ def ungetc(c)
55
+ @buf.unshift(c)
56
+ end
57
+
58
+ def get_screen_size
59
+ @screen_size
60
+ end
61
+
62
+ def cursor_pos
63
+ Reline::CursorPos.new(1, 1)
64
+ end
65
+
66
+ def hide_cursor
67
+ end
68
+
69
+ def show_cursor
70
+ end
71
+
72
+ def move_cursor_column(val)
73
+ end
74
+
75
+ def move_cursor_up(val)
76
+ end
77
+
78
+ def move_cursor_down(val)
79
+ end
80
+
81
+ def erase_after_cursor
82
+ end
83
+
84
+ def scroll_down(val)
85
+ end
86
+
87
+ def clear_screen
88
+ end
89
+
90
+ def set_screen_size(rows, columns)
91
+ @screen_size = [rows, columns]
92
+ end
93
+
94
+ def set_winch_handler(&handler)
95
+ end
96
+
97
+ def in_pasting?
98
+ @pasting
99
+ end
100
+
101
+ def prep
102
+ end
103
+
104
+ def deprep(otio)
105
+ end
106
+ end