Skip to content

align-comparisons

A multi-line boolean chain (and or or) of comparison operands reads as a small table where the operator anchors the relationship between left and right. When each operator sits at a different column the eye walks across each line individually, treating the chain as five sentences rather than one parallel structure.

gathers the operator column into a shared one, so every comparator's last character lands on the same offset and the chain reads top to bottom as a single judgment.

The rule walks each BoolOp whose operands are all Expr::Compare. The widest operand's left side fixes the shared column, with variable-width operators (==, <=, is not) right-aligning so the operator's last character sits in the shared column. A chained compare (0 < x < 100) anchors on its first operator only. A non-comparison operand, a multi-line operand, or a blank line in the gap breaks the run.

Configuration

KeyTypeDefaultMeaning
enabledbooltrueToggles the rule on or off.
max-shiftpositive int | 0 | false16The width-spread budget a contiguous run may shift to reach the shared column. A positive N caps the spread, 0 forbids any shift so every row sits flush, and false lifts the cap so a contiguous run folds into one column. To hold one row out of an otherwise-aligned group, mark it with # prose: skip.

max-shift bounds how far an operator may shift to align. The rule walks each run of comparisons in source order and grows a column while its width spread stays within the cap, breaking a fresh column at the first row that would exceed it. A max-shift of false lifts the cap so a contiguous run folds into one column, and 0 forbids any shift. The per-rule facets reference covers the full semantics.

The Canonical Case

Three single-comparator == operands in a multi-line and-chain share an alignment column. The operator at each row sits one space past the widest operand's left side.

if (
    foo         == 1
    and bar_baz == 2
    and quux    == 3
):
    pass
python

More Examples

A blank line between two qualifying operands breaks the alignment run, so the operators on either side of the gap no longer share a column.

A chained compare such as 0 < bar < 100 anchors on its first operator. The remaining operators stay in place and take no part in the column math, while the surrounding single-comparator rows align around it.

An operand whose own range spans multiple source lines breaks the run. The parenthesized (1 + 2) operand pushes its neighbors out of column, leaving the trailing rows to align among themselves.

A comment on its own line between two operands pushes them onto non-adjacent source lines, so the line-distance check breaks the run regardless of comment content. The rows below the divider still align among themselves.

A call expression on the left side qualifies for the group like any other operand. The call's display width, len(b), counts as the left-hand side that the operator column pads against.

Identity and membership operators join the same aligned group as == and <. The wider is not and not in widen the operator column, and every other operator's last character lands at the shared right edge.

== operands and < operands share one aligned group. The variable-width operators right-align, so the second = of == and the < land in the same column.

Operands across an or chain align with the same column math the rule applies to and chains. The == of each row settles one space past the widest operand's left side.

No Change

An and-chain whose == already sit one space past the widest left side is idempotent under the rule. No edit is emitted and the group passes through unchanged.