Colin's LaTeX Tidy — somewhere between a clang and a splat
Project description
clat
Colin's LaTeX Tidy -- somewhere between a clang and a splat.
📖 Documentation: https://ccaprani.github.io/clat/
A configurable LaTeX source formatter with opinions. Every rule has a weight; you set a threshold. What happens depends on the combination:
- clang -- weight >= threshold and fixable: auto-fixed
- clunk -- weight >= threshold and not fixable: needs your attention
- splat -- weight < threshold: advisory, take it or leave it
Why "clat"?
Prosaically, clat is Colin's LaTeX Tool. But the name also has a bit of printer's noise in it.
In the "Aeolus" episode of Ulysses -- "How a great daily organ is turned out" -- Bloom moves through the newspaper office amid the machinery of print: clanking, rhythmic, three-four time; thump, thump, thump. My great-great-grandfather, a Dublin printer, is mentioned there too, though some editions mangle Caprani as Cuprani.
So clat is meant to sound a little like that composing-room racket: a small, opinionated machine for turning untidy copy into clean type.
Install
pip install clat-tidy
The command is clat. (The distribution is published as clat-tidy because
clat was already taken on PyPI; everything you type is still clat.)
For local development:
pip install -e .
Requires Python >= 3.8. On Python < 3.11, tomli is installed automatically.
Quick start
# Format files in place
clat main.tex appendix.tex
# Format a multi-file document by following LaTeX inputs/includes
clat -r main.tex
# Dry run (report without fixing)
clat --check main.tex
# Dry run a multi-file document
clat --check -r main.tex
# List all rules
clat list
# Override threshold for one run
clat --threshold 3 main.tex
Rules
Run clat list to see all rules with their numbers, weights, and current category.
| # | Rule | Default | Fixable | Description |
|---|---|---|---|---|
| 1 | labels_inline | 8 | yes | Merge \label onto the same line as \section |
| 2 | decorative_comments | 6 | yes | Strip decorative comment separators (%%=== etc.) |
| 3 | heading_spacing | 7 | yes | Two blank lines before headings, none after |
| 4 | equation_separators | 7 | yes | Insert % lines around display-math environments |
| 5 | equation_punctuation | 6 | yes | Add trailing comma or period to display equations |
| 6 | float_indentation | 5 | yes | Tab-indent content inside figure/table/list environments |
| 7 | one_sentence_per_line | 8 | yes | Split sentences onto individual lines |
| 8 | math_delimiters | 5 | yes | Replace \(...\) with $...$ and \[...\] with $$...$$ |
| 9 | tilde_before_refs | 7 | yes | Ensure ~ before \ref, \cite etc. |
| 10 | number_unit_spacing | 6 | yes | Normalise number-unit spacing (100\,kN) |
| 11 | old_font_commands | 5 | yes | Replace {\bf text} with \textbf{text} etc. |
| 12 | ellipsis | 4 | yes | Replace ... with \dots |
| 13 | ordinal_suffixes | 8 | yes | Convert superscript ordinals to plain text (1st, 2nd) |
| 14 | long_file | 3 | no | Warn if file exceeds 2000 lines |
| 15 | hardcoded_refs | 6 | no | Detect Figure 3 instead of \cref{...} |
| 16 | manual_sizing | 3 | no | Detect \big, \Big etc. |
| 17 | float_after_heading | 4 | no | Detect float placed directly after a heading |
Configuration
Config is read from .clat.toml in the project directory, falling back to
~/.config/clat/config.toml.
Create a config file
clat set --init
This generates .clat.toml with all rules and their default weights:
threshold = 5
[weights]
labels_inline = 8 # Merge \label onto the same line as \section (fixable)
decorative_comments = 6 # Strip decorative comment separators (fixable)
heading_spacing = 7 # Two blank lines before headings, none after (fixable)
# ... all 17 rules listed
Edit the file directly, or use the CLI:
Set threshold
clat set --threshold 8
Set a rule weight
# By rule number (see clat list)
clat set 12 9 # set rule 12 (ellipsis) to weight 9
clat set 14 2 # demote hardcoded refs to a splat
Reset to defaults
clat set --reset
One-shot overrides
Override threshold for a single run without modifying the config:
clat --threshold 3 main.tex
CLI reference
clat <files...> Format .tex files in place
clat -r <root.tex...> Recursively format LaTeX inputs/includes
clat --recursive <root.tex> Long form of -r
clat --check <files...> Dry run: report issues without fixing
clat --check -r <root.tex> Dry run a multi-file document
clat -o out.tex in.tex Write to a different file
clat --threshold N <files> Override threshold for this run
clat list List all rules with weights and categories
clat list --config path Use a specific config file
clat set <rule#> <weight> Set a rule weight in .clat.toml
clat set --threshold N Set the threshold in .clat.toml
clat set --init Create .clat.toml with defaults
clat set --reset Restore .clat.toml to defaults
clat set --config path Target a specific config file
clat --version Show version
Multi-file documents
Use -r or --recursive when a root .tex file assembles a document from
other source files:
clat -r main.tex
Recursive mode follows \input, \include, \subfile, \import,
\subimport, \includefrom, and \subincludefrom commands. Paths are
resolved relative to the file containing the command, .tex is appended when
no extension is given, duplicate files are skipped, and missing .tex inputs
are reported through the normal formatter output.
How it works
Each rule is either fixable (clat can rewrite the source) or unfixable (clat can only detect the issue). At runtime, each rule's weight is compared to the threshold:
weight >= threshold + fixable => clang (auto-fixed)
weight >= threshold + NOT fixable => clunk (needs manual fix)
weight < threshold => splat (advisory)
Fixable rules below threshold are still applied (the text is still fixed), but reported as splats rather than clangs.
Development
pip install -e .
python -m pytest tests/ -v
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
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 clat_tidy-0.4.0.tar.gz.
File metadata
- Download URL: clat_tidy-0.4.0.tar.gz
- Upload date:
- Size: 26.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
251a5a8426ae83c8d6d21743cb0586bb3eeaba0721d8a196e3f9952c9dbeb05a
|
|
| MD5 |
ece09f7087e9729409fec3c55a73aeb6
|
|
| BLAKE2b-256 |
c808f1d5110c44c97da03878f4f9a4c62e5cfe51b004963a6befcd2625311503
|
Provenance
The following attestation bundles were made for clat_tidy-0.4.0.tar.gz:
Publisher:
publish.yml on ccaprani/clat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clat_tidy-0.4.0.tar.gz -
Subject digest:
251a5a8426ae83c8d6d21743cb0586bb3eeaba0721d8a196e3f9952c9dbeb05a - Sigstore transparency entry: 1739610758
- Sigstore integration time:
-
Permalink:
ccaprani/clat@38321397287588f3d2039f88d15b923d16be9783 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/ccaprani
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@38321397287588f3d2039f88d15b923d16be9783 -
Trigger Event:
release
-
Statement type:
File details
Details for the file clat_tidy-0.4.0-py3-none-any.whl.
File metadata
- Download URL: clat_tidy-0.4.0-py3-none-any.whl
- Upload date:
- Size: 20.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8e28d5ac64825085a05c98bff30fccbadffa4c1c65a2e93b7351ec9cee8cb73
|
|
| MD5 |
a8eec0875e3c43314796a1b054b5648b
|
|
| BLAKE2b-256 |
ef06a1bc12920b2e746009de3efae44f0bdde360941d838a7ee17f7970ffabb7
|
Provenance
The following attestation bundles were made for clat_tidy-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on ccaprani/clat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
clat_tidy-0.4.0-py3-none-any.whl -
Subject digest:
e8e28d5ac64825085a05c98bff30fccbadffa4c1c65a2e93b7351ec9cee8cb73 - Sigstore transparency entry: 1739610895
- Sigstore integration time:
-
Permalink:
ccaprani/clat@38321397287588f3d2039f88d15b923d16be9783 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/ccaprani
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@38321397287588f3d2039f88d15b923d16be9783 -
Trigger Event:
release
-
Statement type: