Como fazer uma função vimscript com argumentos opcionais?


34

Eu quero fazer uma função que tenha argumentos opcionais.

Em python, eu faria algo assim:

def functionName(arg1,arg2=false,arg3=false):
    if arg2:
        #Do stuff with arguments
    else:
        #Do stuff without arguments

Eu tentei fazer function FunctionName(arg1,arg2=false,arg3=false), mas isso apenas me dá um erro dizendo argumento inválido.

Como eu faria isso no vimscript?

Respostas:


35

Sim, você pode aceitar argumentos opcionais em uma função. Não é tão conveniente quanto a maneira de fazê-lo, mas é assim que você faz:

function FooBar(...) " This is like *args in python
    echom a:0 " a:0 contains an integer which is the number of arguments passed to the function
    echom a:1 " a:1 contains the first argument passed, a:2 contains the second and so on
    echo a:000 " a:000 contains a list of all arguments that were passed to the function
endfunction

Observe que você só pode ter até 20 argumentos dessa maneira.

Tópicos de ajuda relevantes:

:help :function
:help function-argument

27

Tarde para a festa um pouco, mas eu não vi o meu favorito:

function! FunctionName(arg1,...)
    let arg2 = get(a:, 1, 0)
    let arg3 = get(a:, 2, 0)

    if arg2
        "Do stuff with arguments"
    else
        "Do stuff without arguments"
    endif
endfunction

no qual get(a:, n, default)o nthargumento opcional retornará defaultse não estiver presente.


Oooh que legal!
Joeytwiddle

3
Eu sei que isso é super antigo, mas apenas para quem está lendo isso. Você não pode let a:arg=mais fazer no vim. Você deve usar algo como let l:arg=ou apenas let arg=. Veja github.com/vim/vim/commit/…
jmzagorski

23

Esse padrão permitirá atribuir nomes significativos a cada argumento e fornecer um valor padrão para todos os argumentos que não foram fornecidos:

function FunctionName(foo, ...)
  let bar = a:0 >= 1 ? a:1 : 0
  let baz = a:0 >= 2 ? a:2 : 0
  ...
  " Code that makes use of a:foo, bar and baz

Como apontado por Boris Brodski:

a:0 conta o número de argumentos opcionais transmitidos

a:1, a:2, ... vamos acessar os argumentos opcionais

Os argumentos obrigatórios (apenas foono exemplo acima) não são contados

condition ? result_if_true : result_if_false é a expressão condicional (ternária), avaliada para o segundo ou terceiro termo, dependendo se o primeiro termo era verdadeiro ou não.

Portanto, se nenhum terceiro argumento for fornecido, bazassumirá o valor padrão de 0.

Uma preocupação com o exemplo acima é que a:foo pode ser acessado com o prefixo, enquanto e pode ser feito sem um prefixo. Como isso não é muito consistente, você pode preferir extrair todos os argumentos para variáveis ​​locais, como:a:barbaz

function FunctionName(...)
  let foo = a:1                  " Will throw an error if no arg was provided
  let bar = a:0 >= 2 ? a:2 : 0
  let baz = a:0 >= 3 ? a:3 : 0
  ...
  " Code that makes use of foo, bar and baz

(Tecnicamente, você pode usar o l:prefixo para se referir a variáveis ​​locais dentro de uma função, por exemplo l:baz, mas isso é redundante, portanto eu não o recomendaria.)


Mas eu recomendo que você use este formulário sempre que possível:

function! s:FunctionName(...)

O !permite redefinir sua função no tempo de execução (por exemplo, recarregando o script) e s:limita a função ao escopo do script. Isso evita poluir o espaço para nome global (e arriscar colisão) se sua função for referenciada apenas de outro lugar dentro do script. Geralmente, é a maneira preferida de definir funções quando elas não precisam ser visíveis globalmente. ;-)


a:0não inclui os parâmetros nomeados fixos. a:1é o primeiro parâmetro dentro do ...(Just testado com VIM 8.0)
Boris Brodski

Obrigado @BorisBrodski, você está certo, boa captura. Eu corrigi a resposta.
Joeytwiddle

8

Não sou versado em vimscript, mas é assim que eu faria:

function Func(foo, ...)
  if a:0 < 1
    let bar = "Unspecified bar"
  else
    let bar = a:1
  endif
  if a:0 < 2
    let baz = "Unspecified baz"
  else
    let baz = a:2
  endif

  echo a:foo
  echo bar
  echo baz
endfunction

Você pode call Func("Hello", "World")ver que ele exibe "Olá", "Mundo", "Baz não especificado".

Isso está usando o recurso varargs das funções do vim, que permite passar um número arbitrário de argumentos extras para a função. Os argumentos são armazenados em variáveis ​​que, dependendo do a:0(comprimento da lista de argumentos extras), são definidas para o argumento correspondente ou para um valor padrão.


2

Desde o Vim 8.1.1310, o Vim também suporta argumentos reais de funções opcionais.

No entanto, isso significa que a maioria das instalações do vim ainda não suporta isso. O neovim também não oferece esse recurso também.

Exemplo de :help optional-function-argument:

  function Something(key, value = 10)
     echo a:key .. ": " .. a:value
  endfunction
  call Something('empty')   "empty: 10"
  call Something('key', 20) "key: 20"   

Arrumado. Você deve expandir sua resposta para dar um exemplo, para que possamos entender rapidamente o que ela adiciona.
Luc Hermitte 21/11

@LucHermitte Modifiquei minha resposta de acordo.
radlan 22/11
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.