reline 0.0.7 → 0.1.4

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: 985d3ce68260542cce79b3d3291c29ca30ee82250e50089c2de7bb16f60d755d
4
- data.tar.gz: d3444d9e894a66fd2a0e5be4fddd5d36b9b254f0aaff7ed1d590fec26c13b3f6
3
+ metadata.gz: 41e0f73e51def110f060454c69c3a3a29d3b0cedce2c432cc594df4f6cccf012
4
+ data.tar.gz: c47d69d20e28f8940c86eedba5349892ecf5e5745e83a8c701eab327e326c6ba
5
5
  SHA512:
6
- metadata.gz: 9a5651134aeb6d0eba7e33b4fa6e85c2ac43677432a7b94e8aa24d1c9f05326126c81669aa297f9cb03bea7f92c2ee8600364205c8a8eafa7c6185441472f9d1
7
- data.tar.gz: 63cc8b0b0b936e8ac1a490c9a1c849631b2c4c33c520eb2dd666b9b93b641417f3640542067de4f64ff2e28fd4dd883ed3821c7704bb82a64485ee52d5273c3b
6
+ metadata.gz: b494460955ab34ccf2e4c0443e76598c692d2846162be5081ecc8234181b47771721e5969fa76acd54bcce7f6d2c3dbc7e6469b23897c144c6233db5c08c915b
7
+ data.tar.gz: 7c0f5bd0caf7f79113b479e9785aa2260536356ff7196fa1d034fe669f60fca7078771575d8002edf18a5c256105e22d550d9b4e0382071e2c240ef0a34b0287
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  [![Build Status](https://travis-ci.com/ruby/reline.svg?branch=master)](https://travis-ci.com/ruby/reline)
2
2
 
3
+ This is a screen capture of *IRB improved by Reline*.
4
+
5
+ ![IRB improved by Reline](https://raw.githubusercontent.com/wiki/ruby/reline/images/irb_improved_by_reline.gif)
6
+
3
7
  # Reline
4
8
 
5
9
  Reline is compatible with the API of Ruby's stdlib 'readline', GNU Readline and Editline by pure Ruby implementation.
@@ -32,55 +32,69 @@ module Reline
32
32
  dig_perfect_match_proc
33
33
  ).each(&method(:attr_reader))
34
34
 
35
- ATTR_ACCESSOR_NAMES = %i(
36
- completion_case_fold
37
- ).each(&method(:attr_accessor))
38
-
39
35
  attr_accessor :config
40
36
  attr_accessor :key_stroke
41
37
  attr_accessor :line_editor
42
38
  attr_accessor :ambiguous_width
39
+ attr_accessor :last_incremental_search
43
40
  attr_reader :output
44
41
 
45
42
  def initialize
46
43
  self.output = STDOUT
47
44
  yield self
45
+ @completion_quote_character = nil
46
+ end
47
+
48
+ def encoding
49
+ Reline::IOGate.encoding
48
50
  end
49
51
 
50
52
  def completion_append_character=(val)
51
53
  if val.nil?
52
54
  @completion_append_character = nil
53
55
  elsif val.size == 1
54
- @completion_append_character = val.encode(Encoding::default_external)
56
+ @completion_append_character = val.encode(Reline::IOGate.encoding)
55
57
  elsif val.size > 1
56
- @completion_append_character = val[0].encode(Encoding::default_external)
58
+ @completion_append_character = val[0].encode(Reline::IOGate.encoding)
57
59
  else
58
60
  @completion_append_character = nil
59
61
  end
60
62
  end
61
63
 
62
64
  def basic_word_break_characters=(v)
63
- @basic_word_break_characters = v.encode(Encoding::default_external)
65
+ @basic_word_break_characters = v.encode(Reline::IOGate.encoding)
64
66
  end
65
67
 
66
68
  def completer_word_break_characters=(v)
67
- @completer_word_break_characters = v.encode(Encoding::default_external)
69
+ @completer_word_break_characters = v.encode(Reline::IOGate.encoding)
68
70
  end
69
71
 
70
72
  def basic_quote_characters=(v)
71
- @basic_quote_characters = v.encode(Encoding::default_external)
73
+ @basic_quote_characters = v.encode(Reline::IOGate.encoding)
72
74
  end
73
75
 
74
76
  def completer_quote_characters=(v)
75
- @completer_quote_characters = v.encode(Encoding::default_external)
77
+ @completer_quote_characters = v.encode(Reline::IOGate.encoding)
76
78
  end
77
79
 
78
80
  def filename_quote_characters=(v)
79
- @filename_quote_characters = v.encode(Encoding::default_external)
81
+ @filename_quote_characters = v.encode(Reline::IOGate.encoding)
80
82
  end
81
83
 
82
84
  def special_prefixes=(v)
83
- @special_prefixes = v.encode(Encoding::default_external)
85
+ @special_prefixes = v.encode(Reline::IOGate.encoding)
86
+ end
87
+
88
+ def completion_case_fold=(v)
89
+ @config.completion_ignore_case = v
90
+ end
91
+
92
+ def completion_case_fold
93
+ @config.completion_ignore_case
94
+ end
95
+
96
+ def completion_quote_character
97
+ @completion_quote_character
84
98
  end
85
99
 
86
100
  def completion_proc=(p)
@@ -161,7 +175,7 @@ module Reline
161
175
 
162
176
  whole_buffer = line_editor.whole_buffer.dup
163
177
  whole_buffer.taint if RUBY_VERSION < '2.7'
164
- if add_hist and whole_buffer and whole_buffer.chomp.size > 0
178
+ if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
165
179
  Reline::HISTORY << whole_buffer
166
180
  end
167
181
 
@@ -174,8 +188,8 @@ module Reline
174
188
 
175
189
  line = line_editor.line.dup
176
190
  line.taint if RUBY_VERSION < '2.7'
177
- if add_hist and line and line.chomp.size > 0
178
- Reline::HISTORY << line.chomp
191
+ if add_hist and line and line.chomp("\n").size > 0
192
+ Reline::HISTORY << line.chomp("\n")
179
193
  end
180
194
 
181
195
  line_editor.reset_line if line_editor.line.nil?
@@ -191,7 +205,7 @@ module Reline
191
205
  otio = Reline::IOGate.prep
192
206
 
193
207
  may_req_ambiguous_char_width
194
- line_editor.reset(prompt)
208
+ line_editor.reset(prompt, encoding: Reline::IOGate.encoding)
195
209
  if multiline
196
210
  line_editor.multiline_on
197
211
  if block_given?
@@ -202,6 +216,7 @@ module Reline
202
216
  end
203
217
  line_editor.output = output
204
218
  line_editor.completion_proc = completion_proc
219
+ line_editor.completion_append_character = completion_append_character
205
220
  line_editor.output_modifier_proc = output_modifier_proc
206
221
  line_editor.prompt_proc = prompt_proc
207
222
  line_editor.auto_indent_proc = auto_indent_proc
@@ -321,8 +336,14 @@ module Reline
321
336
  @ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or STDOUT.is_a?(File)
322
337
  return if ambiguous_width
323
338
  Reline::IOGate.move_cursor_column(0)
324
- print "\u{25bd}"
325
- @ambiguous_width = Reline::IOGate.cursor_pos.x
339
+ begin
340
+ output.write "\u{25bd}"
341
+ rescue Encoding::UndefinedConversionError
342
+ # LANG=C
343
+ @ambiguous_width = 1
344
+ else
345
+ @ambiguous_width = Reline::IOGate.cursor_pos.x
346
+ end
326
347
  Reline::IOGate.move_cursor_column(0)
327
348
  Reline::IOGate.erase_after_cursor
328
349
  end
@@ -335,12 +356,14 @@ module Reline
335
356
  # Documented API
336
357
  #--------------------------------------------------------
337
358
 
338
- (Core::ATTR_READER_NAMES + Core::ATTR_ACCESSOR_NAMES).each { |name|
359
+ (Core::ATTR_READER_NAMES).each { |name|
339
360
  def_single_delegators :core, "#{name}", "#{name}="
340
361
  }
341
362
  def_single_delegators :core, :input=, :output=
342
363
  def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
343
364
  def_single_delegators :core, :readline
365
+ def_single_delegators :core, :completion_case_fold, :completion_case_fold=
366
+ def_single_delegators :core, :completion_quote_character
344
367
  def_instance_delegators self, :readline
345
368
  private :readline
346
369
 
@@ -367,16 +390,22 @@ module Reline
367
390
  def_single_delegator :line_editor, :rerender, :redisplay
368
391
  def_single_delegators :core, :vi_editing_mode?, :emacs_editing_mode?
369
392
  def_single_delegators :core, :ambiguous_width
393
+ def_single_delegators :core, :last_incremental_search
394
+ def_single_delegators :core, :last_incremental_search=
370
395
 
371
396
  def_single_delegators :core, :readmultiline
372
397
  def_instance_delegators self, :readmultiline
373
398
  private :readmultiline
374
399
 
400
+ def self.encoding_system_needs
401
+ self.core.encoding
402
+ end
403
+
375
404
  def self.core
376
405
  @core ||= Core.new { |core|
377
406
  core.config = Reline::Config.new
378
407
  core.key_stroke = Reline::KeyStroke.new(core.config)
379
- core.line_editor = Reline::LineEditor.new(core.config)
408
+ core.line_editor = Reline::LineEditor.new(core.config, Reline::IOGate.encoding)
380
409
 
381
410
  core.basic_word_break_characters = " \t\n`><=;|&{("
382
411
  core.completer_word_break_characters = " \t\n`><=;|&{("
@@ -390,14 +419,11 @@ module Reline
390
419
  def self.line_editor
391
420
  core.line_editor
392
421
  end
393
-
394
- HISTORY = History.new(core.config)
395
422
  end
396
423
 
397
424
  if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
398
425
  require 'reline/windows'
399
- if Reline::Windows.get_screen_size == [0, 0]
400
- # Maybe Mintty on Cygwin
426
+ if Reline::Windows.msys_tty?
401
427
  require 'reline/ansi'
402
428
  Reline::IOGate = Reline::ANSI
403
429
  else
@@ -407,4 +433,5 @@ else
407
433
  require 'reline/ansi'
408
434
  Reline::IOGate = Reline::ANSI
409
435
  end
436
+ Reline::HISTORY = Reline::History.new(Reline.core.config)
410
437
  require 'reline/general_io'
@@ -1,16 +1,49 @@
1
+ require 'io/console'
2
+
1
3
  class Reline::ANSI
4
+ def self.encoding
5
+ Encoding.default_external
6
+ end
7
+
8
+ def self.win?
9
+ false
10
+ end
11
+
2
12
  RAW_KEYSTROKE_CONFIG = {
13
+ # Console (80x25)
14
+ [27, 91, 49, 126] => :ed_move_to_beg, # Home
15
+ [27, 91, 52, 126] => :ed_move_to_end, # End
16
+ [27, 91, 51, 126] => :key_delete, # Del
3
17
  [27, 91, 65] => :ed_prev_history, # ↑
4
18
  [27, 91, 66] => :ed_next_history, # ↓
5
19
  [27, 91, 67] => :ed_next_char, # →
6
20
  [27, 91, 68] => :ed_prev_char, # ←
7
- [27, 91, 51, 126] => :key_delete, # Del
8
- [27, 91, 49, 126] => :ed_move_to_beg, # Home
9
- [27, 91, 52, 126] => :ed_move_to_end, # End
21
+
22
+ # KDE
10
23
  [27, 91, 72] => :ed_move_to_beg, # Home
11
24
  [27, 91, 70] => :ed_move_to_end, # End
25
+ # Del is 0x08
26
+ [27, 71, 65] => :ed_prev_history, # ↑
27
+ [27, 71, 66] => :ed_next_history, # ↓
28
+ [27, 71, 67] => :ed_next_char, # →
29
+ [27, 71, 68] => :ed_prev_char, # ←
30
+
31
+ # GNOME
32
+ [27, 79, 72] => :ed_move_to_beg, # Home
33
+ [27, 79, 70] => :ed_move_to_end, # End
34
+ # Del is 0x08
35
+ # Arrow keys are the same of KDE
36
+
37
+ # others
12
38
  [27, 32] => :em_set_mark, # M-<space>
13
39
  [24, 24] => :em_exchange_mark, # C-x C-x TODO also add Windows
40
+ [27, 91, 49, 59, 53, 67] => :em_next_word, # Ctrl+→
41
+ [27, 91, 49, 59, 53, 68] => :ed_prev_word, # Ctrl+←
42
+
43
+ [27, 79, 65] => :ed_prev_history, # ↑
44
+ [27, 79, 66] => :ed_next_history, # ↓
45
+ [27, 79, 67] => :ed_next_char, # →
46
+ [27, 79, 68] => :ed_prev_char, # ←
14
47
  }
15
48
 
16
49
  @@input = STDIN
@@ -28,7 +61,8 @@ class Reline::ANSI
28
61
  unless @@buf.empty?
29
62
  return @@buf.shift
30
63
  end
31
- @@input.getbyte
64
+ c = @@input.raw(intr: true, &:getbyte)
65
+ (c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
32
66
  end
33
67
 
34
68
  def self.ungetc(c)
@@ -36,16 +70,23 @@ class Reline::ANSI
36
70
  end
37
71
 
38
72
  def self.retrieve_keybuffer
73
+ begin
39
74
  result = select([@@input], [], [], 0.001)
40
75
  return if result.nil?
41
76
  str = @@input.read_nonblock(1024)
42
77
  str.bytes.each do |c|
43
78
  @@buf.push(c)
44
79
  end
80
+ rescue EOFError
81
+ end
45
82
  end
46
83
 
47
84
  def self.get_screen_size
48
- @@input.winsize
85
+ s = @@input.winsize
86
+ return s if s[0] > 0 && s[1] > 0
87
+ s = [ENV["LINES"].to_i, ENV["COLUMNS"].to_i]
88
+ return s if s[0] > 0 && s[1] > 0
89
+ [24, 80]
49
90
  rescue Errno::ENOTTY
50
91
  [24, 80]
51
92
  end
@@ -60,14 +101,18 @@ class Reline::ANSI
60
101
  def self.cursor_pos
61
102
  begin
62
103
  res = ''
104
+ m = nil
63
105
  @@input.raw do |stdin|
64
106
  @@output << "\e[6n"
65
107
  @@output.flush
66
108
  while (c = stdin.getc) != 'R'
67
109
  res << c if c
68
110
  end
111
+ m = res.match(/\e\[(?<row>\d+);(?<column>\d+)/)
112
+ (m.pre_match + m.post_match).chars.reverse_each do |ch|
113
+ stdin.ungetc ch
114
+ end
69
115
  end
70
- m = res.match(/(?<row>\d+);(?<column>\d+)/)
71
116
  column = m[:column].to_i - 1
72
117
  row = m[:row].to_i - 1
73
118
  rescue Errno::ENOTTY
@@ -79,12 +124,12 @@ class Reline::ANSI
79
124
  end
80
125
 
81
126
  def self.move_cursor_column(x)
82
- print "\e[#{x + 1}G"
127
+ @@output.write "\e[#{x + 1}G"
83
128
  end
84
129
 
85
130
  def self.move_cursor_up(x)
86
131
  if x > 0
87
- print "\e[#{x}A" if x > 0
132
+ @@output.write "\e[#{x}A" if x > 0
88
133
  elsif x < 0
89
134
  move_cursor_down(-x)
90
135
  end
@@ -92,24 +137,24 @@ class Reline::ANSI
92
137
 
93
138
  def self.move_cursor_down(x)
94
139
  if x > 0
95
- print "\e[#{x}B" if x > 0
140
+ @@output.write "\e[#{x}B" if x > 0
96
141
  elsif x < 0
97
142
  move_cursor_up(-x)
98
143
  end
99
144
  end
100
145
 
101
146
  def self.erase_after_cursor
102
- print "\e[K"
147
+ @@output.write "\e[K"
103
148
  end
104
149
 
105
150
  def self.scroll_down(x)
106
151
  return if x.zero?
107
- print "\e[#{x}S"
152
+ @@output.write "\e[#{x}S"
108
153
  end
109
154
 
110
155
  def self.clear_screen
111
- print "\e[2J"
112
- print "\e[1;1H"
156
+ @@output.write "\e[2J"
157
+ @@output.write "\e[1;1H"
113
158
  end
114
159
 
115
160
  @@old_winch_handler = nil
@@ -120,24 +165,12 @@ class Reline::ANSI
120
165
  def self.prep
121
166
  retrieve_keybuffer
122
167
  int_handle = Signal.trap('INT', 'IGNORE')
123
- otio = `stty -g`.chomp
124
- setting = ' -echo -icrnl cbreak'
125
- stty = `stty -a`
126
- if /-parenb\b/ =~ stty
127
- setting << ' pass8'
128
- end
129
- if /\bdsusp *=/ =~ stty
130
- setting << ' dsusp undef'
131
- end
132
- setting << ' -ixoff'
133
- `stty #{setting}`
134
168
  Signal.trap('INT', int_handle)
135
- otio
169
+ nil
136
170
  end
137
171
 
138
172
  def self.deprep(otio)
139
173
  int_handle = Signal.trap('INT', 'IGNORE')
140
- system("stty #{otio}", err: File::NULL)
141
174
  Signal.trap('INT', int_handle)
142
175
  Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
143
176
  end
@@ -3,8 +3,6 @@ require 'pathname'
3
3
  class Reline::Config
4
4
  attr_reader :test_mode
5
5
 
6
- DEFAULT_PATH = '~/.inputrc'
7
-
8
6
  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}|./
9
7
 
10
8
  class InvalidInputrc < RuntimeError
@@ -54,7 +52,7 @@ class Reline::Config
54
52
  @key_actors[:emacs] = Reline::KeyActor::Emacs.new
55
53
  @key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
56
54
  @key_actors[:vi_command] = Reline::KeyActor::ViCommand.new
57
- @history_size = 500
55
+ @history_size = -1 # unlimited
58
56
  @keyseq_timeout = 500
59
57
  @test_mode = false
60
58
  end
@@ -83,8 +81,34 @@ class Reline::Config
83
81
  @key_actors[@keymap_label]
84
82
  end
85
83
 
84
+ def inputrc_path
85
+ case ENV['INPUTRC']
86
+ when nil, ''
87
+ else
88
+ return File.expand_path(ENV['INPUTRC'])
89
+ end
90
+
91
+ # In the XDG Specification, if ~/.config/readline/inputrc exists, then
92
+ # ~/.inputrc should not be read, but for compatibility with GNU Readline,
93
+ # if ~/.inputrc exists, then it is given priority.
94
+ home_rc_path = File.expand_path('~/.inputrc')
95
+ return home_rc_path if File.exist?(home_rc_path)
96
+
97
+ case path = ENV['XDG_CONFIG_HOME']
98
+ when nil, ''
99
+ else
100
+ path = File.join(path, 'readline/inputrc')
101
+ return path if File.exist?(path) and path == File.expand_path(path)
102
+ end
103
+
104
+ path = File.expand_path('~/.config/readline/inputrc')
105
+ return path if File.exist?(path)
106
+
107
+ return home_rc_path
108
+ end
109
+
86
110
  def read(file = nil)
87
- file ||= File.expand_path(ENV['INPUTRC'] || DEFAULT_PATH)
111
+ file ||= inputrc_path
88
112
  begin
89
113
  if file.respond_to?(:readlines)
90
114
  lines = file.readlines
@@ -157,7 +181,7 @@ class Reline::Config
157
181
  case directive
158
182
  when 'if'
159
183
  condition = false
160
- case args # TODO: variables
184
+ case args
161
185
  when 'mode'
162
186
  when 'term'
163
187
  when 'version'
@@ -184,9 +208,8 @@ class Reline::Config
184
208
 
185
209
  def bind_variable(name, value)
186
210
  case name
187
- when VARIABLE_NAMES then
188
- variable_name = :"@#{name.tr(?-, ?_)}"
189
- instance_variable_set(variable_name, value.nil? || value == '1' || value == 'on')
211
+ when 'history-size'
212
+ @history_size = value.to_i
190
213
  when 'bell-style'
191
214
  @bell_style =
192
215
  case value
@@ -225,6 +248,9 @@ class Reline::Config
225
248
  end
226
249
  when 'keyseq-timeout'
227
250
  @keyseq_timeout = value.to_i
251
+ when *VARIABLE_NAMES then
252
+ variable_name = :"@#{name.tr(?-, ?_)}"
253
+ instance_variable_set(variable_name, value.nil? || value == '1' || value == 'on')
228
254
  end
229
255
  end
230
256