class SyntaxTree::Formatter

comments.
A slightly enhanced PP that knows how to format recursively including

def self.format(source, node, base_indentation = 0)

def self.format(source, node, base_indentation = 0)
  q = new(source, [])
  q.format(node)
  q.flush(base_indentation)
  q.output.join
end

def format(node, stackable: true)

def format(node, stackable: true)
  stack << node if stackable
  doc = nil
  # If there are comments, then we're going to format them around the node
  # so that they get printed properly.
  if node.comments.any?
    trailing = []
    last_leading = nil
    # First, we're going to print all of the comments that were found before
    # the node. We'll also gather up any trailing comments that we find.
    node.comments.each do |comment|
      if comment.leading?
        comment.format(self)
        breakable(force: true)
        last_leading = comment
      else
        trailing << comment
      end
    end
    # If the node has a stree-ignore comment right before it, then we're
    # going to just print out the node as it was seen in the source.
    doc =
      if last_leading&.ignore?
        range = source[node.start_char...node.end_char]
        first = true
        range.each_line(chomp: true) do |line|
          if first
            first = false
          else
            breakable_return
          end
          text(line)
        end
        breakable_return if range.end_with?("\n")
      else
        node.format(self)
      end
    # Print all comments that were found after the node.
    trailing.each do |comment|
      line_suffix(priority: COMMENT_PRIORITY) do
        comment.inline? ? text(" ") : breakable
        comment.format(self)
        break_parent
      end
    end
  else
    doc = node.format(self)
  end
  stack.pop if stackable
  doc
end

def format_each(nodes)

def format_each(nodes)
  nodes.each { |node| format(node) }
end

def grandparent

def grandparent
  stack[-3]
end

def group

up expensive computation time.
any of the more advanced options because we don't need them and they take
This is a simplified version of prettyprint's group. It doesn't provide
def group
  contents = []
  doc = Group.new(0, contents: contents)
  groups << doc
  target << doc
  with_target(contents) { yield }
  groups.pop
  doc
end

def initialize(source, *args, options: Options.new)

def initialize(source, *args, options: Options.new)
  super(*args)
  @source = source
  @stack = []
  # Memoizing these values to make access faster.
  @quote = options.quote
  @trailing_comma = options.trailing_comma
  @disable_auto_ternary = options.disable_auto_ternary
  @target_ruby_version = options.target_ruby_version
end

def parent

def parent
  stack[-2]
end

def parents

def parents
  stack[0...-1].reverse_each
end

def seplist(list, sep = nil, iter_method = :each)

separator proc with the instance of `self`.
A similar version to the super, except that it calls back into the
def seplist(list, sep = nil, iter_method = :each)
  first = true
  list.__send__(iter_method) do |*v|
    if first
      first = false
    elsif sep
      sep.call(self)
    else
      comma_breakable
    end
    yield(*v)
  end
end

def text(string)

calculating width by pushing the string directly onto the target.
This is a much simplified version of prettyprint's text. It avoids
def text(string)
  target << string
end