Vim Recipes ‣ Navigation ‣ Bookmarking Lines with Visible Markers (Signs)
You want to assign visible marks to the margins of certain lines.
For example, you're using Vim as an IDE and want breakpoints to be clearly marked. Or, you want to label lines in need of editing with a question mark icon.
Vim allows you to define a sign and then associate it with one or more lines of a file. It is displayed in the right-hand margin as a two-character string in the terminal, and an icon in Gvim.
Before you use a sign you must define it. For example:
:sign define fixme text=!! linehl=Todo texthl=Error icon=/path/to/todo.xpm
Let's break this down. We name the sign fixme, which is how we'll refer to it later. We specify that in the terminal the sign should be displayed as !!, and that in the GUI the icon stored at /path/to/todo.xpm should be used instead. The linehl argument defines the highlight group used for the entire line the sign is attached to; texthl defines the highlight group for the sign itself.
Now the sign is defined, presumably in vimrc, you can use it in any file. To attach the sign to a specific line you use:
:sign place id line=line name=name
file=file-path
For example:
:sign place 22 line=200 name=fixme file=/home/user/novel.txt
The id is arbitrary, but must be unique and numeric. The name is the same name you used when you defined the sign. The value of the line argument is the number of the line on which the sign should be attached. The file argument is the full path (no expansion is done) to a currently loaded file to which the sign should be attached. So, in the above example, two exclamation marks are inserted in the margin of the 200th line of /home/user/novel.txt.
You only need to define signs once, so that's easy enough, but the syntax for placing signs is particularly unwieldy. Let's look at some alternative approaches.
You could place the following stanza in your vimrc so <F5> places the previously defined fixme sign on the current line of the current file:
function! SignFixme()
execute(":sign place ".line(".")." line=".line(".")." name=fixme file=".expand("%:p"))
endfunction
map <F5> :call SignFixme()<CR>
Rather than placing signs manually, you may prefer to have them automatically placed on lines satisfying some criteria. The following stanza attaches the fixme sign to lines containing notes like TODO: check for race conditions. It operates on the current line or selection. So, you can select a range of lines, press <F6> then have your to-do list items flagged in the margin.
function! SignLines() range
let n = a:firstline
execute(":sign define fixme text=!! texthl=Todo")
while n <= a:lastline
if getline(n) =~ '\(TODO\|FIXME\)'
execute(":sign place ".n." line=".n." name=fixme file=".expand("%:p"))
endif
let n = n + 1
endwhile
endfunction
map <F6> :call SignLines()<CR>