Skip to main content

Badness

Build and Test Crates.io Open VSX VS Code PyPI version npm version

Badness is a language server, formatter, and linter for LaTeX, built on a lossless concrete syntax tree.

It parses LaTeX once and serves three tools from that tree:

  • Formatter (badness format): deterministic, rule-based layout.
  • Linter (badness lint): diagnostics with source snippets.
  • Language server (badness lsp): both, live in your editor.

The architecture follows rust-analyzer: a generic, error-tolerant, hand-written parser produces a lossless tree, semantics are layered on top as a separate concern, and recomputation is incremental. Badness never requires resolving macros or catcodes to succeed. Anything it cannot statically recognize degrades to generic nodes rather than a crash. Two properties hold by construction and are enforced as tests: losslessness (the tree reconstructs the input byte-for-byte) and idempotence (formatting an already formatted file changes nothing).

Installation

Badness is available from several sources:

  • crates.io: cargo install badness
  • Homebrew: brew install jolars/tap/badness
  • npm: npm install -g badness (bundles a prebuilt binary)
  • PyPI: uv tool install badness/pipx install badness
  • Aqua: aqua install jolars/badness
  • Prebuilt binaries: from the releases page
  • VS Code/Open VSX: the Badness extension (also works in Positron and Cursor)
  • From source: cargo install --path . in a checkout

If you prefer a one-liner installer that picks the right release artifact for your platform, you can use the installer scripts below. These scripts are fetched directly from this repository and then download the latest matching Badness release asset for your platform, installing to a user-local directory by default. If you prefer, download and inspect the script before running it.

For macOS and Linux:

curl --proto '=https' --tlsv1.2 -LsSf \
    https://raw.githubusercontent.com/jolars/badness/refs/heads/main/scripts/badness-installer.sh | sh

For Windows PowerShell:

powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://raw.githubusercontent.com/jolars/badness/refs/heads/main/scripts/badness-installer.ps1 | iex"

The VS Code/Open VSX extension bundles the badness binary and starts the language server automatically when you open a .tex file.

Usage

# Format a file in place (or stdin → stdout with no path)
badness format paper.tex

# Verify formatting without writing—diffs the change, exits non-zero if any
badness format --check paper.tex

# Lint, reporting parse diagnostics
badness lint paper.tex

# Run the language server over stdio
badness lsp

Formatting is configurable via a TOML file named badness.toml. See the documentation for the full reference.

The language server runs over stdio (badness lsp); see the editor setup guide for Neovim and VS Code wiring.

Pre-Commit Hook

badness-pre-commit provides pre-commit hooks for linting and formatting. It installs a prebuilt binary wheel from PyPI, so no Rust toolchain or LaTeX distribution is required:

repos:
  - repo: https://github.com/jolars/badness-pre-commit
    # badness version
    rev: v0.11.0
    hooks:
      # Lint .tex, .sty, .cls, .dtx, .ins, and .bib files
      - id: badness-lint
      # Format the same files in place
      - id: badness-format

GitHub Actions

badness-action installs badness and runs format and lint checks in CI:

jobs:
  badness:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: jolars/badness-action@v1

Documentation

See https://badness.dev/ for the full documentation, including a user guide, reference, and developer guide.

Contributing

See CONTRIBUTING.md.

License

MIT

Download files

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

Source Distribution

badness-0.14.0.tar.gz (1.8 MB view details)

Uploaded Source

Built Distributions

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

badness-0.14.0-py3-none-win_arm64.whl (3.2 MB view details)

Uploaded Python 3Windows ARM64

badness-0.14.0-py3-none-win_amd64.whl (3.3 MB view details)

Uploaded Python 3Windows x86-64

