Skip to main content

Semantic line break formatter for Org, LaTeX, Markdown, and plaintext

Project description

img

Table of Contents

About

A fast, format-aware semantic line break formatter. Reformats prose so each sentence occupies its own line, producing minimal and meaningful git diffs when collaborating on documents.

Why?

When multiple authors collaborate on a paper using Git, traditional line wrapping at a fixed column width causes problems. A single word change can trigger a diff that spans an entire paragraph. By breaking at sentence boundaries instead, each edit affects only the sentence that changed.

This convention, often called "semantic linefeeds," enjoys longstanding support from technical writers. Existing tools fall short: latexindent.pl only handles LaTeX, SemBr requires Python and neural networks, and most lack multi-format awareness. snapper solves this as a standalone Rust binary with no runtime dependencies, handling Org-mode, LaTeX, Markdown, and plaintext.

Design

snapper runs a three-stage pipeline:

  • Parse: Classify input into prose regions and structure regions
  • Split: Detect sentence boundaries in prose regions
  • Emit: Output each sentence on its own line

Structure regions (code blocks, math environments, tables, front matter, drawers, comments) pass through unchanged. Sentence detection relies on Unicode UAX #29 segmentation with abbreviation-aware post-processing that avoids false breaks at titles (Dr., Prof.), references (Fig., Eq.), and Latin terms (e.g., i.e., et al.).

Installation

Pre-built binary (fastest):

cargo binstall snapper-fmt

Shell one-liner (Linux/macOS):

curl -LsSf https://github.com/TurtleTech-ehf/snapper/releases/latest/download/snapper-fmt-installer.sh | sh

Homebrew:

brew install TurtleTech-ehf/tap/snapper-fmt

pip:

pip install snapper-fmt

Compile from source:

cargo install snapper-fmt

Nix:

nix build github:TurtleTech-ehf/snapper

The crate is snapper-fmt on all registries; the binary it installs is snapper.

Usage

Format a file (output to stdout):

snapper paper.org

Format in place:

snapper --in-place paper.org

Pipe through stdin (for editor integration):

cat draft.org | snapper --format org

Check formatting without modifying (for CI):

snapper --check paper.org paper.tex notes.md

Limit line width (wrap long sentences at word boundaries):

snapper --max-width 80 paper.org

Preview changes as a unified diff before committing:

snapper --diff paper.org

Compare two versions at the sentence level (whitespace reflow produces zero diff):

snapper sdiff paper_v1.org paper_v2.org

Watch files and auto-reformat on save:

snapper watch '*.org' 'sections/*.tex'

Initialize a project (generates config, pre-commit, gitattributes):

snapper init

Supported formats

Format Extensions Structure preserved
Org-mode .org Blocks, drawers, tables, keywords
LaTeX .tex, .latex Preamble, math, environments, comments
Markdown .md, .markdown Code blocks, front matter, HTML
Plaintext everything else (none; all text treated as prose)

Pre-commit hook

- repo: https://github.com/TurtleTech-ehf/snapper
  rev: v0.1.0
  hooks:
    - id: snapper

Emacs (Apheleia)

(with-eval-after-load 'apheleia
  (push '(snapper . ("snapper" "--format" "org")) apheleia-formatters)
  (push '(org-mode . snapper) apheleia-mode-alist))

Git smudge/clean filter

Auto-format on commit, transparent to collaborators:

git config filter.snapper.clean "snapper --format org"
git config filter.snapper.smudge cat

Then add to .gitattributes:

*.org filter=snapper

Vale integration

snapper ships a vale style package for editor hints. Add to your .vale.ini:

StylesPath = /path/to/snapper/vale
[*.org]
BasedOnStyles = snapper

For precise CI checks, use snapper --check directly.

Project config

Drop a .snapperrc.toml in your project root:

extra_abbreviations = ["GROMACS", "LAMMPS", "DFT"]
ignore = ["*.bib", "*.cls"]
format = "org"
max_width = 0

snapper walks up from the current directory to find it.

Documentation

Build the docs site with:

pixi run docbld

Development

Key dependencies

  • Clap 4 (derive): CLI argument parsing
  • unicode-segmentation: UAX #29 sentence boundaries
  • regex: Abbreviation and format pattern matching
  • textwrap: Optional line width limiting
  • thiserror: Typed error handling

Conventions

We use cocogitto via cog to handle commit conventions.

Readme

Construct the readme via:

./scripts/org_to_md.sh readme_src.org README.md

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

snapper_fmt-0.3.2.tar.gz (1.1 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

snapper_fmt-0.3.2-py3-none-win_amd64.whl (6.9 MB view details)

Uploaded Python 3Windows x86-64

snapper_fmt-0.3.2-py3-none-manylinux_2_28_aarch64.whl (5.9 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

snapper_fmt-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

snapper_fmt-0.3.2-py3-none-macosx_11_0_arm64.whl (5.7 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

snapper_fmt-0.3.2-py3-none-macosx_10_12_x86_64.whl (6.2 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file snapper_fmt-0.3.2.tar.gz.

File metadata

  • Download URL: snapper_fmt-0.3.2.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for snapper_fmt-0.3.2.tar.gz
Algorithm Hash digest
SHA256 8287917472c1ae65ee0e54fb926d024434dd75582fb0b45162277022195014e0
MD5 5d9a512ff25d4f33c81df7299adc5f8a
BLAKE2b-256 2f463e7217bb2526fdb1091c5669762d41e4892849ff957ddb785dddcd1868b4

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.3.2.tar.gz:

Publisher: pypi.yml on TurtleTech-ehf/snapper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file snapper_fmt-0.3.2-py3-none-win_amd64.whl.

File metadata

  • Download URL: snapper_fmt-0.3.2-py3-none-win_amd64.whl
  • Upload date:
  • Size: 6.9 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for snapper_fmt-0.3.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 79b05844a8f279178b916c072a62270b0d5a4790210c053796190b3dc4b36377
MD5 4f87636ed6918a34ac21e71f67768efd
BLAKE2b-256 938dd6d54d44da28da64830ddd4f93235ce2e8828b2b5a35dde093f9a49ed94a

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.3.2-py3-none-win_amd64.whl:

Publisher: pypi.yml on TurtleTech-ehf/snapper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file snapper_fmt-0.3.2-py3-none-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for snapper_fmt-0.3.2-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 b1eb9679800ae8a93a7d8ea2c2c7489894bc366af7d36bf35f14364870964713
MD5 be01ef7b28638907d105ac1402c78b39
BLAKE2b-256 78f404e5996d004690153e7e939d36d3e75c1fe2d883e44ca423f165b1739307

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.3.2-py3-none-manylinux_2_28_aarch64.whl:

Publisher: pypi.yml on TurtleTech-ehf/snapper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file snapper_fmt-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for snapper_fmt-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a3400d94d80e260b354fdb734a09ccb38b5c732c855ce0499bfd3ca1398e53fc
MD5 6f07e48d87375f330140775e3952e2fb
BLAKE2b-256 fdeb771c990441f65fd02263460d3a910e2499f5a7e0c4dec8b2b2ab7386b55d

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: pypi.yml on TurtleTech-ehf/snapper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file snapper_fmt-0.3.2-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for snapper_fmt-0.3.2-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 858c4492798b1df6f652effc98d4b143befc8e90d4c6ad4f2aa3ddbdb4a60391
MD5 3d79794669ce6ce9b8b110839c192562
BLAKE2b-256 eba720c708904e3e8846668b7adde0ab1ed4fe549b5567773ade0bdc2e0519ee

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.3.2-py3-none-macosx_11_0_arm64.whl:

Publisher: pypi.yml on TurtleTech-ehf/snapper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file snapper_fmt-0.3.2-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for snapper_fmt-0.3.2-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 dec36f2eea9477e631582e9650487326c300267ef0cbe96b35ddd4bda6c63382
MD5 e8adc4e1d0568ea25b5b9fed4f2b3179
BLAKE2b-256 4d2d091c71118845f71bc1e20a702e3abca284e6c75464198268a67d683ad925

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.3.2-py3-none-macosx_10_12_x86_64.whl:

Publisher: pypi.yml on TurtleTech-ehf/snapper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page