Skip to content

align-match-case

align-match-case folds each single-statement case arm onto its case line and pads the space before the : so consecutive arms share one column, with the patterns flush left and the bodies starting at one column to the right. A match whose arms each contain one statement then reads as a dispatch table, patterns on the left and results on the right, and the reader scans rows rather than tracing each body.

The rule acts only on runs of single-statement arms at the same indentation, and an arm folds only where its one-line form fits within code-line-length. An arm stays multi-line and ends the run when it holds more than one statement, when its body is a compound statement or spans several lines, or when its folded form would overflow the budget, leaving the arms on each side of it aligned on their own. An own-line comment between two arms passes through, and the arms on both sides of it still share one column. A nested match aligns as a group of its own. Pair the rule with strip-stranded-padding, which strips the padding on a one-arm match, and with align-colons, which aligns the separators inside a dict a case body returns.

Configuration

KeyTypeDefaultMeaning
enabledbooltrueTurns the rule on or off.
max-shiftpositive int | 0 | false16How far apart the widest and narrowest rows of a run may be for the run to still align on one column. A positive N caps that gap, 0 forbids any padding so every row sits flush, and false lifts the cap so a run of any width aligns on one column. A row marked # prose: skip stays out of its group.

max-shift limits how much padding one : may take. The rule reads each run of arms in source order and extends a column while the gap between the widest and narrowest patterns stays within the limit, starting a new column at the first arm that would exceed it. Setting max-shift to false removes the limit, so a run of any width aligns on one column, and 0 forbids padding altogether, so every : sits flush against its pattern. The per-rule facets reference covers the full semantics.

The Canonical Case

Every arm body in the match on token is a single statement, spanning pass, continue, break, a raise, a bare log(token) call, and a return. Each folds onto its case line and every : moves to one shared column, with the wildcard _ padded out to the width the string patterns set.

def dispatch(token):
    match token:
        case "noop" : pass
        case "skip" : continue
        case "stop" : break
        case "boom" : raise RuntimeError("boom")
        case "echo" : log(token)
        case _      : return None
python

More Examples

The own-line comment # legacy synonyms sits between the first two arms of the match on credential.kind. The comment passes through unchanged and the arms on both sides of it still share one : column, so all three bodies fold onto their case lines and "certification" and "program" below the comment pad to the width "apprenticeship" sets above it.

The first arm's tuple pattern spreads 1 and 2 over parenthesized lines, so its : sits on a different line from its case. That arm passes through unchanged, whereas case other folds handle2() onto its line with the : flush against the pattern, because a pattern spanning several lines disqualifies the arm and no other folded arm remains to align with.

case "fail" holds one assignment whose right-hand side spreads base + extra over parenthesized lines. That arm passes through unchanged even though it holds a single statement, because a body spanning several lines disqualifies the arm, whereas case "ok" folds result = simple onto its line and, alone in its group, takes no padding.

case "certification" holds two statements, icon = "scroll" and notes.append("verified"), between three one-statement arms. The two-statement arm stays multi-line and splits the match into two groups, so case "apprenticeship" above it folds alone with its : flush against the pattern, and "program" and _ below it fold together on the column "program" sets.

case "wrap" holds a whole match inner: as its body, and case "skip" holds value = 0. The inner match aligns as its own group, folding "alpha", "beta", and "gamma" onto their case lines with their : on one column, whereas the outer case "wrap" stays multi-line because a compound body cannot fold, and case "skip" folds with its : flush against the pattern because it aligns alone.

The arms match | alternations of differing width, "ok" | "pass", "warn", and "fail" | "error" | "panic". The widest arm folds but drops out of the shared column, its : flush against the pattern, because padding "warn" out to "fail" | "error" | "panic" would exceed max-shift, whereas "ok" | "pass" and "warn" fold and share one column.

Five arms each hold one assignment, with patterns running from "under_88_columns" to "kind_with_descriptive_long_label". Only "under_88_columns" and "exactly_88_columns" fold onto their case lines and align their :, because an arm folds only where its one-line form fits within the 88-column code-line-length.

"longer_pattern_name" would reach 89 columns, "kind_with_descriptive_long_label" runs wider still, and the if some_long_predicate_check(event.kind) guard counts toward its arm's width, so those three arms stay multi-line.

  1. The "alpha" and "beta" arms of dispatch each return a long inline dict, and the wildcard arm returns None. Each dict explodes to one entry per line, its keys sort so "comment_text" leads, and the : of each entry pads into one column within its arm, while align-match-case joins the wildcard's return None onto its case _: line.

  2. Three methods of Dispatcher sit out of order, and handle_alpha contains a match whose arms each return a single value. The methods sort so handle_alpha leads, align-match-case joins each return onto its case line and pads the : into one column, and space-statements writes one blank line between the methods.

  3. dispatch opens with the assignments x, yz, and qrs above a match whose arms each return one of those bindings. align-equals pads the three = into one column one space past qrs, and align-match-case joins each single return onto its case line with every arm : padded one space past the widest pattern, "alpha".