class SXP::Generator
An S-expression generator.
Takes an object and pretty-prints it using reasonable indentation rules
Public Class Methods
Initialize output with a stack of IO buffers
@param [#write] buffer
# File lib/sxp/generator.rb, line 127 def initialize(buffer) @output = buffer end
Format S-expressions to STDOUT
@param [Array] sxps @return [Object]
# File lib/sxp/generator.rb, line 105 def self.print(*sxps) write($stdout, *sxps) end
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 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 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