reline 0.2.8.pre.8 → 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: 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