My goal is to make a mapping, that depending on the value of type in the yaml header, will run a command sourcing a file named the same as the value of type.

I have file containing a yaml header like

opt1: test
opt2: something else
type: mytemplate

and I've made a mapping

nnoremap <leader>mp :w!<cr>:exe "!command --template=/home/.../{}.ext -o " . fnameescape(expand('%:p:r')) . ".ext " . fnameescape(expand('%:p'))<cr>

and the characters {} should be replaced with the value of type I have succeeded in making a bashcript, that will get the value like this

TYPE=$(egrep 'type:' filename.ext | awk -F 'type: ' '{print $2}')
command --template=/home/.../$TYPE.ext $@

But I'd like to do it purely in vim. I've tried using vim-grep, and got

:vimgrep 'type: ' % | %s=^\(type:\s\)\zs.*=

but this is a substitution, and can't be used in the mapping. Any help would be gratefully appreciated :-)


What about using a function to do so?

function! SourceByType()
    " save position
    let savePosition = getpos('.')

    " Get the line containing the type
    normal! gg
    let line = search('^type: .*\n---', 'W') 

    " no type found: abort
    if (line == 0)
        echo "no type found"
        return 1

    " Get the type
    let type = matchlist(getline(line), 'type: \(.*\)')[1]

    " Execute the commands
    execute ':w!'
    execute '!command --template=/home/.../'. type . '.ext -o ' . fnameescape(expand('%:p:r')) . '.ext ' . fnameescape(expand('%:p'))

    " restore position
    call setpos('.', savePosition)

And a mapping calling the function:

nnoremap <leader>mp :call SourceByType()<CR>

What the function does:

  • Saves the position of the cursor
  • Goes to the top of the file
  • Searches for a line containing type: something followed by a line containing ---
  • If no line was found, stop the execution
  • Matches the something in type: something
  • Executes your commands replacing {} by the type found.
  • This works great, but what does the line let line = search('^type: .*\n---', 'W') do? – martinmch Nov 4 '16 at 9:21
  • See :h search(): I get the number of the line matching the pattern ^type: .*\n--- which means a line containing type: followed by any number of characters .* followed by a new line \n containing ---. This allows me to then get the content of the line and match the type with let type = matchlist(getline(line), 'type: \(.*\)')[1] (I had to edit this line because of a typo. – statox Nov 4 '16 at 9:25
  • Could \n--- be substituted for $, so type: doesn't have to be the final yaml option? – martinmch Nov 4 '16 at 9:30
  • @martinmch Absolutely it should work properly. – statox Nov 4 '16 at 9:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.