You're reading docs for unreleased changes —  switch to v0.19.0.
Skip to content

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 ​

KeyWhere insertion begins
iBefore the selection
aAfter the selection
IFirst non-blank character on line
AEnd of line
oNew line below
ONew 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.
  • Backspace between an empty pair deletes both characters.
  • Enter between a pair of brackets opens an indented block (see Indentation).
  • Text you paste is never auto-paired.

Deleting and changing text ​

KeyEffect
dDelete selection (pushed onto the kill ring)
cDelete 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 ​

KeyEffect
r + charReplace 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 ​

KeyEffect
G LLowercase the selection
G UUppercase the selection
G CCapitalize each word in the selection

Numbers and dates ​

KeyEffect
Ctrl-aAdd the count (1 without one) to the number or date at each selection
Ctrl-sSubtract the count from the number or date at each selection
G AAdd the count to the first selection's number or date, twice the count to the second's, and so on
G SSubtract 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: in x-1, 1-1 and f(x)-1 it separates, and only the last 1 changes.
  • A number right after a letter, _ or closing bracket never goes below zero: item1 minus 3 is item0.
  • Characters listed in the buffer's word-chars option 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 (007 becomes 008), and _ separators are kept (999_999 becomes 1_000_000).
  • Digits inside a word count: item1 becomes item2.
  • A . separates two numbers: in 1.2.3, each part changes on its own.

Dates and times:

  • Dates are written 2026-10-18 or 2026/10/18, optionally followed by a space or T and a time such as 14:30 or 14: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-31 plus one day is 2027-01-01. A month or year change keeps the day valid: 2024-01-31 plus one month is 2024-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 ​

KeyEffect
JJoin 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 in indent-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 ​

KeyEffect
G GComment 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 G says 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 ​

KeyEffect
|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-cStop 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-c in 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 "name is busy: a pipe is running", naming the buffer.
  • Closing the buffer, the pane you ran | from or its tab, quitting, and :e are refused. The message says how to go on: stop the commands with Ctrl-c, or add ! to the command, as in :q!, to stop them and go ahead. :wq refuses after writing the file, and Ctrl-p c refuses 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 ​

KeyEffect
uUndo (accepts a count: 5u undoes five steps)
U / Ctrl-rRedo (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 ​

KeyEffect
.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 | or Ctrl-|, . 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.

KeyEffect
Q Q or Q qStart recording into the default register q
Q <0-9>Start recording into a numbered register
Q (while recording)Stop recording
q qReplay register q
q <0-9>Replay a numbered register
<count> q qReplay 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.

KeyEffect
m s + charSelect the surrounding delimiter pair (both ends)
m w + charWrap 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.

Cursor inside, press m s (
call(one, two)

Press d
callone, two

...or press r [ instead
call[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.

Released under the MIT License.