MARKS

Learning Vim

Chapter 5 — Marks

The Problem Marks Solve

As files grow longer, navigation becomes a two-part problem. The first part — getting to a known location quickly — is solved by search and line-number jumps (Chapter 3). The second part is subtler: getting back to where you were.

Imagine you are editing a configuration function on line 340. You need to check how a variable is defined on line 12, then verify a related function on line 580, then return to your original work. Without marks you have to remember three line numbers and type :340, :12, :580, :340 repeatedly — and if you navigate elsewhere in between, you lose track entirely.

Marks are named bookmarks you can place at any position in a file (or across files). They remember both the line number and the column, and they survive navigation, edits, and even closing and reopening Vim. Combined with the jump list, they form a complete navigation history system.

Setting and Jumping to Marks

Creating a mark

To set a mark, press m in Normal mode followed by a single letter — the mark's name:

ma    # set mark 'a' at the current cursor position (line + column)
mB    # set mark 'B' (uppercase — works across files)
mz    # set mark 'z'

The mark is set silently — no confirmation appears. You can verify it was set with :marks.

Jumping to a mark

There are two jump commands, and the difference between them is important:

CommandJumps toUse when
'a (single quote)The beginning of the line containing mark aYou want to work with the whole line
`a (backtick)The exact cursor position (line and column) of mark aYou want to return to the precise character
# Set a mark, move away, return to it:
ma          # mark current position as 'a'
G           # jump to end of file
'a          # jump back to the LINE containing mark 'a'
`a          # jump back to the EXACT COLUMN of mark 'a'
Backtick vs single quote in practice: Most of the time 'a (single quote) is what you want — it puts you at the start of the relevant line, which is natural for editing. Use `a (backtick) when column precision matters, such as when returning to a specific character inside a long expression.

Types of Marks

a – z  ·  Local marks

Set with mamz. Each mark is local to the buffer (file) it was set in. If you open a different file, 'a still refers to the position in the original file — it will switch you back to that buffer. You have 26 of these available per file.

A – Z  ·  Global marks

Set with mAmZ. Global marks work across files. Jumping to a global mark with 'A will open the file containing that mark (if it is not already open) and jump to the position. Ideal for bookmarking key files you switch between frequently.

Automatic marks — set by Vim itself

These are always available without any setup. They are among the most useful marks in daily editing.

MarkJump commandWhat it records
.'. or `.Position of the last change made to the file
```Position before the last jump (a single backtick typed twice)
'''Line of the last jump (two single quotes)
['[Start of the last changed or yanked text
]']End of the last changed or yanked text
<'<Start of the last Visual selection
>'>End of the last Visual selection
^'^Position where Insert mode was last exited
The dot mark '. is invaluable. After making an edit anywhere in the file — even after extensive navigation away — `. takes you back to the exact character you last changed. No need to remember line numbers. This is one of the first automatic marks to build into muscle memory.

The special `` mark — jump back

The double backtick `` (or double single quote '' for line-level) is your instant "go back" command. Any time Vim performs a large jump — G, gg, /{search}, :{line}, a mark jump — it records your position before the jump. Pressing `` returns you there.

G        # jump to end of file
``       # jump back to where you were before pressing G
``       # jump forward again (toggles between the two positions)

This toggle behaviour — `` bouncing between two locations — is extremely useful when comparing two distant parts of a file.

Managing Marks

Viewing all marks

:marks          # list all marks and their positions
:marks abc      # list only marks a, b, and c

The output shows the mark letter, the line number, the column, and a snippet of the text at that position:

 mark line  col file/text
  'a    42    8 function processOrder(id) {
  'B   103    0 ~/projects/config.yaml
  '.    28   15 const result = calculateTotal(items)
  ''   100    0 // End of configuration section

Deleting marks

:delmarks a      # delete mark 'a'
:delmarks a-d    # delete marks a, b, c, and d
:delmarks!       # delete all lowercase marks in the current buffer

Using marks with operators

One of the most powerful and underused applications of marks: using them as motion endpoints with operators. Any operator (d, y, c, etc.) can take a mark as its motion target:

# Yank from current position to mark 'a':
y`a      # yank to exact position of mark a
y'a      # yank to start of line containing mark a (linewise)

# Delete from current line to mark 'b':
d'b

# Classic pattern: mark the start of a block, move to the end, operate:
ma           # mark the start of a function
/^}          # search for the closing brace on its own line
d'a          # delete everything from mark 'a' to here

The Jump List

Marks are for positions you explicitly choose to remember. The jump list is different — it is an automatic record of every "large" movement you make, maintained by Vim without any action on your part.

What counts as a jump?

Not every cursor movement is recorded. Vim records a jump when you use:

  • File-level navigation: G, gg, {n}G, :{n}
  • Search: /pattern, ?pattern, n, N, *, #
  • Mark jumps: 'a, `a
  • Paragraph/sentence jumps: {, }, (, )
  • Opening a file: :e, gf

