← back to latest

Jump back to where you were editing after wandering off to read

NORMALg;Jump back to where you were editing after wandering off to read

anatomy

g
Prefix for a large family of extra commands. On its own it does nothing; it waits for the next key.
;
Go to the previous position in the change list, the per-buffer record of where you made changes. Each press steps one change further into the past. A count, as in 3g;, steps that many at once.

In the buffer

You changed the retry count on line 3, then lowercased Usage on line 7, then scrolled down to read the rest of the function. Before:

# Configuration
DEBUG = True
MAX_RETRIES = 5

def main():
    if len(sys.argv) < 2:
        print("usage: script.py <directory>")
        sys.exit(1)
        ^

After typing g;:

# Configuration
DEBUG = True
MAX_RETRIES = 5

def main():
    if len(sys.argv) < 2:
        print("usage: script.py <directory>")
               ^
        sys.exit(1)

After typing g; a second time:

# Configuration
DEBUG = True
MAX_RETRIES = 5
              ^

def main():
    if len(sys.argv) < 2:
        print("usage: script.py <directory>")
        sys.exit(1)

The first press lands on the most recent change, the second on the one before it. The buffer does not change; only the cursor moves.

When you would reach for it

You were halfway through an edit when you needed to check something: a function signature two hundred lines down, a constant at the top, the other half of an if. Now you have read what you needed and you want to get back to work, but you did not set a mark and <C-o> keeps stopping at every search you ran along the way. g; ignores searches and jumps entirely. It only remembers where the text actually changed, so it takes you back to the place you were typing.

Gotchas

  • Small changes on the same line collapse into one entry. If two changes sit on one line less than 'textwidth' columns apart (79 when 'textwidth' is zero), only the newer one is kept. Typing xxxxx leaves a single entry, not five, which is usually what you want.
  • g; is not a motion, so it does not combine with an operator. dg; does not delete back to the last change. Use a mark for that: d`. deletes from the cursor to the last change.
  • At the oldest entry, g; fails with E662: At start of changelist and the cursor stays put. g, walks forward again and gives E663 at the newest end.
  • The change list belongs to the buffer, not the window. Switching to another file and back keeps it, but g; never jumps between files. For that, use <C-o> and the jump list.

Variants

g,

Moves the other way, to the next newer change. Use it when g; overshoots.

`.

Jumps to the exact position of the last change and nothing older. Because it is a mark, it also works as a motion target: y`. yanks from the cursor to the last change.

gi

Jumps to where insert mode last ended and starts insert mode there. One step faster than g; followed by i when the change you want to continue was typed text.

lineage

The change list and the g; and g, commands arrived in Vim 7.0 in 2006. Vi had the jump list's ancestor, the '' mark, but nothing that tracked edits separately from jumps. Vim stores the change list in the viminfo file, so it survives closing and reopening a file, and Neovim does the same through its shada file.

-- INSERT --vim-hacks.com023-023-jump-back-to-where-you-were-editing.html
utf-81,1All