class SyntaxSuggest::AroundBlockScan

This class is useful for exploring contents before and after a block

It searches above and below the passed in block to match for whatever criteria you give it:

Example:

def dog         # 1
  puts "bark"   # 2
  puts "bark"   # 3
end             # 4

scan = AroundBlockScan.new(
  code_lines: code_lines
  block: CodeBlock.new(lines: code_lines[1])
)

scan.scan_while { true }

puts scan.before_index # => 0
puts scan.after_index  # => 3

Contents can also be filtered using AroundBlockScan#skip

To grab the next surrounding indentation use AroundBlockScan#scan_adjacent_indent

Public Class Methods

new(code_lines:, block:) click to toggle source
# File syntax_suggest/around_block_scan.rb, line 31
def initialize(code_lines:, block:)
  @code_lines = code_lines
  @orig_before_index = block.lines.first.index
  @orig_after_index = block.lines.last.index
  @orig_indent = block.current_indent
  @skip_array = []
  @after_array = []
  @before_array = []
  @stop_after_kw = false

  @skip_hidden = false
  @skip_empty = false
end

Public Instance Methods

after_index() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 212
def after_index
  @after_index ||= @orig_after_index
end
before_index() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 208
def before_index
  @before_index ||= @orig_before_index
end
capture_neighbor_context() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 108
def capture_neighbor_context
  lines = []
  kw_count = 0
  end_count = 0
  before_lines.reverse_each do |line|
    next if line.empty?
    break if line.indent < @orig_indent
    next if line.indent != @orig_indent

    kw_count += 1 if line.is_kw?
    end_count += 1 if line.is_end?
    if kw_count != 0 && kw_count == end_count
      lines << line
      break
    end

    lines << line
  end

  lines.reverse!

  kw_count = 0
  end_count = 0
  after_lines.each do |line|
    next if line.empty?
    break if line.indent < @orig_indent
    next if line.indent != @orig_indent

    kw_count += 1 if line.is_kw?
    end_count += 1 if line.is_end?
    if kw_count != 0 && kw_count == end_count
      lines << line
      break
    end

    lines << line
  end

  lines
end
code_block() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 200
def code_block
  CodeBlock.new(lines: lines)
end
lines() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 204
def lines
  @code_lines[before_index..after_index]
end
next_down() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 177
def next_down
  @code_lines[after_index.next]
end
next_up() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 173
def next_up
  @code_lines[before_index.pred]
end
on_falling_indent() { |line| ... } click to toggle source
# File syntax_suggest/around_block_scan.rb, line 149
def on_falling_indent
  last_indent = @orig_indent
  before_lines.reverse_each do |line|
    next if line.empty?
    if line.indent < last_indent
      yield line
      last_indent = line.indent
    end
  end

  last_indent = @orig_indent
  after_lines.each do |line|
    next if line.empty?
    if line.indent < last_indent
      yield line
      last_indent = line.indent
    end
  end
end
scan_adjacent_indent() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 181
def scan_adjacent_indent
  before_after_indent = []
  before_after_indent << (next_up&.indent || 0)
  before_after_indent << (next_down&.indent || 0)

  indent = before_after_indent.min
  scan_while { |line| line.not_empty? && line.indent >= indent }

  self
end
scan_neighbors() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 169
def scan_neighbors
  scan_while { |line| line.not_empty? && line.indent >= @orig_indent }
end
scan_while() { |line| ... } click to toggle source
# File syntax_suggest/around_block_scan.rb, line 62
def scan_while
  stop_next = false

  kw_count = 0
  end_count = 0
  index = before_lines.reverse_each.take_while do |line|
    next false if stop_next
    next true if @skip_hidden && line.hidden?
    next true if @skip_empty && line.empty?

    kw_count += 1 if line.is_kw?
    end_count += 1 if line.is_end?
    if @stop_after_kw && kw_count > end_count
      stop_next = true
    end

    yield line
  end.last&.index

  if index && index < before_index
    @before_index = index
  end

  stop_next = false
  kw_count = 0
  end_count = 0
  index = after_lines.take_while do |line|
    next false if stop_next
    next true if @skip_hidden && line.hidden?
    next true if @skip_empty && line.empty?

    kw_count += 1 if line.is_kw?
    end_count += 1 if line.is_end?
    if @stop_after_kw && end_count > kw_count
      stop_next = true
    end

    yield line
  end.last&.index

  if index && index > after_index
    @after_index = index
  end
  self
end
skip(name) click to toggle source
# File syntax_suggest/around_block_scan.rb, line 45
def skip(name)
  case name
  when :hidden?
    @skip_hidden = true
  when :empty?
    @skip_empty = true
  else
    raise "Unsupported skip #{name}"
  end
  self
end
start_at_next_line() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 192
def start_at_next_line
  before_index
  after_index
  @before_index -= 1
  @after_index += 1
  self
end
stop_after_kw() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 57
def stop_after_kw
  @stop_after_kw = true
  self
end

Private Instance Methods

after_lines() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 220
        def after_lines
  @code_lines[after_index.next..-1] || []
end
before_lines() click to toggle source
# File syntax_suggest/around_block_scan.rb, line 216
        def before_lines
  @code_lines[0...before_index] || []
end