An LSP, formatter, and linter for LaTeX
Project description
Badness 
Badness is a formatter, linter, and language server 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 written in Rust. Build from a checkout:
git clone https://github.com/jolars/badness
cd badness
cargo install --path .
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
Formatter style is set through flags: --line-width (default 80),
--indent-width (default 2), and --wrap (reflow by default; also
preserve, with sentence/semantic planned). See the documentation for the
full reference.
Documentation
Full documentation lives at https://jolars.github.io/badness/ (built with
mdBook from docs/).
Contributing
Architecture, tenets, and conventions are documented in
AGENTS.md, written for both human and AI contributors. In short:
keep the syntactic layer free of semantic knowledge, every parser feature needs
corpus and snapshot tests plus a losslessness assertion, and code stays
rustfmt-clean with clippy warnings treated as errors.
License
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
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file badness-0.1.0.tar.gz.
File metadata
- Download URL: badness-0.1.0.tar.gz
- Upload date:
- Size: 248.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
581ae9905788f4c456058f2aa39822f97032ab89c1282c4544987ff2ed9bb2d5
|
|
| MD5 |
a189b950fea45fff30ee2a054626db0f
|
|
| BLAKE2b-256 |
31935dc574e6e956d483a37e6616b677d15043d76d0da2d5cedd6238c834f402
|
Provenance
The following attestation bundles were made for badness-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on jolars/badness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
badness-0.1.0.tar.gz -
Subject digest:
581ae9905788f4c456058f2aa39822f97032ab89c1282c4544987ff2ed9bb2d5 - Sigstore transparency entry: 1802011348
- Sigstore integration time:
-
Permalink:
jolars/badness@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jolars
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Trigger Event:
push
-
Statement type:
File details
Details for the file badness-0.1.0-py3-none-win_arm64.whl.
File metadata
- Download URL: badness-0.1.0-py3-none-win_arm64.whl
- Upload date:
- Size: 876.8 kB
- Tags: Python 3, Windows ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a9a40bca483162e29f1911d24c43da126c441e67fb83dbdeae5e9a8f4526e9b
|
|
| MD5 |
1a38c01a3770627fb3182e82714c8a27
|
|
| BLAKE2b-256 |
988484a150c8058c97b89ab4df23985774f529ee5df0dbce6532cc0ac2a7dc3d
|
Provenance
The following attestation bundles were made for badness-0.1.0-py3-none-win_arm64.whl:
Publisher:
publish-pypi.yml on jolars/badness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
badness-0.1.0-py3-none-win_arm64.whl -
Subject digest:
3a9a40bca483162e29f1911d24c43da126c441e67fb83dbdeae5e9a8f4526e9b - Sigstore transparency entry: 1802012139
- Sigstore integration time:
-
Permalink:
jolars/badness@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jolars
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Trigger Event:
push
-
Statement type:
File details
Details for the file badness-0.1.0-py3-none-win_amd64.whl.
File metadata
- Download URL: badness-0.1.0-py3-none-win_amd64.whl
- Upload date:
- Size: 919.2 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
092e64b7f3fa045ca6ab3367c2afdebe49ba642e573e47227fa9f48c50c32d36
|
|
| MD5 |
6d3652f0a2b654f3bf12e3a717e16f0f
|
|
| BLAKE2b-256 |
dd1560e7265bb6c64192389d95737955073459e81d8c372591a5d148159b08f5
|
Provenance
The following attestation bundles were made for badness-0.1.0-py3-none-win_amd64.whl:
Publisher:
publish-pypi.yml on jolars/badness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
badness-0.1.0-py3-none-win_amd64.whl -
Subject digest:
092e64b7f3fa045ca6ab3367c2afdebe49ba642e573e47227fa9f48c50c32d36 - Sigstore transparency entry: 1802012401
- Sigstore integration time:
-
Permalink:
jolars/badness@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jolars
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Trigger Event:
push
-
Statement type:
File details
Details for the file badness-0.1.0-py3-none-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: badness-0.1.0-py3-none-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 1.1 MB
- Tags: Python 3, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d855242ff071aeeab9ce4dd8bc520b699e2365305c6b0ed5c58305f940a5f710
|
|
| MD5 |
ca0c084dfa1be03784f2c54d742addd6
|
|
| BLAKE2b-256 |
fa42dd506acc544dfe3ade617e2cdd4c94337257d9e158086f1920bcac63cbf6
|
Provenance
The following attestation bundles were made for badness-0.1.0-py3-none-musllinux_1_2_x86_64.whl:
Publisher:
publish-pypi.yml on jolars/badness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
badness-0.1.0-py3-none-musllinux_1_2_x86_64.whl -
Subject digest:
d855242ff071aeeab9ce4dd8bc520b699e2365305c6b0ed5c58305f940a5f710 - Sigstore transparency entry: 1802012031
- Sigstore integration time:
-
Permalink:
jolars/badness@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jolars
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Trigger Event:
push
-
Statement type:
File details
Details for the file badness-0.1.0-py3-none-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: badness-0.1.0-py3-none-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 1.0 MB
- Tags: Python 3, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4bc1554ff87b20813602b9b8072e5a4050329121709a71cfb87154440baaee5a
|
|
| MD5 |
cabfb12aa13ed500b753aeecc14dab7e
|
|
| BLAKE2b-256 |
19f7b787a1da3c9a10de6b3be2ebdb44261a05b107006dd5aa7f727f945ef8cc
|
Provenance
The following attestation bundles were made for badness-0.1.0-py3-none-musllinux_1_2_aarch64.whl:
Publisher:
publish-pypi.yml on jolars/badness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
badness-0.1.0-py3-none-musllinux_1_2_aarch64.whl -
Subject digest:
4bc1554ff87b20813602b9b8072e5a4050329121709a71cfb87154440baaee5a - Sigstore transparency entry: 1802012309
- Sigstore integration time:
-
Permalink:
jolars/badness@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jolars
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Trigger Event:
push
-
Statement type:
File details
Details for the file badness-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: badness-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.0 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60f4874b2e01c5c57b1d56013b4af80b990a4f5da3b36da7bb033a9727860c9c
|
|
| MD5 |
c99be7579cf13ed4bef0a764eaad75cc
|
|
| BLAKE2b-256 |
e5ef60170e170010660e2471bcfde0b344c84a26ba81610564e1ee1ac9796b33
|
Provenance
The following attestation bundles were made for badness-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
publish-pypi.yml on jolars/badness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
badness-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
60f4874b2e01c5c57b1d56013b4af80b990a4f5da3b36da7bb033a9727860c9c - Sigstore transparency entry: 1802012210
- Sigstore integration time:
-
Permalink:
jolars/badness@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jolars
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Trigger Event:
push
-
Statement type:
File details
Details for the file badness-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: badness-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 963.1 kB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ad44de69629a167b1df42644c96c3b50c422068949691242d4be030ca9d7687
|
|
| MD5 |
9a8031d8900a00ad0a42a36919c6aea8
|
|
| BLAKE2b-256 |
c8b51c260886419152fe42f6c75c6fde540f44ea47dc4341a274d14b26cbff7a
|
Provenance
The following attestation bundles were made for badness-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
publish-pypi.yml on jolars/badness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
badness-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
7ad44de69629a167b1df42644c96c3b50c422068949691242d4be030ca9d7687 - Sigstore transparency entry: 1802011483
- Sigstore integration time:
-
Permalink:
jolars/badness@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jolars
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Trigger Event:
push
-
Statement type:
File details
Details for the file badness-0.1.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: badness-0.1.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 949.4 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
607e7ebb0171ebd743523ccfb536fc71840d046cb4db118aac46d9f6d526f652
|
|
| MD5 |
b6f5cb8bc90a396b5eb63453824efb98
|
|
| BLAKE2b-256 |
87d11ccf2ca4b92e3f3f0a8f55711066affdc74e7f459e50b147d1b21ddacd77
|
Provenance
The following attestation bundles were made for badness-0.1.0-py3-none-macosx_11_0_arm64.whl:
Publisher:
publish-pypi.yml on jolars/badness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
badness-0.1.0-py3-none-macosx_11_0_arm64.whl -
Subject digest:
607e7ebb0171ebd743523ccfb536fc71840d046cb4db118aac46d9f6d526f652 - Sigstore transparency entry: 1802011749
- Sigstore integration time:
-
Permalink:
jolars/badness@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jolars
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Trigger Event:
push
-
Statement type:
File details
Details for the file badness-0.1.0-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: badness-0.1.0-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 981.9 kB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62f9dff22a56e3d55d24db3548454e06aa287fd633df3b1d0011123e76e92496
|
|
| MD5 |
7c561e91ed527b76bb0a25049d546d5f
|
|
| BLAKE2b-256 |
ed310afec8908cfb4b982e37e80f47d7ff49a6ab442b4bd3e0a62b4a47969e7d
|
Provenance
The following attestation bundles were made for badness-0.1.0-py3-none-macosx_10_12_x86_64.whl:
Publisher:
publish-pypi.yml on jolars/badness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
badness-0.1.0-py3-none-macosx_10_12_x86_64.whl -
Subject digest:
62f9dff22a56e3d55d24db3548454e06aa287fd633df3b1d0011123e76e92496 - Sigstore transparency entry: 1802011892
- Sigstore integration time:
-
Permalink:
jolars/badness@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jolars
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@1672ab889d1039ef6aab1f63f002a85125d79b99 -
Trigger Event:
push
-
Statement type: