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.4.0.tar.gz (1.4 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.4.0-py3-none-win_amd64.whl (7.2 MB view details)

Uploaded Python 3Windows x86-64

snapper_fmt-0.4.0-py3-none-manylinux_2_28_aarch64.whl (6.3 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

snapper_fmt-0.4.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (7.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

snapper_fmt-0.4.0-py3-none-macosx_11_0_arm64.whl (6.1 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

snapper_fmt-0.4.0-py3-none-macosx_10_12_x86_64.whl (6.6 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: snapper_fmt-0.4.0.tar.gz
  • Upload date:
  • Size: 1.4 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.4.0.tar.gz
Algorithm Hash digest
SHA256 1fbc13be0b7523b896b3f567e6f09455726564ea296e9501d1591bf6a2ace7f1
MD5 85610e5e2063ba32c15a873e5b9506d4
BLAKE2b-256 197ebbe97725ab10b4a1bfcf02cf1cb94ec660d0c4a765e914c4a29bdd234e06

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.4.0.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.4.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: snapper_fmt-0.4.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 7.2 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.4.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 ea1f7a34600195c468184d01281a52bbb60857f97cf1b343cc7e2236478ab0a0
MD5 c08a66245d11401588af10b003b9fca3
BLAKE2b-256 e1f52f71a4b80449cd0d1345fad0efc59cd02f78cedde88daf3dfc896e74ee40

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.4.0-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.4.0-py3-none-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for snapper_fmt-0.4.0-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 265d3f38ae69587cc6149ebe6d36317ef525d76f0d8cc89e3d1e58f4821707b3
MD5 b84a14634380c4a46ceb98d1cbcf303d
BLAKE2b-256 c4bbd8f76c397517056a0cc3071341883a4e12c56508c834c324e77cfa4cfc0d

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.4.0-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.4.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for snapper_fmt-0.4.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b90b4fac64ee6c9ad99fb0a4fd003aa0bb07c1df398e92a28b119895b6d247a5
MD5 271c7596b39023adfff9ea562969d806
BLAKE2b-256 4e9fcc2a2bc2affe957f5e164807756850447451030a4f92f1bfda3a85b7ecde

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.4.0-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.4.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for snapper_fmt-0.4.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 461e877ef5f0d8324ea389f1998ffbbcf3e29104267f33d3e33dd6f99860c001
MD5 34061b1b54ae9d829bb2ee889f25a742
BLAKE2b-256 74f5e359342796f4a2a78eddf51c0834df13f7c4bc55c53cb15f42e49fb58114

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.4.0-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.4.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for snapper_fmt-0.4.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 1597f2ceaa832ec8527534d7be036281a2b37644a8fc79bf30b47c10959e14fb
MD5 21adedfe5499d566560281b02d18fb0b
BLAKE2b-256 c6e19ce4b0c0a4e093324be4570828f63a6aa720646b10d731618d19e4356e81

See more details on using hashes here.

Provenance

The following attestation bundles were made for snapper_fmt-0.4.0-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