vimvim-pluginsurround

Vim binding to wrap word under cursor in double curly braces


When working with Jinja templates and YAML for Ansible configuration, I often copy+paste a variable name (say, nginx_root) and then need to wrap it in double curly braces: {{ nginx_root }}. This gets cumbersome to do manually, so I want to be able to type a Vim key binding to wrap the current word under the cursor in double curly braces.

Using the vim-surround plugin, I can add the desired curly braces to the word under the cursor via ysiw}lysiw{, but that is many more key strokes than I would prefer. I have tried the following Vim key binding, but invoking it in normal mode has no visible effect at all:

" Wrap text under cursor with double curly braces (e.g., for Jinja variables)
nnoremap <C-J> ysiw}lysiw{

Ergo, my questions are:

  1. Using stock Vim functionality, the vim-surround plugin, and/or any other combination of tooling, how can one bind a key that will wrap the current word under the cursor with space-padded double curly braces? e.g., nginx_root{{ nginx_root }}

  2. Is there a way to also achieve this in insert mode, with the cursor just to the right of the word? (nginx_root*, where * is the cursor position)

  3. How would one bind a key (preferably available in both normal and insert modes) to insert {{ * }} at the current cursor position, where * is the position of the cursor after insertion? (This would facilitate entering new Jinja variables, versus operating on copy+pasted variables as noted above.)


Solution

  • Fixing your mapping

    Your mapping does not work because it uses :noremap. It is correct to avoid remapping (via the nore part of the command) as much as possible, but as you're invoking surround.vim's ys mapping in there, there's no (easy) way around it:

    nmap <C-J> ysiw}lysiw{
    

    A surround.vim alternative

    That double surrounding is awkward, and actually not necessary, because the plugin allows to define custom replacements, as per :help surround-customizing.

    The following defines a new replacement on d (for "double"; 100 = char2nr('d')); with it, you can add double curlies to a word via ysiwd:

    let g:surround_100 = "{{ \r }}"
    

    To only define the mapping for certain filetype(s), replace the g: with b:. I would recommend putting this then into ~/.vim/ftplugin/{filetype}_whatever.vim (or {filetype}/whatever.vim; cp. :help ftplugin-name) instead of defining lots of :autocmd FileType {filetype} ...; it's cleaner and scales better; requires that you have :filetype plugin on, though.

    Your other questions

    The surround.vim plugin also offers an insert mode <C-g>s mapping. I would recommend against insert mode mappings for these kinds of edits; it's against Vim's mode-based model, and only few (and awkward key combinations with Ctrl or Alt) keys are available there.

    To insert a template, a simple mapping will do. You can position the cursor in between the added curlies via the special <Left> keys:

    :nnoremap <C-g>d a{{  }}<Left><Left><Left>
    :inoremap <C-g>d {{  }}<Left><Left><Left>