Cancelling a running operation

Cancelling a running operation with <C-g>: what it stops (project search, LSP commands you asked for), what it deliberately leaves alone (automatic requests, background work), and why <Esc> and <C-c> are not the cancel key.

On this page

Most of what the editor does finishes before you notice. Some things don't: a search across a large repository, a rename that touches hundreds of files, a language server thinking hard about a symbol.

<C-g> stops whatever you started and puts you back in Normal mode.

With nothing running it is simply a mode reset — it clears a half-typed chord, a pending count, a pending register — so pressing it speculatively is always safe. That is deliberate: a cancel key you have to think twice about before using is not much of an escape hatch.

It never discards unsaved changes (that's :q!) and never clears your registers or yank ring.


What it stops

Operation<C-g>
Project-wide search (project-search-mode)Stops the scan. Results found so far stay in the buffer
Refreshing a search with grStops the replacement scan
Hover (K), go-to-definition (gd / gD / gy / gI), references (gr)Abandons the request
Document + workspace symbols, call hierarchy, type hierarchyAbandons the request
Rename, format, code actions, expand-regionAbandons the request

A cancelled search leaves what it had already found. That is the useful behaviour — you stopped it because you had seen enough, not because you wanted the results thrown away.

What it deliberately leaves alone

<C-g> cancels work you asked for. It does not touch work the editor is doing on its own behalf:

  • Completion and signature help while you type
  • Symbol highlighting under the cursor, inlay hints, semantic highlighting, code lenses, folding ranges
  • Background indexing, file watching, auto-save
  • A language server still starting up

This is not an omission. Those requests fire on every keystroke and cursor move, so treating them as cancellable would make <C-g> unpredictable — and, worse, would mean typing interfered with the search you were waiting on.


Starting something new also stops the old

You rarely need <C-g> for this. Running a second search abandons the first automatically, so you can retype a query without waiting, and gr replacing a search stops the one it replaces. A second hover supersedes the first the same way.

What supersede does not do is cross between unrelated things. Pressing K to glance at a symbol while a search is running leaves the search alone — only <C-g> stops both.


Why not <Esc>

<Esc> does not cancel, and that is on purpose.

Most vim users press <Esc> constantly and without thinking — to confirm they're in Normal mode, between edits, out of habit. If it cancelled, a reflexive double-tap would kill a thirty-second search, and you would have no way to tell "it finished" from "I stopped it."

A key you press without deliberation should not be able to destroy work in progress. So cancelling got its own key, and <Esc> kept doing exactly what it always did.

Why not <C-c>

<C-c> is vim's interrupt, so it would have been the obvious choice. It is reserved here as a prefix: <C-c>g opens magit's dispatch menu, <C-c>f its file dispatch, <C-c><C-c> confirms a commit message, <C-c><C-k> aborts one.

A key bound to a command directly can't also be a prefix — the command fires the moment you press it, and everything underneath becomes unreachable. Binding <C-c> to cancel would have silently deleted all of those chords.

Individual modes still use <C-c> for their own more specific stop: compilation-mode kills the build, an AI conversation interrupts the turn, and the : and / lines cancel that line. Those are scoped to the buffer you're in.

<C-g> in Visual and Select

There, <C-g> keeps its vim meaning — it toggles between Visual and Select while preserving the selection — so those two modes have no cancel chord. Press <Esc> first to drop the selection, then <C-g>.

Worth the trade: you are rarely sitting in Visual with a selection while waiting on a search, and the alternative was taking a vim-standard chord away.


Notes

Mid-chord it takes two presses. With a pending operator (you typed d and stopped), <C-g> aborts the operator — the same thing vim does for any invalid continuation. A second press then cancels. You are never stuck, just one key slower.

With emacs-keys off, <C-g> still works. It is a builtin binding, not part of the emacs-keys tribute, so :set noemacs-keys doesn't take your cancel key away.

See also