Selections
Selections are central to how HUME works. Every editing command acts on the current selection. There is no cursor-without-selection. Even a single-character "cursor position" is a one-character selection.
How selections work
A selection has two ends: the anchor and the head. The head is the moving end; the anchor stays fixed until you reset the selection. The selection always covers at least one character.
Building a selection
Extend mode
Press e to enter Extend mode. In Extend mode, every motion grows the selection instead of moving it, and moving back toward where you started shrinks it again, since only the moving end travels while the anchor stays put. Press e again or Esc to return to Normal. The status bar shows EXT while Extend mode is active.
You can also do a one-shot extend without entering Extend mode: under the kitty keyboard protocol, holding Ctrl with a motion key (Ctrl-h/Ctrl-j/Ctrl-k/Ctrl-l, Ctrl-w/Ctrl-b, Ctrl-f/Ctrl-t, Ctrl-g h, and so on) runs that motion with extend on for that single keypress. Keys that have their own Ctrl binding keep it (Ctrl-d, Ctrl-u, Ctrl-o, Ctrl-e), and Ctrl with a key that is not a motion does nothing. Ctrl-x extends the line selection downward on any terminal; its backward twin Ctrl-Shift-x needs kitty, since older terminals can't tell the two apart.
The same one-shot extend applies to search: Ctrl-n (kitty only) jumps the head to the next search match while the anchor stays put, growing the selection to cover everything from where you started through the new match, without entering Extend mode. Ctrl-Shift-n does the same backward, extending to the previous match.
Extending to a brand-new search
Extend mode also works with a fresh / or ? search, not just Ctrl-n/Ctrl-Shift-n stepping through an existing one. Enter Extend mode with e, then start a search: the anchor stays where you were, and the head jumps to the first match as you type and again on every n/N afterward.
In Extend mode, w/b and x/X additionally shrink in whole units: pressing the opposite key shrinks the selection back down one word or one line at a time, rather than one character at a time. The word or line where you started stays fully selected no matter which way you shrink or grow from there. Crossing back past your starting point flips the selection's direction instead of cutting it off partway.
w, then e to enter Extend modeLorem ipsum dolor sit
Press
wLorem ipsum dolor sit
Press
w againLorem ipsum dolor sit
Press
bLorem ipsum dolor sit
The anchor stays pinned on Lorem's trailing whitespace throughout: w grows the head forward one word at a time, b shrinks it back the same way.
Text objects
Text objects select structured regions in one step. They use the m prefix: m i for inner content, m a for around (including delimiters, or one adjacent whitespace run for words):
| Sequence | Selects |
|---|---|
m i w / m a w | Inner word / word + one adjacent whitespace run (see word-selects-whitespace) |
m i W / m a W | Inner WORD / WORD + one adjacent whitespace run (see word-selects-whitespace) |
m i ( / m a ( | Inside () / including () |
m i [ / m a [ | Inside [] / including [] |
m i { / m a { | Inside {} / including {} |
m i < / m a < | Inside <> / including <> |
m i " / m a " | Inside "…" / including "…" |
m i ' / m a ' | Inside '…' / including '…' |
m i ` / m a ` | Inside `…` / including `…` |
m i a / m a a | Argument (trimmed) / argument + separator comma |
m i l / m a l | Line content (no newline) / full line (with newline) |
m i p / m a p | Paragraph text / the paragraph plus its trailing blank gap |
m i f / m a f | Inside a function / the function including its signature (and attributes, decorators, …) |
m i t / m a t | Inside a class or type / the class or type including its header |
m i c / m a c | Inside a comment / the whole comment block |
m i u / m a u | Inside a unit test function's body / the whole unit test, including its attribute or decorator |
m i v / m a v | Inside an array/tuple/struct value / the value plus its separator comma |
Closing brackets work as well as opening ones: m i ) is the same as m i (, and likewise for ], }, and >.
m i a / m a a and the last five rows above (f, t, c, u, v) are structure-aware: for a language whose grammar ships a textobjects.scm (PLUM installs one alongside highlights where the upstream grammar has one), they select the actual function, class, comment, unit test, or value node, falling back to a lexical scan for m i a / m a a wherever the grammar doesn't cover the cursor (a syntax error, a buffer with no grammar at all). Without a grammar, f/t/c/u/v are a silent no-op. Because the argument object is structure-aware, a nested list, tuple, or struct literal passed as a call argument is itself the argument. Use m i v / m a v for its members.
Each of f/t/a/c/u/v also jumps to the next/previous instance of its kind under the g prefix (lowercase forward, uppercase backward, e.g. g f/g F). See Moving Around.
Two shortcuts select the word under the cursor directly:
| Key | Effect |
|---|---|
m m | Word under the cursor, same as m a w (plus one adjacent whitespace run by default, same rule as w/b; set word-selects-whitespace to off for m i w instead; see Configuration) |
M M | WORD under the cursor, same as m a W |
m i selects just the structure's content; m a includes what surrounds it: one adjacent whitespace run for words, the delimiters themselves for brackets:
m i wLorem ipsum dolor
Press
m a wLorem ipsum dolor
Cursor inside the parens, press
m i (call(one, two)
Press
m a (call(one, two)
m i i selects the text you most recently typed before leaving Insert mode, however you entered it (i, a, o, O, A, I, c). Type something, press Esc, then m i i to act on what you just wrote. It keeps following the inserted text through later edits and stops working only once that text is deleted or the buffer's text is replaced. There is no m a i: an insertion has no delimiters or surrounding structure to select "around".
Select all
| Key | Effect |
|---|---|
% | Select entire buffer |
m / | Turn every search match in the buffer into a selection. See Moving Around |
Flipping and collapsing the selection
| Key | Effect |
|---|---|
; | Collapse selection to head and exit Extend mode |
Ctrl-; | Collapse selection to anchor and exit Extend mode (kitty only) |
Ctrl-e | Swap anchor and head of each selection (any mode; works on legacy terminals too) |
Multiple selections
HUME supports multiple simultaneous selections. Each selection behaves independently: editing commands act on all of them at once.
| Action | Key | Effect |
|---|---|---|
| Sift within selection | s | Enter a regex pattern; each selection is narrowed to its sub-matches |
| Split on newlines | S | Split multi-line selections into one selection per line |
| Copy to next line | C | Duplicate each selection to the same character column on the line below, adding a multi-cursor. No text is copied: the new selections cover the same column range on the next line. Each copy sits one selection-height below the last, so a one-line selection copies to the next line and a selection spanning three lines copies three lines further down. A count prefix (e.g. 3C) adds that many copies in one step, stopping where the buffer ends; repeating C also stacks cursors line by line for column-style editing. HUME has no rectangular/visual-block selection primitive. |
| Trim whitespace | _ | Shrink each selection so it starts and ends on non-whitespace; the text is unchanged |
| Keep primary | , | Remove all selections except the primary |
| Remove primary | Ctrl-, | Remove the primary selection, promote next (kitty only) |
| Cycle primary forward | ) | Make the next selection the primary |
| Cycle primary backward | ( | Make the previous selection the primary |
Sift within (s)
Press s to enter Sift mode. Type a regex pattern and press Enter. Each existing selection is narrowed down to only the sub-ranges matching the pattern, creating one new selection per match. This is useful for splitting a line selection into individual tokens:
- Select a line (
x) - Press
sand type\w+to select each word individually - Press
dto delete all words at once
s requires at least one selection wider than a single character. On a bare single-character cursor it does nothing. Pressing Enter on an invalid pattern, or one with no match, reports it and leaves the selections as they were. See Regex syntax for the pattern flavor and case-sensitivity rules.