Heading 2 Reader API class mt-12 Markdown The Reader API provides functions and utilities for creating readers that supply lines to the Document API. Heading 3 Reader Type class mt-8 mb-4 Markdown A `Reader` is a callable that returns the next line in a document or `None` when the end is reached. CodeBlock python from typing import Optional, Callable # Type definition Reader = Callable[[], Optional[str]] Heading 3 Built-in Readers class mt-8 mb-4 Markdown **String Reader** Create a reader from a string, splitting on newlines. CodeBlock python def create_string_reader(content: str) -> Reader: """Create a reader from a string""" lines = content.split('\n') # Remove trailing empty line if content ended with newline if len(lines) > 0 and content.endswith('\n') and lines[-1] == '': lines = lines[:-1] index = 0 def reader() -> Optional[str]: nonlocal index if index >= len(lines): return None line = lines[index] index += 1 return line return reader Markdown **File Reader** Create a reader from a file path. CodeBlock python def create_file_reader(file_path: str) -> Reader: """Create a reader from a file path""" file_handle = open(file_path, 'r', encoding='utf-8') def reader() -> Optional[str]: line = file_handle.readline() if not line: file_handle.close() return None return line.rstrip('\n\r') return reader Markdown **Lines Reader** Create a reader from a list of strings. CodeBlock python def create_lines_reader(lines: List[str]) -> Reader: """Create a reader from a list of lines""" index = 0 def reader() -> Optional[str]: nonlocal index if index >= len(lines): return None line = lines[index] index += 1 return line.rstrip('\n\r') return reader Heading 3 Custom Readers class mt-8 mb-4 Markdown You can create custom readers for any data source by implementing a function that returns `Optional[str]`. CodeBlock python import json from typing import Iterator def create_json_lines_reader(file_path: str) -> Reader: """Create a reader that processes JSON Lines format""" def generator() -> Iterator[str]: with open(file_path, 'r') as f: for line in f: try: data = json.loads(line.strip()) # Convert JSON object to Terrace format yield f"entry {data.get('name', 'unnamed')}" for key, value in data.items(): if key != 'name': yield f" {key} {value}" except json.JSONDecodeError: continue iterator = generator() def reader() -> Optional[str]: try: return next(iterator) except StopIteration: return None return reader Heading 3 Usage Examples class mt-8 mb-4 Markdown **Reading from a string** CodeBlock python from terrace import use_document, create_string_reader content = """ title My Document author John Doe date 2023-12-01 """ reader = create_string_reader(content) doc = use_document(reader) for node in doc: print(f"Level {node.level}: {node.content}") Markdown **Reading from a file** CodeBlock python from terrace import use_document, create_file_reader reader = create_file_reader('document.tce') doc = use_document(reader) for node in doc: if node.is_('title'): print(f"Document: {node.tail}") Markdown **Reading from a list of lines** CodeBlock python from terrace import use_document, create_lines_reader lines = [ "config", " host localhost", " port 8080", "routes", " / home", " /api api" ] reader = create_lines_reader(lines) doc = use_document(reader) for node in doc: print(f"{' ' * node.level}{node.head}: {node.tail}")