4

E.g., in this snippet

    if words[0] == "\"spellgood:"
      call remove(words, 0)
      for word in words
        execute "silent spellgood! " . word
      endfor
    endif

taken from "The first and last 5 lines of a file? Use for file specific spell ignore list?"

5
  • 10
    call calls a function, execute executes an ex command. Feb 22, 2016 at 18:49
  • Can you please elaborate and make this into an answer? Credit where credit is due.
    – Yossi Gil
    Feb 22, 2016 at 19:13
  • 1
    I try to avoid posting answers these days, because I disagree with SE's new licence policy. As for call vs. execute, you can get more information from the manual: :h call(), :h :exe. Feb 22, 2016 at 19:28
  • @SatoKatsura wasn't the policy change postponed? And doesn't the new policy only affect code? I'd say your answer wouldn't have much code in it in this case?
    – muru
    Feb 23, 2016 at 0:21
  • 1
    @muru The fact that this issue exists to begin with is ample proof that some level of mutual trust between SE and regular posters needs to be re-established. In my book, the way the issue was handled by SE is not conductive to that. I don't know about you, but posting to SE is not exactly the goal of my life. I'd say SE needs reasonably qualified posters, rather than the other way around. shrug Feb 23, 2016 at 9:42

3 Answers 3

9

As described in :help call, call is for invoking a built-in or user-defined function. It's useful to use call if you're invoking a function without the intention of capturing the return value, because of how vim's scripting works. That is, if you have a function foo that returns an integer, you must:

call foo()

to call foo without caring about the result, whereas:

let result = foo()

can be used to call foo and put the result in result. Note how call is not required for the second example. call also can take a range, which has the effect of invoking the function for every line in that range, usually.

:help execute, on the other hands, reveals that execute is for evaluating strings as Ex commands. Normally you don't need to use execute in vim scripts, as most of what you type in them is interpreted as an Ex command. However, execute exists and is particularly useful for invoking commands built up at runtime, as was done in the answer you linked to in order to add a word discovered at runtime to the spelling dictionary.

1
  • 7
    Looking at it from another perspective: vimscript only runs commands. There's no way to directly run a function. You can use the call command if you want to discard the return value, echo if you want up print it, let if you want to save it, but you have to use a command.
    – muru
    Feb 24, 2016 at 8:58
2
  • We use a command just by writing it
  • When we use a string as a command, put execute before the string

These 2 lines get the same output

:echo 'hi_1'

:execute "echo 'hi_1'"

NOTE
: indicates a ex command, instead of an option, motion or other things in vim (try :help :bar vs :help bar )


(Thank @filbranden for reminding me of my mistakes. And since answers above have pointed out differences between :execute vs :call, below I add something I think useful, without repeating my revise of answers above)

:execute

in vim's help

:exe[cute] {expr1} ..

Executes the string that results from the evaluation  of {expr1} as an Ex command.

When I need to give multiple commands in one line, I usually use | (see :help :bar, not :help bar). When that line is complicated, I need to use :excute as a work around of |

Example of using | :

: echo 'hi_1' | echo 'hi_2'

A real example of using | and execute:

autocmd BufReadPost *
     \ if line("'\"") > 0 && line("'\"") <= line("$") |
     \   execute "normal g`\"zv" |
     \ endif

About :normal

:norm[al][!] {commands}                 *:norm* *:normal*
            Execute Normal mode commands {commands}.  This makes
            it possible to execute Normal mode commands typed on
            the command-line.  {commands} are executed like they
            are typed.
            This command cannot be followed by another command,
            since any '|' is considered part of the command.

            An alternative is to use |:execute|, which uses an
            expression as argument.  This allows the use of
            printable characters to represent special characters.

Example of representing special characters:

:exe "normal \<c-r>" (redo)

:normal and bar

:normal command see the '|' as a argument, and can therefore not be followed by another Vim command

:normal gg | echo 'hi' can't get anything printed. It meas: under normal mode, types gg | echo 'hi', where | is a motion

:help | (:help bar)

To screen column [count] in the current line. |exclusive| motion. Ceci n'est pas une pipe.

"Ceci n'est pas une pipe", French for "This is not a pipe" . (One interpretation is that the pipe in the painting is not a pipe, but rather a drawing of a pipe.)

A real example of :execute (with :normal)

func Print_n()
    if &filetype == 'python'
        execute "normal yiwoprint(f'{= }')"
        execute "normal hhhhhp"
    elseif &filetype == 'cpp'
        " execute 'normal yiwocout<<""<<' | execute 'normal hhhpf<lpa<<endl;'
        execute 'normal yiwocout<<""<<'
        execute 'normal hhhpf<lpa<<endl;'
    elseif &filetype == 'zsh'
        execute 'normal yiwoecho ${}'
        execute "normal hp"
    elseif &filetype == 'vim'
        execute 'normal yiwoecho &'
        execute "normal p"
    endif
