reline 0.2.8.pre.8 → 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: 6f03d46c602265d3a197f00021df365a9686e4fd0b5d0ef2a037a9ad25143b91
4
- data.tar.gz: e97bfb610d3c9498e651b25de97e87380e624b56ea970ab7048b25dca7be9488
3
+ metadata.gz: 2e8c2181e5eb21934546d6b768715cb47eab6e1ea1edb2fd2300f43af62dc2b1
4
+ data.tar.gz: 99a61e2729d4b5d150f6f59d99d6de235ea4f1aab6ac262c92fff6a77101b85f
5
5
  SHA512:
6
- metadata.gz: be1a180b58930985ea7ba5d63be81b62c8ffb0b960daf33c5ad984652fa6021151519cc1fa41055c240d7675d628c6749ab69ca67c2c2bfa306a9deab8200c56
7
- data.tar.gz: 68be299c9815a350c8afec2c5b27aa02905c8fcc04c6fbba331aded2aded1d0dc160d2e8b01be58a91f308b1ad1dd880209e237de770002422910c6014ddc51a
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,31 +46,39 @@ 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>
39
58
  [24, 24] => :em_exchange_mark, # C-x C-x
40
- [27, 91, 90] => :completion_journey_up, # S-Tab
41
59
  }.each_pair do |key, func|
42
60
  config.add_default_key_binding_by_keymap(:emacs, key, func)
43
61
  end
44
62
  end
45
63
 
46
64
  def self.set_default_key_bindings_terminfo(config)
47
- {
48
- Reline::Terminfo.tigetstr('khome').bytes => :ed_move_to_beg,
49
- Reline::Terminfo.tigetstr('kend').bytes => :ed_move_to_end,
50
- Reline::Terminfo.tigetstr('kcuu1').bytes => :ed_prev_history,
51
- Reline::Terminfo.tigetstr('kcud1').bytes => :ed_next_history,
52
- Reline::Terminfo.tigetstr('kcuf1').bytes => :ed_next_char,
53
- Reline::Terminfo.tigetstr('kcub1').bytes => :ed_prev_char,
54
- # Escape sequences that omit the move distance and are set to defaults
55
- # value 1 may be sometimes sent by pressing the arrow-key.
56
- Reline::Terminfo.tigetstr('cuu').sub(/%p1%d/, '').bytes => :ed_prev_history,
57
- Reline::Terminfo.tigetstr('cud').sub(/%p1%d/, '').bytes => :ed_next_history,
58
- Reline::Terminfo.tigetstr('cuf').sub(/%p1%d/, '').bytes => :ed_next_char,
59
- Reline::Terminfo.tigetstr('cub').sub(/%p1%d/, '').bytes => :ed_prev_char,
60
- }.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|
61
82
  config.add_default_key_binding_by_keymap(:emacs, key, func)
62
83
  config.add_default_key_binding_by_keymap(:vi_insert, key, func)
63
84
  config.add_default_key_binding_by_keymap(:vi_command, key, func)
@@ -126,8 +147,8 @@ class Reline::ANSI
126
147
  unless @@buf.empty?
127
148
  return @@buf.shift
128
149
  end
129
- until c = @@input.raw(intr: true, &:getbyte)
130
- sleep 0.1
150
+ until c = @@input.raw(intr: true) { @@input.wait_readable(0.1) && @@input.getbyte }
151
+ Reline.core.line_editor.resize
131
152
  end
132
153
  (c == 0x16 && @@input.raw(min: 0, tim: 0, &:getbyte)) || c
133
154
  rescue Errno::EIO
@@ -261,7 +282,7 @@ class Reline::ANSI
261
282
 
262
283
  def self.move_cursor_up(x)
263
284
  if x > 0
264
- @@output.write "\e[#{x}A" if x > 0
285
+ @@output.write "\e[#{x}A"
265
286
  elsif x < 0
266
287
  move_cursor_down(-x)
267
288
  end
@@ -269,7 +290,7 @@ class Reline::ANSI
269
290
 
270
291
  def self.move_cursor_down(x)
271
292
  if x > 0
272
- @@output.write "\e[#{x}B" if x > 0
293
+ @@output.write "\e[#{x}B"
273
294
  elsif x < 0
274
295
  move_cursor_up(-x)
275
296
  end
@@ -277,7 +298,11 @@ class Reline::ANSI
277
298
 
278
299
  def self.hide_cursor
279
300
  if Reline::Terminfo.enabled?
280
- @@output.write Reline::Terminfo.tigetstr('civis')
301
+ begin
302
+ @@output.write Reline::Terminfo.tigetstr('civis')
303
+ rescue Reline::Terminfo::TerminfoError
304
+ # civis is undefined
305
+ end
281
306
  else
282
307
  # ignored
283
308
  end
@@ -285,7 +310,11 @@ class Reline::ANSI
285
310
 
286
311
  def self.show_cursor
287
312
  if Reline::Terminfo.enabled?
