reline 0.2.7 → 0.3.0

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: 1bb2255429504a1beb1a5a9f863f7cba5c4c65781b7cd8b2aa843b0df639fb26
4
- data.tar.gz: c9372db87ad831e06d0e99d20981cb14a08e8b15ca3011f4b6df2a05aaeef7b3
3
+ metadata.gz: 2e8c2181e5eb21934546d6b768715cb47eab6e1ea1edb2fd2300f43af62dc2b1
4
+ data.tar.gz: 99a61e2729d4b5d150f6f59d99d6de235ea4f1aab6ac262c92fff6a77101b85f
5
5
  SHA512:
6
- metadata.gz: 63e8b6f4a9de8a69a8f22c979b6fee92026143be658b9e928da43dddb868fb6b641b5f140de436c1dd5ed1f3cdbc3c42c7c41084fcc1d811cd713c684aedda8e
7
- data.tar.gz: 7a459412f528f43d5e65f4c7c6a5c74055e2c5334f21a65411bc4f187b55b649c15fd612ed27f2dc0032f7fdc5973c7fa57b674b0a323ac2d9537b23fff19664
6
+ metadata.gz: 96ceefe0bf71e7e44ccd2a5970b35fc44019af9d7da4d2e04ac1d827eb6bc6a201e679a5e40c4db976554159286f16e39cdeac68bcf69c2c5abeb00a2045e563
7
+ data.tar.gz: 251c2029df6b3073010ad6a591fb216990124ed4f9e00f533e79461be66c6a2383ea56c1554dd273e4af3cfc9358dee37b76a1b4bff25a1867972201bfebace3
data/lib/reline/ansi.rb CHANGED
@@ -4,6 +4,19 @@ require 'timeout'
4
4
  require_relative 'terminfo'
5
5
 
6
6
  class Reline::ANSI
7
+ CAPNAME_KEY_BINDINGS = {
8
+ 'khome' => :ed_move_to_beg,
9
+ 'kend' => :ed_move_to_end,
10
+ 'kcuu1' => :ed_prev_history,
11
+ 'kcud1' => :ed_next_history,
12
+ 'kcuf1' => :ed_next_char,
13
+ 'kcub1' => :ed_prev_char,
14
+ 'cuu' => :ed_prev_history,
15
+ 'cud' => :ed_next_history,
16
+ 'cuf' => :ed_next_char,
17
+ 'cub' => :ed_prev_char,
18
+ }
19
+
7
20
  if Reline::Terminfo.enabled?
8
21
  Reline::Terminfo.setupterm(0, 2)
9
22
  end
@@ -33,6 +46,12 @@ class Reline::ANSI
33
46
  config.add_default_key_binding_by_keymap(:vi_insert, key, func)
34
47
  config.add_default_key_binding_by_keymap(:vi_command, key, func)
35
48
  end
