Auto-pair & smart indentation¶
As you type, the editor closes brackets and quotes for you, keeps your indentation on new lines, opens blocks between braces, and applies one consistent indent unit (tabs or spaces) to the Tab key, backspace-unindent and auto-indent alike. Everything here is a built-in feature of the editor; the matching menu commands and the indent-style setting come from the bundled Indentation plugin.
It is meant to be invisible — it only acts on the character you just typed, and stands down wherever it would get in the way (inside comments and strings, in front of existing words, with the wrong partner character).
Auto-pairing brackets and quotes¶
Typing an opening bracket or quote inserts its partner and leaves the caret between the two:
| You type | You get | Caret |
|---|---|---|
( |
() |
between |
[ |
[] |
between |
{ |
{} |
between |
" |
"" |
between |
' |
'' |
between |
A few rules keep this from being annoying:
- Type-over. Typing a closing character when the same character is
already to the right of the caret steps over it instead of inserting a second
one — so typing straight through
()or""leaves a single, balanced pair. - No pairing in front of a word. An opener is only completed when the next
character is whitespace, a closer, or end of line — so adding
(just before existing text does not inject a stray)into the middle of it. - Apostrophe-aware quotes. A
'typed right after a letter (as indon't) is treated as an apostrophe and is not paired. Quotes only auto-pair in a neutral context (start of a token, after whitespace or an operator). - Angle brackets only in markup.
<…>auto-pair only in HTML/XML documents, where<opens a tag. Everywhere else<is a comparison or shift operator and is left alone.
Wrapping a selection (type-to-wrap)¶
With text selected, typing an opener does not replace the selection — it wraps it:
- Works with
([{"'(not<— outside markup it's an operator). - The inner text stays selected afterwards, so wraps chain: type
(then"and you get("value"). - With multiple carets, every selection is wrapped independently — and the whole operation is one undo step.
Deleting a pair¶
Pressing Backspace with the caret between an empty auto-inserted pair
((|), [|], {|}, "|", '|', or <|> in markup) deletes both
characters in one step, so you can undo an auto-pair with a single keystroke.
Once there is content between the pair, Backspace behaves normally.
Smart indentation on Enter¶
Pressing Enter carries the current line's leading whitespace onto the new line, so you stay at the same depth without re-typing tabs or spaces:
- Keep indent. The new line starts with the same indentation as the line you left.
- Open one level. If the line you left ends with an opener (
{,[,(), the new line is indented one extra level. - Open a block. If the caret sits between an opener and its matching closer, the block opens out: the new line is indented one level deeper and the closer drops to its own line at the opener's depth.
Indent style — tabs, spaces, or auto¶
One indent unit drives the Tab key, backspace-unindent and the automatic indentation above, so they always agree. Choose it in Preferences ▸ Plugins ▸ Indentation:
| Style | Behaviour |
|---|---|
| Tabs (default for new files) | One level is a real tab character; Spaces per indent sets its visual width. |
| Spaces | One level is Spaces per indent space characters. |
| Auto (detect from document) | The editor scans the document's existing indentation and follows it — a tab-indented file keeps using tabs, a 2-space file keeps using two spaces. A file with no indentation yet falls back to the default (tabs). |
New, untitled files default to Tabs, width 4.
Adjusting indentation by hand¶
The Indentation plugin adds two commands (also under Edit ▸ Indent) that indent or outdent every line touched by the selection — or the caret's line when nothing is selected:
| Command | Shortcut |
|---|---|
| Increase Indent | Ctrl+] |
| Decrease Indent | Ctrl+[ |
Per-language defaults¶
Some languages have one near-universal indentation convention, and the editor ships it as that language's default — a freshly opened file of the type indents correctly with no configuration at all:
| Language | Default |
|---|---|
| Python | 4 spaces (PEP 8) |
| Rust | 4 spaces (rustfmt) |
| Markdown | 4 spaces (nested lists) |
| YAML | 2 spaces (tabs are not allowed) |
| JSON | 2 spaces |
| Go | tabs (gofmt) |
| C / C++ | tabs |
Every other language deliberately carries no default and follows your global indent setting. Switching a document's language by hand (the Language menu) re-applies the matching default immediately.
The default lives in the language's definition file
(colorizers/<id>.json, key "indent": { "style": "tabs|spaces", "width": N }).
A power user can change a shipped default by placing an edited copy of that
file in the user override directory — the catalog replaces definitions by id.
Planned: per-language overrides in Preferences
A settings table for overriding these defaults per language (without touching any JSON) is designed and planned as the next step of this feature; until it lands, the JSON override above and the layers below are the ways to steer indentation.
Where the indent unit comes from (precedence)¶
When several sources have an opinion about indentation, the editor resolves them in one place and applies the winner, highest precedence first:
- The project's
.editorconfig— when present and "Apply .editorconfig settings" is on, a project'sindent_style/indent_size/tab_widthwin for matching files. - The language's shipped default — the table above, when the document's language declares one.
- Your global indent setting — the Tabs / Spaces / Auto choice above.
So a project that ships an .editorconfig overrides everything for that
project's files; a Python file outside any such project indents with PEP-8
spaces even when your global setting is tabs; and everything else follows your
global setting. You can always change a document's indentation by hand
afterwards.
The precedence holds the moment anything changes: applying a different
Tabs / Spaces / Auto choice in Preferences re-resolves the open document
immediately, so a file governed by an .editorconfig or a language default
keeps its indentation without you having to switch tabs.
Multi-caret¶
All of the above apply at every caret when you edit with
multiple carets: typing ( inserts () at each, Enter keeps
each line's indentation, and Backspace between empty pairs deletes both cells at
each. A single Undo reverts the whole multi-caret edit in one step.
Backspace across mixed carets
Backspace only deletes pairs when every caret sits between an empty pair. If some carets are elsewhere, Backspace falls back to its normal behaviour at all of them, so it never deletes a stray closer at one caret while editing a word at another.
In comments and strings¶
When a syntax colorizer is active, auto-pairing and the brace-driven block-open
stand down inside comments and string/character literals — there a { or
" is ordinary text, not code, so the editor leaves it exactly as typed. Plain
indentation (carrying the previous line's whitespace) still works. In a
plain-text document with no colorizer there is nothing to suppress, so pairing
behaves the same everywhere.
Related¶
- Indentation plugin — the indent-style setting and the Increase/Decrease commands.
- EditorConfig — per-project indentation that overrides your global setting.
- Multi-caret editing — placing and editing with several carets at once.