endfunc

func Print_v()
    if &filetype == 'python'
        # execute "visual y"
        execute "normal oprint(f'{= }')"
        execute "normal k$hp"
    endif
endfunc

nnoremap _p :call Print_n()<CR>
vnoremap _p :call Print_v()<CR>
3
  • You start by explaining that execute is useful to invoke commands built up at runtime... But then all your examples are using commands which are composed of a single string, so they're definitely not being built up at runtime (from variables, or expressions)... This is more of a case of execute being used to work around :bar (see :help :bar) or, maybe in most of these cases, out of an abundance of caution for possible trailing whitespace interfering with the normal command...
    – filbranden
    Jan 4, 2022 at 2:27
  • 1
    Also, while this answer gives some examples of execute (perhaps without enough explanation), it doesn't even try to address call, so it hardly answers "what's the difference between call and execute"...
    – filbranden
    Jan 4, 2022 at 2:29
  • 1
    thank you. What about now?
    – Good Pen
    Jan 30, 2022 at 8:09
-1

Petrie's answer is only partially true.

By partially I mean, take for example, bdelete. Supposedly, as stated by vim's manual, it states that by providing a number N identifying a buffer (as in using the number provided by ls or ls!), you can delete a buffer in vimscript. Well that is only true, if you provide a literal number, like bdelete 6, you will delete buffer 6. However, if you pass a variable to bdelete that contains the buffer number to delete like, bdelete g:buffer_to_delete (where g:buffer_to_delete=6), it will not work! In fact in vimscript you can not write :bdelete g:buffer_to_delete or call bdelete g:buffer_t_delete. However, you can treat the command as a string and execute it like so, exec "bdelete".g:buff_to_delete, that will work!

Thus vimscript call DOES NOT invoke user-defined or internal functions all the time. There are situations where exec must be used because call doesn't function as it is supposed to. This situation has been around for many years and still lingers today with vim 8.0. So be aware and follow the rule:

If you can't make the call try executing instead.

It is not clear when you can use call and when you must use exec for I have found the above situation occurring erratically. So start with call then if it fails, exec will work, as of yet I haven't found an instance when it doesn't, fortunately!

Note to Vimscript World: there are other nuances like the above that should be spelled out clearly in the vim documentation, or at least fixed in the vim code! I and many others I know have spent many many hours in years passed wasting time figuring out these nuances. I thought Emacs was truly terrible in this regard, but Vim too has its own undisclosed idiosyncrasies.

And before you say it....yes I have provided these issues years ago. I am only writing this now, because I feel a lot of sympathy for Yossi for going through this problem, because I had the same problem many years ago.

Yossi: keep an open mind with Vimscript it lacks quite a bit of common-sense, but if you keep your wits about yourself you can get much for your time spent on vim, than you would with say with Emacs! Trust me, I've been using Emacs and (G)Vi(m) for 30 years now. (G)Vi(m) is the way to go...Emacs is fast dying, and rightly so :-( {Hey Stallman, don't you think its time to admit Emacs sux? Why go to all the trouble and create Evil, when Vim is free?}

Keep pushing Yossi! It will pay off! (Yes everybody, I know this reply is a year late, but I can bet you there are many other Yossi's out there)

Let's hope, Vim 9.0, will do a better job than Vim 8.0. (I hope I will be still alive to see 9.0!)

6
  • 3
    :call is an Ex command that can only call (sic) functions (user defined, or builtin). We use it when we don't care about the returned value. :execute is an Ex command that can only execute an Ex command. Vim interpreter already executes Ex commands on its own, however it doesn't permit to pass dynamic parameters to these commands. Hence :execute. There is also the call() function that eases dynamic calling of functions (dynamic name, dynamic number of parameters). In a way, call() simplifies what we used to do to forward calls with execute in Vim6 & in prior versions. Jan 30, 2017 at 16:15
  • 2
    That is not quite true. call works perfectly fine. Jan 30, 2017 at 16:41
  • 1
    IOW, we can't say that :call doesn't do its job. Executing Ex commands is not its job. It's :execute job. I won't say this isn't cumbersome. Fighting with (against?) :exe is really cumbersome. Jan 30, 2017 at 16:41
  • 1
    bdelete isn't a function.
    – Rich
    Jan 30, 2017 at 17:20
  • 3
    If you can't make the call try executing instead. You really sound like you don't totally understand what you're talking about.
    – statox
    Jan 30, 2017 at 17:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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