Using a register in a .vimrc mapping

1.4k views Asked by At

I'm doing a job involving multiple modifications of HTML template files in which values to be replaced are designated in the template with tokens such as "%%ARTICLE_DATE". I'd like to use the "+" or "*" (clipboard, X-clipboard) vim registers in a mapping in my .vimrc to set up a search using the value in the clipboard. For instance:

cmap <esc>q %s/%%ARTICLE_DATE/<something>/c

So if I had "June 12, 2016" in my X-clipboard from another app, I could key Esc-q and have

:%s/%%ARTICLE_DATE/June 12, 2016/c

in my vim command line, and I could press Enter and selectively replace the matched tokens. Is there a functional representation of clipboard contents which I could use for <something> which would do this?

2

There are 2 answers

8
DJMcMayhem On BEST ANSWER

There are two different ways you could do this.

  1. The easy way:

    cmap <esc>q %s/%%ARTICLE_DATE/<C-r>*/c
    

    This doesn't use any fancy tricks. It just uses the <C-r> key to insert the contents of a register.

  2. The robust way:

    cmap <expr> <esc>q "%s/\V%%ARTICLE_DATE/".escape(getreg("*"), "\\/")."/c"
    

    This uses an "expr" mapping, which means it will evaluate the vimscript to a string and run that string as a mapping. This has some extra things in place to make sure that if you have a slash (forward or backward) in your register, it won't screw up the search.

2
Peter Rincker On

@DJMcMayhem answered your direct question. However, this does not feel Vim-like and using cmap's are tricky as they expand in unexpected places (e.g. /<esc>q).

Make a command

Making a command which does this is pretty easy.

command! -range=% -nargs=+ TemplateReplace keeppaterns <line1>,<line2>s/<args>/\=@*/gc

Now you can do :TemplateReplace %%ARTICLE_DATE and it will replace with the "* register.

Making use of :s and mappings

Use a mapping which creates a substitution command from the current search pattern.

nnoremap gS :<c-u>%s//\=@*/gc<cr>

Set your search pattern (e.g. /%%ARTICLE_DATE then use gS.

Or take a register as an argument:

nnoremap gS :<c-u>%s//\=getreg(v:register)/gc<cr>

Use "*gS to replace the current search pattern with contents of a register, this case it would be "* register.

Visual Star mapping

Use a visual star mapping like the following to simplify setting the search pattern.

xnoremap * :<c-u>let @/=@"<cr>gvy:let [@/,@"]=[@",@/]<cr>/\V<c-r>=substitute(escape(@/,'/\'),'\n','\\n','g')<cr><cr>``

Now you can visually select your text then use * to set the search pattern.

Use the gn motion

Set your search pattern (e.g. /%%ARTICLE_DATE) then do cgn<c-r>*<esc>. Now you can use n and . to make your replacements.

Vimcasts episode: Operating on search matches using gn.

This approach would also benefit from a visual star mapping as well.

Substitution preview with traces.vim

Traces.vim will allow you to preview your substitution while you writing it. Sort of like 'incsearch', but for :s. This doesn't directly help you with your current problem, but might help give you feedback and catch errors in the future.