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 stdin → stdout with no path)
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.15.0.tar.gz (917.6 kB view details)

Uploaded Source

Built Distributions

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

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

Uploaded Python 3Windows ARM64

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

Uploaded Python 3Windows x86-64

badness-0.15.0-py3-none-musllinux_1_2_x86_64.whl (3.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

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

Uploaded Python 3musllinux: musl 1.2+ ARM64

badness-0.15.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

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

Uploaded Python 3manylinux: glibc 2.17+ ARM64

badness-0.15.0-py3-none-macosx_11_0_arm64.whl (3.2 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

badness-0.15.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.15.0.tar.gz.

File metadata

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

File hashes

Hashes for badness-0.15.0.tar.gz
Algorithm Hash digest
SHA256 3feedd163ade54c078df7a4894471560a801a4e429aa5f386c3792d9c31b6bba
MD5 8401d7327b139d6e293c940b54f69b4a
BLAKE2b-256 c8f18f6e14bc35e06d60a545a262b83f297c04dffcc66a865fecdbc4dcfa3848

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: badness-0.15.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.15.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 de578f0fbae2a363ee760a22dbad653382a88c9f2f3a75d41b75703200b754f9
MD5 a53502c4ad755341e01bf981cb1ef34e
BLAKE2b-256 021a78ecafe50734e30ccd91a70c3ed3554156ccbf6ac702adace97bfb890176

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: badness-0.15.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.15.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 9703b54727f22276f29e020b49265b7185ba79a8b064a62907b0d0ad4d3e581c
MD5 6007d25f9e6927284ee60c4983ccf693
BLAKE2b-256 f60008e4e6df71c141e3a81350f82c9658696ae2bc7f0dab1dbfeb0e51b69442

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.15.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 445e66337e7a7f18837a69f1fdb13d8a3b49b43a78a0918821453d600e8d8f48
MD5 3e7e035b9e83b8ce9f2f6b54ea5268c3
BLAKE2b-256 c1d86f3132ed7f2e97c2d8141f310fa35c8b6fc658c2eeb278c3e36ca69429c6

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.15.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 b1caf9933c55a7f9708449db3b4b67ff2f22778281f79c9ccd977d775dfaa46a
MD5 44845eec984e010863d9d33b72cd0dcb
BLAKE2b-256 49c15850940073f190b973311328b9a28b604117e1343d32c9fe187fff6c8436

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.15.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 57ad8428652d13d84a743b0c85b191c484e1f58e110924b5558166a67fe6d2e4
MD5 5ed4d9002bfa845f10254c74e3394dfa
BLAKE2b-256 39ad6d88cd7eef597c4d12a89f3f2caad5ca63975e0011c7fd4fdd641b025efc

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.15.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ad812d848ce25feb33926522bac0a8cab92852f50e886e373f9f5b7ec93197af
MD5 3f2c8f5f4005b8f810ed01a4ad4e1a04
BLAKE2b-256 001a4a5332c414671e1070cbc2dbda29604ec7a013479215c7730949fd23be75

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.15.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 128e181c1a5a475b402d5590877b9a2fd16eef6faf4275570ce5b0ebb7399cb8
MD5 d70d19f649307b4185221c2f318a0a29
BLAKE2b-256 bd48260f314783ddb52c3d9b227f64fb2b291cf8ae7335ba8afde476ee072501

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.15.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 efcb96df1f1c697d7c49969140d5bec2c89dceb013cea823d785495e9a314a61
MD5 0d51c5df7df63a20de108b2db8877ad0
BLAKE2b-256 cf99d6fac10d160608ab2b1196dce3245d3526839000fc964fb999d5a991defd

See more details on using hashes here.

Provenance

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