Comment créer une fonction vimscript avec des arguments optionnels?

35

Je veux faire une fonction qui a des arguments optionnels.

En python, je ferais quelque chose comme ça:

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

J'ai essayé de le faire function FunctionName(arg1,arg2=false,arg3=false), mais cela me donne une erreur en disant un argument invalide.

Comment ferais-je cela dans vimscript?

iProgramme
la source

Réponses:

35

Oui, vous pouvez prendre des arguments optionnels dans une fonction. Ce n'est pas aussi pratique que la façon de faire de python, mais voici comment vous le faites:

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

Notez que vous ne pouvez avoir que 20 arguments de cette manière.

Sujets d'aide pertinents:

:help :function
:help function-argument
Arbre à feuilles persistantes
la source
27

En retard à la fête un peu mais je n'ai pas vu mon préféré:

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

dans lequel get(a:, n, default)obtiendra l' nthargument optionnel retournant defaults'il n'est pas présent.

phicr
la source
Oooh c'est gentil!
joeytwiddle
3
Je sais que c'est très vieux, mais juste pour information à quiconque lit ceci. Vous ne pouvez let a:arg=plus faire dans vim. Vous devez utiliser quelque chose comme let l:arg=ou tout simplement let arg=. Voir github.com/vim/vim/commit/…
jmzagorski le
23

Ce modèle vous permettra d'attribuer des noms significatifs à chaque argument et de fournir une valeur par défaut pour tous les arguments non fournis:

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

Comme l'a souligné Boris Brodski:

a:0 compte le nombre d'arguments optionnels passés

a:1, a:2... laissez-nous accéder aux arguments optionnels

Les arguments obligatoires (juste foodans l'exemple ci-dessus) ne sont pas comptés

condition ? result_if_true : result_if_false est l'expression conditionnelle (ternaire), qui correspond au deuxième ou au troisième terme selon que le premier terme était vrai ou non.

Donc, si aucun troisième argument n'est fourni, bazprendra la valeur par défaut de 0.

Un problème avec l'exemple ci - dessus est que a:foopeut uniquement accessible avec le a:préfixe, tout baret bazpeut faire sans préfixe. Comme cela n’est pas très cohérent, vous préférerez peut-être extraire tous les arguments en variables locales, comme ceci:

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

(Techniquement, vous pouvez utiliser le l:préfixe pour faire référence à des variables locales dans une fonction, par exemple l:baz, mais ceci est redondant, je ne le recommanderais donc pas.)


Mais je vous recommande d'utiliser ce formulaire chaque fois que possible:

function! s:FunctionName(...)

Le !vous permet de redéfinir votre fonction lors de l' exécution (par exemple en rechargeant le script), et la s:limite de la fonction portée du script. Cela évite de polluer l'espace de nom global (et le risque de collision) si votre fonction est uniquement référencée ailleurs dans le script. C'est généralement le moyen préféré pour définir des fonctions lorsqu'elles n'ont pas besoin d'être globalement visibles. ;-)

Joeytwiddle
la source
a:0n'inclut pas les paramètres nommés fixes. a:1est le premier paramètre de la ...(vient de l’être avec VIM 8.0)
Boris Brodski
Merci @BorisBrodski vous avez raison, bonne prise. J'ai corrigé la réponse.
joeytwiddle
8

Je ne connais pas bien vimscript, mais voici comment je le ferais:

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

Vous pouvez alors call Func("Hello", "World")voir que les messages "Hello", "World", "Unspecified baz" sont affichés.

Ceci utilise la fonctionnalité varargs des fonctions vim, qui vous permet de transmettre un nombre arbitraire d'arguments supplémentaires à la fonction. Les arguments sont stockés dans des variables qui, en fonction de a:0(la longueur de la liste des arguments supplémentaires), sont définies sur leur argument correspondant ou sur une valeur par défaut.

Score_Under
la source
2

Depuis Vim 8.1.1310, Vim prend également en charge les arguments de fonctions optionnelles réelles.

Cependant, cela signifie que la plupart des installations de vim ne le supportent pas encore. De plus, neovim n'offre pas cette fonctionnalité.

Exemple 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"   
radlan
la source
Soigné. Vous devriez développer votre réponse pour donner un exemple afin que nous puissions comprendre rapidement ce qu’elle ajoute.
Luc Hermitte
@ LucHermitte, j'ai modifié ma réponse en conséquence.
Radlan