Editing
The selection comes first, so you see what an edit will touch before it happens, and the same few keys act on a character, a word, a block or many places at once.
Inserting text
| Key | Where insertion begins |
|---|---|
i | Before the selection |
a | After the selection |
I | First non-blank character on line |
A | End of line |
o | New line below |
O | New line above |
Press Esc or Ctrl-c to return to Normal mode. Ctrl-w deletes the word before the cursor while you type.
Leaving Insert mode selects the text you typed, so you can act on it right away: delete it, surround it, search for it. If you typed nothing, the cursor stays where you started. The insert-select-on-exit option turns this off (see Buffer options). With the typed text selected, i continues before it and a after it.
However you entered Insert mode, and even with insert-select-on-exit off, m i i selects what you last typed once you leave Insert mode. See Text objects.
Auto-pairs
With insert-auto-pairs on (the default), typing (, [, {, ", ' or ` in Insert mode also inserts the matching closing character, with the cursor between the two. This happens only when the cursor sits on whitespace, a line end, the end of the buffer or a closing character, so typing in front of a word inserts only what you typed.
- A quote typed right after a word character, or right after the same quote, is inserted on its own:
don't,```and"""come out as typed. - Typing a closing character while the cursor sits on that same character moves past it instead of adding another.
Backspacebetween an empty pair deletes both characters.Enterbetween a pair of brackets opens an indented block (see Indentation).- Text you paste is never auto-paired.
Deleting and changing text
| Key | Effect |
|---|---|
d | Delete selection (pushed onto the kill ring) |
c | Delete selection content and enter Insert mode (one undo group). A trailing newline is kept, so c on a line rewrites its content but keeps the line. |
For a line-wise delete, select the line first: x then d.
d deletes everything the selection covers except the buffer's final line break (see Lines and inline text). When deletions from several cursors overlap, such as Ctrl-w in Insert mode with cursors in the same word, the shared text is removed once.
Copy & Paste explains the kill ring and how to paste from it.
Replacing text
| Key | Effect |
|---|---|
r + char | Replace every selected character with the typed character |
Line endings in the selection are kept, so replacing across several lines doesn't join them. Enter and Tab work as the typed character, replacing with a newline or a tab.
On a cursor that sits on a bracket or quote, typing either half of a pair writes the half that matches the side it replaces: r [ on ) writes ]. To change both halves of a pair, select both first: m s ( then r [ turns (…) into […] (see Surround).
Changing case
| Key | Effect |
|---|---|
G L | Lowercase the selection |
G U | Uppercase the selection |
G C | Capitalize each word in the selection |
Numbers and dates
| Key | Effect |
|---|---|
Ctrl-a | Add the count (1 without one) to the number or date at each selection |
Ctrl-s | Subtract the count from the number or date at each selection |
G A | Add the count to the first selection's number or date, twice the count to the second's, and so on |
G S | Subtract in the same way as G A |
Which number or date changes:
- A cursor changes the one it is on, or else the first one after it on the same line.
- A wider selection changes the one at its start, or else the first one inside it.
- Selections with nothing to change are left alone.
The new value is selected (for a date or time, the part that changed), so pressing the key again keeps changing it.
G A numbers a list: select the lines, split them into one selection each with S, and three lines of 0 become 1, 2 and 3. Selections with nothing to change don't count towards the sequence.
Numbers:
- A
-before a digit is a minus sign, unless it follows a letter, digit,_or closing bracket: inx-1,1-1andf(x)-1it separates, and only the last1changes. - A number right after a letter,
_or closing bracket never goes below zero:item1minus 3 isitem0. - Characters listed in the buffer's
word-charsoption count as letters for both rules (see Buffer options). - Hexadecimal (
0x1f), octal (0o17) and binary (0b101) numbers change in their own base and never go below zero. Hex letters keep their case. - Leading zeros keep the width (
007becomes008), and_separators are kept (999_999becomes1_000_000). - Digits inside a word count:
item1becomesitem2. - A
.separates two numbers: in1.2.3, each part changes on its own.
Dates and times:
- Dates are written
2026-10-18or2026/10/18, optionally followed by a space orTand a time such as14:30or14:30:15. A time can also stand on its own. - The part the selection starts on changes: with the cursor on the month, the month. A selection that starts before the date changes the day, or the minutes of a time on its own. Several selections on one date each change their own part.
- Days, hours, minutes and seconds carry over:
2026-12-31plus one day is2027-01-01. A month or year change keeps the day valid:2024-01-31plus one month is2024-02-29. A time on its own wraps around midnight. - Something that is not a real date, such as
2026-13-45, changes as separate numbers.
When no selection has anything to change, or a result doesn't fit (past the largest supported number, or a year past 9999), nothing changes and a message says so.
Lines and alignment
| Key | Effect |
|---|---|
J | Join the selected lines into one |
& | Align selections into a column |
> | Indent lines touched by a selection |
< | Unindent lines touched by a selection |
J replaces each line break with one space and drops the next line's indentation, so joined code or prose has no gap in the middle. When the next line is empty or only whitespace, no space is added. Joining several lines at once leaves a cursor on each inserted space.
& lines up your selections in one column, using the primary selection's line as the starting point:
- It inserts spaces at the left edge of each selection to reach that column.
- If another line needs more room, the column widens for all of them, so the primary selection can shift right too.
- Where a selection already sits too far right, the run of spaces or tabs before it shrinks instead (never below one).
- Multi-line selections are left alone.
Which end of the selection is the anchor decides whether it aligns to the left or the right; Ctrl-e swaps anchor and head. See Selections.
>/< shift every line touched by a selection by one indent level, using the buffer's indent-width and indent-style (see Buffer options). A count shifts by that many levels at once (3>).
Blank lines, mixed indentation and narrow indents
- Blank and whitespace-only lines in the selection are left alone, so they never pick up trailing whitespace.
- Each touched line's whole indent is rewritten at the new width in the current
indent-style, so<right after>restores the previous indent width. A mixed tabs-and-spaces indent comes back rewritten inindent-style, not character for character. <on an indent narrower than one level moves the line to the left margin instead of going negative, so a following>lands on a full level, not where the first<started.
Indentation
Enter, o and O start the new line at the indent the surrounding code calls for: one level deeper after a line that opens a block, level with the code around it otherwise. With insert-auto-pairs on, Enter between a pair of brackets opens a block: the cursor lands on an indented line and the closing bracket moves to the line below.
When the first thing you type on a new line closes a block, such as a closing bracket or keyword, the line moves back to the block's indent. A closing word moves back once it is finished: when you type a space or punctuation after it, or press Enter. A line whose indent you changed by hand is left alone.
This uses the language's grammar and its indentation rules, which PLUM installs with :plum-install-grammar <language>. Without them, a new line copies the current line's indent, and nothing moves back as you type. Set indent-smart to #f to turn automatic indentation off: new lines then start at the left margin.
New indentation follows the buffer's indent-width and indent-style, as > and < do. To indent with spaces in a language, set its indent-style to soft (see Buffer options).
Comments
| Key | Effect |
|---|---|
G G | Comment or uncomment the lines of each selection |
On a cursor, or a selection within one line, G G puts the language's line comment in front of the line's text. In a language with only block comments, it wraps the line's text in one instead.
A selection over several lines is wrapped in one block comment, from its first non-blank character to its last. Its lines get line comments instead:
- in a language with only line comments;
- with
:set global comment-prefer-line=true, even where the language has block comments; - when the text already contains the end of a block comment, since wrapping it would end the comment early. A language with only block comments then leaves the text alone and
G Gsays why.
Line comments on several lines all start at the same column, and blank lines are left alone.
G G on a commented line removes the comment, whichever kind it is: a line comment with the space after it, or a block comment's start and end with the space inside each.
With several selections, the primary selection decides, or the first selection with text when the primary's lines are all blank. If its lines are commented, G G uncomments every selection. Otherwise it comments every selection, including lines that already have a comment.
Inside an embedded block, such as a fenced code block in Markdown, the block's own language decides the comment. To change a language's comments, see configure-language! in Language settings.
Shell commands
| Key | Effect |
|---|---|
| | Run a shell command on each selection and replace the selection with its output |
Ctrl-| (Insert mode, kitty) | Run a shell command and insert its output at each cursor |
Ctrl-c | Stop the shell command running in this buffer |
| asks for a command and runs it once for each selection, each in its own process, with the selection's text as its input. The output replaces the selection, and the selection then covers the output. | sort sorts the lines of each selection; | jq . formats a selected JSON value. Any program that reads text and prints a result works.
In Insert mode, Ctrl-| runs the command once for each cursor, with no input, and inserts its output where you are typing. You stay in Insert mode. Every cursor gets its own process, so uuidgen gives each cursor a different value.
When the selection doesn't end with a line break, one line break at the end of the output is dropped, so | sort on a word keeps it on its line. Ctrl-| has no input, so it always drops one: Ctrl-| date inserts the date without starting a new line.
If any process fails (it can't start, exits with an error, or prints something that isn't UTF-8 text), nothing changes. The error goes to :messages, with what the command printed on its error output. When a command succeeds but prints on its error output, that text goes to :messages without an error.
A run is one undo step. In Insert mode its output belongs to the insert session's undo step, like the text you type. A run that fails or is stopped leaves . repeating whatever it repeated before.
Commands run with sh -c, in HUME's working directory. Set the shell option to use another shell (see Global options). A command that asks the terminal for input, such as fzf or a sudo password prompt, can't get it and waits until you press Ctrl-c.
While a command runs
| runs its commands in the background. You can keep working in other buffers and panes, and move around in this one, but this buffer's text can't change until they finish.
- A buffer runs one
|at a time. - If the commands take more than a moment, the statusline shows the command and how many of its processes have finished, while you are in that buffer:
running `sort` 3/10. Ctrl-cin Normal mode stops them and changes nothing.- When they finish, their output replaces the selections
|ran on, even if you have moved since or the pane now shows another buffer.
What is refused while a command runs
- Editing, undo, paste and entering Insert mode in that buffer, reloading it after it changes on disk, and changes from plugins and language servers are refused with "
nameis busy: a pipe is running", naming the buffer. - Closing the buffer, the pane you ran
|from or its tab, quitting, and:eare refused. The message says how to go on: stop the commands withCtrl-c, or add!to the command, as in:q!, to stop them and go ahead.:wqrefuses after writing the file, andCtrl-p crefuses too. - A failure or a stop is reported with the buffer's name, since you may be somewhere else when it happens.
Ctrl-| waits for its commands instead. So does | while you record a macro, and when . or a macro runs a command again, because the keys after it need the output.
While the editor waits, Ctrl-c stops the commands and changes nothing, and other keys you press take effect once the commands finish. A command run again by . or a macro doesn't show on the statusline, but Ctrl-c still stops it, along with the rest of the . or the macro. A command that fails doesn't stop the rest.
The command prompt
The prompt edits like the : prompt and keeps its own history: Up and Down recall earlier commands. Tab completes the word under the cursor:
- a program on your
PATH, where a command's name goes (at the start of the line, or after|,;,&or() - a file path anywhere else, or when the word contains a path separator
A completed name with spaces or other special characters is escaped or quoted the way the shell set by the shell option expects.
Shells and quoting
Completion reads and writes words the way these shells do: sh, bash, zsh, dash, ksh, ash, mksh, yash, posh, busybox, fish, PowerShell (pwsh, powershell) and cmd.
A word you started in quotes, like cat "my no, completes inside them. A completed name closes its quote, a directory's too, and Tab again after a closed word completes inside it: cat "my dir/" then Tab gives cat "my dir/notes.txt".
Shell keywords such as if and then, NAME=value before a command, and backticks are not read, so the word after them completes as a path.
For any other shell, Tab completes nothing and the message line says so the first time. A plugin can teach HUME a shell's rules with register-shell-dialect!.
Undo and redo
| Key | Effect |
|---|---|
u | Undo (accepts a count: 5u undoes five steps) |
U / Ctrl-r | Redo (accepts a count: 5U redoes five steps) |
Undo history is a tree rather than a straight line. Redo follows the branch you last moved along: the newest edit, or the branch you jumped into with core:undotree. The history lives in memory only and starts fresh each time you open a file.
Repeat
| Key | Effect |
|---|---|
. | Repeat the last editing command |
. repeats the last editing command or insert session: delete, change, paste and so on, but not y.
- Typed keys re-run at the new cursor.
- A choice you made (the character after
r, a picker or menu item, a prompt answer) is reused, not asked again. - After
|orCtrl-|,.runs the same command again, so its output can differ. - An accepted completion writes the same text at the cursor, without its edits elsewhere, such as an added import.
- A pick in a drawer (references, the undo tree) is never repeated.
For custom Insert-mode bindings, see Falling back to a key's normal Insert-mode behaviour.
Macros
A macro records a sequence of keys into a register and replays it. Register q is the default.
| Key | Effect |
|---|---|
Q Q or Q q | Start recording into the default register q |
Q <0-9> | Start recording into a numbered register |
Q (while recording) | Stop recording |
q q | Replay register q |
q <0-9> | Replay a numbered register |
<count> q q | Replay register q <count> times |
See Macros for how macros share registers with yanked text and how recording behaves.
Numeric count
Prefix a command with digits to repeat it. The first digit must be 1–9; 0 counts only after another digit. So 3w moves forward 3 words and 10j moves down 10 lines. Counts are capped at 10,000.
0 on its own does nothing by default; g h goes to the start of the line. The core:vim-keybind plugin binds 0 to it.
Surround
The surround commands, under the m prefix, select or wrap delimiter pairs. See Selections for the full list of m i/m a text objects.
| Key | Effect |
|---|---|
m s + char | Select the surrounding delimiter pair (both ends) |
m w + char | Wrap each selection with a delimiter pair |
To delete or replace a pair, select it with m s and then act: m s ( then d deletes the parentheses, r replaces them.
m s (call(one, two)
Press
dcallone, two
...or press
r [ insteadcall[one, two]
To use Helix's surround keys instead, where m s wraps, m d deletes a pair and m r replaces one, load core:helix-surround.