Làm thế nào để tạo một hàm vimscript với các đối số tùy chọn?


34

Tôi muốn tạo một hàm có các đối số tùy chọn.

Trong python tôi sẽ làm một cái gì đó như thế này:

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

Tôi đã thử làm function FunctionName(arg1,arg2=false,arg3=false), nhưng nó chỉ cho tôi một lỗi khi nói đối số không hợp lệ.

Làm thế nào tôi có thể làm điều này trong vimscript?

Câu trả lời:


35

Có, bạn có thể lấy các đối số tùy chọn trong một hàm. Nó không thuận tiện như cách làm của trăn, nhưng đây là cách bạn làm:

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

Lưu ý rằng bạn chỉ có thể có tối đa 20 đối số theo cách này.

Các chủ đề trợ giúp liên quan:

:help :function
:help function-argument

27

Đến bữa tiệc muộn một chút nhưng tôi không thấy người mình yêu thích:

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

trong đó get(a:, n, default)sẽ nhận được nthđối số tùy chọn trả về defaultnếu nó không xuất hiện.


Ôi thật tuyệt!
joeytwiddle

3
Tôi biết điều này là siêu cũ, nhưng chỉ là FYI cho bất cứ ai đọc nó. Bạn không thể làm let a:arg=nữa trong vim. Bạn phải sử dụng một cái gì đó như let l:arg=hoặc chỉ let arg=. Xem github.com/vim/vim/commit/
Mạnh

23

Mẫu này sẽ cho phép bạn gán tên có ý nghĩa cho từng đối số và cung cấp giá trị mặc định cho mọi đối số không được cung cấp:

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

Như được chỉ ra bởi Boris Brodski:

a:0 đếm số lượng đối số tùy chọn được thông qua

a:1,, a:2... chúng ta hãy truy cập các đối số tùy chọn

Các đối số bắt buộc (chỉ footrong ví dụ trên) không được tính

condition ? result_if_true : result_if_false là biểu thức có điều kiện (ternary), đánh giá thuật ngữ thứ hai hoặc thứ ba tùy thuộc vào thuật ngữ đầu tiên có đúng hay không.

Vì vậy, nếu không có đối số thứ ba được cung cấp, bazsẽ lấy giá trị mặc định là 0.

Một mối quan tâm với ví dụ trên là a:foocó thể chỉ được truy cập với các a:tiền tố, trong khi barbazcó thể làm mà không có một tiền tố. Vì điều này không nhất quán lắm, bạn có thể muốn rút tất cả các đối số thành các biến cục bộ, như vậy:

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

(Về mặt kỹ thuật, bạn có thể sử dụng l:tiền tố để chỉ các biến cục bộ bên trong một hàm, chẳng hạn l:baz, nhưng điều này là dư thừa nên tôi không khuyến nghị điều đó.)


Nhưng tôi khuyên bạn nên sử dụng mẫu này bất cứ khi nào có thể:

function! s:FunctionName(...)

Việc này !cho phép bạn xác định lại chức năng của mình khi chạy (ví dụ: bằng cách tải lại tập lệnh) và s:giới hạn chức năng trong phạm vi tập lệnh. Điều đó tránh gây ô nhiễm không gian tên toàn cầu (và có nguy cơ va chạm) nếu chức năng của bạn chỉ được tham chiếu từ nơi khác trong tập lệnh. Nói chung, đó là cách ưa thích để xác định các chức năng khi chúng không cần hiển thị trên toàn cầu. ;-)


a:0không bao gồm các tham số được đặt tên cố định. a:1là tham số đầu tiên trong ...(Chỉ được thử nghiệm với VIM 8.0)
Boris Brodski

Cảm ơn @BorisBrodski bạn đã đúng, nắm bắt tốt. Tôi đã sửa câu trả lời.
joeytwiddle

8

Tôi không rành về vimscript, nhưng đây là cách tôi sẽ làm:

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

Sau đó call Func("Hello", "World"), bạn có thể thấy rằng nó in "Xin chào", "Thế giới", "Không xác định baz".

Điều này đang sử dụng tính năng varargs của các hàm vim, cho phép bạn truyền một số lượng đối số bổ sung tùy ý cho hàm. Các đối số được lưu trữ trong các biến, tùy thuộc vào a:0(độ dài của danh sách đối số phụ), được đặt thành đối số tương ứng hoặc giá trị mặc định.


2

Vim 8.1.1310 Vim cũng hỗ trợ các đối số chức năng tùy chọn thực sự.

Tuy nhiên, điều đó có nghĩa là hầu hết cài đặt vim chưa hỗ trợ này. Ngoài ra neovim cũng không cung cấp tính năng đó.

Ví dụ từ :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"   

Khéo léo. Bạn nên mở rộng câu trả lời của mình để đưa ra một ví dụ để chúng tôi có thể nắm bắt nhanh những gì nó bổ sung.
Luc Hermitte

@LucHermitte Tôi đã sửa đổi câu trả lời của mình cho phù hợp.
radlan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.