153 lines
4.1 KiB
Plaintext
153 lines
4.1 KiB
Plaintext
Heading 2 Document API
|
|
class mt-12
|
|
|
|
Markdown
|
|
The Document API provides a higher-level interface for parsing Terrace documents with Python idioms and best practices.
|
|
|
|
Heading 3 TerraceDocument
|
|
class mt-8 mb-4
|
|
|
|
Markdown
|
|
Main document iterator for Terrace documents that supports Python's iteration protocols.
|
|
|
|
CodeBlock python
|
|
class TerraceDocument:
|
|
"""Main document iterator for Terrace documents"""
|
|
|
|
def __init__(self, reader: Reader, indent: str = ' '):
|
|
"""Create a new TerraceDocument with the given reader"""
|
|
|
|
def __iter__(self) -> Iterator[TerraceNode]:
|
|
"""Make the document iterable"""
|
|
|
|
Heading 3 TerraceNode
|
|
class mt-8 mb-4
|
|
|
|
Markdown
|
|
Represents a single node/line in a Terrace document with convenient property access.
|
|
|
|
CodeBlock python
|
|
class TerraceNode:
|
|
"""Represents a single node/line in a Terrace document"""
|
|
|
|
@property
|
|
def head(self) -> str:
|
|
"""Get the first word of the line"""
|
|
|
|
@property
|
|
def tail(self) -> str:
|
|
"""Get everything after the first word"""
|
|
|
|
@property
|
|
def content(self) -> str:
|
|
"""Get the line content without indentation"""
|
|
|
|
@property
|
|
def level(self) -> int:
|
|
"""Get the indentation level"""
|
|
|
|
@property
|
|
def line_number(self) -> int:
|
|
"""Get the line number (zero-indexed)"""
|
|
|
|
def is_(self, value: str) -> bool:
|
|
"""Check if the head matches the given value"""
|
|
|
|
def is_empty(self) -> bool:
|
|
"""Check if the line is empty/blank"""
|
|
|
|
def raw(self, offset: Optional[int] = None) -> str:
|
|
"""Get raw content with custom offset"""
|
|
|
|
def children(self) -> Generator[TerraceNode, None, None]:
|
|
"""Iterate through all descendant nodes"""
|
|
|
|
def siblings(self) -> Generator[TerraceNode, None, None]:
|
|
"""Iterate through sibling nodes at the same level"""
|
|
|
|
Heading 3 Factory Functions
|
|
class mt-8 mb-4
|
|
|
|
CodeBlock python
|
|
def use_document(reader: Reader, indent: str = ' ') -> TerraceDocument:
|
|
"""Create a new Terrace document iterator"""
|
|
|
|
# Convenience functions for creating readers
|
|
def create_string_reader(content: str) -> Reader:
|
|
"""Create a reader from a string"""
|
|
|
|
def create_file_reader(file_path: str) -> Reader:
|
|
"""Create a reader from a file path"""
|
|
|
|
def create_lines_reader(lines: List[str]) -> Reader:
|
|
"""Create a reader from a list of lines"""
|
|
|
|
Heading 3 Usage Examples
|
|
class mt-8 mb-4
|
|
|
|
Markdown
|
|
**Basic Document Iteration**
|
|
|
|
CodeBlock python
|
|
from terrace import use_document, create_string_reader
|
|
|
|
content = """
|
|
title My Document
|
|
section Introduction
|
|
paragraph This is an example.
|
|
section Conclusion
|
|
paragraph That's all!
|
|
"""
|
|
|
|
reader = create_string_reader(content)
|
|
doc = use_document(reader)
|
|
|
|
for node in doc:
|
|
if node.is_('title'):
|
|
print(f"Document title: {node.tail}")
|
|
elif node.is_('section'):
|
|
print(f"Section: {node.tail} (level {node.level})")
|
|
elif node.is_('paragraph'):
|
|
print(f" - {node.tail}")
|
|
|
|
Markdown
|
|
**Working with Child Nodes**
|
|
|
|
CodeBlock python
|
|
from terrace import use_document, create_string_reader
|
|
|
|
content = """
|
|
config
|
|
database
|
|
host localhost
|
|
port 5432
|
|
server
|
|
port 8080
|
|
"""
|
|
|
|
reader = create_string_reader(content)
|
|
doc = use_document(reader)
|
|
|
|
for node in doc:
|
|
if node.is_('config'):
|
|
print("Configuration:")
|
|
for child in node.children():
|
|
print(f" {child.head}: {child.tail}")
|
|
for grandchild in child.children():
|
|
print(f" {grandchild.head}: {grandchild.tail}")
|
|
|
|
Markdown
|
|
**Functional Programming Style**
|
|
|
|
CodeBlock python
|
|
# Filter nodes by predicate
|
|
titles = doc.filter(lambda node: node.is_('title'))
|
|
|
|
# Find first matching node
|
|
first_section = doc.find(lambda node: node.is_('section'))
|
|
|
|
# Map nodes to values
|
|
all_heads = doc.map(lambda node: node.head)
|
|
|
|
# Convert to list
|
|
all_nodes = doc.to_list() |