reline 0.2.7 → 0.3.0

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