Character movement (HJKL, w, b, e) does not create jump entries.

Navigating the jump list

CommandAction
Ctrl+OGo to the older (previous) position in the jump list — jump backward through history
Ctrl+IGo to the newer (next) position in the jump list — jump forward through history
:jumpsDisplay the complete jump history list
# Example session — the jump list builds up automatically:
:100        # jump to line 100 (recorded)
/function   # search for "function" (recorded)
G           # jump to end of file (recorded)
Ctrl+O      # back to where /function landed
Ctrl+O      # back to line 100
Ctrl+I      # forward to /function result again
Ctrl+O / Ctrl+I work across files. If you jump to a different file with :e or gf (go to file under cursor), Ctrl+O will take you back to the previous file at the position you left. This makes the jump list a cross-file navigation history, complementing global marks.

Viewing the jump list

:jumps
 jump line  col file/text
   4   340    0 function processOrder(id) {
   3   100    0 // Configuration section
   2    12    4 const BASE_URL = "https://...
   1   580   12 function validateResult(x) {
>  0   340    0 function processOrder(id) {

The > shows your current position in the list. Numbers on the left show how many Ctrl+O presses are needed to reach that entry.

Marks in a Multi-File Workflow

Global marks (A–Z) deserve a dedicated example because they fundamentally change how you work with projects containing multiple files.

Workflow — jumping between project files with global marks

1 vim app.py Open your main application file.
2 mA Set global mark A here — "this is my main entry point".
3 :e config.yaml Switch to the config file.
4 mC Set global mark C here — "this is the config file".
5 :e tests/test_app.py Switch to the test file.
6 mT Set global mark T — "this is the test file".
7 'A Jump instantly back to app.py at the marked position — no :e needed.
8 'C / 'T Toggle freely between config and tests. These marks persist across sessions too.

Practical Editing Workflow with Marks

Here is a realistic scenario that ties together marks, the jump list, and the editing commands from earlier chapters.

Editing a Markdown document with a table of contents

Suppose you have a long Markdown file where the table of contents at the top lists section headers, and you want to add content under each header. Marks make this vastly more efficient than scrolling back and forth:

Workflow — table of contents to section content

1 gg / mT Go to the top of the file and set mark T on the table of contents — your reference point.
2 'T + yy Return to the TOC and yank a chapter title line you want to work on next.
3 /^## Chapter 2 Search for the corresponding section heading in the body of the document.
4 ms Set mark s here — "this is the section I'm currently writing".
5 o + (type content) Open a new line below the heading and write the section content.
6 Esc / 'T Finished writing? Jump back to the TOC instantly to pick the next section.
7 `. (backtick-dot) At any point, jump back to the exact character of the last edit — even if you have navigated far away.

Navigating a large file by line number with marks

# Sherlock.txt navigation with marks:
:20       # jump to line 20
ms        # mark it as 's' (start of interesting section)
:100      # jump to line 100
me        # mark it as 'e' (end of section)

# Now operate between the two marks:
's        # jump to mark s
y'e       # yank from here to mark e (linewise — whole lines)
G         # go to end of file
p         # paste the copied section at the end

Commands Introduced in This Chapter

Chapter 5 — Command Reference

Setting marks
m{a-z}Set a local mark (current buffer only)
m{A-Z}Set a global mark (works across files, persists across sessions)
Jumping to marks
'{mark}Jump to the start of the line containing the mark
`{mark}Jump to the exact position (line and column) of the mark
''Jump back to line of last jump (toggle between two lines)
``Jump back to exact position before last large jump (toggle)
Automatic marks
`. (backtick-dot)Jump to exact position of last change
'.Jump to line of last change
`[ and `]Start and end of last changed or yanked text
`< and `>Start and end of last Visual selection
`^Position where Insert mode was last exited
Managing marks
:marksList all current marks
:marks {letters}List specific marks (e.g. :marks abc)
:delmarks {letter}Delete a named mark
:delmarks!Delete all lowercase marks in the current buffer
Marks as operator targets
y`{mark}Yank from cursor to exact position of mark
d'{mark}Delete from cursor to line of mark (linewise)
c`{mark}Change from cursor to exact position of mark
The jump list
Ctrl+OGo to older (previous) position in jump list
Ctrl+IGo to newer (next) position in jump list
:jumpsDisplay the full jump history