175 lines
4.1 KiB
Plaintext
175 lines
4.1 KiB
Plaintext
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}") |