Module: Rvim::MatchMotion
- Defined in:
- lib/rvim/match_motion.rb
Constant Summary collapse
- OPEN_TO_CLOSE =
{ '(' => ')', '[' => ']', '{' => '}' }.freeze
- CLOSE_TO_OPEN =
OPEN_TO_CLOSE.invert.freeze
- BRACKETS =
(OPEN_TO_CLOSE.keys + OPEN_TO_CLOSE.values).freeze
Class Method Summary collapse
- .locate_starting_bracket(line, byte_pointer) ⇒ Object
-
.match_at(buffer_of_lines, line_index, byte_pointer) ⇒ Object
Returns [target_line, target_byte] or nil.
- .scan_backward(buffer_of_lines, line_index, start_byte, open_ch, close_ch) ⇒ Object
-
.scan_forward(buffer_of_lines, line_index, start_byte, open_ch, close_ch) ⇒ Object
‘open_ch` is the bracket we started on; `close_ch` is its match.
Class Method Details
.locate_starting_bracket(line, byte_pointer) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/rvim/match_motion.rb', line 27 def self.locate_starting_bracket(line, byte_pointer) return nil if line.empty? pos = byte_pointer.clamp(0, line.bytesize - 1) ch = line.byteslice(pos, 1) return pos if BRACKETS.include?(ch) i = pos while i < line.bytesize c = line.byteslice(i, 1) return i if BRACKETS.include?(c) i += 1 end nil end |
.match_at(buffer_of_lines, line_index, byte_pointer) ⇒ Object
Returns [target_line, target_byte] or nil. The starting bracket is the bracket at (line_index, byte_pointer); if not on a bracket, scans forward on the current line to find the first one (vim semantics).
12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/rvim/match_motion.rb', line 12 def self.match_at(buffer_of_lines, line_index, byte_pointer) line = buffer_of_lines[line_index] return nil unless line start_byte = locate_starting_bracket(line, byte_pointer) return nil unless start_byte ch = line.byteslice(start_byte, 1) if OPEN_TO_CLOSE.key?(ch) scan_forward(buffer_of_lines, line_index, start_byte, ch, OPEN_TO_CLOSE[ch]) elsif CLOSE_TO_OPEN.key?(ch) scan_backward(buffer_of_lines, line_index, start_byte, CLOSE_TO_OPEN[ch], ch) end end |
.scan_backward(buffer_of_lines, line_index, start_byte, open_ch, close_ch) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/rvim/match_motion.rb', line 69 def self.scan_backward(buffer_of_lines, line_index, start_byte, open_ch, close_ch) depth = 1 li = line_index bp = start_byte - 1 while li >= 0 line = buffer_of_lines[li] while bp >= 0 c = line.byteslice(bp, 1) if c == close_ch depth += 1 elsif c == open_ch depth -= 1 return [li, bp] if depth.zero? end bp -= 1 end li -= 1 bp = li >= 0 ? buffer_of_lines[li].bytesize - 1 : -1 end nil end |
.scan_forward(buffer_of_lines, line_index, start_byte, open_ch, close_ch) ⇒ Object
‘open_ch` is the bracket we started on; `close_ch` is its match. Walking forward, depth starts at 1 (we counted the start). When it returns to 0 we found the match.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/rvim/match_motion.rb', line 47 def self.scan_forward(buffer_of_lines, line_index, start_byte, open_ch, close_ch) depth = 1 li = line_index bp = start_byte + 1 while li < buffer_of_lines.size line = buffer_of_lines[li] while bp < line.bytesize c = line.byteslice(bp, 1) if c == open_ch depth += 1 elsif c == close_ch depth -= 1 return [li, bp] if depth.zero? end bp += 1 end li += 1 bp = 0 end nil end |