Python API¶
Beyond the command line, clat is a small library. Import it to format LaTeX
source from your own scripts, editors, or build tools.
from clat import texfmt, load_config
config = load_config() # nearest .clat.toml, or defaults
result = texfmt(open("main.tex").read(), filename="main.tex", config=config)
print(result.text) # the formatted source
for rule, n_hits in result.clangs: # what was auto-fixed
print(f"clang: {rule.name} ({n_hits})")
for rule, fname, line, msg in result.clunks:
print(f"clunk: {fname}:{line}: {msg}")
If you omit config, texfmt uses the built-in defaults (threshold
5, every rule at its default weight). To run with a custom
threshold without a file on disk, build the dict yourself:
Formatting¶
clat.texfmt
¶
Apply formatting rules according to config.
Returns a ClatResult with the formatted text and categorised issues.
For backwards compatibility, also accessible as (text, warnings) via the legacy property — but prefer ClatResult directly.
Source code in src/clat/rules.py
clat.ClatResult
dataclass
¶
Result of running clat on a file.
Attributes:
| Name | Type | Description |
|---|---|---|
text |
str — the (possibly modified) source text
|
|
clangs |
list[tuple] — (rule, count) for auto-fixed rules above threshold
|
|
clunks |
list[tuple] — (rule, filename, line, msg) for unfixable issues above threshold
|
|
splats |
list[tuple] — (rule, filename, line, msg) for issues below threshold
|
|
Source code in src/clat/rules.py
Configuration¶
clat.load_config
¶
Load config from .clat.toml or fallback locations.
Returns a dict with 'threshold' (int) and 'weights' (dict[str, int]).
Source code in src/clat/rules.py
clat.save_config
¶
Write config dict back to a .clat.toml file.
Source code in src/clat/rules.py
clat.generate_default_config
¶
Return a .clat.toml string with all rules and their default weights.
Source code in src/clat/rules.py
The rule registry¶
clat.Rule
dataclass
¶
A single clat rule.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str — unique key, used in config overrides (e.g. 'labels_inline')
|
|
name |
str — human-readable description
|
|
fn |
callable — fix function f(text) -> text (fixable=True)
|
or warn function f(text, filename) -> [(file, line, msg)] |
weight |
int — default severity 1–10; 0 disables the rule
|
|
fixable |
bool — True if clat can auto-fix this
|
|
order |
int — execution order (lower = earlier); fixes run before warns
|
|
Source code in src/clat/rules.py
clat.RULES
module-attribute
¶
RULES = [Rule(1, 'labels_inline', 'Merge \\label onto the same line as \\section', rule1_labels_inline, weight=8, fixable=True, order=10), Rule(2, 'decorative_comments', 'Strip decorative comment separators (%%===, %%--- etc.)', rule7_strip_decorative_comments, weight=6, fixable=True, order=20), Rule(3, 'heading_spacing', 'Two blank lines before headings, none after', rule5_heading_spacing, weight=7, fixable=True, order=30), Rule(4, 'equation_separators', 'Insert % lines around display-math environments', rule2_equation_separators, weight=7, fixable=True, order=40), Rule(5, 'equation_punctuation', 'Add trailing comma or period to display equations', rule4_equation_punctuation, weight=6, fixable=True, order=50), Rule(6, 'float_indentation', 'Tab-indent content inside figure/table/list environments', rule6_figure_indentation, weight=5, fixable=True, order=60), Rule(7, 'one_sentence_per_line', 'Split sentences onto individual lines', rule3_one_sentence_per_line, weight=8, fixable=True, order=70), Rule(8, 'math_delimiters_inline', 'Replace \\(...\\) with $...$', rule8_math_delimiters_inline, weight=5, fixable=True, order=80), Rule(9, 'tilde_before_refs', 'Ensure non-breaking space before \\ref, \\cite etc.', rule9_tilde_before_refs, weight=7, fixable=True, order=90), Rule(10, 'number_unit_spacing', 'Normalise number-unit spacing (100\\,kN)', rule10_number_unit_spacing, weight=6, fixable=True, order=100), Rule(11, 'old_font_commands', 'Replace {\\bf text} with \\textbf{text} etc.', rule11_old_font_commands, weight=5, fixable=True, order=110), Rule(12, 'ellipsis', 'Replace ... with \\dots', rule12_ellipsis, weight=4, fixable=True, order=120), Rule(13, 'ordinal_suffixes', 'Convert superscript ordinals to plain text (1st, 2nd)', rule13_ordinal_suffixes, weight=8, fixable=True, order=130), Rule(14, 'long_file', 'Warn if file exceeds 2000 lines', warn_long_file, weight=3, fixable=False, order=200), Rule(15, 'hardcoded_refs', 'Detect "Figure 3" instead of \\cref{...}', warn_hardcoded_refs, weight=6, fixable=False, order=210), Rule(16, 'manual_sizing', 'Detect \\big, \\Big etc. (prefer \\left/\\right)', warn_manual_sizing, weight=3, fixable=False, order=220), Rule(17, 'float_after_heading', 'Detect float placed directly after a heading', warn_float_after_heading, weight=4, fixable=False, order=230), Rule(18, 'math_delimiters_display', 'Replace \\[...\\] with $$...$$', rule18_math_delimiters_display, weight=0, fixable=True, order=85)]
Multi-file discovery¶
For multi-file documents, clat.cli.discover_tex_files expands a list of root
files into the full, ordered, de-duplicated set of .tex files reachable
through \input/\include-style commands — the same traversal the -r flag
uses. See Multi-file documents.
clat.cli.discover_tex_files
¶
Return files plus recursively discovered LaTeX inputs/includes.
Roots are visited in the order provided. Dependencies are depth-first, de-duplicated, and resolved relative to the file that references them. Missing .tex dependencies are included in the returned list so the normal formatter path reports them as missing.