Layout and whitespace display
Development reference · View source
Space p holds text presentation and the commands that lay out selected
lines.
| Key | Action |
|---|---|
Space p . | Toggle whitespace markers for this session |
Space p s | Toggle soft wrap for this session |
Space p w | Hard-wrap each selection at editor.hard_wrap_width |
Space p r | Reflow selected prose at editor.hard_wrap_width |
Space p j | Join selected lines with a typed delimiter |
J | Join selected lines with a space |
Space p t | Align the columns of the selected table |
Whitespace markers
Space p . shows:
| Character | Marker |
|---|---|
| Space | · |
| Tab | →, followed by enough cells to reach the same tab stop |
| LF or CRLF line ending | one ¬ |
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) | |
|---|---|---|
| Width | editor.hard_wrap_width (80) | editor.hard_wrap_width (80) |
| Existing newlines | Kept as boundaries | Refilled; blank lines stay paragraph boundaries |
| Long words | Kept whole unless one word is wider than the line | Kept 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
falseto 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.
| Typed | Result |
|---|---|
Space p j Enter | Lines run together |
Space p j Space Enter | Lines separated by a space |
Space p j, any other text, Enter | That text, such as , , |, or a word, inserted literally |
- Select the lines first:
xorXfor whole lines,vfor 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
Jabove 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_widthstops, 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.