Prepend text to a different file from within Vim

66 Views Asked by At

I am trying to prepend text from within Vim to another file. Specifically the current line, but a visual selection would be nice as well. Eventually I would like to map it to something like <leader>i.

In bash I can use the following sed command to achieve this:

sed -i '1i some new text' myfile.md

So I tried this from within vim:

:execute "!sed -i '1i" .getline('.') "' myfile.md"

This works but when there is an ! in the currentline: shell returned 2.

Then I found out about shellescape, and I got the following command to work. Now it seems like I'm doing something wrong escaping characters as this will add single quotes around the string.

:execute "!sed -i \"1i " . shellescape(getline('.'), 1) . "\" myfile.m

What am I missing? Is there a better way?

2

There are 2 best solutions below

4
phd On BEST ANSWER
function! PrependLine()
    " Save the current file to avoid problems with switching buffers
    update
    " Copy the current line to the default register
    yank
    " Open a new buffer or switch to exiting one
    edit myfile.md
    " Paste content of the default register before the 1st line
    1put!
    " Save the file
    update
    " Return to the previous file
    edit #
endfunction

map <leader>i :call PrependLine()<CR>

The only problem is — the filename is fixed. Vim macros don't have parameters. Functions do have.

0
Friedrich On

To suggest an alternative that makes use of Vim's buffer functions, you could tweak the example given in :help bufadd() just a little bit. I took the liberty of borrowing the function name from phd's excellent answer.

I'd prefer to have the destination file name as an argument to the function but that's largely up to personal taste.

function PrependLine(filename) abort
    let dstbuf = bufadd(a:filename)
    call bufload(dstbuf)
    call appendbufline(dstbuf, 0, getline('.'))
endfunction

nnoremap <leader>i <Cmd>call PrependLine('myfile.md')<CR>

Note that this will not write a file to disc right now but keep it open as an unlisted buffer. It will be written only when you explicitly do so, e.g. through :wall. This function also avoids the side effect of writing the current buffer.