Come rendere una funzione vimscript con argomenti opzionali?


35

Voglio fare una funzione che abbia argomenti opzionali.

In Python farei qualcosa del genere:

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

Ho provato a farlo function FunctionName(arg1,arg2=false,arg3=false), ma mi dà solo un errore dicendo argomento non valido.

Come lo farei in vimscript?

Risposte:


35

Sì, puoi prendere argomenti opzionali in una funzione. Non è conveniente come il modo di farlo di Python, ma è così che lo fai:

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

Tieni presente che in questo modo potresti avere fino a 20 argomenti.

Argomenti della guida pertinenti:

:help :function
:help function-argument

27

Un po 'tardi alla festa, ma non ho visto il mio preferito:

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 cui get(a:, n, default)verrà nthrestituito l'argomento facoltativo defaultse non è presente.


Oooh è carino!
Joeytwiddle,

3
So che è super vecchio, ma solo FYI a chiunque legga questo. Non puoi fare let a:arg=più in vim. Devi usare qualcosa di simile let l:arg=o giusto let arg=. Vedi github.com/vim/vim/commit/…
jmzagorski il

23

Questo modello ti permetterà di assegnare nomi significativi a ciascun argomento e fornirà un valore predefinito per tutti gli argomenti che non sono stati forniti:

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

Come sottolineato da Boris Brodski:

a:0 conta il numero di argomenti opzionali passati

a:1, a:2, ... cerchiamo di accedere agli argomenti opzionali

Gli argomenti obbligatori (solo foonell'esempio sopra) non vengono conteggiati

condition ? result_if_true : result_if_false è l'espressione condizionale (ternaria), che valuta il secondo o il terzo termine a seconda che il primo termine fosse vero o meno.

Quindi, se non viene fornito un terzo argomento, bazprenderà il valore predefinito di 0.

Una preoccupazione con l'esempio di cui sopra è che a:foopuò solo essere letta con il a:prefisso, mentre bare bazpuò fare a meno di un prefisso. Poiché ciò non è molto coerente, potresti preferire estrarre tutti gli argomenti in variabili locali, in questo modo:

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, puoi usare il l:prefisso per fare riferimento alle variabili locali all'interno di una funzione, ad esempio l:baz, ma questo è ridondante, quindi non lo consiglierei.)


Ma ti consiglio di utilizzare questo modulo ogni volta che è possibile:

function! s:FunctionName(...)

Ciò !consente di ridefinire la funzione in fase di esecuzione (ad esempio ricaricando lo script) e s:limita la funzione all'ambito dello script. Ciò evita di inquinare lo spazio dei nomi globale (e rischiare la collisione) se alla tua funzione viene fatto riferimento solo da un'altra parte dello script. È generalmente il modo preferito per definire le funzioni quando non devono essere visibili a livello globale. ;-)


a:0non include i parametri nominali fissi. a:1è il primo parametro all'interno di ...(Appena testato con VIM 8.0)
Boris Brodski il

Grazie @BorisBrodski hai ragione, buona cattura. Ho corretto la risposta.
joeytwiddle,

8

Non sono esperto di vimscript, ma è così che lo farei:

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

È quindi possibile call Func("Hello", "World")e vedere che stampa "Hello", "World", "Unspecified baz".

Questo sta usando la funzione varargs delle funzioni vim, che consente di passare un numero arbitrario di argomenti extra alla funzione. Gli argomenti sono memorizzati in variabili che, in base a a:0(la lunghezza dell'elenco degli argomenti extra), vengono impostate sull'argomento corrispondente o su un valore predefinito.


2

Dal momento che Vim 8.1.1310 Vim supporta anche argomenti di funzioni opzionali reali.

Tuttavia, ciò significa che la maggior parte dell'installazione di VIM non lo supporta ancora. Anche Neovim non offre questa funzionalità.

Esempio da :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"   

Neat. Dovresti espandere la tua risposta per fare un esempio in modo che possiamo capire rapidamente cosa aggiunge.
Luc Hermitte,

@LucHermitte Ho modificato la mia risposta di conseguenza.
Radlan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.