class RubyLex

def process_indent_level(tokens, lines, line_index, is_newline)

def process_indent_level(tokens, lines, line_index, is_newline)
  line_results = IRB::NestingParser.parse_by_line(tokens)
  result = line_results[line_index]
  if result
    _tokens, prev_opens, next_opens, min_depth = result
  else
    # When last line is empty
    prev_opens = next_opens = line_results.last[2]
    min_depth = next_opens.size
  end
  # To correctly indent line like `end.map do`, we use shortest open tokens on each line for indent calculation.
  # Shortest open tokens can be calculated by `opens.take(min_depth)`
  indent = 2 * calc_indent_level(prev_opens.take(min_depth))
  preserve_indent = lines[line_index - (is_newline ? 1 : 0)][/^ */].size
  prev_open_token = prev_opens.last
  next_open_token = next_opens.last
  # Calculates base indent for pasted code on the line where prev_open_token is located
  # irb(main):001:1*   if a # base_indent is 2, indent calculated from tokens is 0
  # irb(main):002:1*         if b # base_indent is 6, indent calculated from tokens is 2
  # irb(main):003:0>           c # base_indent is 6, indent calculated from tokens is 4
  if prev_open_token
    base_indent = [0, indent_difference(lines, line_results, prev_open_token.pos[0] - 1)].max
  else
    base_indent = 0
  end
  if free_indent_token?(prev_open_token)
    if is_newline && prev_open_token.pos[0] == line_index
      # First newline inside free-indent token
      base_indent + indent
    else
      # Accept any number of indent inside free-indent token
      preserve_indent
    end
  elsif prev_open_token&.event == :on_embdoc_beg || next_open_token&.event == :on_embdoc_beg
    if prev_open_token&.event == next_open_token&.event
      # Accept any number of indent inside embdoc content
      preserve_indent
    else
      # =begin or =end
      0
    end
  elsif prev_open_token&.event == :on_heredoc_beg
    tok = prev_open_token.tok
    if prev_opens.size <= next_opens.size
      if is_newline && lines[line_index].empty? && line_results[line_index - 1][1].last != next_open_token
        # First line in heredoc
        tok.match?(/^<<[-~]/) ? base_indent + indent : indent
      elsif tok.match?(/^<<~/)
        # Accept extra indent spaces inside `<<~` heredoc
        [base_indent + indent, preserve_indent].max
      else
        # Accept any number of indent inside other heredoc
        preserve_indent
      end
    else
      # Heredoc close
      prev_line_indent_level = calc_indent_level(prev_opens)
      tok.match?(/^<<[~-]/) ? base_indent + 2 * (prev_line_indent_level - 1) : 0
    end
  else
    base_indent + indent
  end
end