termflow-md 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- termflow_md-0.1.0/.github/workflows/ci.yml +67 -0
- termflow_md-0.1.0/.github/workflows/publish.yml +30 -0
- termflow_md-0.1.0/.gitignore +107 -0
- termflow_md-0.1.0/CHANGELOG.md +72 -0
- termflow_md-0.1.0/LICENSE +21 -0
- termflow_md-0.1.0/PKG-INFO +330 -0
- termflow_md-0.1.0/README.md +295 -0
- termflow_md-0.1.0/demo.py +244 -0
- termflow_md-0.1.0/examples/config.toml +78 -0
- termflow_md-0.1.0/pyproject.toml +119 -0
- termflow_md-0.1.0/termflow/__init__.py +58 -0
- termflow_md-0.1.0/termflow/__main__.py +6 -0
- termflow_md-0.1.0/termflow/ansi/__init__.py +103 -0
- termflow_md-0.1.0/termflow/ansi/codes.py +92 -0
- termflow_md-0.1.0/termflow/ansi/color.py +160 -0
- termflow_md-0.1.0/termflow/ansi/style.py +51 -0
- termflow_md-0.1.0/termflow/ansi/utils.py +352 -0
- termflow_md-0.1.0/termflow/cli.py +310 -0
- termflow_md-0.1.0/termflow/config/__init__.py +23 -0
- termflow_md-0.1.0/termflow/config/config.py +251 -0
- termflow_md-0.1.0/termflow/core/__init__.py +37 -0
- termflow_md-0.1.0/termflow/core/enums.py +151 -0
- termflow_md-0.1.0/termflow/core/state.py +549 -0
- termflow_md-0.1.0/termflow/parser/__init__.py +123 -0
- termflow_md-0.1.0/termflow/parser/entities.py +66 -0
- termflow_md-0.1.0/termflow/parser/events.py +352 -0
- termflow_md-0.1.0/termflow/parser/inline.py +303 -0
- termflow_md-0.1.0/termflow/parser/parser.py +662 -0
- termflow_md-0.1.0/termflow/render/__init__.py +134 -0
- termflow_md-0.1.0/termflow/render/code.py +190 -0
- termflow_md-0.1.0/termflow/render/heading.py +123 -0
- termflow_md-0.1.0/termflow/render/list.py +186 -0
- termflow_md-0.1.0/termflow/render/renderer.py +602 -0
- termflow_md-0.1.0/termflow/render/style.py +145 -0
- termflow_md-0.1.0/termflow/render/table.py +236 -0
- termflow_md-0.1.0/termflow/render/text.py +203 -0
- termflow_md-0.1.0/termflow/syntax/__init__.py +32 -0
- termflow_md-0.1.0/termflow/syntax/highlighter.py +506 -0
- termflow_md-0.1.0/test_document.md +341 -0
- termflow_md-0.1.0/tests/__init__.py +1 -0
- termflow_md-0.1.0/tests/conftest.py +162 -0
- termflow_md-0.1.0/tests/test_ansi.py +216 -0
- termflow_md-0.1.0/tests/test_config.py +213 -0
- termflow_md-0.1.0/tests/test_inline.py +175 -0
- termflow_md-0.1.0/tests/test_integration.py +348 -0
- termflow_md-0.1.0/tests/test_parser.py +353 -0
- termflow_md-0.1.0/tests/test_renderer.py +255 -0
- termflow_md-0.1.0/tests/test_syntax.py +191 -0
- termflow_md-0.1.0/uv.lock +897 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
quality:
|
|
11
|
+
name: Quality (${{ matrix.python-version }})
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout code
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Install uv
|
|
23
|
+
uses: astral-sh/setup-uv@v4
|
|
24
|
+
with:
|
|
25
|
+
enable-cache: true
|
|
26
|
+
|
|
27
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
28
|
+
run: uv python install ${{ matrix.python-version }}
|
|
29
|
+
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: uv sync --all-extras
|
|
32
|
+
|
|
33
|
+
- name: Lint with ruff
|
|
34
|
+
run: uvx ruff check .
|
|
35
|
+
|
|
36
|
+
- name: Format check with ruff
|
|
37
|
+
run: uvx ruff format --check .
|
|
38
|
+
|
|
39
|
+
- name: Type check with mypy
|
|
40
|
+
run: uv run mypy termflow --ignore-missing-imports
|
|
41
|
+
continue-on-error: true # Optional for now
|
|
42
|
+
|
|
43
|
+
- name: Run tests
|
|
44
|
+
run: uv run pytest tests/ -v --tb=short
|
|
45
|
+
|
|
46
|
+
build:
|
|
47
|
+
name: Build Package
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
steps:
|
|
50
|
+
- name: Checkout code
|
|
51
|
+
uses: actions/checkout@v4
|
|
52
|
+
|
|
53
|
+
- name: Install uv
|
|
54
|
+
uses: astral-sh/setup-uv@v4
|
|
55
|
+
|
|
56
|
+
- name: Build package
|
|
57
|
+
run: uv build
|
|
58
|
+
|
|
59
|
+
- name: Check distribution
|
|
60
|
+
run: uvx twine check dist/*
|
|
61
|
+
|
|
62
|
+
- name: Upload artifacts
|
|
63
|
+
uses: actions/upload-artifact@v4
|
|
64
|
+
with:
|
|
65
|
+
name: dist
|
|
66
|
+
path: dist/
|
|
67
|
+
retention-days: 5
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Publishes to PyPI on release
|
|
2
|
+
# Set PYPI_API_TOKEN in repo secrets
|
|
3
|
+
|
|
4
|
+
name: Publish to PyPI
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
release:
|
|
8
|
+
types: [published]
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build-publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
contents: write
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout code
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v4
|
|
22
|
+
|
|
23
|
+
- name: Build package
|
|
24
|
+
run: uv build
|
|
25
|
+
|
|
26
|
+
- name: Publish to PyPI
|
|
27
|
+
env:
|
|
28
|
+
TWINE_USERNAME: __token__
|
|
29
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
30
|
+
run: uvx twine upload dist/*
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
MANIFEST
|
|
27
|
+
|
|
28
|
+
# PyInstaller
|
|
29
|
+
*.manifest
|
|
30
|
+
*.spec
|
|
31
|
+
|
|
32
|
+
# Installer logs
|
|
33
|
+
pip-log.txt
|
|
34
|
+
pip-delete-this-directory.txt
|
|
35
|
+
|
|
36
|
+
# Unit test / coverage reports
|
|
37
|
+
htmlcov/
|
|
38
|
+
.tox/
|
|
39
|
+
.nox/
|
|
40
|
+
.coverage
|
|
41
|
+
.coverage.*
|
|
42
|
+
.cache
|
|
43
|
+
nosetests.xml
|
|
44
|
+
coverage.xml
|
|
45
|
+
*.cover
|
|
46
|
+
*.py,cover
|
|
47
|
+
.hypothesis/
|
|
48
|
+
.pytest_cache/
|
|
49
|
+
|
|
50
|
+
# Translations
|
|
51
|
+
*.mo
|
|
52
|
+
*.pot
|
|
53
|
+
|
|
54
|
+
# Environments
|
|
55
|
+
.env
|
|
56
|
+
.venv
|
|
57
|
+
env/
|
|
58
|
+
venv/
|
|
59
|
+
ENV/
|
|
60
|
+
env.bak/
|
|
61
|
+
venv.bak/
|
|
62
|
+
|
|
63
|
+
# IDE
|
|
64
|
+
.idea/
|
|
65
|
+
.vscode/
|
|
66
|
+
*.swp
|
|
67
|
+
*.swo
|
|
68
|
+
*~
|
|
69
|
+
.project
|
|
70
|
+
.pydevproject
|
|
71
|
+
.settings/
|
|
72
|
+
*.sublime-project
|
|
73
|
+
*.sublime-workspace
|
|
74
|
+
|
|
75
|
+
# Linting / Type checking
|
|
76
|
+
.ruff_cache/
|
|
77
|
+
.mypy_cache/
|
|
78
|
+
.dmypy.json
|
|
79
|
+
dmypy.json
|
|
80
|
+
|
|
81
|
+
# Jupyter Notebook
|
|
82
|
+
.ipynb_checkpoints
|
|
83
|
+
|
|
84
|
+
# pyenv
|
|
85
|
+
.python-version
|
|
86
|
+
|
|
87
|
+
# uv cache
|
|
88
|
+
.uv/
|
|
89
|
+
|
|
90
|
+
# OS files
|
|
91
|
+
.DS_Store
|
|
92
|
+
.DS_Store?
|
|
93
|
+
._*
|
|
94
|
+
.Spotlight-V100
|
|
95
|
+
.Trashes
|
|
96
|
+
ehthumbs.db
|
|
97
|
+
Thumbs.db
|
|
98
|
+
|
|
99
|
+
# Local development
|
|
100
|
+
*.local
|
|
101
|
+
*.log
|
|
102
|
+
tmp/
|
|
103
|
+
temp/
|
|
104
|
+
|
|
105
|
+
# Documentation builds
|
|
106
|
+
docs/_build/
|
|
107
|
+
site/
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to termflow will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2025-01-XX
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Initial release of termflow 🌊
|
|
15
|
+
- Streaming markdown parser with event-based architecture
|
|
16
|
+
- Terminal renderer with ANSI true-color (24-bit) support
|
|
17
|
+
- Syntax highlighting via Pygments (100+ languages supported)
|
|
18
|
+
- CLI tool (`tf`) with streaming support
|
|
19
|
+
- Configuration via TOML files
|
|
20
|
+
|
|
21
|
+
#### Markdown Support
|
|
22
|
+
|
|
23
|
+
- **Headings** (H1-H6) with distinct visual styles
|
|
24
|
+
- H1: Centered, bold, bright color with double-line underline
|
|
25
|
+
- H2: Bold, bright color with underline
|
|
26
|
+
- H3-H6: Progressively subtle styling
|
|
27
|
+
- **Code blocks** with:
|
|
28
|
+
- Unicode box drawing borders (╭╮╰╯│─)
|
|
29
|
+
- Language labels
|
|
30
|
+
- Syntax highlighting
|
|
31
|
+
- OSC 52 clipboard integration
|
|
32
|
+
- **Inline code** with background highlighting
|
|
33
|
+
- **Text formatting**: bold, italic, underline, strikethrough
|
|
34
|
+
- **Lists**:
|
|
35
|
+
- Bullet lists with cycling bullets (• ◦ ▪ ▫ ▸ ▹)
|
|
36
|
+
- Ordered lists with multiple styles (1. a) i. A))
|
|
37
|
+
- Nested lists with proper indentation
|
|
38
|
+
- **Tables** with Unicode box drawing borders
|
|
39
|
+
- **Block quotes** with vertical bar prefix
|
|
40
|
+
- **Think blocks** for LLM chain-of-thought (`<think>...</think>`)
|
|
41
|
+
- **Horizontal rules**
|
|
42
|
+
- **Links** with OSC 8 hyperlink support
|
|
43
|
+
- **Images** (displayed as alt text with 🖼 icon)
|
|
44
|
+
- **Footnotes**
|
|
45
|
+
|
|
46
|
+
#### CLI Features
|
|
47
|
+
|
|
48
|
+
- `tf <file>` - Render markdown file
|
|
49
|
+
- `cat file.md | tf` - Pipe markdown input
|
|
50
|
+
- `-w, --width` - Set terminal width
|
|
51
|
+
- `--style` - Choose color preset (default, dracula, nord, gruvbox)
|
|
52
|
+
- `--syntax-style` - Choose Pygments syntax style
|
|
53
|
+
- `--no-clipboard` - Disable OSC 52 clipboard
|
|
54
|
+
- `--no-hyperlinks` - Disable OSC 8 links
|
|
55
|
+
- `--no-pretty` - Disable decorative borders
|
|
56
|
+
- `--list-syntax-styles` - List available syntax styles
|
|
57
|
+
|
|
58
|
+
#### Configuration
|
|
59
|
+
|
|
60
|
+
- TOML configuration file support
|
|
61
|
+
- Search order: `$TERMFLOW_CONFIG` → `~/.config/termflow/config.toml` → `~/.termflow.toml`
|
|
62
|
+
- Customizable colors, features, and syntax style
|
|
63
|
+
|
|
64
|
+
#### Style Presets
|
|
65
|
+
|
|
66
|
+
- **default**: Soft, readable colors for dark backgrounds
|
|
67
|
+
- **dracula**: Purple-tinted dark theme
|
|
68
|
+
- **nord**: Arctic, bluish color scheme
|
|
69
|
+
- **gruvbox**: Warm, retro color scheme
|
|
70
|
+
|
|
71
|
+
[Unreleased]: https://github.com/username/termflow/compare/v0.1.0...HEAD
|
|
72
|
+
[0.1.0]: https://github.com/username/termflow/releases/tag/v0.1.0
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 termflow contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: termflow-md
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A streaming markdown renderer for modern terminals
|
|
5
|
+
Project-URL: Homepage, https://github.com/mpfaffenberger/termflow
|
|
6
|
+
Project-URL: Repository, https://github.com/mpfaffenberger/termflow
|
|
7
|
+
Project-URL: Documentation, https://github.com/mpfaffenberger/termflow#readme
|
|
8
|
+
Project-URL: Issues, https://github.com/mpfaffenberger/termflow/issues
|
|
9
|
+
Author-email: Your Name <your.email@example.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ansi,cli,markdown,renderer,streaming,syntax-highlighting,terminal
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Terminals
|
|
23
|
+
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Requires-Dist: pygments>=2.17.0
|
|
27
|
+
Requires-Dist: wcwidth>=0.2.12
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: mypy>=1.10.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: twine>=6.0.0; extra == 'dev'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
<div align="center">
|
|
37
|
+
|
|
38
|
+
<!-- Logo placeholder -->
|
|
39
|
+
<!-- <img src="assets/logo.png" alt="termflow logo" width="200"/> -->
|
|
40
|
+
|
|
41
|
+
# termflow 🌊
|
|
42
|
+
|
|
43
|
+
**A streaming markdown renderer for modern terminals**
|
|
44
|
+
|
|
45
|
+
[](https://pypi.org/project/termflow/)
|
|
46
|
+
[](https://pypi.org/project/termflow/)
|
|
47
|
+
[](https://opensource.org/licenses/MIT)
|
|
48
|
+
[](https://github.com/your-username/termflow/actions)
|
|
49
|
+
|
|
50
|
+
*Perfect for rendering LLM output in real-time.*
|
|
51
|
+
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## ✨ Features
|
|
57
|
+
|
|
58
|
+
- **📡 Streaming Rendering** - Render markdown as it arrives, line by line
|
|
59
|
+
- **🎨 Syntax Highlighting** - Beautiful code blocks powered by Pygments
|
|
60
|
+
- **📊 Tables** - Full support for GitHub-flavored markdown tables
|
|
61
|
+
- **📝 Lists** - Ordered, unordered, and nested lists with smart indentation
|
|
62
|
+
- **💻 Code Blocks** - Fenced code blocks with language detection and clipboard support
|
|
63
|
+
- **💭 Think Blocks** - Special rendering for `<think>` tags (great for LLM chain-of-thought)
|
|
64
|
+
- **🔗 Hyperlinks** - OSC 8 clickable links in supported terminals
|
|
65
|
+
- **📋 Clipboard** - OSC 52 clipboard integration for code blocks
|
|
66
|
+
- **🎛️ Configurable** - Customize colors, styles, and features via TOML config
|
|
67
|
+
- **⚡ Fast** - Lightweight and performant, minimal dependencies
|
|
68
|
+
|
|
69
|
+
## 🚀 Quick Installation
|
|
70
|
+
|
|
71
|
+
### Using uvx (recommended)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uvx termflow
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Using pip
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install termflow-md
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### From source
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
git clone https://github.com/your-username/termflow.git
|
|
87
|
+
cd termflow
|
|
88
|
+
pip install -e ".[dev]"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 📖 Usage
|
|
92
|
+
|
|
93
|
+
### Command Line
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Render a file
|
|
97
|
+
tf README.md
|
|
98
|
+
|
|
99
|
+
# Pipe markdown content
|
|
100
|
+
echo "# Hello World" | tf
|
|
101
|
+
|
|
102
|
+
# Pipe from LLM output
|
|
103
|
+
curl -s https://api.example.com/chat | tf
|
|
104
|
+
|
|
105
|
+
# Set terminal width
|
|
106
|
+
tf -w 100 document.md
|
|
107
|
+
|
|
108
|
+
# Use a color preset
|
|
109
|
+
tf --style dracula README.md
|
|
110
|
+
|
|
111
|
+
# Use a syntax highlighting theme
|
|
112
|
+
tf --syntax-style nord file.md
|
|
113
|
+
|
|
114
|
+
# Disable clipboard integration
|
|
115
|
+
tf --no-clipboard document.md
|
|
116
|
+
|
|
117
|
+
# List available syntax styles
|
|
118
|
+
tf --list-syntax-styles
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### CLI Options
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
usage: tf [-h] [-w N] [-c PATH] [--style {default,dracula,nord,gruvbox}]
|
|
125
|
+
[--syntax-style NAME] [--list-syntax-styles] [--no-clipboard]
|
|
126
|
+
[--no-hyperlinks] [--no-pretty] [-V]
|
|
127
|
+
[file]
|
|
128
|
+
|
|
129
|
+
options:
|
|
130
|
+
-h, --help show this help message and exit
|
|
131
|
+
-w, --width N Terminal width (default: auto-detect)
|
|
132
|
+
-c, --config PATH Path to config file
|
|
133
|
+
--style PRESET Color style preset (default, dracula, nord, gruvbox)
|
|
134
|
+
--syntax-style NAME Pygments syntax highlighting style
|
|
135
|
+
--list-syntax-styles List available syntax highlighting styles
|
|
136
|
+
--no-clipboard Disable OSC 52 clipboard for code blocks
|
|
137
|
+
--no-hyperlinks Disable OSC 8 hyperlinks
|
|
138
|
+
--no-pretty Disable pretty code block borders
|
|
139
|
+
-V, --version show program's version number and exit
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Programmatic Usage
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from termflow import Parser, Renderer, render_markdown
|
|
146
|
+
|
|
147
|
+
# Quick rendering to stdout
|
|
148
|
+
render_markdown("# Hello World!")
|
|
149
|
+
|
|
150
|
+
# Render to a file or buffer
|
|
151
|
+
from io import StringIO
|
|
152
|
+
|
|
153
|
+
output = StringIO()
|
|
154
|
+
render_markdown("# Hello\n\nThis is **bold** text.", output=output)
|
|
155
|
+
print(output.getvalue())
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Streaming Mode
|
|
159
|
+
|
|
160
|
+
For real-time rendering of streaming content (e.g., LLM responses):
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
from termflow import Parser, Renderer
|
|
164
|
+
import sys
|
|
165
|
+
|
|
166
|
+
# Create parser and renderer
|
|
167
|
+
parser = Parser()
|
|
168
|
+
renderer = Renderer(output=sys.stdout, width=80)
|
|
169
|
+
|
|
170
|
+
# Process markdown line by line as it streams in
|
|
171
|
+
for line in markdown_stream:
|
|
172
|
+
events = parser.parse_line(line)
|
|
173
|
+
renderer.render_all(events)
|
|
174
|
+
|
|
175
|
+
# Finalize to close any open blocks
|
|
176
|
+
renderer.render_all(parser.finalize())
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Custom Styling
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
from termflow import Renderer, RenderStyle, RenderFeatures
|
|
183
|
+
from io import StringIO
|
|
184
|
+
|
|
185
|
+
# Use a preset style
|
|
186
|
+
style = RenderStyle.dracula() # or .nord(), .gruvbox()
|
|
187
|
+
|
|
188
|
+
# Or create a custom style
|
|
189
|
+
style = RenderStyle(
|
|
190
|
+
bright="#87ceeb", # Main accent color
|
|
191
|
+
head="#98fb98", # Heading color
|
|
192
|
+
symbol="#dda0dd", # Bullets, borders
|
|
193
|
+
link="#87cefa", # Link color
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# Configure features
|
|
197
|
+
features = RenderFeatures(
|
|
198
|
+
clipboard=True, # OSC 52 clipboard support
|
|
199
|
+
hyperlinks=True, # OSC 8 clickable links
|
|
200
|
+
pretty_pad=True, # Pretty code block borders
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# Create renderer with custom config
|
|
204
|
+
output = StringIO()
|
|
205
|
+
renderer = Renderer(
|
|
206
|
+
output=output,
|
|
207
|
+
width=100,
|
|
208
|
+
style=style,
|
|
209
|
+
features=features,
|
|
210
|
+
)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## 🔧 Configuration
|
|
214
|
+
|
|
215
|
+
Create a config file at `~/.config/termflow/config.toml`:
|
|
216
|
+
|
|
217
|
+
```toml
|
|
218
|
+
# Terminal width (null = auto-detect)
|
|
219
|
+
width = null
|
|
220
|
+
max_width = 120
|
|
221
|
+
|
|
222
|
+
# Pygments syntax highlighting style
|
|
223
|
+
syntax_style = "monokai"
|
|
224
|
+
|
|
225
|
+
# Color scheme
|
|
226
|
+
[style]
|
|
227
|
+
bright = "#87ceeb" # Main accent color
|
|
228
|
+
head = "#98fb98" # Heading color
|
|
229
|
+
symbol = "#dda0dd" # Bullets, table borders, code block borders
|
|
230
|
+
grey = "#808080" # Muted text
|
|
231
|
+
dark = "#404040" # Dark accents
|
|
232
|
+
mid = "#a0a0a0" # Medium text
|
|
233
|
+
light = "#d0d0d0" # Light accents
|
|
234
|
+
link = "#87cefa" # Hyperlink color
|
|
235
|
+
error = "#ff6b6b" # Error messages
|
|
236
|
+
|
|
237
|
+
# Feature toggles
|
|
238
|
+
[features]
|
|
239
|
+
clipboard = true # OSC 52 clipboard for code blocks
|
|
240
|
+
hyperlinks = true # OSC 8 clickable links
|
|
241
|
+
pretty_pad = true # Pretty unicode borders on code blocks
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
You can also set the config path via environment variable:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
export TERMFLOW_CONFIG=/path/to/config.toml
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## 🎨 Style Presets
|
|
251
|
+
|
|
252
|
+
termflow includes several built-in color presets:
|
|
253
|
+
|
|
254
|
+
| Preset | Description |
|
|
255
|
+
|--------|-------------|
|
|
256
|
+
| `default` | Soft pastel colors |
|
|
257
|
+
| `dracula` | Purple-tinted dark theme |
|
|
258
|
+
| `nord` | Arctic, bluish color palette |
|
|
259
|
+
| `gruvbox` | Retro, earthy colors |
|
|
260
|
+
|
|
261
|
+
Use them via CLI:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
tf --style dracula README.md
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Or programmatically:
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
from termflow import RenderStyle
|
|
271
|
+
|
|
272
|
+
style = RenderStyle.dracula()
|
|
273
|
+
style = RenderStyle.nord()
|
|
274
|
+
style = RenderStyle.gruvbox()
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## 💭 Think Block Support
|
|
278
|
+
|
|
279
|
+
termflow has special support for `<think>` blocks, commonly used in LLM
|
|
280
|
+
chain-of-thought prompting:
|
|
281
|
+
|
|
282
|
+
```markdown
|
|
283
|
+
<think>
|
|
284
|
+
Let me reason through this step by step...
|
|
285
|
+
1. First, I'll analyze the problem
|
|
286
|
+
2. Then, I'll formulate a solution
|
|
287
|
+
</think>
|
|
288
|
+
|
|
289
|
+
Here's my answer based on my reasoning above.
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Think blocks are rendered with a distinct style to visually separate the
|
|
293
|
+
model's reasoning from its final response.
|
|
294
|
+
|
|
295
|
+
## 🦀 Origin
|
|
296
|
+
|
|
297
|
+
termflow is a Python port of [streamdown-rs](https://github.com/streamdown-rs/streamdown),
|
|
298
|
+
a high-performance streaming markdown renderer written in Rust. This project brings
|
|
299
|
+
the same streaming rendering capabilities to the Python ecosystem with a clean,
|
|
300
|
+
Pythonic API.
|
|
301
|
+
|
|
302
|
+
## 🤝 Contributing
|
|
303
|
+
|
|
304
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
# Clone and install for development
|
|
308
|
+
git clone https://github.com/your-username/termflow.git
|
|
309
|
+
cd termflow
|
|
310
|
+
pip install -e ".[dev]"
|
|
311
|
+
|
|
312
|
+
# Run tests
|
|
313
|
+
pytest tests/ -v
|
|
314
|
+
|
|
315
|
+
# Run linter
|
|
316
|
+
ruff check .
|
|
317
|
+
ruff format .
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## 📄 License
|
|
321
|
+
|
|
322
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
<div align="center">
|
|
327
|
+
|
|
328
|
+
Made with ❤️ for the terminal
|
|
329
|
+
|
|
330
|
+
</div>
|