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://github.com/jolars/badness/releases/latest/download/badness-installer.sh | sh

For Windows PowerShell:

powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://github.com/jolars/badness/releases/latest/download/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 `badness format -` for stdin → stdout)
badness format paper.tex

# Verify formatting without writing, showing diffs
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.16.0.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.

badness-0.16.0-py3-none-win_arm64.whl (3.5 MB view details)

Uploaded Python 3Windows ARM64

badness-0.16.0-py3-none-win_amd64.whl (3.7 MB view details)

Uploaded Python 3Windows x86-64

badness-0.16.0-py3-none-musllinux_1_2_x86_64.whl (3.9 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

badness-0.16.0-py3-none-musllinux_1_2_aarch64.whl (3.5 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

badness-0.16.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.8 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

badness-0.16.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

badness-0.16.0-py3-none-macosx_11_0_arm64.whl (3.5 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

badness-0.16.0-py3-none-macosx_10_12_x86_64.whl (3.6 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

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

File metadata

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

File hashes

Hashes for badness-0.16.0.tar.gz
Algorithm Hash digest
SHA256 076258f3ed117193d90b4b44250fd68593c35f979a736819709bb37d71cd6da2
MD5 42df87520a73cedcd2d09348570d9352
BLAKE2b-256 c3fea20163671eadf53fdd631acf744a686424b9fabd466e992efed86e6d0a23

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.16.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.16.0-py3-none-win_arm64.whl.

File metadata

  • Download URL: badness-0.16.0-py3-none-win_arm64.whl
  • Upload date:
  • Size: 3.5 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.16.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 bea1185eba76601f2c2d27108425ba374901079feaeebe2efe972cf2cba97a61
MD5 d8b62cceee3615d549e197cabf76d972
BLAKE2b-256 4825f79b83adb93c0cad92ce488dd97eaa6792a8dcf5b2bf77d72d235d115c0b

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.16.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.16.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: badness-0.16.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 3.7 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.16.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 89d94479dab276b8d395276b4d054677c116623d1a8015956aa62b9098014433
MD5 9497a93a6e1e767bab9d1aa9d8ac80a5
BLAKE2b-256 c5d1c2ad4622eb7be37baac6986584c08a963663b51088a5fb0a3ca43b0b0e18

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.16.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.16.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for badness-0.16.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1fa450a743b39ad9a6bca43d1b2c80708ff8f26b0adefd45b1bcf042a7113996
MD5 59b7847d602e3961aea39149a27a501a
BLAKE2b-256 51cd644aad4dc0774b9d0dca1d3ba1674686c9629f83757b8ea3b9dabf3cf523

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.16.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.16.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for badness-0.16.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 ecd658b86d274e83cdbd1dacdd1d26c8b45843238b73bbf72fccb53e052659ed
MD5 c6665a24189682a169f20b7fa0ed1af4
BLAKE2b-256 258d2d3064314f6d72e50cdf75e0a7eff32c03eaa058949741ed4c3c037c8c62

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.16.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.16.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for badness-0.16.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 aeccb430d44125e8166f2fc88d2b6ffc418432b8a0da2f30337faf6d9095e99c
MD5 aac790836127b736f8f016908749a9e3
BLAKE2b-256 954b09b305e0f1f76e4a43b10c2cf7f0fbebecff5630f7ee15bd55dd4b6a14c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.16.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.16.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for badness-0.16.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 51907b30f2faf20002cde0192b0cac00e95812a71ccd6e7d9e6953ae4dc8bec8
MD5 1af03879b0c1ae2e4e14b56d4b564456
BLAKE2b-256 845029b6fccdbb79b4f1ce27cf4756906aa85ba8d863f2ce415075e6a41bcd2c

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.16.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.16.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for badness-0.16.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d43187a90b86e90113f5bf1a76fe2bdc6a263c63d40412bb56c3452e038a45cb
MD5 6cdbcdc314363349375c142abb99b9f7
BLAKE2b-256 aa117427ae7e3848720735b6349c68d9ca39b16fe3bc27b3d58bda55be31d666

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.16.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.16.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for badness-0.16.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 713a21b472ed0c2a4f12860e0fc6995ceb5b3de04e1bfc680edacf672b36adca
MD5 2724ff1bcb8c789f9c64154095a76dd3
BLAKE2b-256 424b02ed93658f2e59db0269f25469d392a9fd2c30f5e76e02780662880a1dac

See more details on using hashes here.

Provenance

The following attestation bundles were made for badness-0.16.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