flowmark 0.2.1__tar.gz → 0.3.1__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.
- flowmark-0.3.1/.copier-answers.yml +9 -0
- flowmark-0.3.1/.github/workflows/ci.yml +63 -0
- flowmark-0.3.1/.github/workflows/publish.yml +38 -0
- flowmark-0.3.1/.gitignore +176 -0
- flowmark-0.3.1/Makefile +32 -0
- flowmark-0.3.1/PKG-INFO +189 -0
- flowmark-0.3.1/README.md +175 -0
- flowmark-0.3.1/development.md +64 -0
- flowmark-0.3.1/devtools/lint.py +45 -0
- flowmark-0.3.1/poetry.lock +778 -0
- flowmark-0.3.1/pyproject.toml +88 -0
- {flowmark-0.2.1 → flowmark-0.3.1}/src/flowmark/cli.py +27 -9
- flowmark-0.3.1/src/flowmark/frontmatter.py +44 -0
- {flowmark-0.2.1 → flowmark-0.3.1}/src/flowmark/markdown_filling.py +47 -10
- flowmark-0.3.1/tests/__init__.py +0 -0
- flowmark-0.3.1/tests/test_filling.py +286 -0
- flowmark-0.3.1/tests/test_frontmatter.py +72 -0
- flowmark-0.3.1/tests/test_ref_docs.py +41 -0
- flowmark-0.3.1/tests/test_wrapping.py +130 -0
- flowmark-0.3.1/tests/testdocs/testdoc.orig.md +593 -0
- flowmark-0.3.1/tests/testdocs/testdoc.out.plain.md +877 -0
- flowmark-0.3.1/tests/testdocs/testdoc.out.semantic.md +918 -0
- flowmark-0.3.1/uv.lock +579 -0
- flowmark-0.2.1/PKG-INFO +0 -142
- flowmark-0.2.1/README.md +0 -122
- flowmark-0.2.1/pyproject.toml +0 -102
- {flowmark-0.2.1 → flowmark-0.3.1}/LICENSE +0 -0
- {flowmark-0.2.1 → flowmark-0.3.1}/src/flowmark/__init__.py +0 -0
- {flowmark-0.2.1 → flowmark-0.3.1}/src/flowmark/line_wrappers.py +0 -0
- {flowmark-0.2.1 → flowmark-0.3.1}/src/flowmark/sentence_split_regex.py +0 -0
- {flowmark-0.2.1 → flowmark-0.3.1}/src/flowmark/text_filling.py +0 -0
- {flowmark-0.2.1 → flowmark-0.3.1}/src/flowmark/text_wrapping.py +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Changes here will be overwritten by Copier. Do not edit manually.
|
|
2
|
+
_commit: 1742e95
|
|
3
|
+
_src_path: gh:jlevy/simple-modern-uv
|
|
4
|
+
package_author_email: joshua@cal.berkeley.edu
|
|
5
|
+
package_author_name: Joshua Levy
|
|
6
|
+
package_description: Better line wrapping and formatting for plaintext and Markdown
|
|
7
|
+
package_github_org: jlevy
|
|
8
|
+
package_name: flowmark
|
|
9
|
+
package_slug: flowmark
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
|
|
3
|
+
|
|
4
|
+
name: CI
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
# Use ["main", "master"] for CI only on the default branch.
|
|
9
|
+
# Use ["**"] for CI on all branches.
|
|
10
|
+
branches: ["main", "master"]
|
|
11
|
+
pull_request:
|
|
12
|
+
branches: ["main", "master"]
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
strategy:
|
|
20
|
+
matrix:
|
|
21
|
+
# Update this as needed:
|
|
22
|
+
|
|
23
|
+
# Common platforms: ["ubuntu-latest", "macos-latest", "windows-latest"]
|
|
24
|
+
os: ["ubuntu-latest"]
|
|
25
|
+
python-version: ["3.10","3.11", "3.12", "3.13"]
|
|
26
|
+
|
|
27
|
+
# Linux only by default. Use ${{ matrix.os }} for other OSes.
|
|
28
|
+
runs-on: ${{ matrix.os }}
|
|
29
|
+
|
|
30
|
+
steps:
|
|
31
|
+
# Generally following uv docs:
|
|
32
|
+
# https://docs.astral.sh/uv/guides/integration/github/
|
|
33
|
+
|
|
34
|
+
- name: Checkout (official GitHub action)
|
|
35
|
+
uses: actions/checkout@v4
|
|
36
|
+
with:
|
|
37
|
+
# Important for versioning plugins:
|
|
38
|
+
fetch-depth: 0
|
|
39
|
+
|
|
40
|
+
- name: Install uv (official Astral action)
|
|
41
|
+
uses: astral-sh/setup-uv@v5
|
|
42
|
+
with:
|
|
43
|
+
version: "0.6.5"
|
|
44
|
+
enable-cache: true
|
|
45
|
+
python-version: ${{ matrix.python-version }}
|
|
46
|
+
|
|
47
|
+
- name: Set up Python (using uv)
|
|
48
|
+
run: uv python install
|
|
49
|
+
|
|
50
|
+
# Alternately can use the official Python action:
|
|
51
|
+
# - name: Set up Python (using actions/setup-python)
|
|
52
|
+
# uses: actions/setup-python@v5
|
|
53
|
+
# with:
|
|
54
|
+
# python-version: ${{ matrix.python-version }}
|
|
55
|
+
|
|
56
|
+
- name: Install all dependencies
|
|
57
|
+
run: uv sync --all-extras --dev
|
|
58
|
+
|
|
59
|
+
- name: Run linting
|
|
60
|
+
run: uv run python devtools/lint.py
|
|
61
|
+
|
|
62
|
+
- name: Run tests
|
|
63
|
+
run: uv run pytest
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch: # Enable manual trigger.
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-and-publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write # Mandatory for OIDC.
|
|
13
|
+
contents: read
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout (official GitHub action)
|
|
16
|
+
uses: actions/checkout@v4
|
|
17
|
+
with:
|
|
18
|
+
# Important for versioning plugins:
|
|
19
|
+
fetch-depth: 0
|
|
20
|
+
|
|
21
|
+
- name: Install uv (official Astral action)
|
|
22
|
+
uses: astral-sh/setup-uv@v5
|
|
23
|
+
with:
|
|
24
|
+
version: "0.6.5"
|
|
25
|
+
enable-cache: true
|
|
26
|
+
python-version: "3.12"
|
|
27
|
+
|
|
28
|
+
- name: Set up Python (using uv)
|
|
29
|
+
run: uv python install
|
|
30
|
+
|
|
31
|
+
- name: Install all dependencies
|
|
32
|
+
run: uv sync --all-extras --dev
|
|
33
|
+
|
|
34
|
+
- name: Build package
|
|
35
|
+
run: uv build
|
|
36
|
+
|
|
37
|
+
- name: Publish to PyPI (using uv)
|
|
38
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Additions to standard GitHub .gitignore:
|
|
2
|
+
tmp/
|
|
3
|
+
trash/
|
|
4
|
+
.kmd/
|
|
5
|
+
|
|
6
|
+
# Byte-compiled / optimized / DLL files
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.py[cod]
|
|
9
|
+
*$py.class
|
|
10
|
+
|
|
11
|
+
# C extensions
|
|
12
|
+
*.so
|
|
13
|
+
|
|
14
|
+
# Distribution / packaging
|
|
15
|
+
.Python
|
|
16
|
+
build/
|
|
17
|
+
develop-eggs/
|
|
18
|
+
dist/
|
|
19
|
+
downloads/
|
|
20
|
+
eggs/
|
|
21
|
+
.eggs/
|
|
22
|
+
lib/
|
|
23
|
+
lib64/
|
|
24
|
+
parts/
|
|
25
|
+
sdist/
|
|
26
|
+
var/
|
|
27
|
+
wheels/
|
|
28
|
+
share/python-wheels/
|
|
29
|
+
*.egg-info/
|
|
30
|
+
.installed.cfg
|
|
31
|
+
*.egg
|
|
32
|
+
MANIFEST
|
|
33
|
+
|
|
34
|
+
# PyInstaller
|
|
35
|
+
# Usually these files are written by a python script from a template
|
|
36
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
37
|
+
*.manifest
|
|
38
|
+
*.spec
|
|
39
|
+
|
|
40
|
+
# Installer logs
|
|
41
|
+
pip-log.txt
|
|
42
|
+
pip-delete-this-directory.txt
|
|
43
|
+
|
|
44
|
+
# Unit test / coverage reports
|
|
45
|
+
htmlcov/
|
|
46
|
+
.tox/
|
|
47
|
+
.nox/
|
|
48
|
+
.coverage
|
|
49
|
+
.coverage.*
|
|
50
|
+
.cache
|
|
51
|
+
nosetests.xml
|
|
52
|
+
coverage.xml
|
|
53
|
+
*.cover
|
|
54
|
+
*.py,cover
|
|
55
|
+
.hypothesis/
|
|
56
|
+
.pytest_cache/
|
|
57
|
+
cover/
|
|
58
|
+
|
|
59
|
+
# Translations
|
|
60
|
+
*.mo
|
|
61
|
+
*.pot
|
|
62
|
+
|
|
63
|
+
# Django stuff:
|
|
64
|
+
*.log
|
|
65
|
+
local_settings.py
|
|
66
|
+
db.sqlite3
|
|
67
|
+
db.sqlite3-journal
|
|
68
|
+
|
|
69
|
+
# Flask stuff:
|
|
70
|
+
instance/
|
|
71
|
+
.webassets-cache
|
|
72
|
+
|
|
73
|
+
# Scrapy stuff:
|
|
74
|
+
.scrapy
|
|
75
|
+
|
|
76
|
+
# Sphinx documentation
|
|
77
|
+
docs/_build/
|
|
78
|
+
|
|
79
|
+
# PyBuilder
|
|
80
|
+
.pybuilder/
|
|
81
|
+
target/
|
|
82
|
+
|
|
83
|
+
# Jupyter Notebook
|
|
84
|
+
.ipynb_checkpoints
|
|
85
|
+
|
|
86
|
+
# IPython
|
|
87
|
+
profile_default/
|
|
88
|
+
ipython_config.py
|
|
89
|
+
|
|
90
|
+
# pyenv
|
|
91
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
92
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
93
|
+
# .python-version
|
|
94
|
+
|
|
95
|
+
# pipenv
|
|
96
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
97
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
98
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
99
|
+
# install all needed dependencies.
|
|
100
|
+
#Pipfile.lock
|
|
101
|
+
|
|
102
|
+
# UV
|
|
103
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
104
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
105
|
+
# commonly ignored for libraries.
|
|
106
|
+
#uv.lock
|
|
107
|
+
|
|
108
|
+
# poetry
|
|
109
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
110
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
111
|
+
# commonly ignored for libraries.
|
|
112
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
113
|
+
#poetry.lock
|
|
114
|
+
|
|
115
|
+
# pdm
|
|
116
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
117
|
+
#pdm.lock
|
|
118
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
119
|
+
# in version control.
|
|
120
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
121
|
+
.pdm.toml
|
|
122
|
+
.pdm-python
|
|
123
|
+
.pdm-build/
|
|
124
|
+
|
|
125
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
126
|
+
__pypackages__/
|
|
127
|
+
|
|
128
|
+
# Celery stuff
|
|
129
|
+
celerybeat-schedule
|
|
130
|
+
celerybeat.pid
|
|
131
|
+
|
|
132
|
+
# SageMath parsed files
|
|
133
|
+
*.sage.py
|
|
134
|
+
|
|
135
|
+
# Environments
|
|
136
|
+
.env
|
|
137
|
+
.venv
|
|
138
|
+
env/
|
|
139
|
+
venv/
|
|
140
|
+
ENV/
|
|
141
|
+
env.bak/
|
|
142
|
+
venv.bak/
|
|
143
|
+
|
|
144
|
+
# Spyder project settings
|
|
145
|
+
.spyderproject
|
|
146
|
+
.spyproject
|
|
147
|
+
|
|
148
|
+
# Rope project settings
|
|
149
|
+
.ropeproject
|
|
150
|
+
|
|
151
|
+
# mkdocs documentation
|
|
152
|
+
/site
|
|
153
|
+
|
|
154
|
+
# mypy
|
|
155
|
+
.mypy_cache/
|
|
156
|
+
.dmypy.json
|
|
157
|
+
dmypy.json
|
|
158
|
+
|
|
159
|
+
# Pyre type checker
|
|
160
|
+
.pyre/
|
|
161
|
+
|
|
162
|
+
# pytype static type analyzer
|
|
163
|
+
.pytype/
|
|
164
|
+
|
|
165
|
+
# Cython debug symbols
|
|
166
|
+
cython_debug/
|
|
167
|
+
|
|
168
|
+
# PyCharm
|
|
169
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
170
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
171
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
172
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
173
|
+
#.idea/
|
|
174
|
+
|
|
175
|
+
# PyPI configuration file
|
|
176
|
+
.pypirc
|
flowmark-0.3.1/Makefile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Makefile for easy development workflows.
|
|
2
|
+
# GitHub Actions call uv directly.
|
|
3
|
+
|
|
4
|
+
.DEFAULT_GOAL := default
|
|
5
|
+
|
|
6
|
+
.PHONY: default install_deps lint test build clean gen_test_docs
|
|
7
|
+
|
|
8
|
+
default: install_deps lint test
|
|
9
|
+
|
|
10
|
+
install_deps:
|
|
11
|
+
uv sync --all-extras --dev
|
|
12
|
+
|
|
13
|
+
lint:
|
|
14
|
+
uv run python devtools/lint.py
|
|
15
|
+
|
|
16
|
+
test:
|
|
17
|
+
uv run pytest
|
|
18
|
+
|
|
19
|
+
build:
|
|
20
|
+
uv build
|
|
21
|
+
|
|
22
|
+
clean:
|
|
23
|
+
-rm -rf dist/
|
|
24
|
+
-rm -rf *.egg-info/
|
|
25
|
+
-rm -rf .pytest_cache/
|
|
26
|
+
-rm -rf .mypy_cache/
|
|
27
|
+
-rm -rf .venv/
|
|
28
|
+
-find . -type d -name "__pycache__" -exec rm -rf {} +
|
|
29
|
+
|
|
30
|
+
gen_test_docs:
|
|
31
|
+
poetry run flowmark tests/testdocs/testdoc.orig.md -o tests/testdocs/testdoc.out.plain.md
|
|
32
|
+
poetry run flowmark --semantic tests/testdocs/testdoc.orig.md -o tests/testdocs/testdoc.out.semantic.md
|
flowmark-0.3.1/PKG-INFO
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flowmark
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: Better line wrapping and formatting for plaintext and Markdown
|
|
5
|
+
Project-URL: Repository, https://github.com//flowmark
|
|
6
|
+
Author-email: Joshua Levy <joshua@cal.berkeley.edu>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: <4.0,>=3.10
|
|
10
|
+
Requires-Dist: marko>=2.1.2
|
|
11
|
+
Requires-Dist: regex>=2024.11.6
|
|
12
|
+
Requires-Dist: strif>=2.0.0
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# flowmark
|
|
16
|
+
|
|
17
|
+
Flowmark is a new Python implementation of **text and Markdown line wrapping and
|
|
18
|
+
filling**, with an emphasis on making **git diffs** and **LLM edits** to text documents
|
|
19
|
+
easier to diff and review.
|
|
20
|
+
|
|
21
|
+
In addition, it adds **support for Markdown** and offers **Markdown auto-formatting and
|
|
22
|
+
normalization** as a library or from the command line.
|
|
23
|
+
This is much like [markdownfmt](https://github.com/shurcooL/markdownfmt) or
|
|
24
|
+
[prettier's Markdown support](https://prettier.io/blog/2017/11/07/1.8.0) but is pure
|
|
25
|
+
Python and has (in my humble opinion) better options and defaults.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
The simplest way to use the tool is to use [uv](https://github.com/astral-sh/uv):
|
|
30
|
+
|
|
31
|
+
```shell
|
|
32
|
+
uv tool install flowmark
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or [pipx](https://github.com/pypa/pipx):
|
|
36
|
+
|
|
37
|
+
```shell
|
|
38
|
+
pipx install flowmark
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
flowmark --help
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
To use as a library, use pip/poetry/uv to install
|
|
48
|
+
[`flowmark`](https://pypi.org/project/flowmark/).
|
|
49
|
+
|
|
50
|
+
## Use in VSCode/Cursor
|
|
51
|
+
|
|
52
|
+
You can use Flowmark to auto-format Markdown on save in VSCode or Cursor.
|
|
53
|
+
Install the "Run on Save" (`emeraldwalk.runonsave`) extension.
|
|
54
|
+
Then add to your `settings.json`:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
"emeraldwalk.runonsave": {
|
|
58
|
+
"commands": [
|
|
59
|
+
{
|
|
60
|
+
"match": "\\.md$",
|
|
61
|
+
"cmd": "flowmark --auto ${file}"
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The `--auto` option is just the same as `--inplace --nobackup --semantic`.
|
|
68
|
+
|
|
69
|
+
## Use Cases
|
|
70
|
+
|
|
71
|
+
- As a **command line formatter** to format text or Markdown files using the `flowmark`
|
|
72
|
+
command.
|
|
73
|
+
|
|
74
|
+
- To **autoformat Markdown on save in VSCode/Cursor** or any other editor that supports
|
|
75
|
+
running a command on save.
|
|
76
|
+
Flowmark uses a readable format that makes diffs easy to read and use on GitHub.
|
|
77
|
+
It also normalizes all Markdown syntax variations (such as different header or
|
|
78
|
+
formatting styles). This can be especially useful for documentation and editing
|
|
79
|
+
workflows where clean diffs and minimal merge conflicts on GitHub are important.
|
|
80
|
+
|
|
81
|
+
- As a **library to autoformat Markdown**. For example, it is great to normalize the
|
|
82
|
+
outputs from LLMs to be consistent, or to run on the inputs and outputs of LLM
|
|
83
|
+
transformations that edit text, so that the resulting diffs are clean.
|
|
84
|
+
Having this as a simple Python library makes this easy in AI-related document
|
|
85
|
+
pipelines.
|
|
86
|
+
|
|
87
|
+
- As a **drop-in replacement library for Python's default
|
|
88
|
+
[`textwrap`](https://docs.python.org/3/library/textwrap.html)** but with more options.
|
|
89
|
+
It simplifies and generalizes that library, offering better control over **initial and
|
|
90
|
+
subsequent indentation** and **when to split words and lines**, e.g. using a word
|
|
91
|
+
splitter that won't break lines within HTML tags.
|
|
92
|
+
|
|
93
|
+
- Flowmark has the option to to use **semantic line breaks** (using a heuristic to break
|
|
94
|
+
lines on sentences sentences when that is reasonable), which is an underrated feature
|
|
95
|
+
that can **make diffs on GitHub much more readable**. The the change may seem subtle
|
|
96
|
+
but avoids having paragraphs reflow for very small edits, which does a lot to
|
|
97
|
+
**minimize merge conflicts**. An example of what sentence-guided wrapping looks like,
|
|
98
|
+
see the
|
|
99
|
+
[Markdown source](https://github.com/jlevy/flowmark/blob/main/README.md?plain=1) of
|
|
100
|
+
this readme file.)
|
|
101
|
+
|
|
102
|
+
- Very, very simple and fast **regex-based sentence splitting**. This should work fine
|
|
103
|
+
for English and many other latin/Cyrillic languages but it hasn't been tested on CJK.
|
|
104
|
+
|
|
105
|
+
It aims to be small and simple and have only a few dependencies, currently only
|
|
106
|
+
[`marko`](https://github.com/frostming/marko),
|
|
107
|
+
[`regex`](https://pypi.org/project/regex/), and
|
|
108
|
+
[`strif`](https://github.com/jlevy/strif).
|
|
109
|
+
|
|
110
|
+
Because **YAML frontmatter** is common on Markdown files, the Markdown autoformat
|
|
111
|
+
preserves all frontmatter (content between `---` delimiters at the front of a file).
|
|
112
|
+
|
|
113
|
+
## Why a New Markdown Formatter?
|
|
114
|
+
|
|
115
|
+
Previously I'd implemented something very similar with
|
|
116
|
+
[for Atom](https://github.com/jlevy/atom-flowmark).
|
|
117
|
+
I found the Markdown formatting conventions enforced by the that plugin worked really
|
|
118
|
+
well for editing and publishing large or collaboratively edited documents.
|
|
119
|
+
|
|
120
|
+
This is new, pure Python implementation.
|
|
121
|
+
There are numerous needs for a tool like this on the command line and in Python.
|
|
122
|
+
|
|
123
|
+
With LLM tools now using Markdown everywhere, there are enormous advantages to having
|
|
124
|
+
very clean and well-formatted Markdown documents, since you can then cleanly see diffs
|
|
125
|
+
or edits made by LLMs.
|
|
126
|
+
|
|
127
|
+
If you are in a workspace where you are editing lots of text, having them all be
|
|
128
|
+
Markdown with frontmatter, auto-formatted for every git commit makes for a *much* better
|
|
129
|
+
experience.
|
|
130
|
+
|
|
131
|
+
## Usage
|
|
132
|
+
|
|
133
|
+
Flowmark can be used as a library or as a CLI.
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
$ flowmark --help
|
|
137
|
+
usage: flowmark [-h] [-o OUTPUT] [-w WIDTH] [-p] [-s] [-i] [--nobackup] [file]
|
|
138
|
+
|
|
139
|
+
Flowmark: Better line wrapping and formatting for plaintext and Markdown
|
|
140
|
+
|
|
141
|
+
positional arguments:
|
|
142
|
+
file Input file (use '-' for stdin)
|
|
143
|
+
|
|
144
|
+
options:
|
|
145
|
+
-h, --help show this help message and exit
|
|
146
|
+
-o, --output OUTPUT Output file (use '-' for stdout)
|
|
147
|
+
-w, --width WIDTH Line width to wrap to
|
|
148
|
+
-p, --plaintext Process as plaintext (no Markdown parsing)
|
|
149
|
+
-s, --semantic Enable sentence-based line breaks (only applies to Markdown mode)
|
|
150
|
+
-i, --inplace Edit the file in place (ignores --output)
|
|
151
|
+
--nobackup Do not make a backup of the original file when using --inplace
|
|
152
|
+
|
|
153
|
+
Flowmark provides enhanced text wrapping capabilities with special handling for
|
|
154
|
+
Markdown content. It can:
|
|
155
|
+
|
|
156
|
+
- Format Markdown with proper line wrapping while preserving structure
|
|
157
|
+
and normalizing Markdown formatting
|
|
158
|
+
|
|
159
|
+
- Optionally break lines at sentence boundaries for better diff readability
|
|
160
|
+
|
|
161
|
+
- Process plaintext with HTML-aware word splitting
|
|
162
|
+
|
|
163
|
+
It is both a library and a command-line tool.
|
|
164
|
+
|
|
165
|
+
Command-line usage examples:
|
|
166
|
+
|
|
167
|
+
# Format a Markdown file to stdout
|
|
168
|
+
flowmark README.md
|
|
169
|
+
|
|
170
|
+
# Format a Markdown file and save to a new file
|
|
171
|
+
flowmark README.md -o README_formatted.md
|
|
172
|
+
|
|
173
|
+
# Edit a file in-place (with or without making a backup)
|
|
174
|
+
flowmark --inplace README.md
|
|
175
|
+
flowmark --inplace --nobackup README.md
|
|
176
|
+
|
|
177
|
+
# Process plaintext instead of Markdown
|
|
178
|
+
flowmark --plaintext text.txt
|
|
179
|
+
|
|
180
|
+
# Use sentences to guide line breaks (good for many purposes git history and diffs)
|
|
181
|
+
flowmark --semantic README.md
|
|
182
|
+
|
|
183
|
+
For more details, see: https://github.com/jlevy/flowmark
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
* * *
|
|
187
|
+
|
|
188
|
+
*This project was built from
|
|
189
|
+
[simple-modern-uv](https://github.com/jlevy/simple-modern-uv).*
|
flowmark-0.3.1/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# flowmark
|
|
2
|
+
|
|
3
|
+
Flowmark is a new Python implementation of **text and Markdown line wrapping and
|
|
4
|
+
filling**, with an emphasis on making **git diffs** and **LLM edits** to text documents
|
|
5
|
+
easier to diff and review.
|
|
6
|
+
|
|
7
|
+
In addition, it adds **support for Markdown** and offers **Markdown auto-formatting and
|
|
8
|
+
normalization** as a library or from the command line.
|
|
9
|
+
This is much like [markdownfmt](https://github.com/shurcooL/markdownfmt) or
|
|
10
|
+
[prettier's Markdown support](https://prettier.io/blog/2017/11/07/1.8.0) but is pure
|
|
11
|
+
Python and has (in my humble opinion) better options and defaults.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
The simplest way to use the tool is to use [uv](https://github.com/astral-sh/uv):
|
|
16
|
+
|
|
17
|
+
```shell
|
|
18
|
+
uv tool install flowmark
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or [pipx](https://github.com/pypa/pipx):
|
|
22
|
+
|
|
23
|
+
```shell
|
|
24
|
+
pipx install flowmark
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
flowmark --help
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
To use as a library, use pip/poetry/uv to install
|
|
34
|
+
[`flowmark`](https://pypi.org/project/flowmark/).
|
|
35
|
+
|
|
36
|
+
## Use in VSCode/Cursor
|
|
37
|
+
|
|
38
|
+
You can use Flowmark to auto-format Markdown on save in VSCode or Cursor.
|
|
39
|
+
Install the "Run on Save" (`emeraldwalk.runonsave`) extension.
|
|
40
|
+
Then add to your `settings.json`:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
"emeraldwalk.runonsave": {
|
|
44
|
+
"commands": [
|
|
45
|
+
{
|
|
46
|
+
"match": "\\.md$",
|
|
47
|
+
"cmd": "flowmark --auto ${file}"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The `--auto` option is just the same as `--inplace --nobackup --semantic`.
|
|
54
|
+
|
|
55
|
+
## Use Cases
|
|
56
|
+
|
|
57
|
+
- As a **command line formatter** to format text or Markdown files using the `flowmark`
|
|
58
|
+
command.
|
|
59
|
+
|
|
60
|
+
- To **autoformat Markdown on save in VSCode/Cursor** or any other editor that supports
|
|
61
|
+
running a command on save.
|
|
62
|
+
Flowmark uses a readable format that makes diffs easy to read and use on GitHub.
|
|
63
|
+
It also normalizes all Markdown syntax variations (such as different header or
|
|
64
|
+
formatting styles). This can be especially useful for documentation and editing
|
|
65
|
+
workflows where clean diffs and minimal merge conflicts on GitHub are important.
|
|
66
|
+
|
|
67
|
+
- As a **library to autoformat Markdown**. For example, it is great to normalize the
|
|
68
|
+
outputs from LLMs to be consistent, or to run on the inputs and outputs of LLM
|
|
69
|
+
transformations that edit text, so that the resulting diffs are clean.
|
|
70
|
+
Having this as a simple Python library makes this easy in AI-related document
|
|
71
|
+
pipelines.
|
|
72
|
+
|
|
73
|
+
- As a **drop-in replacement library for Python's default
|
|
74
|
+
[`textwrap`](https://docs.python.org/3/library/textwrap.html)** but with more options.
|
|
75
|
+
It simplifies and generalizes that library, offering better control over **initial and
|
|
76
|
+
subsequent indentation** and **when to split words and lines**, e.g. using a word
|
|
77
|
+
splitter that won't break lines within HTML tags.
|
|
78
|
+
|
|
79
|
+
- Flowmark has the option to to use **semantic line breaks** (using a heuristic to break
|
|
80
|
+
lines on sentences sentences when that is reasonable), which is an underrated feature
|
|
81
|
+
that can **make diffs on GitHub much more readable**. The the change may seem subtle
|
|
82
|
+
but avoids having paragraphs reflow for very small edits, which does a lot to
|
|
83
|
+
**minimize merge conflicts**. An example of what sentence-guided wrapping looks like,
|
|
84
|
+
see the
|
|
85
|
+
[Markdown source](https://github.com/jlevy/flowmark/blob/main/README.md?plain=1) of
|
|
86
|
+
this readme file.)
|
|
87
|
+
|
|
88
|
+
- Very, very simple and fast **regex-based sentence splitting**. This should work fine
|
|
89
|
+
for English and many other latin/Cyrillic languages but it hasn't been tested on CJK.
|
|
90
|
+
|
|
91
|
+
It aims to be small and simple and have only a few dependencies, currently only
|
|
92
|
+
[`marko`](https://github.com/frostming/marko),
|
|
93
|
+
[`regex`](https://pypi.org/project/regex/), and
|
|
94
|
+
[`strif`](https://github.com/jlevy/strif).
|
|
95
|
+
|
|
96
|
+
Because **YAML frontmatter** is common on Markdown files, the Markdown autoformat
|
|
97
|
+
preserves all frontmatter (content between `---` delimiters at the front of a file).
|
|
98
|
+
|
|
99
|
+
## Why a New Markdown Formatter?
|
|
100
|
+
|
|
101
|
+
Previously I'd implemented something very similar with
|
|
102
|
+
[for Atom](https://github.com/jlevy/atom-flowmark).
|
|
103
|
+
I found the Markdown formatting conventions enforced by the that plugin worked really
|
|
104
|
+
well for editing and publishing large or collaboratively edited documents.
|
|
105
|
+
|
|
106
|
+
This is new, pure Python implementation.
|
|
107
|
+
There are numerous needs for a tool like this on the command line and in Python.
|
|
108
|
+
|
|
109
|
+
With LLM tools now using Markdown everywhere, there are enormous advantages to having
|
|
110
|
+
very clean and well-formatted Markdown documents, since you can then cleanly see diffs
|
|
111
|
+
or edits made by LLMs.
|
|
112
|
+
|
|
113
|
+
If you are in a workspace where you are editing lots of text, having them all be
|
|
114
|
+
Markdown with frontmatter, auto-formatted for every git commit makes for a *much* better
|
|
115
|
+
experience.
|
|
116
|
+
|
|
117
|
+
## Usage
|
|
118
|
+
|
|
119
|
+
Flowmark can be used as a library or as a CLI.
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
$ flowmark --help
|
|
123
|
+
usage: flowmark [-h] [-o OUTPUT] [-w WIDTH] [-p] [-s] [-i] [--nobackup] [file]
|
|
124
|
+
|
|
125
|
+
Flowmark: Better line wrapping and formatting for plaintext and Markdown
|
|
126
|
+
|
|
127
|
+
positional arguments:
|
|
128
|
+
file Input file (use '-' for stdin)
|
|
129
|
+
|
|
130
|
+
options:
|
|
131
|
+
-h, --help show this help message and exit
|
|
132
|
+
-o, --output OUTPUT Output file (use '-' for stdout)
|
|
133
|
+
-w, --width WIDTH Line width to wrap to
|
|
134
|
+
-p, --plaintext Process as plaintext (no Markdown parsing)
|
|
135
|
+
-s, --semantic Enable sentence-based line breaks (only applies to Markdown mode)
|
|
136
|
+
-i, --inplace Edit the file in place (ignores --output)
|
|
137
|
+
--nobackup Do not make a backup of the original file when using --inplace
|
|
138
|
+
|
|
139
|
+
Flowmark provides enhanced text wrapping capabilities with special handling for
|
|
140
|
+
Markdown content. It can:
|
|
141
|
+
|
|
142
|
+
- Format Markdown with proper line wrapping while preserving structure
|
|
143
|
+
and normalizing Markdown formatting
|
|
144
|
+
|
|
145
|
+
- Optionally break lines at sentence boundaries for better diff readability
|
|
146
|
+
|
|
147
|
+
- Process plaintext with HTML-aware word splitting
|
|
148
|
+
|
|
149
|
+
It is both a library and a command-line tool.
|
|
150
|
+
|
|
151
|
+
Command-line usage examples:
|
|
152
|
+
|
|
153
|
+
# Format a Markdown file to stdout
|
|
154
|
+
flowmark README.md
|
|
155
|
+
|
|
156
|
+
# Format a Markdown file and save to a new file
|
|
157
|
+
flowmark README.md -o README_formatted.md
|
|
158
|
+
|
|
159
|
+
# Edit a file in-place (with or without making a backup)
|
|
160
|
+
flowmark --inplace README.md
|
|
161
|
+
flowmark --inplace --nobackup README.md
|
|
162
|
+
|
|
163
|
+
# Process plaintext instead of Markdown
|
|
164
|
+
flowmark --plaintext text.txt
|
|
165
|
+
|
|
166
|
+
# Use sentences to guide line breaks (good for many purposes git history and diffs)
|
|
167
|
+
flowmark --semantic README.md
|
|
168
|
+
|
|
169
|
+
For more details, see: https://github.com/jlevy/flowmark
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
* * *
|
|
173
|
+
|
|
174
|
+
*This project was built from
|
|
175
|
+
[simple-modern-uv](https://github.com/jlevy/simple-modern-uv).*
|