3

It seems like the command command expects a one line set of arguments. What is a good way to define a command from something longer?

I suppose defining a function with no argument and then calling the function from the command would work, but is that the standard, good, way?

  • 3
    That, or using \ at the start of the continuation line(s). – VanLaser Mar 23 '16 at 13:24
  • 3
    I personally prefer to define a function as fun! s:my_fun(), this will only be visible inside the current file (and is not "exposed" needlessly when running Vim). I don't like the \ line-continuation and | to chain commands as I find them unreadable and awkward to deal with. – Martin Tournoij Mar 23 '16 at 13:38
  • 1
    I'd say the function is the way to go indeed: I'm not sure it is possible to define a multiline command, but if it is I think that would be pretty "ugly" – statox Mar 23 '16 at 13:41
  • 1
    Yes, it's possible to define a multiline command - you have an ("official") example at the end of :h command-completion-custom :) – VanLaser Mar 23 '16 at 13:44
  • 2
    Also, for the OP, your function can have arguments, and you can pass them from the command using (preferably) <f-args> (see :h <f-args>) – VanLaser Mar 23 '16 at 13:47
5

When wondering about the standard, good way of writing something in VimL I usually check two main resources: the Vim documentation, which is extremely comprehensive and well written, and Steve Losh's blogs (Learn Vimscript the Hard Way and Writing Vim Plugins).

One approach to find examples in the Vim documentation is finding the entry on the subject and them check the start of that file; for :help :command:

This subject is introduced in sections |05.3|, |24.7| and |40.1| of the user
manual.

Searching the file for the 40.1 section:

The <f-args> keyword contains the same information as the <args> keyword,
except in a format suitable for use as function call arguments.  For example:
>
    :command -nargs=* DoIt :call AFunction(<f-args>)
    :DoIt a b c

It shows something similar to what you guessed: calling separated functions, but with arguments.

Unfortunately I couldn't find anything about this subject on the blogs mentioned above.

As was mentioned on the question comments, the alternative is to use \ as line continuation, but that usually leads to clumsy and hard-to-read/edit code.

There is a pattern that I have seen many times when people use the function approach and the <bang> which is made available by :command:

command -bang MyCmd call MyFunction(<bang>0, arg2)

This is useful because <bang> expands on ! or nothing, so concatenating it with 0 makes it easier to check with an if.


Edit:

As mentioned by Carpetsmoker, it is better to use script-local s:a_function() instead of a global AFunction(), as it is more localized and doesn't appear in tab completions and such.

  • 4
    Instead of a global AFunction() I like to use s:a_function() − this is more localized and doesn't appear in tab completions and such... – Martin Tournoij Mar 23 '16 at 14:51

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.