reline 0.0.7 → 0.1.4

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: 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