Class: ASTTransform::Layout

Inherits:
Object
  • Object
show all
Defined in:
lib/ast_transform/layout.rb

Overview

Line-addressed output: text is placed at absolute line numbers, top to bottom, and the cursor never rewinds. When a placement's target line is already behind the cursor, the text is packed (; ) onto the current line instead — Ruby lets statements share a physical line, so alignment degrades locally and the next placement whose target is still ahead re-anchors. Knows nothing about Ruby structure or ASTs; callers decide WHAT goes on WHICH line, the layout owns the pad-or-pack mechanics.

Instance Method Summary collapse

Constructor Details

#initializeLayout

Returns a new instance of Layout.



10
11
12
# File 'lib/ast_transform/layout.rb', line 10

def initialize
  @lines = []
end

Instance Method Details

#cursorObject

The line number currently being written; the next fresh line would be +cursor + 1+.



15
16
17
# File 'lib/ast_transform/layout.rb', line 15

def cursor
  @lines.size
end

#pack(text) ⇒ Object

Appends text to the current line with a ; separator. The last line is never blank here: padding blanks are only created inside place, which immediately overwrites the padded line.



45
46
47
48
49
50
51
# File 'lib/ast_transform/layout.rb', line 45

def pack(text)
  if @lines.empty?
    @lines << text
  else
    @lines[-1] = "#{@lines.last}; #{text}"
  end
end

#place(target_line, text, column: nil) ⇒ Object

Places text at target_line when the cursor hasn't passed it; otherwise packs onto the current line. Multi-line text advances the cursor by its height. When opening a fresh line, the first line is indented to column — cosmetic only (leading whitespace is never significant in emitted code), but it keeps the artifact visually close to the source. Packed text ignores the column, as do continuation lines (they keep their own relative indentation).



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/ast_transform/layout.rb', line 24

def place(target_line, text, column: nil)
  first, *rest = text.split("\n")

  if target_line && target_line > @lines.size
    @lines << '' while @lines.size < target_line
    @lines[-1] = indented(first, column)
  else
    pack(first)
  end

  @lines.concat(rest)
end

#place_on_fresh_line(text) ⇒ Object

Appends text on a new line unconditionally — for text that must never be ;-packed after a statement (e.g. keywords).



39
40
41
# File 'lib/ast_transform/layout.rb', line 39

def place_on_fresh_line(text)
  @lines << text
end

#to_sourceString

Returns the laid-out text, with a trailing newline.

Returns:

  • (String)

    the laid-out text, with a trailing newline.



54
55
56
# File 'lib/ast_transform/layout.rb', line 54

def to_source
  "#{@lines.join("\n")}\n"
end