Marks

Marks are, in essence, in-page bookmarks that you can use to quickly jump between important parts of your file(s). They have one non-trivial problem. You can’t easily see them while working on your document. Fortunately, there’s a plugin for that.

Before we continue, let’s get a bit more specific about what a mark is. A mark is a named cursor location. There are local, and global marks. Each mark is named with a single letter between a and z in the English alphabet. So, no ñ or ç. You can re-use the same letter in any buffer. Alternately, you can use capital letters A-Z (again English alphabet) BUT capital letter buffers are global, and returning to them may not work as you’d expect.

First I’m going to cover the basic stuff that’s most useful. Then we’ll go to the more advanced commands, which you’ll probably never care about.

Basic Usage

Creating A Mark

Creating a mark is pretty simple. You switch to “normal” mode and type m followed by the letter you wish to name the mark. This will mark the exact position of your cursor in the current buffer.

I suggest going with a letter that might be related to what you’re poking. So, since this line is about “poking” I might mark it with p. To do this I’d hit <ESC> to return to normal mode and then type mp. Note that I am not typing a colon first.

If you prefer verbosity you can actually say :mark p.

NOTE: Because marks are cursor positions you can put multiple marks on the same line.

Returning To A Mark

To return to a mark you just type a backtick followed by the letter you named the mark with. So,

p


would return my cursor to the p mark. Remember, marks are cursor positions not lines. So returning to a mark will jump your cursor to exactly where it was in the line when you set the mark. Unless you use a single quote instead of a backtick. 'p will jump you to the first non-whitespace character of the line instead of the cursor position of your mark.

If you’re already in the buffer it’ll just move your cursor as you’d expect. But, if you are returning to a Global mark (one with an upper-case name) it will replace the contents of your window with the other buffer.

If you use tabs a lot, like I do, it will not switch you to an already open tab with that buffer. Instead, you’ll end up with the current tab’s contents being replaced with those of the buffer you jumped to, and you’ll still have the old tab with the same contents. This makes a lot of sense when you’re using Vim in a terminal, but it’s not so great when you’re using a GUI Vim.

Deleting marks

You don’t need to delete marks, but you may want to delete them. The command for this is pretty straightforward :delmarks <mark(s) to delete> It has a bunch of options but all you really need to know is if you want to delete mark x you type :delmarks x If you want to delete all the marks you type :delmarks!

If you really want to get fancy with deleting ranges or lists of marks you can. Just check :help delmarks for details.

Seeing Marks

Without Plugins

Without plugins you can “see” your marks by running :marks which shows you a quickfix window that lists all your marks. It looks something like this:

Why do some of the lines show the actual text of the line and some not? No clue. Even worse, you can not use mouse scrolling. You can’t navigate it like a list of files and hit enter (or click) to go to the selection.

I find the :marks view useful for remembering global (capital letter) marks in files that I’m not looking at at the moment, but I wouldn’t use it otherwise. It’s just another list of things for your brain to process. You’ll see other non-letter marks in the list, but you can ignore all of them. You don’t need them.

With Plugins

With plugins life is a lot easier. I recommend you use the vim-show-marks plugin by Andreas Politz. There are alternatives, but some of them are fancier and not as reliable.

Here’s an example of what it looks like with some code.

In this example I’ve got a global mark set on my Converter class (C), a local mark set on my initialize function (i), and another local one set on my process function (p). By giving them names that are somewhat relevant I’ll be able to remember them when they’re scrolled off the page. Sometimes you just end up having to use “random” letters and being able to see them really helps you to keep them in mind when you’re working near them, and thus remember them when you’ve navigated away.

It also has an improved version of the :marks command called :PreviewMarks which looks like this

The colors you see are dependent upon your color scheme, but plugins that use the “gutter” are frequently pretty ugly by default. I’ve tweaked the colors of mine by adding the following lines to my color scheme:

" this displays marks as blue on a black background
hi hlShowMarks guifg=#5A6CCD ctermfg=9 guibg=black ctermbg=black
" SignColumn sets colors the "gutter" between the marks
hi SignColumn guibg=black ctermbg=black


vim-show-marks isn’t perfect. It doesn’t auto-update when marks change. So, you may want to re-run its :DoShowMarks after you make a change. I’ve just made <leader>m call the plugin’s DoShowMark function for me by adding this to my vimrc.

nnoremap <leader>m :DoShowMark<cr>


It also can’t show you multiple marks on the same line when you’re using the gutter view (a vim limitation). However, the:PreviewMarks view shown above will list when there are multiple marks on the same line.

Also, it displays a few marks I haven’t been able to explain yet, like assorted letters prefaced by a forward slash.

Once you’re comfortable jumping around with marks you can start doing some more interesting things.

Delete To Mark

You can combine the delete character (d) with mark jumping. To delete everything to the cursor position of mark p you would say

dp


You could delete everything including the line mark p is on with

d'p


Note that both of these work backwards and forwards.

Deleting code / text on lines with marks screws up mark locations. Instead of deleting the marks along with the lines they were on, the marks seem to persist, but shift down. It is as if the recording mechanism is something like “this mark is 4 lines from the top” instead of “this mark is this position in this line of text”. The former is independent of the text in your document, and quickly becomes problematic.

Note that this problematic behavior is not limited to this deletion to mark stuff. It’ll happen even if you just use deletion without any mark indicators.

Yank To Mark

Pretty much the same thing as deletion only without weird side effects. Just use y instead of d. So, y'p Would yank everything up to, and including, the line that the p mark was on. Again, backtick will yank to the cursor position of your mark.

Non-Letter Marks

As you saw in my screenshot of the :marks command there are other marks.

The single quote mark is set by Vim to indicate the last place you jumped from. When you’re jumping back and forth between two pieces of code this can be pretty useful because you can just hit backtick single quote to keep jumping back and forth between the last two jump destinations.

'


. " jump to the position of the last edit


The square brackets are to jump to the beginning or end of the previously yanked text and when you see them in :marks it’s showing you where that is.

[ " jump to start of previously yanked text

< " jump to the start of the last visual selection

You can also jump without changing the jump history, or set the mark for the start / end of the visual selection, without making a visual selection. The numbered marks come from your .viminfo file (a cache of info from past Vim sessions). And there are many more options that you will probably never want or need. The magic incantation you need to learn more about them is :help mark-motions