class Rufo::Formatter

def initialize(code, **options)

def initialize(code, **options)
  @code = code
  @tokens = Ripper.lex(code).reverse!
  @sexp = Ripper.sexp(code)
  unless @sexp
    raise ::Rufo::SyntaxError.new
  end
  @indent = 0
  @line = 0
  @column = 0
  @last_was_newline = false
  @output = ""
  # The column of a `obj.method` call, so we can align
  # calls to that dot
  @dot_column = nil
  # The column of a `obj.method` call, but only the name part,
  # so we can also align arguments accordingly
  @name_dot_column = nil
  # Heredocs list, associated with calls ([heredoc, tilde])
  @heredocs = []
  # Current node, to be able to associate it to heredocs
  @current_node = nil
  # The current heredoc being printed
  @current_heredoc = nil
  # The current hash or call or method that has hash-like parameters
  @current_hash = nil
  # Map lines to commands that start at the begining of a line with the following info:
  # - line indent
  # - first param indent
  # - first line ends with '(', '[' or '{'?
  # - line of matching pair of the previous item
  # - last line of that call
  #
  # This is needed to dedent some calls that look like this:
  #
  # foo bar(
  #   2,
  # )
  #
  # Without the dedent it would normally look like this:
  #
  # foo bar(
  #       2,
  #     )
  #
  # Because the formatter aligns this to the first parameter in the call.
  # However, for these cases it's better to not align it like that.
  @line_to_call_info = {}
  # Each line that belongs to a heredoc content is put here
  @heredoc_lines = {}
  # Position of comments that occur at the end of a line
  @comments_positions = []
  # Associate lines to alignments
  # Associate a line to an index inside @comments_position
  # becuase when aligning something to the left of a comment
  # we need to adjust the relative comment
  @line_to_alignments_positions = Hash.new { |h, k| h[k] = [] }
  # Position of assignments
  @assignments_positions = []
  # Range of assignment (line => end_line)
  #
  # We need this because when we have to format:
  #
  # ```
  # abc = 1
  # a = foo bar: 2
  #         baz: #
  # ```
  #
  # Because we'll insert two spaces after `a`, this will
  # result in a mis-alignment for baz (and possibly other lines
  # below it). So, we remember the line ranges of an assignment,
  # and once we align the first one we fix the other ones.
  @assignments_ranges = {}
  # Hash keys positions
  @hash_keys_positions = []
  # Case when positions
  @case_when_positions = []
  # Settings
  indent_size options.fetch(:indent_size, 2)
  space_after_hash_brace options.fetch(:space_after_hash_brace, :dynamic)
  space_after_array_bracket options.fetch(:space_after_array_bracket, :never)
  align_comments options.fetch(:align_comments, true)
  align_assignments options.fetch(:align_assignments, false)
  align_hash_keys options.fetch(:align_hash_keys, true)
  align_case_when options.fetch(:align_case_when, true)
  align_chained_calls options.fetch(:align_chained_calls, true)
  preserve_whitespace options.fetch(:preserve_whitespace, true)
  trailing_commas options.fetch(:trailing_commas, :always)
end