Module: Rvim::Search

Defined in:
lib/rvim/search.rb

Class Method Summary collapse

Class Method Details

.compile(pattern_str, ignorecase: false) ⇒ Object



52
53
54
55
56
57
58
# File 'lib/rvim/search.rb', line 52

def compile(pattern_str, ignorecase: false)
  return nil if pattern_str.nil? || pattern_str.empty?

  Regexp.new(pattern_str, ignorecase ? Regexp::IGNORECASE : 0)
rescue RegexpError
  nil
end

.effective_ignorecase(pattern_str, ignorecase:, smartcase:) ⇒ Object



60
61
62
63
64
65
# File 'lib/rvim/search.rb', line 60

def effective_ignorecase(pattern_str, ignorecase:, smartcase:)
  return false unless ignorecase
  return true unless smartcase

  !pattern_str.to_s.match?(/[A-Z]/)
end

.next_match(matches, line, col, direction, include_start: false, wrapscan: true) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/rvim/search.rb', line 31

def next_match(matches, line, col, direction, include_start: false, wrapscan: true)
  return nil if matches.empty?

  case direction
  when :forward
    forward = if include_start
      matches.find { |l, s, _| l > line || (l == line && s >= col) }
    else
      matches.find { |l, s, _| l > line || (l == line && s > col) }
    end
    forward || (wrapscan ? matches.first : nil)
  when :backward
    back = if include_start
      matches.reverse_each.find { |l, _, e| l < line || (l == line && e <= col) }
    else
      matches.reverse_each.find { |l, _, e| l < line || (l == line && e < col) }
    end
    back || (wrapscan ? matches.last : nil)
  end
end

.scan(buffer_of_lines, pattern_str, ignorecase: false) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/rvim/search.rb', line 7

def scan(buffer_of_lines, pattern_str, ignorecase: false)
  pattern = compile(pattern_str, ignorecase: ignorecase)
  return [] unless pattern

  out = []
  buffer_of_lines.each_with_index do |line, line_idx|
    char_offset = 0
    while (m = pattern.match(line, char_offset))
      b = m.pre_match.bytesize
      e = b + m[0].bytesize
      if e == b
        # Zero-width match: step forward by one character to avoid infinite loop.
        char_offset = m.begin(0) + 1
        break if char_offset > line.length
      else
        out << [line_idx, b, e - 1]
        # Advance char_offset past this match.
        char_offset = m.end(0)
      end
    end
  end
  out
end