align-colons
AlignmentAligns the : separator across dict literals, annotated assignments, function-signature annotations, and Google-style docstring sections.
A dictionary, list, or set with five non-trivial entries on one line reads as a single chunky token, and the reader's eye flicks across to find the entry it wants. The same data on five separate lines reads as a column of entries, each one a unit.
expands multi-entry collections to the one-per-line shape whenever the entries cross the atomicity threshold, and it leaves short single-line collections alone when each entry is already small enough to skim.The rule fires on dictionary, list, set, and tuple literals, a tuple expanding only when it carries its parentheses, since a bare comma tuple such as return a, b, c has no bracket pair to break on. A literal expands when any entry is non-atomic (a function call, a nested collection, a computed expression) or when the entry count exceeds max-atomics. Single-line collections of atomic literals (ints, floats, strings, single-name identifiers) inside the cap stay on one line. Pair with
The rule runs the inverse move as well, rejoining a fractured construct whose single-line form fits the budget. The repair reaches a multi-line subscript such as data[key] or matrix[row + step], a multi-line collection key inside a dict, and a comprehension or generator expression broken across its for and if clauses, so a tuple key split across lines rejoins and reads as the single clean member
A literal the author laid out as a flush bracketed column is a different case, because its breaks sit at the entry boundaries the one-per-line shape is built from. keep-multiline-literals, on by default, holds that literal multi-line and re-expands it to the canonical layout rather than joining it back, so the vertical column the author laid down survives along with the : alignment
: to align and reads no differently from the single row it rejoins to. A break falling anywhere else, such as a soft wrap that leaves the opening bracket sharing its line, reads as a fracture and rejoins whatever the facet holds, and clearing the facet restores the join for the columnar case as well.A dict also expands once it holds more than max-dict-entries entries, whatever its width, taking any enclosing collection with it. It mirrors
max-params, the same count-gate shape applied to parameters. The trigger is dict-only, since a list or set reads acceptably as a packed run while a dict's key-value pairs earn the vertical layout. Set the facet to false to leave width as the only dict gate.A dict entry whose key: value width overflows the budget at the item-indent column breaks at : and hangs the value at item_indent + INDENT_STEP. The hang applies per-row, so a multi-item dict hangs only the rows that need it. A single-entry dict whose entry overflows enters the expand path and applies the same break. Tuples, lists, and sets stay out of the hang shape because their elements carry no : separator.
Each shape move sits behind its own facet, so a project can switch one off without disturbing the others. keep-multiline-literals governs whether an authored multi-line literal holds that shape, explode governs every expansion (the width-driven spread and the max-dict-entries count trigger alike, so false leaves the cap inert), and wrap-dict-entries governs the over-wide-entry break at :. Each defaults on, preserving the combined behavior above, and clearing one drops that move while the others keep running. Fracture repair sits behind no facet at all, since rejoining a construct broken somewhere other than an entry boundary is correct rendering rather than a preference.
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Toggles the rule on or off. |
explode | bool | true | Expands an overflowing or over-count collection to one entry per line. false suppresses every expansion and leaves the count cap inert. |
keep-multiline-literals | bool | true | Holds a literal the author laid out as a flush bracketed column of two or more entries. false joins one whose single-line form fits the budget, and every other break rejoins either way. |
max-atomics | positive int | false | 8 | Keeps short collections on one line when each entry is an atomic literal and the run fits the cap. false removes the cap and packs by width alone. |
max-dict-entries | positive int | false | 3 | Expands a dict once its entry count exceeds the cap, whatever its width. false disables the count trigger. |
wrap-dict-entries | bool | true | Breaks an over-wide key: value at its : and hangs the value beneath. false leaves the oversized entry on one line. |
A short tuple inside a function-call argument list, like numpy.zeros((3, 4)), stays inline at the default cap. A dict literal with eight non-atomic entries expands regardless of length. A four-entry dict expands at the default max-dict-entries of 3 even when it fits the line.
A dict literal with non-atomic entries expands to one entry per line, and the reader reads the entries as a column of key-value pairs. A dict the author already laid out as a column of two or more entries holds that shape rather than joining back, because keep-multiline-literals defaults on, whereas a single-entry one rejoins.
short_dict = {"alpha": 1, "beta": 2, "gamma": 3}
long_dict = {
"alpha": 1,
"beta": 2,
"gamma": 3,
"delta": 4,
"epsilon": 5,
"zeta": 6,
"eta": 7
}
single_entry_dict = {"default_action": "noop"}
held_dict = {
"alpha": 1,
"beta": 2,
"gamma": 3
}
Only a parenthesized tuple expands. A bare comma tuple carries no bracket pair to hang the broken lines on, so it holds its source line whatever its width, while its parenthesized sibling flows across lines like a list.
Literals, names, attribute chains, and unary operands are all atomic and flow together across balanced lines. A non-atomic call expression in the middle breaks its surrounding run into two independent flow segments, each balancing on its own.
Clearing keep-multiline-literals restores the join, so a fitting multi-line literal comes back onto one line while an overflowing single-line literal still explodes to its packed rows. The keep-multiline-literals and explode facets move independently, in that clearing one leaves the other live.
Setting wrap-dict-entries to false keeps an over-wide key: value on a single line as the dict expands, rather than breaking at : and hanging the value beneath. The width and count caps keep their meaning.
A literal the author laid out as a flush bracketed column holds that shape and re-expands to the canonical layout, whereas a multi-line subscript and a multi-line collection key rejoin onto one line whatever keep-multiline-literals holds. Neither the subscript nor the key carries an entry boundary for a break to sit on, so each reads as a fracture rather than as an authored column.
A nested matrix stays fully inline within the 88-character budget. When the outer list overflows, it expands row by row, each inner row checking fit at its own column and staying inline when it fits, producing the matrix-by-row layout rather than one cell per line.
A literal whose opening bracket shares its line with an entry, or whose closing bracket trails one, reads as a soft wrap rather than an authored column, so it rejoins onto one line. A set, a ** spread, and a one-element tuple each rejoin the same way, the tuple keeping the trailing , that makes it a tuple at all. The dict beside them opens and closes on bracket-only lines, which is the shape keep-multiline-literals holds.
A dict past max-dict-entries standing as a subscript base expands on the count trigger, and the enclosing subscript then reads the expanded dict as a break the rejoin cannot swallow. The literal reaches one shape on the first run rather than exploding and rejoining on alternate passes.
A parenthesized tuple that overflows the budget breaks across lines through the same flow layout
already gives alist. Atomic elements flow across as few balanced lines as fit under code-line-length and the max-atomics cap, while a run of non-atomic elements lands one per line.A dict row whose key: value width overflows at the item-indent column breaks at : and hangs the value at item_indent + INDENT_STEP. Rows that fit stay on one line, and an already-multi-line nested value runs its own expansion without triggering the hang.
A list, set, or dict comprehension or a generator expression broken across lines joins back onto one line when its single-line form fits the budget, the collapse-only move a subscript already takes. A comprehension is one expression rather than a run of entries, so it only ever collapses and never explodes, leaving one too wide to fit at its source line breaks.
A dict carrying more entries than max-dict-entries breaks to one entry per line even when it fits the line budget, while a dict at or under the cap stays inline and an already-expanded dict past the cap stays expanded.
A list stays inline within the 88-character budget and expands when it overflows. Inside the expanded form, atomic items flow across as few balanced lines as fit under code-line-length and the max-atomics cap. A list the author wrote across lines holds its break and flow-packs its atomics the same way rather than joining back inline.
A multi-line collection key joins onto one line so it reads as the single clean member the alignment and ordering rules fold into their run rather than one stranded across a break. A key that would overflow once joined keeps its source break.
Each nested collection runs its own layout decision at its own column. An expanding outer literal drags its inners along, whereas a pinned outer leaves each inner to its own pass. Dict-value nesting folds the key-text offset into the inner's column, so a long key can push its value past the budget even when the outer fits. An inner the author wrote across lines holds its own break, and that break then keeps the outer from joining.
The list sits inside an f-string replacement field on a line running past the budget, and it still holds its source shape, since an f-string literal is opaque to layout and expanding the list would splice a line break into the string.
The dict carries more entries than max-dict-entries allows, which normally expands the dict and every collection around it whatever the widths involved. Sitting inside an f-string replacement field puts it out of reach, so the count cap reads neither the dict nor the list holding the string.
Setting explode to false suppresses every expansion. An overflowing literal keeps its single line, an over-count dict that fits stays inline because the count cap goes inert, and a literal already spread across lines is left untouched.
With explode off, a dict whose key: value entry overflows the budget keeps its whole single line rather than expanding and hanging the value beneath. The wrap is a facet of the expansion explode gates, so clearing explode freezes it too.
A one-element tuple keeps its load-bearing trailing , and stays inline, since breaking a single element gains nothing. A grouping-parenthesized expression is left untouched because it shares the ( ) spelling yet is no tuple.
An inline literal that already fits and a multi-line literal whose inline form would overflow both round-trip with no edit. A dict already hanging an oversized entry's value at the post-: column also passes through unchanged.
Aligns the : separator across dict literals, annotated assignments, function-signature annotations, and Google-style docstring sections.
Alphabetizes import siblings, dict-key blocks, and class-body members.
Normalizes function signatures to one line or one parameter per line, gated by line length and inline-parameter count.
Removes trailing commas from collections, signatures, calls, and every other bracketed container.