288
- @@output.write Reline::Terminfo.tigetstr('cnorm')
313
+ begin
314
+ @@output.write Reline::Terminfo.tigetstr('cnorm')
315
+ rescue Reline::Terminfo::TerminfoError
316
+ # cnorm is undefined
317
+ end
289
318
  else
290
319
  # ignored
291
320
  end
@@ -316,8 +345,6 @@ class Reline::ANSI
316
345
  end
317
346
 
318
347
  def self.deprep(otio)
319
- int_handle = Signal.trap('INT', 'IGNORE')
320
- Signal.trap('INT', int_handle)
321
348
  Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler
322
349
  end
323
350
  end
data/lib/reline/config.rb CHANGED
@@ -67,6 +67,7 @@ class Reline::Config
67
67
  @keyseq_timeout = 500
68
68
  @test_mode = false
69
69
  @autocompletion = false
70
+ @convert_meta = true if seven_bit_encoding?(Reline::IOGate.encoding)
70
71
  end
71
72
 
72
73
  def reset
@@ -154,8 +155,11 @@ class Reline::Config
154
155
  end
155
156
 
156
157
  def key_bindings
157
- # override @key_actors[@editing_mode_label].default_key_bindings with @additional_key_bindings[@editing_mode_label]
158
- @key_actors[@editing_mode_label].default_key_bindings.merge(@additional_key_bindings[@editing_mode_label]).merge(@oneshot_key_bindings)
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
159
163
  end
160
164
 
161
165
  def add_oneshot_key_binding(keystroke, target)
@@ -384,4 +388,8 @@ class Reline::Config
384
388
  end
385
389
  ret
386
390
  end
391
+
392
+ private def seven_bit_encoding?(encoding)
393
+ encoding == Encoding::US_ASCII
394
+ end
387
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)
@@ -36,7 +37,7 @@ class Reline::GeneralIO
36
37
  end
37
38
  c = nil
38
39
  loop do
39
- result = select([@@input], [], [], 0.1)
40
+ result = @@input.wait_readable(0.1)
40
41
  next if result.nil?
41
42
  c = @@input.read(1)
42
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,90 +1,88 @@
1
1
  class Reline::KeyStroke
2
- using Module.new {
3
- refine Integer do
4
- def ==(other)
5
- if other.is_a?(Reline::Key)
6
- if other.combined_char == "\e".ord
7
- false
8
- else
9
- other.combined_char == self
10
- end
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
13
+ end
14
+ result
15
+ }
16
+ end
17
+
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
11
30
  else
12
- super
31
+ return false
13
32
  end
33
+ elsif other_is_last
34
+ return true
35
+ elsif me_is_last
36
+ return false
14
37
  end
38
+ i += 1
15
39
  end
40
+ end
16
41
 
17
- refine Array do
18
- def start_with?(other)
19
- compressed_me = compress_meta_key
20
- compressed_other = other.compress_meta_key
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
37
- end
38
- i += 1
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
39
54
  end
55
+ else
56
+ me == other
40
57
  end
41
-
42
- def ==(other)
43
- compressed_me = compress_meta_key
44
- compressed_other = other.compress_meta_key
45
- compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| i[0] == i[1] }
46
- end
47
-
48
- def compress_meta_key
49
- inject([]) { |result, key|
50
- if result.size > 0 and result.last == "\e".ord
51
- result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
52
- else
53
- result << key
54
- end
55
- result
56
- }
57
- end
58
-
59
- def bytes
60
- self
58
+ when Reline::Key
59
+ if other.is_a?(Integer)
60
+ me.combined_char == other
61
+ else
62
+ me == other
61
63
  end
62
64
  end
63
- }
64
-
65
- def initialize(config)
66
- @config = config
67
65
  end
68
66
 
69
67
  def match_status(input)
70
68
  key_mapping.keys.select { |lhs|
71
- lhs.start_with? input
69
+ start_with?(lhs, input)
72
70
  }.tap { |it|
73
- return :matched if it.size == 1 && (it[0] == input)
74
- return :matching if it.size == 1 && (it[0] != input)
71
+ return :matched if it.size == 1 && equal?(it[0], input)
72
+ return :matching if it.size == 1 && !equal?(it[0], input)
75
73
  return :matched if it.max_by(&:size)&.size&.< input.size
76
74
  return :matching if it.size > 1
77
75
  }
78
76
  key_mapping.keys.select { |lhs|
79
- input.start_with? lhs
77
+ start_with?(input, lhs)
80
78
  }.tap { |it|
81
79
  return it.size > 0 ? :matched : :unmatched
82
80
  }
83
81
  end
84
82
 
85
83
  def expand(input)
86
- input = input.compress_meta_key
87
- lhs = key_mapping.keys.select { |item| input.start_with? item }.sort_by(&:size).last
84
+ input = compress_meta_key(input)
85
+ lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
88
86
  return input unless lhs
89
87
  rhs = key_mapping[lhs]
90
88