Wie erstelle ich ein Vimscript mit optionalen Argumenten?

33

Ich möchte eine Funktion erstellen, die optionale Argumente enthält.

In Python würde ich so etwas machen:

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

Ich habe versucht function FunctionName(arg1,arg2=false,arg3=false), es zu tun , aber es gibt mir nur einen Fehler, der ein ungültiges Argument sagt.

Wie würde ich das in Vimscript machen?

iProgram
quelle

Antworten:

34

Ja, Sie können optionale Argumente in eine Funktion aufnehmen. Es ist nicht so bequem wie Pythons Methode, aber so machen Sie es:

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

Beachten Sie, dass Sie auf diese Weise möglicherweise nur bis zu 20 Argumente haben.

Relevante Hilfethemen:

:help :function
:help function-argument
Immergrüner Baum
quelle
26

Ein bisschen zu spät zur Party, aber ich habe meinen Favoriten nicht gesehen:

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

In diesem get(a:, n, default)Fall wird das nthoptionale Argument zurückgegeben, defaultwenn es nicht vorhanden ist.

phicr
quelle
Oh, das ist schön!
Joeytwiddle
3
Ich weiß, das ist super alt, aber nur zu Ihrer Information für jeden, der dies liest. Sie können nicht let a:arg=mehr in vim tun . Sie müssen etwas wie let l:arg=oder nur verwenden let arg=. Siehe github.com/vim/vim/commit/…
jmzagorski
23

Mit diesem Muster können Sie jedem Argument einen aussagekräftigen Namen zuweisen und einen Standardwert für alle Argumente angeben, die nicht angegeben wurden:

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

Boris Brodski wies darauf hin:

a:0 zählt die Anzahl der übergebenen optionalen Argumente

a:1, a:2, ... lassen Sie uns die optionalen Argumente zugreifen

Die obligatorischen Argumente (nur fooim obigen Beispiel) werden nicht gezählt

condition ? result_if_true : result_if_false ist der bedingte (ternäre) Ausdruck, der in Abhängigkeit davon, ob der erste Ausdruck wahr ist oder nicht, als zweiter oder dritter Ausdruck ausgewertet wird.

Wenn also kein drittes Argument angegeben wird, bazwird der Standardwert von verwendet 0.

Ein Problem bei dem obigen Beispiel ist , dass a:fookann nur mit dem zugegriffen wird a:Präfix, während barund bazkann ohne Präfix tun. Da dies nicht sehr konsistent ist, können Sie es vorziehen, alle Argumente in lokale Variablen zu ziehen, wie folgt:

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

(Technisch gesehen können Sie das l:Präfix beispielsweise verwenden, um auf lokale Variablen in einer Funktion zu verweisen. l:bazDies ist jedoch redundant, sodass ich es nicht empfehlen würde.)


Ich empfehle Ihnen jedoch, wann immer möglich dieses Formular zu verwenden:

function! s:FunctionName(...)

Dadurch !können Sie Ihre Funktion zur Laufzeit neu definieren (z. B. durch erneutes Laden des Skripts) und s:die Funktion auf den Skriptbereich beschränken. Dadurch wird vermieden, dass der globale Namespace verschmutzt wird (und eine Kollision riskiert wird), wenn Ihre Funktion nur von einer anderen Stelle im Skript referenziert wird. Es ist im Allgemeinen die bevorzugte Methode, Funktionen zu definieren, wenn sie nicht global sichtbar sein müssen. ;-)

joeytwiddle
quelle
a:0enthält nicht die festgelegten benannten Parameter. a:1ist der erste Parameter in der ...(gerade mit VIM 8.0 getestet)
Boris Brodski
Danke @BorisBrodski, du hast recht, guter Fang. Ich habe die Antwort korrigiert.
Joeytwiddle
8

Ich kenne mich mit Vimscript nicht gut aus, aber so würde ich es machen:

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

Sie können dann call Func("Hello", "World")sehen, dass "Hello", "World", "Unspecified baz" gedruckt wird.

Hierbei wird die varargs-Funktion von vim-Funktionen verwendet, mit der Sie der Funktion eine beliebige Anzahl zusätzlicher Argumente übergeben können. Die Argumente werden in Variablen gespeichert, die abhängig von a:0(der Länge der zusätzlichen Argumentliste) entweder auf das entsprechende Argument oder auf einen Standardwert gesetzt werden.

Score_Under
quelle
2

Seit Vim 8.1.1310 unterstützt Vim auch echte optionale Funktionsargumente.

Dies bedeutet jedoch, dass die meisten vim-Installationen dies noch nicht unterstützen. Auch neovim bietet diese Funktion nicht an.

Beispiel von :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
quelle
Ordentlich. Sie sollten Ihre Antwort um ein Beispiel erweitern, damit wir schnell verstehen, was es hinzufügt.
Luc Hermitte
@LucHermitte Ich habe meine Antwort entsprechend geändert.
Radlan