badness-0.14.0-py3-none-musllinux_1_2_x86_64.whl (3.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

badness-0.14.0-py3-none-musllinux_1_2_aarch64.whl (3.2 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

badness-0.14.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

badness-0.14.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.3 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

badness-0.14.0-py3-none-macosx_11_0_arm64.whl (3.1 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

badness-0.14.0-py3-none-macosx_10_12_x86_64.whl (3.3 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file badness-0.14.0.tar.gz.

File metadata

  • Download URL: badness-0.14.0.tar.gz
  • Upload date:
  • Size: 1.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for badness-0.14.0.tar.gz
Algorithm Hash digest
SHA256 0f6f8c84bc15f5e7e2a13561eafd11cec63cd2d9a031c0cc71a1b29b8d137922
MD5 bd9a0c5e66f102ebeff79e8891d85c4c
BLAKE2b-256 f8dc67454315471286d60bc1e7c9b40d67fe6ff37a65c71beb68214102e1f4b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.14.0.tar.gz:

Publisher: publish-pypi.yml on jolars/badness

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

File details

Details for the file badness-0.14.0-py3-none-win_arm64.whl.

File metadata

  • Download URL: badness-0.14.0-py3-none-win_arm64.whl
  • Upload date:
  • Size: 3.2 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for badness-0.14.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 2c0bb009c51fe7c22488e1e184dbbe06ae38bce34d1340c4f69ff31fbe220d97
MD5 e1f998835df545680ad6d96d17841c4c
BLAKE2b-256 70a1a004216ffae33993e3f48ee958493ab7dee873d907eefc7278ddd2dbf32e

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.14.0-py3-none-win_arm64.whl:

Publisher: publish-pypi.yml on jolars/badness

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

File details

Details for the file badness-0.14.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: badness-0.14.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 3.3 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for badness-0.14.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 629d0adaca896b3e16e5d4d679a29760acda357aa4b70a1c94daedb80a1ccda8
MD5 7b5dd9a7144c2142f4c46410b4b54482
BLAKE2b-256 5eb371bfad445bdc06be6ac537f348030e9459a46720a7363df40a063db96a87

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.14.0-py3-none-win_amd64.whl:

Publisher: publish-pypi.yml on jolars/badness

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

File details

Details for the file badness-0.14.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for badness-0.14.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 898ae75a94d12882375f97c43fdb54af64fb3acfaa450de7183d7888f4c72f2b
MD5 32820cc833c26a091e77aa45edbbe715
BLAKE2b-256 4b9f95b1c7ab64cb373dc9106e19593be23a44d558ad23a274a37a94f8fe7e48

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.14.0-py3-none-musllinux_1_2_x86_64.whl:

Publisher: publish-pypi.yml on jolars/badness

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

File details

Details for the file badness-0.14.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for badness-0.14.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 3df44222df39a2d73f3d1263b9a7e5da432341627f1148f4be809d0890600b6b
MD5 f7a8ecd578b18f3a3cce9e5fbc7dd7ee
BLAKE2b-256 d3119a16376a66ea484d9abcac805028960588acee70b8fbb91332c3b326f66d

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.14.0-py3-none-musllinux_1_2_aarch64.whl:

Publisher: publish-pypi.yml on jolars/badness

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

File details

Details for the file badness-0.14.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for badness-0.14.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4ed5a145ce28c90018b0feeddbec5bc976718f9d9f6c3f39e057e4b2537bee88
MD5 1008bf83f6ea2344d535c007602dd11f
BLAKE2b-256 120e25b9a1d1257a622039cf88c725efd300616848a8cb46a41d8933c4e527cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.14.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish-pypi.yml on jolars/badness

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

File details

Details for the file badness-0.14.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for badness-0.14.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 22cafb4512f27b3114d68ff21d117ab30c17deed89e195a31842774c43232c85
MD5 9bcde494818756d01188d6bdf57e9683
BLAKE2b-256 b8e8e12addd35fb58b74392966e9c291cedbbbf31bf02d84aa33e30950e7fdab

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.14.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish-pypi.yml on jolars/badness

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

File details

Details for the file badness-0.14.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for badness-0.14.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 324d9a242c2463fa4b9c29d6b37fae86fec9c8bacd4e04ffd91b76481e6dcce0
MD5 0836514b7d97fec3bc24002806ce68c7
BLAKE2b-256 7e68f028b6e191510020fb8755d41de7bd2dae8d174169754677152486bcdf09

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.14.0-py3-none-macosx_11_0_arm64.whl:

Publisher: publish-pypi.yml on jolars/badness

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

File details

Details for the file badness-0.14.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for badness-0.14.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 22534d7aceb5eb8f9c9a9c3d16a5a9c1ff18a93f6e84e6434980c814eb06dfc1
MD5 37237c7087dd205b5d188f6613444efc
BLAKE2b-256 748aa5f1c5d990d2fe14da837d3c1a5adbeaa935e9ac2f9fc558f4ff646fa6f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.14.0-py3-none-macosx_10_12_x86_64.whl:

Publisher: publish-pypi.yml on jolars/badness

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 Sentry Error logging StatusPage Status page