49
+ {
50
+ [27, 91, 90] => :completion_journey_up, # S-Tab
51
+ }.each_pair do |key, func|
52
+ config.add_default_key_binding_by_keymap(:emacs, key, func)
53
+ config.add_default_key_binding_by_keymap(:vi_insert, key, func)
54
+ end
36
55
  {
37
56
  # default bindings
38
57
  [27, 32] => :em_set_mark, # M-<space>
@@ -43,20 +62,23 @@ class Reline::ANSI
43
62
  end
44
63
 
45
64
  def self.set_default_key_bindings_terminfo(config)
46
- {
47
- Reline::Terminfo.tigetstr('khome').bytes => :ed_move_to_beg,
48
- Reline::Terminfo.tigetstr('kend').bytes => :ed_move_to_end,
49
- Reline::Terminfo.tigetstr('kcuu1').bytes => :ed_prev_history,
50
- Reline::Terminfo.tigetstr('kcud1').bytes => :ed_next_history,
51
- Reline::Terminfo.tigetstr('kcuf1').bytes => :ed_next_char,
52
- Reline::Terminfo.tigetstr('kcub1').bytes => :ed_prev_char,
53
- # Escape sequences that omit the move distance and are set to defaults
54
- # value 1 may be sometimes sent by pressing the arrow-key.
55
- Reline::Terminfo.tigetstr('cuu').sub(/%p1%d/, '').bytes => :ed_prev_history,
56
- Reline::Terminfo.tigetstr('cud').sub(/%p1%d/, '').bytes => :ed_next_history,
57
- Reline::Terminfo.tigetstr('cuf').sub(/%p1%d/, '').bytes => :ed_next_char,
58
- Reline::Terminfo.tigetstr('cub').sub(/%p1%d/, '').bytes => :ed_prev_char,
59
- }.each_pair do |key, func|
65
+ key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding|
66
+ begin
67
+ key_code = Reline::Terminfo.tigetstr(capname)
68
+ case capname
69
+ # Escape sequences that omit the move distance and are set to defaults
70
+ # value 1 may be sometimes sent by pressing the arrow-key.
71
+ when 'cuu', 'cud', 'cuf', 'cub'
72
+ [ key_code.sub(/%p1%d/, '').bytes, key_binding ]
73
+ else
74
+ [ key_code.bytes, key_binding ]
75
+ end
76
+ rescue Reline::Terminfo::TerminfoError
77
+ # capname is undefined
78
+ end
79
+ end.compact.to_h
80
+
81
+ key_bindings.each_pair do |key, func|
60
82
  config.add_default_key_binding_by_keymap(:emacs, key, func)
61
83
  config.add_default_key_binding_by_keymap(:vi_insert, key, func)
62
84
  config.add_default_key_binding_by_keymap(:vi_command, key, func)
@@ -125,8 +147,8 @@ class Reline::ANSI
125
147
  unless @@buf.empty?
126
148
  return @@buf.shift
127
149
  end
128
- until c = @@input.raw(intr: true, &:getbyte)
129
- sleep 0.1
150
+ until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
151
+ Reline.core.line_editor.resize
130
152
  end
131
153
  (c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
132
154
  rescue Errno::EIO
@@ -260,7 +282,7 @@ class Reline::ANSI
260
282
 
261
283
  def self.move_cursor_up(x)
262
284
  if x > 0
263
- @@output.write "\e[#{x}A" if x > 0
285
+ @@output.write "\e[#{x}A"
264
286
  elsif x < 0
265
287
  move_cursor_down(-x)
266
288
  end
@@ -268,12 +290,36 @@ class Reline::ANSI
268
290
 
269
291
  def self.move_cursor_down(x)
270
292
  if x > 0
271
- @@output.write "\e[#{x}B" if x > 0
293
+ @@output.write "\e[#{x}B"
272
294
  elsif x < 0
273
295
  move_cursor_up(-x)
274
296
  end
275
297
  end
276
298
 
299
+ def self.hide_cursor
300
+ if Reline::Terminfo.enabled?
301
+ begin
302
+ @@output.write Reline::Terminfo.tigetstr('civis')
303
+ rescue Reline::Terminfo::TerminfoError
304
+ # civis is undefined
305
+ end
306
+ else
307
+ # ignored
308
+ end
309
+ end
310
+
311
+ def self.show_cursor
312
+ if Reline::Terminfo.enabled?
313
+ begin
314
+ @@output.write Reline::Terminfo.tigetstr('cnorm')
315
+ rescue Reline::Terminfo::TerminfoError
316
+ # cnorm is undefined
317
+ end
318
+ else
319
+ # ignored
320
+ end
321
+ end
322
+
277
323
  def self.erase_after_cursor
278
324
  @@output.write "\e[K"
279
325
  end
@@ -295,14 +341,10 @@ class Reline::ANSI
295
341
 
296
342
  def self.prep
297
343
  retrieve_keybuffer
298
- int_handle = Signal.trap('INT', 'IGNORE')
299
- Signal.trap('INT', int_handle)
300
344
  nil
301
345
  end
302
346
 
303
347
  def self.deprep(otio)
304
- int_handle = Signal.trap('INT', 'IGNORE')
305
- Signal.trap('INT', int_handle)
306
348
  Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
307
349
  end
308
350
  end
data/lib/reline/config.rb CHANGED
@@ -50,6 +50,7 @@ class Reline::Config
50
50
  @additional_key_bindings[:emacs] = {}
51
51
  @additional_key_bindings[:vi_insert] = {}
52
52
  @additional_key_bindings[:vi_command] = {}
53
+ @oneshot_key_bindings = {}
53
54
  @skip_section = nil
54
55
  @if_stack = nil
55
56
  @editing_mode_label = :emacs
@@ -65,6 +66,8 @@ class Reline::Config
65
66
  @history_size = -1 # unlimited
66
67
  @keyseq_timeout = 500
67
68
  @test_mode = false
69
+ @autocompletion = false
70
+ @convert_meta = true if seven_bit_encoding?(Reline::IOGate.encoding)
68
71
  end
69
72
 
70
73
  def reset
@@ -74,6 +77,7 @@ class Reline::Config
74
77
  @additional_key_bindings.keys.each do |key|
75
78
  @additional_key_bindings[key].clear
76
79
  end
80
+ @oneshot_key_bindings.clear
77
81
  reset_default_key_bindings
78
82
  end
79
83
 
@@ -89,6 +93,14 @@ class Reline::Config
89
93
  (val.respond_to?(:any?) ? val : [val]).any?(@editing_mode_label)
90
94
  end
91
95
 
96
+ def autocompletion=(val)
97
+ @autocompletion = val
98
+ end
99
+
100
+ def autocompletion
101
+ @autocompletion
102
+ end
103
+
92
104
  def keymap
93
105
  @key_actors[@keymap_label]
94
106
  end
@@ -119,8 +131,12 @@ class Reline::Config
119
131
  return home_rc_path
120
132
  end
121
133
 
134
+ private def default_inputrc_path
135
+ @default_inputrc_path ||= inputrc_path
136
+ end
137
+
122
138
  def read(file = nil)
123
- file ||= inputrc_path
139
+ file ||= default_inputrc_path
124
140
  begin
125
141
  if file.respond_to?(:readlines)
126
142
  lines = file.readlines
@@ -139,8 +155,19 @@ class Reline::Config
139
155
  end
140
156
 
141
157
  def key_bindings
142
- # override @key_actors[@editing_mode_label].default_key_bindings with @additional_key_bindings[@editing_mode_label]
143
- @key_actors[@editing_mode_label].default_key_bindings.merge(@additional_key_bindings[@editing_mode_label])
158
+ # The key bindings for each editing mode will be overwritten by the user-defined ones.
159
+ kb = @key_actors[@editing_mode_label].default_key_bindings.dup
160
+ kb.merge!(@additional_key_bindings[@editing_mode_label])
161
+ kb.merge!(@oneshot_key_bindings)
162
+ kb
163
+ end
164
+
165
+ def add_oneshot_key_binding(keystroke, target)
166
+ @oneshot_key_bindings[keystroke] = target
167
+ end
168
+
169
+ def reset_oneshot_key_bindings
170
+ @oneshot_key_bindings.clear
144
171
  end
145
172
 
146
173
  def add_default_key_binding_by_keymap(keymap, keystroke, target)
@@ -361,4 +388,8 @@ class Reline::Config
361
388
  end
362
389
  ret
363
390
  end
391
+
392
+ private def seven_bit_encoding?(encoding)
393
+ encoding == Encoding::US_ASCII
394
+ end
364
395
  end
@@ -1,4 +1,5 @@
1
1
  require 'timeout'
2
+ require 'io/wait'
2
3
 
3
4
  class Reline::GeneralIO
4
5
  def self.reset(encoding: nil)
@@ -24,6 +25,7 @@ class Reline::GeneralIO
24
25
  end
25
26
 
26
27
  @@buf = []
28
+ @@input = STDIN
27
29
 
28
30
  def self.input=(val)
29
31
  @@input = val
@@ -35,7 +37,7 @@ class Reline::GeneralIO
35
37
  end
36
38
  c = nil
37
39
  loop do
38
- result = select([@@input], [], [], 0.1)
40
+ result = @@input.wait_readable(0.1)
39
41
  next if result.nil?
40
42
  c = @@input.read(1)
41
43
  break
@@ -43,7 +43,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
43
43
  # 20 ^T
44
44
  :ed_transpose_chars,
45
45
  # 21 ^U
46
- :em_kill_line,
46
+ :ed_kill_line,
47
47
  # 22 ^V
48
48
  :ed_quoted_insert,
49
49
  # 23 ^W
@@ -1,38 +1,88 @@
1
1
  class Reline::KeyStroke
2
- using Module.new {
3
- refine Array do
4
- def start_with?(other)
5
- other.size <= size && other == self.take(other.size)
2
+ def initialize(config)
3
+ @config = config
4
+ end
5
+
6
+ def compress_meta_key(ary)
7
+ return ary unless @config.convert_meta
8
+ ary.inject([]) { |result, key|
9
+ if result.size > 0 and result.last == "\e".ord
10
+ result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
11
+ else
12
+ result << key
6
13
  end
14
+ result
15
+ }
16
+ end
7
17
 
8
- def bytes
9
- self
18
+ def start_with?(me, other)
19
+ compressed_me = compress_meta_key(me)
20
+ compressed_other = compress_meta_key(other)
21
+ i = 0
22
+ loop do
23
+ my_c = compressed_me[i]
24
+ other_c = compressed_other[i]
25
+ other_is_last = (i + 1) == compressed_other.size
26
+ me_is_last = (i + 1) == compressed_me.size
27
+ if my_c != other_c
28
+ if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
29
+ return true
30
+ else
31
+ return false
32
+ end
33
+ elsif other_is_last
34
+ return true
35
+ elsif me_is_last
36
+ return false
10
37
  end
38
+ i += 1
11
39
  end
12
- }
40
+ end
13
41
 
14
- def initialize(config)
15
- @config = config
42
+ def equal?(me, other)
43
+ case me
44
+ when Array
45
+ compressed_me = compress_meta_key(me)
46
+ compressed_other = compress_meta_key(other)
47
+ compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| equal?(i[0], i[1]) }
48
+ when Integer
49
+ if other.is_a?(Reline::Key)
50
+ if other.combined_char == "\e".ord
51
+ false
52
+ else
53
+ other.combined_char == me
54
+ end
55
+ else
56
+ me == other
57
+ end
58
+ when Reline::Key
59
+ if other.is_a?(Integer)
60
+ me.combined_char == other
61
+ else
62
+ me == other
63
+ end
64
+ end
16
65
  end
17
66
 
18
67
  def match_status(input)
19
68
  key_mapping.keys.select { |lhs|
20
- lhs.start_with? input
69
+ start_with?(lhs, input)
21
70
  }.tap { |it|
22
- return :matched if it.size == 1 && (it.max_by(&:size)&.size&.== input.size)
23
- return :matching if it.size == 1 && (it.max_by(&:size)&.size&.!= input.size)
71
+ return :matched if it.size == 1 && equal?(it[0], input)
72
+ return :matching if it.size == 1 && !equal?(it[0], input)
24
73
  return :matched if it.max_by(&:size)&.size&.< input.size
25
74
  return :matching if it.size > 1
26
75
  }
27
76
  key_mapping.keys.select { |lhs|
28
- input.start_with? lhs
77
+ start_with?(input, lhs)
29
78
  }.tap { |it|
30
79
  return it.size > 0 ? :matched : :unmatched
31
80
  }
32
81
  end
33
82
 
34
83
  def expand(input)
35
- lhs = key_mapping.keys.select { |item| input.start_with? item }.sort_by(&:size).reverse.first
84
+ input = compress_meta_key(input)
85
+ lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
36
86
  return input unless lhs
37
87
  rhs = key_mapping[lhs]
38
88