Class: SXP::Generator
Overview
An S-expression generator.
Takes an object and pretty-prints it using reasonable indentation rules
Defined Under Namespace
Classes: Block
Class Method Summary collapse
-
.print(*sxps) ⇒ Object
Format S-expressions to STDOUT.
-
.string(*sxps) ⇒ Object
Format S-expressions to a String.
-
.write(out, *sxps) ⇒ Object
Write formatted S-expressions to an IO like object.
Instance Method Summary collapse
-
#initialize(buffer) ⇒ Generator
constructor
Initialize output with a stack of IO buffers.
-
#render(sexp) ⇒ Block
Render an element.
Constructor Details
#initialize(buffer) ⇒ Generator
Initialize output with a stack of IO buffers
151 152 153 |
# File 'lib/sxp/generator.rb', line 151 def initialize(buffer) @output = buffer end |
Class Method Details
.print(*sxps) ⇒ Object
Format S-expressions to STDOUT
129 130 131 |
# File 'lib/sxp/generator.rb', line 129 def self.print(*sxps) write($stdout, *sxps) end |
.string(*sxps) ⇒ Object
Format S-expressions to a String
117 118 119 120 121 122 |
# File 'lib/sxp/generator.rb', line 117 def self.string(*sxps) require 'stringio' unless defined?(StringIO) buf = StringIO.new write(buf, *sxps) buf.string end |
.write(out, *sxps) ⇒ Object
Write formatted S-expressions to an IO like object
139 140 141 142 143 144 145 |
# File 'lib/sxp/generator.rb', line 139 def self.write(out, *sxps) generator = self.new(out) sxps.each do |sxp| generator.render(sxp) end generator end |
Instance Method Details
#render(sexp) ⇒ Block
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.
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/sxp/generator.rb', line 167 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 |