Class: Reline::KeyStroke

Inherits:
Object
  • Object
show all
Defined in:
lib/reline/key_stroke.rb

Constant Summary collapse

ESC_BYTE =
27
CSI_PARAMETER_BYTES_RANGE =
0x30..0x3f
CSI_INTERMEDIATE_BYTES_RANGE =
(0x20..0x2f)
MATCHING =

Input exactly matches to a key sequence

:matching
MATCHED =

Input partially matches to a key sequence

:matched
MATCHING_MATCHED =

Input matches to a key sequence and the key sequence is a prefix of another key sequence

:matching_matched
UNMATCHED =

Input does not match to any key sequence

:unmatched

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, encoding) ⇒ KeyStroke

Returns a new instance of KeyStroke.



8
9
10
11
# File 'lib/reline/key_stroke.rb', line 8

def initialize(config, encoding)
  @config = config
  @encoding = encoding
end

Instance Attribute Details

#encodingObject

Returns the value of attribute encoding.



6
7
8
# File 'lib/reline/key_stroke.rb', line 6

def encoding
  @encoding
end

Instance Method Details

#expand(input) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/reline/key_stroke.rb', line 44

def expand(input)
  matched_bytes = nil
  (1..input.size).each do |i|
    bytes = input.take(i)
    status = match_status(bytes)
    matched_bytes = bytes if status == MATCHED || status == MATCHING_MATCHED
    break if status == MATCHED || status == UNMATCHED
  end
  return [[], []] unless matched_bytes

  func = key_mapping.get(matched_bytes)
  s = matched_bytes.pack('c*').force_encoding(@encoding)
  if func.is_a?(Array)
    # Perform simple macro expansion for single byte key bindings.
    # Multibyte key bindings and recursive macro expansion are not supported yet.
    marco = func.pack('c*').force_encoding(@encoding)
    keys = marco.chars.map do |c|
      f = key_mapping.get(c.bytes)
      Reline::Key.new(c, f.is_a?(Symbol) ? f : :ed_insert, false)
    end
  elsif func
    keys = [Reline::Key.new(s, func, false)]
  else
    if s.valid_encoding? && s.size == 1
      keys = [Reline::Key.new(s, :ed_insert, false)]
    else
      keys = []
    end
  end

  [keys, input.drop(matched_bytes.size)]
end

#match_status(input) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/reline/key_stroke.rb', line 22

def match_status(input)
  matching = key_mapping.matching?(input)
  matched = key_mapping.get(input)
  if matching && matched
    MATCHING_MATCHED
  elsif matching
    MATCHING
  elsif matched
    MATCHED
  elsif input[0] == ESC_BYTE
    match_unknown_escape_sequence(input, vi_mode: @config.editing_mode_is?(:vi_insert, :vi_command))
  else
    s = input.pack('c*').force_encoding(@encoding)
    if s.valid_encoding?
      s.size == 1 ? MATCHED : UNMATCHED
    else
      # Invalid string is MATCHING (part of valid string) or MATCHED (invalid bytes to be ignored)
      MATCHING_MATCHED
    end
  end
end