Skip to main content

Badness

Build and Test Documentation Open VSX VS Code

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
  • npm: npm install -g badness (bundles a prebuilt binary)
  • PyPI: uv tool install badness/pipx install 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

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—exits non-zero if anything would change
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

Full documentation lives at https://badness.dev/ (built with mdBook from docs/).

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.12.0.tar.gz (1.7 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.12.0-py3-none-win_arm64.whl (3.0 MB view details)

Uploaded Python 3Windows ARM64

badness-0.12.0-py3-none-win_amd64.whl (3.2 MB view details)

Uploaded Python 3Windows x86-64

badness-0.12.0-py3-none-musllinux_1_2_x86_64.whl (3.4 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

badness-0.12.0-py3-none-musllinux_1_2_aarch64.whl (3.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

badness-0.12.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.3 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

badness-0.12.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

badness-0.12.0-py3-none-macosx_11_0_arm64.whl (3.0 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

badness-0.12.0-py3-none-macosx_10_12_x86_64.whl (3.1 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

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

File metadata

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

File hashes

Hashes for badness-0.12.0.tar.gz
Algorithm Hash digest
SHA256 3e7758011c6d2a9c66252db25474b31bbb8a4d1fbae01765489c472294607933
MD5 84442600fc955f1142f4a89a30b4864c
BLAKE2b-256 7bdac44b8dce2c1159a57c86d22b4bfff9218537ba4c17d0bf61c2952c3b13bd

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: badness-0.12.0-py3-none-win_arm64.whl
  • Upload date:
  • Size: 3.0 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.12.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 afd445f41720d35a3f9e0637b9ecff7dbebf0c8237b3c0102437e51117ef7aff
MD5 65e69a482d4fb5ac95b5bf06f6602c70
BLAKE2b-256 bd18eeacbdbb2c1fcd10721e209cb12980238b8fffc49722b2f3ffc1ebcbae5c

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: badness-0.12.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 3.2 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.12.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 175e48ae26db652b7677500c86ac2b0af171f2b2c61506f82b9659ba334eec87
MD5 499757c5f8420ec4d8dc726ef2489fac
BLAKE2b-256 adcdcc24b0a85c631ea9c6c463e6dc8ce45c9dd6df62f27a5a17fe57c49f12d8

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.12.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 732fcd4b3a9a4d8e81616b437a484d68a0069fdf3442dd303fc26a5653a2959a
MD5 b0514da2e3e2f681be9e3c41c6f2f883
BLAKE2b-256 da21af6d8ad73ac765053b6942c3864c3f2bed837eb17cf287a29af91331f67c

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.12.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 704ba3d3dba8255f81e44da6a03ad94fe0eddba153bae09d2659563efaa6eb8d
MD5 06d4900414fbe393dd9a40022461e987
BLAKE2b-256 12596a65decd57d98bfa3653ffd7fa6eb679f96a73af870d3275c8d53cf25b1b

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.12.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 84e7db3d63f1cb1f3c69ebd07f14dfeacd3c2fd90a1ba305d8cee031b5809506
MD5 1472be6af410ef8b89d920b2c9f70ba0
BLAKE2b-256 b7a59a1602db5cedbaf7af1f97346ef265a09e18a98284e887bbc18945d2a83b

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.12.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 1b4bc7c3b06b34785be2d613dc7e5cd751c92b06306ec661b7fa414bb314ff6a
MD5 c4ddfb31cdb48c4d00e04b87508b0b5a
BLAKE2b-256 570912b915a60cc5a313d7f3ff993981e2c2f4d4044a8fcb16b20c6ad9fa36fb

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.12.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c88aa14209df97f7427c2eaa3ae2113b42b1df6370aa531d0ef43531523b4cc2
MD5 8ab9c76267a72111dc7abec9703d7ae6
BLAKE2b-256 5dc605afbcc3239b67928e82d29db13bd3b79b130f1b78bd178508bf39ae64a4

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for badness-0.12.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 dc8042c1b12f00bab81848cff1c919fc51b8858ddce099c10f1fa0deaffa2d0a
MD5 4bb88e7a4ccc9758f090bda231b6c039
BLAKE2b-256 23ce9617e0eb2e5218a408e80f62d13dff9f6dea2db835b2a7cf30039b6a5105

See more details on using hashes here.

Provenance

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