class SXP::Generator

An S-expression generator.

Takes an object and pretty-prints it using reasonable indentation rules

Public Class Methods

new(buffer) click to toggle source

Initialize output with a stack of IO buffers

@param [#write] buffer

# File lib/sxp/generator.rb, line 127
def initialize(buffer)
  @output = buffer
end
print(*sxps) click to toggle source

Format S-expressions to STDOUT

@param [Array] sxps @return [Object]

string(*sxps) click to toggle source

Format S-expressions to a String

@param [Array] sxps @return [Object]

# File lib/sxp/generator.rb, line 93
def self.string(*sxps)
  require 'stringio' unless defined?(StringIO)
  buf = StringIO.new
  write(buf, *sxps)
  buf.string
end
write(out, *sxps) click to toggle source

Write formatted S-expressions to an IO like object

@param [Object] out @param [Array] sxps @return [Object]

# File lib/sxp/generator.rb, line 115
def self.write(out, *sxps)
  generator = self.new(out)
  sxps.each do |sxp|
    generator.render(sxp)
  end
  generator
end

Public Instance Methods

render(sexp) click to toggle source

Render an element. For Array, this recursively renders each constituent into blocks. If the agregate length of a block is less than MIN_BLOCK characters, combine each constituent block into a single line.

Rendering does not perform final formatting, but returns a recursive array of blocks which are each ultimattely formattted onto their own line with leading whitespace.

@param [Object] sexp @return [Block]

# File lib/sxp/generator.rb, line 143
def render(sexp)
  block = Block.new(sexp, 0)
  if block.length > 40
    buffer = block.formatted

    # Attempt to fold symbols and strings onto proceeding line
    output = ""
    prev_length = 0
    buffer.lines.each do |line|
      if (stripped = line.strip)[0,1] != '(' &&
        prev_length + stripped.length + 1 < Block::BLOCK_MIN_LENGTH

        # Append to previous line
        start, match, rem = output.rpartition(/\S/)
        output = start + match + " " + stripped + rem
        prev_length += stripped.length + 1
      else
        # Terminate line and append this line
        output += line
        prev_length = line.length - 1
      end
    end
    @output.write output.gsub(/\)\s+\)/, '))')
  else
    @output.puts(block.to_sxp)
  end
end