0

I am trying to do a shortcut to resave a file with cmd-S. And if the file is of type vim, it will also re-source %. Here is what I have:

function SaveFile() w if &filetype ==? 'vim' so % endif endfunction nnoremap <leader>S :silent call SaveFile()<CR> 

However, I get the following error:

E127: Cannot redefine function SaveFile: It is in use

Why is this so? What do I need to do to fix this issue? Is :so % not allowed in a function?

1
  • Check what error means with :h E127 Commented Jul 15, 2020 at 21:43

2 Answers 2

1

Your issue is that functions cannot be redefined without ! (as in function!). This is only partially true:

 *E127* *E122* When a function by this name already exists and [!] is not used an error message is given. There is one exception: When sourcing a script again, a function that was previously defined in that script will be silently replaced. When [!] is used, an existing function is silently replaced. Unless it is currently being executed, that is an error. NOTE: Use ! wisely. If used without care it can cause an existing function to be replaced unexpectedly, which is hard to debug. 

I actually do not use ! anymore, but I believe in old versions of vim it was required to be able to re-source a script at runtime and have function/command definitions work. You might want to check on your version.


A more idiomatic way to accomplish your setup is to split the two (this is effectively what I do):

" ~/.vim/vimrc, or some other globally-sourced file nnoremap <leader>fs :write<CR> 

and

" ~/.vim/after/ftplugin/vim.vim " two options: a dedicated map nnoremap <buffer> <localleader>ef :source %<CR> " or an autocommand augroup SourceVim autocmd! * <buffer> autocmd BufWritePost <buffer> source % augroup END 

(I do something similar in clojure with fireplace's :Require)

2
  • Why not :update instead of :write? Commented Jul 16, 2020 at 5:46
  • OP used write @Matt , but also sometimes you want the effect of a write (such as something that watches your code and runs tests or some such) Commented Jul 16, 2020 at 11:13
0

There's always the way out of just ignoring that exception, if you understand what you're doing. Wrap the following around the function definition

try function! s:Something() ... endfunction catch /Cannot redefine function.*It is in use/ endtry 

The caveat is, of course, that the function will not be redefined if the reload is performed by that function. Manually executing :e% (in case of function in ftplugin script) or :so% would work however.

Alternatives include:

  • write the parts that need reload in the mapping itself with multiple commands separated with | if needed
  • use something such as feedkeys() to make the reload outside the function body
  • put the function in a autoload script, then it won't be redefined each time

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.