Skip to content

comment-spacing

A comment's leading edge is the first thing the eye lands on, and a file where one comment opens #note and the next ##note makes the reader re-parse that delimiter before reaching the note itself.

settles the opener onto a single space after the hash run and holds a trailing comment at least two columns clear of the code beside it, so the delimiter reads once and the text lines up behind it.

Indentation inside a comment is sometimes structure the author drew and sometimes drift, and what separates the two is whether the comment stands in a column. A comment opening at the same column as the comment above or below it belongs to a block that was laid out deliberately, so every indent inside that block survives:

python
# options for the run:
#     --fast   skip the checks
#     --slow   run everything

A bare # sustains such a run rather than breaking it, since it opens at that column too, which is what keeps a spacer line from splitting one block into two. A comment sharing its column with nothing has no layout to protect, so its padded opener settles to the single space every other comment carries. A run opening on any whitespace other than a space collapses either way, a lone tab included, since no author draws that shape deliberately.

The space lands after the whole hash run rather than flattening it, leaving a ## or #### heading intact as the section marker it was written as, which is the same shape

reads when it decides a comment block divides its neighbors rather than describing the statement below. A run carrying no text after it is a divider rather than an opener, so a line of hashes alone passes through, and a comment carrying whitespace and no text sheds that whitespace down to a bare #. Where the run is followed by !, :, ', or |, the opener passes through untouched, covering the shebang line and Sphinx's #: attribute doc alongside the quoted and piped forms, whereas a trailing one still moves to the two-column floor, the exemption covering what a comment opens with rather than where it sits.

Two columns is the floor on a trailing comment rather than the target, so a wider gap survives as written and a shared comment column stays reachable. The gap is counted in characters, leaving a lone tab short of the floor and replaced with two spaces.

A trailing #note gains the space its text was missing and moves two columns clear of x = 1, while the block comment below it opens the same way. The two openers land on one shape, so the eye reads the delimiter once rather than re-parsing it per line.

x = 1  # note
# tidy this
python

Three comments opening at one column on consecutive lines read as a block the author laid out, so every indent inside it survives. The trailing comment below shares a column with nothing, so its padded opener settles to the single space a scattered comment carries.

#   options for the run:
#     --fast   skip the checks
#     --slow   run everything
value = 1  # already clear of the code
python

The space lands after the whole hash run rather than flattening it, so a ## or #### heading survives as the section marker it was written as and only its text shifts. A run already carrying its space is left as written.

## notes
### Section
#### deeper
python

Configuration

KeyTypeDefaultMeaning
enabledbooltrueToggles the rule on or off.

The opener shape and the two-column floor are both fixed, so the rule carries enabled as its only facet. A comment that must keep its own spacing takes an inline Suppression directive rather than a project-level knob, since the exception is per-comment rather than per-project.

The Canonical Case

A trailing #note gains the space its text was missing and moves two columns clear of x = 1, while the block comment below it opens the same way. The two openers land on one shape, so the eye reads the delimiter once rather than re-parsing it per line.

x = 1  # note
# tidy this
python

More Examples

Three comments opening at one column on consecutive lines read as a block the author laid out, so every indent inside it survives. The trailing comment below shares a column with nothing, so its padded opener settles to the single space a scattered comment carries.

With no whitespace at all between the value and the hash, the two-column floor arrives as an insertion rather than as a rewrite of an existing gap. The opener already reads right, so that is the only edit the comment takes.

The two-column floor applies wherever a comment trails code, an open bracket included.

declines the padding in that exact position so the comment never fuses onto the bracket, leaving this rule to settle how wide the gap reads.

No space is inserted where nothing follows the hash run, so a decorative rule drawn from hashes alone survives verbatim. A rule drawn from another character does carry text, so its opener settles like any other comment's.

The space lands after the whole hash run rather than flattening it, so a ## or #### heading survives as the section marker it was written as and only its text shifts. A run already carrying its space is left as written.

Sphinx's #: attribute doc keeps its opener verbatim, and the two-column floor still applies to the gap ahead of it. The exemption covers what the comment opens with rather than where the comment sits.

No Change

Two columns is the floor rather than the target, so a wider gap between the code and its trailing comment survives untouched. That leaves a shared comment column reachable by an alignment rule rather than flattened before one can read it.

No Change

A hash run followed by !, :, ', or | carries meaning to a tool downstream, so its opener passes through untouched. That covers the shebang line, Sphinx's #: attribute doc, and the quoted and piped forms, each of them own-line here and so carrying no gap to settle either.