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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28ee53a9963a33e9eb1159bea507695d94cc4f67b05ce005175808b7ec2d5175
4
- data.tar.gz: c165de2edcc223bc4e3e149208fe29994063445ea0cf02b93658010a245df5e4
3
+ metadata.gz: 2fb74f487afccdfb3b0530a043cfb7090f2a4860f2fdd168bc94112818b5f57d
4
+ data.tar.gz: 96b74e0f611f24022f204e9551d8692ef017c52a197ae169fbfdc1074a130857
5
5
  SHA512:
6
- metadata.gz: af0f93e54d3a414c63dfb369746f00e8fa9cac609c646c0a48ad5f87275e7b6f5c88c47d4c30218075d3774fd41ba7978f49a0ffbfa070ee42921ba0e500c06e
7
- data.tar.gz: 5b0a45b7ae2cfb0e23c9d3b4a863e381f4d9ba5d6298f864c261e408cb5c366031d6137d623d0d46e3729b7bbe086fc5da5c5e636163bce230ae0f297441e016
6
+ metadata.gz: ffdcec13818f2445bd9f639e75b36405c76a439378335fa7c05fad90a26f06965e54cd9dce1b8e1411e16df9ffc80c3c0ac356320654af2ebd40a33fd28cb247
7
+ data.tar.gz: 24be10266aebce2d07f1519010f6ce0e6b92b816b17e526ede204943880b54388aa5ebf5da086bde0212b5e1f837936e4972c09a57a2d6c94f7c9a41412966d9
data/lib/reline/config.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  class Reline::Config
2
2
  attr_reader :test_mode
3
3
 
