User guide / Key bindings

Layout and whitespace display

Development reference · View source

Space p holds text presentation and the commands that lay out selected lines.

KeyAction
Space p .Toggle whitespace markers for this session
Space p sToggle soft wrap for this session
Space p wHard-wrap each selection at editor.hard_wrap_width
Space p rReflow selected prose at editor.hard_wrap_width
Space p jJoin selected lines with a typed delimiter
JJoin selected lines with a space
Space p tAlign the columns of the selected table

Whitespace markers

Space p . shows:

CharacterMarker
Space·
Tab→, followed by enough cells to reach the same tab stop
LF or CRLF line endingone ¬

An unterminated final line has no marker. The markers are display-only: text, offsets, selections, wrapping, and saved files are unchanged. The setting is editor.render_whitespace.

Soft wrap

Space p s toggles editor.soft_wrap for this session. When enabled, the global status line shows ↪ before the cursor position. The arrow reports this general setting, even when a rendered Markdown page wraps independently. editor.always_wrap_rendered_markdown defaults to true; set it to false to make rendered pages follow Space p s too.

  • Wrapping follows the live pane width, including after a resize. It does not use the hard-wrap width and never changes the text.
  • It breaks at word boundaries, and within a word only when the word is wider than the pane.
  • A document whose longest line exceeds 64,000,000 bytes is never wrapped. The length is measured once, when the file is read, before anything is drawn.
  • Layouts are reused while the text, pane width, and tab width stay the same, so moving through a minified file of a few megabytes does not recalculate its whole line each keypress. Drawing seeks straight to the visible text, even near the end of the line. An edit or a new width recalculates the affected layout; the line-length limit above protects against extremely costly layouts.

Hard wrap and reflow

Space p w (hard wrap)Space p r (reflow)
Widtheditor.hard_wrap_width (80)editor.hard_wrap_width (80)
Existing newlinesKept as boundariesRefilled; blank lines stay paragraph boundaries
Long wordsKept whole unless one word is wider than the lineKept whole

Reflow in Markdown keeps headings, fenced and indented code, block quotes, tables, thematic breaks, and separate bullet or numbered items. Wrapped list continuations get a hanging indent.

Reflow in source files changes only # and // line-comment paragraphs, repeating the indentation and comment leader on every line, so selecting nearby code can never join statements. Lists inside comments get the same hanging indent.

The scratch buffer has no path to name a language, so editor.scratch_markdown (on by default) makes Space p r refill it as Markdown.

  • Set it to false to reflow a scratchpad as plain text.
  • Reflow and ? read the option together: a scratchpad whose lists survive a refill is also one that renders. Highlighting, completion, and saving are unaffected.
  • Scratch text whose first lines already identify a language keeps it, and is refilled as a source file.

Joining lines

Space p j is the inverse of Space p w: it removes every line break inside the selection and asks what to put in their place.

TypedResult
Space p j EnterLines run together
Space p j Space EnterLines separated by a space
Space p j, any other text, EnterThat text, such as , , |, or a word, inserted literally
  • Select the lines first: x or X for whole lines, v for part of them.
  • Whitespace against each removed break goes with it, so joining indented lines leaves no runs of spaces. The first line keeps its indentation.
  • Only the selection is joined. A single-line selection reports that it holds no line break, and the line after the selection is never drawn in, even when a pointer drag ends on it.
  • A selected blank line joins as an empty piece and leaves its own delimiter.
  • All selections are joined in one transaction, so one undo reverts them.

J is the promptless join from Vim and Helix:

  • It joins the lines a selection touches with one space, like Space p j Space Enter.
  • A single-line selection or a bare caret pulls the line below up instead.
  • A blank line contributes neither text nor a space, so J above an empty line removes it without a trailing space.
  • The file’s final line terminator is never joined away, even after %.

Formatting tables

Space p t pads every cell to the widest one in its column:

| Column 1 | Column 2 |
|---|---|
| Value | abc |
| Longer text | Very very long text |

becomes

| Column 1    | Column 2            |
|-------------|---------------------|
| Value       | abc                 |
| Longer text | Very very long text |

What counts as a table: rows opening with |, cells divided by |, and at least one separator row of dashes. Without a separator, a selection is refused even if every line looks like a row. The separator may be anywhere, so a selection may start on it or end below a footer rule.

What is kept:

  • A +---+---+ separator keeps its + signs.
  • GitHub alignment colons :---, :---:, and ---: survive and set left, centred, or right alignment.
  • An escaped \| stays inside its cell.
  • A tab inside a cell becomes spaces at editor.tab_width stops, because a column boundary cannot be worked out from a tab.

Selecting:

  • Select the rows first. This command widens the selection to whole rows.
  • Selections on the same or consecutive rows are formatted together as one table.
  • Blank lines inside the selection are allowed and left alone, so selecting a little more than the table is fine. Rows below the selection are never drawn in.
  • Rows with different cell counts are squared up with empty cells; no cell is dropped.
  • All rows take the indentation of the first.
  • If any line is neither blank nor a row, or there is no separator, nothing changes and an INFO notification says no table was detected.