feat: templates
This commit is contained in:
@@ -161,6 +161,15 @@ def _parse_line(keyword: str, args: list[str], line_num: int) -> IRNode:
|
||||
return Box(title=title, weight=weight, source_line=line_num)
|
||||
|
||||
elif keyword == "row":
|
||||
# Table row (has | separators) vs layout Row (has gap number or nothing)
|
||||
raw = " ".join(args)
|
||||
if "|" in raw:
|
||||
# Split by | and strip quotes from each cell, preserving @modifiers
|
||||
cells: list[str] = []
|
||||
for part in raw.split("|"):
|
||||
cell = part.strip().strip('"')
|
||||
cells.append(cell)
|
||||
return _TableRow(cells, line_num)
|
||||
gap = int(args[0]) if args else 1
|
||||
return Row(gap=gap, source_line=line_num)
|
||||
|
||||
@@ -263,10 +272,41 @@ def _parse_line(keyword: str, args: list[str], line_num: int) -> IRNode:
|
||||
state = args[1] if len(args) > 1 else "unknown"
|
||||
return Status(label=label, state=state, source_line=line_num)
|
||||
|
||||
elif keyword == "table":
|
||||
title = args[0] if args else ""
|
||||
return Table(title=title, source_line=line_num)
|
||||
|
||||
elif keyword == "columns":
|
||||
# columns "Name" 24 | "Hops" 6 | "Status" 10
|
||||
# Re-join args and split by |
|
||||
raw = " ".join(args)
|
||||
cols: list[tuple[str, int]] = []
|
||||
for part in raw.split("|"):
|
||||
tokens = _split_args(part.strip())
|
||||
if tokens:
|
||||
col_name = tokens[0]
|
||||
col_w = int(tokens[1]) if len(tokens) > 1 else 0
|
||||
cols.append((col_name, col_w))
|
||||
return _TableColumns(cols, line_num)
|
||||
|
||||
else:
|
||||
raise ParseError(f"Unknown keyword: {keyword!r}", line=line_num)
|
||||
|
||||
|
||||
class _TableColumns(IRNode):
|
||||
"""Temporary node — absorbed by parent Table during tree building."""
|
||||
def __init__(self, columns: list[tuple[str, int]], line_num: int):
|
||||
super().__init__(source_line=line_num)
|
||||
self.columns = columns
|
||||
|
||||
|
||||
class _TableRow(IRNode):
|
||||
"""Temporary node — absorbed by parent Table during tree building."""
|
||||
def __init__(self, cells: list[str], line_num: int):
|
||||
super().__init__(source_line=line_num)
|
||||
self.cells = cells
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Style directives — pseudo-nodes that modify their parent's style
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -326,6 +366,17 @@ def parse(source: str) -> Page:
|
||||
setattr(parent.style, node.attr, node.value)
|
||||
continue
|
||||
|
||||
# Table children: columns and rows are absorbed by the Table node
|
||||
if isinstance(node, _TableColumns):
|
||||
if stack and isinstance(stack[-1][1], Table):
|
||||
stack[-1][1].columns = node.columns
|
||||
continue
|
||||
|
||||
if isinstance(node, _TableRow):
|
||||
if stack and isinstance(stack[-1][1], Table):
|
||||
stack[-1][1].rows.append(node.cells)
|
||||
continue
|
||||
|
||||
# Attach to parent
|
||||
if stack:
|
||||
parent = stack[-1][1]
|
||||
|
||||
Reference in New Issue
Block a user