4
- KEYSEQ_PATTERN = /\\(?:C|Control)-[A-Za-z_]|\\(?:M|Meta)-[0-9A-Za-z_]|\\(?:C|Control)-(?:M|Meta)-[A-Za-z_]|\\(?:M|Meta)-(?:C|Control)-[A-Za-z_]|\\e|\\[\\\"\'abdfnrtv]|\\\d{1,3}|\\x\h{1,2}|./
4
+ KEYSEQ_PATTERN = /\\(?:C|Control)-[A-Za-z_]|\\(?:M|Meta)-[0-9A-Za-z_]|\\(?:C|Control)-\\(?:M|Meta)-[A-Za-z_]|\\(?:M|Meta)-\\(?:C|Control)-[A-Za-z_]|\\e|\\[\\\"\'abdfnrtv]|\\\d{1,3}|\\x\h{1,2}|./
5
5
 
6
6
  class InvalidInputrc < RuntimeError
7
7
  attr_accessor :file, :lineno
@@ -29,6 +29,17 @@ class Reline::Config
29
29
  attr_accessor :autocompletion
30
30
 
31
31
  def initialize
32
+ reset_variables
33
+ end
34
+
35
+ def reset
36
+ if editing_mode_is?(:vi_command)
37
+ @editing_mode_label = :vi_insert
38
+ end
39
+ @oneshot_key_bindings.clear
40
+ end
41
+
42
+ def reset_variables
32
43
  @additional_key_bindings = { # from inputrc
33
44
  emacs: Reline::KeyActor::Base.new,
34
45
  vi_insert: Reline::KeyActor::Base.new,
@@ -51,16 +62,11 @@ class Reline::Config
51
62
  @keyseq_timeout = 500
52
63
  @test_mode = false
53
64
  @autocompletion = false
54
- @convert_meta = true if seven_bit_encoding?(Reline::IOGate.encoding)
65
+ @convert_meta = seven_bit_encoding?(Reline::IOGate.encoding)
55
66
  @loaded = false
56
67
  @enable_bracketed_paste = true
57
- end
58
-
59
- def reset
60
- if editing_mode_is?(:vi_command)
61
- @editing_mode_label = :vi_insert
62
- end
63
- @oneshot_key_bindings.clear
68
+ @show_mode_in_prompt = false
69
+ @default_inputrc_path = nil
64
70
  end
65
71
 
66
72
  def editing_mode
@@ -188,13 +194,14 @@ class Reline::Config
188
194
  # value ignores everything after a space, raw_value does not.
189
195
  var, value, raw_value = $1.downcase, $2.partition(' ').first, $2
190
196
  bind_variable(var, value, raw_value)
191
- next
192
- when /\s*("#{KEYSEQ_PATTERN}+")\s*:\s*(.*)\s*$/o
193
- key, func_name = $1, $2
194
- func_name = func_name.split.first
195
- keystroke, func = bind_key(key, func_name)
196
- next unless keystroke
197
- @additional_key_bindings[@keymap_label].add(@keymap_prefix + keystroke, func)
197
+ when /^\s*(?:M|Meta)-([a-zA-Z_])\s*:\s*(.*)\s*$/o
198
+ bind_key("\"\\M-#$1\"", $2)
199
+ when /^\s*(?:C|Control)-([a-zA-Z_])\s*:\s*(.*)\s*$/o
200
+ bind_key("\"\\C-#$1\"", $2)
201
+ when /^\s*(?:(?:C|Control)-(?:M|Meta)|(?:M|Meta)-(?:C|Control))-([a-zA-Z_])\s*:\s*(.*)\s*$/o
202
+ bind_key("\"\\M-\\C-#$1\"", $2)
203
+ when /^\s*("#{KEYSEQ_PATTERN}+")\s*:\s*(.*)\s*$/o
204
+ bind_key($1, $2)
198
205
  end
199
206
  end
200
207
  unless if_stack.empty?
@@ -245,22 +252,6 @@ class Reline::Config
245
252
  rescue ArgumentError
246
253
  @history_size = 500
247
254
  end
248
- when 'bell-style'
249
- @bell_style =
250
- case value
251
- when 'none', 'off'
252
- :none
253
- when 'audible', 'on'
254
- :audible
255
- when 'visible'
256
- :visible
257
- else
258
- :audible
259
- end
260
- when 'comment-begin'
261
- @comment_begin = value.dup
262
- when 'completion-query-items'
263
- @completion_query_items = value.to_i
264
255
  when 'isearch-terminators'
265
256
  @isearch_terminators = retrieve_string(raw_value)
266
257
  when 'editing-mode'
@@ -320,7 +311,12 @@ class Reline::Config
320
311
  parse_keyseq(str).map { |c| c.chr(Reline.encoding_system_needs) }.join
321
312
  end
322
313
 
323
- def bind_key(key, func_name)
314
+ def bind_key(key, value)
315
+ keystroke, func = parse_key_binding(key, value)
316
+ @additional_key_bindings[@keymap_label].add(@keymap_prefix + keystroke, func) if keystroke
317
+ end
318
+
319
+ def parse_key_binding(key, func_name)
324
320
  if key =~ /\A"(.*)"\z/
325
321
  keyseq = parse_keyseq($1)
326
322
  else
@@ -329,27 +325,19 @@ class Reline::Config
329
325
  if func_name =~ /"(.*)"/
330
326
  func = parse_keyseq($1)
331
327
  else
332
- func = func_name.tr(?-, ?_).to_sym # It must be macro.
328
+ func = func_name.split.first.tr(?-, ?_).to_sym # It must be macro.
333
329
  end
334
330
  [keyseq, func]
335
331
  end
336
332
 
337
333
  def key_notation_to_code(notation)
338
334
  case notation
335
+ when /(?:\\(?:C|Control)-\\(?:M|Meta)|\\(?:M|Meta)-\\(?:C|Control))-([A-Za-z_])/
336
+ [?\e.ord, $1.ord % 32]
339
337
  when /\\(?:C|Control)-([A-Za-z_])/
340
- (1 + $1.downcase.ord - ?a.ord)
338
+ ($1.upcase.ord % 32)
341
339
  when /\\(?:M|Meta)-([0-9A-Za-z_])/
342
- modified_key = $1
343
- case $1
344
- when /[0-9]/
345
- ?\M-0.bytes.first + (modified_key.ord - ?0.ord)
346
- when /[A-Z]/
347
- ?\M-A.bytes.first + (modified_key.ord - ?A.ord)
348
- when /[a-z]/
349
- ?\M-a.bytes.first + (modified_key.ord - ?a.ord)
350
- end
351
- when /\\(?:C|Control)-(?:M|Meta)-[A-Za-z_]/, /\\(?:M|Meta)-(?:C|Control)-[A-Za-z_]/
352
- # 129 M-^A
340
+ [?\e.ord, $1.ord]
353
341
  when /\\(\d{1,3})/ then $1.to_i(8) # octal
354
342
  when /\\x(\h{1,2})/ then $1.to_i(16) # hexadecimal
355
343
  when "\\e" then ?\e.ord
@@ -369,11 +357,14 @@ class Reline::Config
369
357
  end
370
358
 
371
359
  def parse_keyseq(str)
372
- ret = []
373
- str.scan(KEYSEQ_PATTERN) do
374
- ret << key_notation_to_code($&)
360
+ str.scan(KEYSEQ_PATTERN).flat_map do |notation|
361
+ key_notation_to_code(notation)
375
362
  end
376
- ret
363
+ end
364
+
365
+ def reload
366
+ reset_variables
367
+ read
377
368
  end
378
369
 
379
370
  private def seven_bit_encoding?(encoding)
data/lib/reline/face.rb CHANGED
@@ -107,7 +107,7 @@ class Reline::Face
107
107
 
108
108
  def sgr_rgb_256color(key, value)
109
109
  # 256 colors are
110
- # 0..15: standard colors, hight intensity colors
110
+ # 0..15: standard colors, high intensity colors
111
111
  # 16..232: 216 colors (R, G, B each 6 steps)
112
112
  # 233..255: grayscale colors (24 steps)
113
113
  # This methods converts rgb_expression to 216 colors
@@ -19,7 +19,7 @@ class Reline::History < Array
19
19
 
20
20
  def []=(index, val)
21
21
  index = check_index(index)
22
- super(index, String.new(val, encoding: Reline.encoding_system_needs))
22
+ super(index, Reline::Unicode.safe_encode(val, Reline.encoding_system_needs))
23
23
  end
24
24
 
25
25
  def concat(*val)
@@ -45,7 +45,7 @@ class Reline::History < Array
45
45
  end
46
46
  end
47
47
  super(*(val.map{ |v|
48
- String.new(v, encoding: Reline.encoding_system_needs)
48
+ Reline::Unicode.safe_encode(v, Reline.encoding_system_needs)
49
49
  }))
50
50
  end
51
51
 
@@ -56,7 +56,7 @@ class Reline::History < Array
56
56
  if @config.history_size.positive?
57
57
  shift if size + 1 > @config.history_size
58
58
  end
59
- super(String.new(val, encoding: Reline.encoding_system_needs))
59
+ super(Reline::Unicode.safe_encode(val, Reline.encoding_system_needs))
60
60
  end
61
61
 
62
62
  private def check_index(index)
@@ -2,18 +2,6 @@ require 'io/console'
2
2
  require 'io/wait'
3
3
 
4
4
  class Reline::ANSI < Reline::IO
5
- CAPNAME_KEY_BINDINGS = {
6
- 'khome' => :ed_move_to_beg,
7
- 'kend' => :ed_move_to_end,
8
- 'kdch1' => :key_delete,
9
- 'kpp' => :ed_search_prev_history,
10
- 'knp' => :ed_search_next_history,
11
- 'kcuu1' => :ed_prev_history,
12
- 'kcud1' => :ed_next_history,
13
- 'kcuf1' => :ed_next_char,
14
- 'kcub1' => :ed_prev_char,
15
- }
16
-
17
5
  ANSI_CURSOR_KEY_BINDINGS = {
18
6
  # Up
19
7
  'A' => [:ed_prev_history, {}],
@@ -29,29 +17,27 @@ class Reline::ANSI < Reline::IO
29
17
  'H' => [:ed_move_to_beg, {}],
30
18
  }
31
19
 
32
- if Reline::Terminfo.enabled?
33
- Reline::Terminfo.setupterm(0, 2)
34
- end
20
+ attr_writer :input, :output
35
21
 
36
22
  def initialize
37
23
  @input = STDIN
38
24
  @output = STDOUT
39
25
  @buf = []
26
+ @output_buffer = nil
40
27
  @old_winch_handler = nil
41
28
  end
42
29
 
43
30
  def encoding
31
+ @input.external_encoding || Encoding.default_external
32
+ rescue IOError
33
+ # STDIN.external_encoding raises IOError in Ruby <= 3.0 when STDIN is closed
44
34
  Encoding.default_external
45
35
  end
46
36
 
47
- def set_default_key_bindings(config, allow_terminfo: true)
37
+ def set_default_key_bindings(config)
48
38
  set_bracketed_paste_key_bindings(config)
49
39
  set_default_key_bindings_ansi_cursor(config)
50
- if allow_terminfo && Reline::Terminfo.enabled?
51
- set_default_key_bindings_terminfo(config)
52
- else
53
- set_default_key_bindings_comprehensive_list(config)
54
- end
40
+ set_default_key_bindings_comprehensive_list(config)
55
41
  {
56
42
  [27, 91, 90] => :completion_journey_up, # S-Tab
57
43
  }.each_pair do |key, func|
@@ -75,7 +61,10 @@ class Reline::ANSI < Reline::IO
75
61
 
76
62
  def set_default_key_bindings_ansi_cursor(config)
77
63
  ANSI_CURSOR_KEY_BINDINGS.each do |char, (default_func, modifiers)|
78
- bindings = [["\e[#{char}", default_func]] # CSI + char
64
+ bindings = [
65
+ ["\e[#{char}", default_func], # CSI + char
66
+ ["\eO#{char}", default_func] # SS3 + char, application cursor key mode
67
+ ]
79
68
  if modifiers[:ctrl]
80
69
  # CSI + ctrl_key_modifier + char
81
70
  bindings << ["\e[1;5#{char}", modifiers[:ctrl]]
@@ -95,23 +84,6 @@ class Reline::ANSI < Reline::IO
95
84
  end
96
85
  end
97
86
 
98
- def set_default_key_bindings_terminfo(config)
99
- key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding|
100
- begin
101
- key_code = Reline::Terminfo.tigetstr(capname)
102
- [ key_code.bytes, key_binding ]
103
- rescue Reline::Terminfo::TerminfoError
104
- # capname is undefined
105
- end
106
- end.compact.to_h
107
-
108
- key_bindings.each_pair do |key, func|
109
- config.add_default_key_binding_by_keymap(:emacs, key, func)
110
- config.add_default_key_binding_by_keymap(:vi_insert, key, func)
111
- config.add_default_key_binding_by_keymap(:vi_command, key, func)
112
- end
113
- end
114
-
115
87
  def set_default_key_bindings_comprehensive_list(config)
116
88
  {
117
89
  # xterm
@@ -123,27 +95,9 @@ class Reline::ANSI < Reline::IO
123
95
  [27, 91, 49, 126] => :ed_move_to_beg, # Home
124
96
  [27, 91, 52, 126] => :ed_move_to_end, # End
125
97
 
126
- # KDE
127
- # Del is 0x08
128
- [27, 71, 65] => :ed_prev_history, # ↑
129
- [27, 71, 66] => :ed_next_history, # ↓
130
- [27, 71, 67] => :ed_next_char, # →
131
- [27, 71, 68] => :ed_prev_char, # ←
132
-
133
98
  # urxvt / exoterm
134
99
  [27, 91, 55, 126] => :ed_move_to_beg, # Home
135
100
  [27, 91, 56, 126] => :ed_move_to_end, # End
136
-
137
- # GNOME
138
- [27, 79, 72] => :ed_move_to_beg, # Home
139
- [27, 79, 70] => :ed_move_to_end, # End
140
- # Del is 0x08
141
- # Arrow keys are the same of KDE
142
-
143
- [27, 79, 65] => :ed_prev_history, # ↑
144
- [27, 79, 66] => :ed_next_history, # ↓
145
- [27, 79, 67] => :ed_next_char, # →
146
- [27, 79, 68] => :ed_prev_char, # ←
147
101
  }.each_pair do |key, func|
148
102
  config.add_default_key_binding_by_keymap(:emacs, key, func)
149
103
  config.add_default_key_binding_by_keymap(:vi_insert, key, func)
@@ -151,14 +105,6 @@ class Reline::ANSI < Reline::IO
151
105
  end
152
106
  end
153
107
 
154
- def input=(val)
155
- @input = val
156
- end
157
-
158
- def output=(val)
159
- @output = val
160
- end
161
-
162
108
  def with_raw_input
163
109
  if @input.tty?
164
110
  @input.raw(intr: true) { yield }
@@ -245,52 +191,57 @@ class Reline::ANSI < Reline::IO
245
191
  self
246
192
  end
247
193
 
248
- def cursor_pos
249
- if both_tty?
250
- res = +''
251
- m = nil
252
- @input.raw do |stdin|
253
- @output << "\e[6n"
254
- @output.flush
255
- loop do
256
- c = stdin.getc
257
- next if c.nil?
258
- res << c
259
- m = res.match(/\e\[(?<row>\d+);(?<column>\d+)R/)
260
- break if m
194
+ private def cursor_pos_internal(timeout:)
195
+ match = nil
196
+ @input.raw do |stdin|
197
+ @output << "\e[6n"
198
+ @output.flush
199
+ timeout_at = Time.now + timeout
200
+ buf = +''
201
+ while (wait = timeout_at - Time.now) > 0 && stdin.wait_readable(wait)
202
+ buf << stdin.readpartial(1024)
203
+ if (match = buf.match(/\e\[(?<row>\d+);(?<column>\d+)R/))
204
+ buf = match.pre_match + match.post_match
205
+ break
261
206
  end
262
- (m.pre_match + m.post_match).chars.reverse_each do |ch|
263
- stdin.ungetc ch
264
- end
265
- end
266
- column = m[:column].to_i - 1
267
- row = m[:row].to_i - 1
268
- else
269
- begin
270
- buf = @output.pread(@output.pos, 0)
271
- row = buf.count("\n")
272
- column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0
273
- rescue Errno::ESPIPE, IOError
274
- # Just returns column 1 for ambiguous width because this I/O is not
275
- # tty and can't seek.
276
- row = 0
277
- column = 1
278
207
  end
208
+ @buf.concat buf.bytes
279
209
  end
280
- Reline::CursorPos.new(column, row)
210
+ [match[:column].to_i - 1, match[:row].to_i - 1] if match
211
+ end
212
+
213
+ def cursor_pos
214
+ col, row = cursor_pos_internal(timeout: 0.5) if both_tty?
215
+ Reline::CursorPos.new(col || 0, row || 0)
281
216
  end
282
217
 
283
218
  def both_tty?
284
219
  @input.tty? && @output.tty?
285
220
  end
286
221
 
222
+ def write(string)
223
+ if @output_buffer
224
+ @output_buffer << string
225
+ else
226
+ @output.write(string)
227
+ end
228
+ end
229
+
230
+ def buffered_output
231
+ @output_buffer = +''
232
+ yield
233
+ @output.write(@output_buffer)
234
+ ensure
235
+ @output_buffer = nil
236
+ end
237
+
287
238
  def move_cursor_column(x)
288
- @output.write "\e[#{x + 1}G"
239
+ write "\e[#{x + 1}G"
289
240
  end
290
241
 
291
242
  def move_cursor_up(x)
292
243
  if x > 0
293
- @output.write "\e[#{x}A"
244
+ write "\e[#{x}A"
294
245
  elsif x < 0
295
246
  move_cursor_down(-x)
296
247
  end
@@ -298,38 +249,22 @@ class Reline::ANSI < Reline::IO
298
249
 
299
250
  def move_cursor_down(x)
300
251
  if x > 0
301
- @output.write "\e[#{x}B"
252
+ write "\e[#{x}B"
302
253
  elsif x < 0
303
254
  move_cursor_up(-x)
304
255
  end
305
256
  end
306
257
 
307
258
  def hide_cursor
308
- seq = "\e[?25l"
309
- if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
310
- begin
311
- seq = Reline::Terminfo.tigetstr('civis')
312
- rescue Reline::Terminfo::TerminfoError
313
- # civis is undefined
314
- end
315
- end
316
- @output.write seq
259
+ write "\e[?25l"
317
260
  end
318
261
 
319
262
  def show_cursor
320
- seq = "\e[?25h"
321
- if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
322
- begin
323
- seq = Reline::Terminfo.tigetstr('cnorm')
324
- rescue Reline::Terminfo::TerminfoError
325
- # cnorm is undefined
326
- end
327
- end
328
- @output.write seq
263
+ write "\e[?25h"
329
264
  end
330
265
 
331
266
  def erase_after_cursor
332
- @output.write "\e[K"
267
+ write "\e[K"
333
268
  end
334
269
 
335
270
  # This only works when the cursor is at the bottom of the scroll range
@@ -337,28 +272,47 @@ class Reline::ANSI < Reline::IO
337
272
  def scroll_down(x)
338
273
  return if x.zero?
339
274
  # We use `\n` instead of CSI + S because CSI + S would cause https://github.com/ruby/reline/issues/576
340
- @output.write "\n" * x
275
+ write "\n" * x
341
276
  end
342
277
 
343
278
  def clear_screen
344
- @output.write "\e[2J"
345
- @output.write "\e[1;1H"
279
+ write "\e[2J"
280
+ write "\e[1;1H"
346
281
  end
347
282
 
348
283
  def set_winch_handler(&handler)
349
- @old_winch_handler = Signal.trap('WINCH', &handler)
284
+ @old_winch_handler = Signal.trap('WINCH') do |arg|
285
+ handler.call
286
+ @old_winch_handler.call(arg) if @old_winch_handler.respond_to?(:call)
287
+ end
288
+ @old_cont_handler = Signal.trap('CONT') do |arg|
289
+ @input.raw!(intr: true) if @input.tty?
290
+ # Rerender the screen. Note that screen size might be changed while suspended.
291
+ handler.call
292
+ @old_cont_handler.call(arg) if @old_cont_handler.respond_to?(:call)
293
+ end
294
+ rescue ArgumentError
295
+ # Signal.trap may raise an ArgumentError if the platform doesn't support the signal.
296
+ end
297
+
298
+ def read_single_char(keyseq_timeout)
299
+ # Disable intr to read `C-c` `C-z` `C-\` for quoted insert
300
+ @input.raw(intr: false) do
301
+ super
302
+ end
350
303
  end
351
304
 
352
305
  def prep
353
306
  # Enable bracketed paste
354
- @output.write "\e[?2004h" if Reline.core.config.enable_bracketed_paste && both_tty?
307
+ write "\e[?2004h" if Reline.core.config.enable_bracketed_paste && both_tty?
355
308
  retrieve_keybuffer
356
309
  nil
357
310
  end
358
311
 
359
312
  def deprep(otio)
360
313
  # Disable bracketed paste
361
- @output.write "\e[?2004l" if Reline.core.config.enable_bracketed_paste && both_tty?
314
+ write "\e[?2004l" if Reline.core.config.enable_bracketed_paste && both_tty?
362
315
  Signal.trap('WINCH', @old_winch_handler) if @old_winch_handler
316
+ Signal.trap('CONT', @old_cont_handler) if @old_cont_handler
363
317
  end
364
318
  end
@@ -3,8 +3,11 @@ require 'io/wait'
3
3
  class Reline::Dumb < Reline::IO
4
4
  RESET_COLOR = '' # Do not send color reset sequence
5
5
 
6
+ attr_writer :output
7
+
6
8
  def initialize(encoding: nil)
7
9
  @input = STDIN
10
+ @output = STDOUT
8
11
  @buf = []
9
12
  @pasting = false
10
13
  @encoding = encoding
@@ -21,8 +24,11 @@ class Reline::Dumb < Reline::IO
21
24
  elsif RUBY_PLATFORM =~ /mswin|mingw/
22
25
  Encoding::UTF_8
23
26
  else
24
- Encoding::default_external
27
+ @input.external_encoding || Encoding.default_external
25
28
  end
29
+ rescue IOError
30
+ # STDIN.external_encoding raises IOError in Ruby <= 3.0 when STDIN is closed
31
+ Encoding.default_external
26
32
  end
27
33
 
28
34
  def set_default_key_bindings(_)
@@ -36,6 +42,14 @@ class Reline::Dumb < Reline::IO
36
42
  yield
37
43
  end
38
44
 
45
+ def write(string)
46
+ @output.write(string)
47
+ end
48
+
49
+ def buffered_output
50
+ yield
51
+ end
52
+
39
53
  def getc(_timeout_second)
40
54
  unless @buf.empty?
41
55
  return @buf.shift
@@ -60,7 +74,7 @@ class Reline::Dumb < Reline::IO
60
74
  end
61
75
 
62
76
  def cursor_pos
63
- Reline::CursorPos.new(1, 1)
77
+ Reline::CursorPos.new(0, 0)
64
78
  end
65
79
 
66
80
  def hide_cursor