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

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.

Word selected with w, then e to enter Extend mode
Lorem ipsum dolor sit

Press w
Lorem ipsum dolor sit

Press w again
Lorem ipsum dolor sit

Press b
Lorem 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):

SequenceSelects
m i w / m a wInner word / word + one adjacent whitespace run (see word-selects-whitespace)
m i W / m a WInner 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 aArgument (trimmed) / argument + separator comma
m i l / m a lLine content (no newline) / full line (with newline)
m i p / m a pParagraph text / the paragraph plus its trailing blank gap
m i f / m a fInside a function / the function including its signature (and attributes, decorators, …)
m i t / m a tInside a class or type / the class or type including its header
m i c / m a cInside a comment / the whole comment block
m i u / m a uInside a unit test function's body / the whole unit test, including its attribute or decorator
m i v / m a vInside 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:

KeyEffect
m mWord 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 MWORD 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:

Cursor mid-word, press m i w
Lorem ipsum dolor
Press m a w
Lorem 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 ​

KeyEffect
%Select entire buffer
m /Turn every search match in the buffer into a selection. See Moving Around

Flipping and collapsing the selection ​

KeyEffect
;Collapse selection to head and exit Extend mode
Ctrl-;Collapse selection to anchor and exit Extend mode (kitty only)
Ctrl-eSwap 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.

ActionKeyEffect
Sift within selectionsEnter a regex pattern; each selection is narrowed to its sub-matches
Split on newlinesSSplit multi-line selections into one selection per line
Copy to next lineCDuplicate 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 primaryCtrl-,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:

  1. Select a line (x)
  2. Press s and type \w+ to select each word individually
  3. Press d to 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.

Released under the MIT License.