วิธีการสร้างฟังก์ชั่น vimscript ด้วยอาร์กิวเมนต์ที่เป็นตัวเลือก?


33

ฉันต้องการสร้างฟังก์ชันที่มีอาร์กิวเมนต์เป็นตัวเลือก

ในหลามฉันจะทำสิ่งนี้:

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

ฉันได้ลองทำfunction FunctionName(arg1,arg2=false,arg3=false)แล้ว แต่มันก็ทำให้ฉันมีข้อผิดพลาดในการบอกว่าอาร์กิวเมนต์ไม่ถูกต้อง

ฉันจะทำสิ่งนี้ใน vimscript ได้อย่างไร

คำตอบ:


34

ใช่คุณสามารถรับอาร์กิวเมนต์ตัวเลือกในฟังก์ชั่น มันไม่สะดวกเท่ากับวิธีของงูเหลือมในการทำ แต่นี่คือวิธีที่คุณทำ:

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

โปรดทราบว่าคุณอาจมีอาร์กิวเมนต์ได้สูงสุด 20 ข้อในวิธีนี้

หัวข้อความช่วยเหลือที่เกี่ยวข้อง:

:help :function
:help function-argument

26

สายไปงานเลี้ยงเล็กน้อย แต่ฉันไม่เห็นคนที่ฉันชอบ:

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

ซึ่งget(a:, n, default)จะได้รับnthอาร์กิวเมนต์ที่เป็นตัวเลือกคืนdefaultหากไม่มีอยู่


Oooh ที่ดี!
joeytwiddle

3
ฉันรู้ว่ามันเก่ามาก แต่เพียงแค่ FYI ให้กับทุกคนที่อ่านข้อความนี้ คุณไม่สามารถทำได้let a:arg=อีกต่อไปในกลุ่ม คุณต้องใช้สิ่งที่ชอบหรือเพียงแค่let l:arg= let arg=ดูgithub.com/vim/vim/commit/…
jmzagorski

23

รูปแบบนี้จะช่วยให้คุณกำหนดชื่อที่มีความหมายให้กับแต่ละอาร์กิวเมนต์และให้ค่าเริ่มต้นสำหรับอาร์กิวเมนต์ที่ไม่มีให้:

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 ชี้ให้เห็น:

a:0 นับจำนวนอาร์กิวเมนต์ตัวเลือกที่ส่งผ่าน

a:1,, a:2... ให้เราเข้าถึงอาร์กิวเมนต์ที่เป็นตัวเลือก

อาร์กิวเมนต์ที่จำเป็น ( fooในตัวอย่างด้านบน) จะไม่ถูกนับ

condition ? result_if_true : result_if_false เป็นนิพจน์เงื่อนไข (ประกอบไปด้วย) ซึ่งประเมินเป็นคำที่สองหรือสามขึ้นอยู่กับว่าคำแรกเป็นจริงหรือไม่

ดังนั้นหากไม่มีการระบุอาร์กิวเมนต์ที่สามbazจะใช้ค่าเริ่มต้น0เป็น

หนึ่งกังวลกับตัวอย่างข้างต้นคือการที่a:fooสามารถเพียงเข้าถึงได้กับa:คำนำหน้าในขณะที่barและbazสามารถทำได้โดยไม่ต้องคำนำหน้า เนื่องจากสิ่งนี้ไม่สอดคล้องกันมากคุณอาจต้องการดึงอาร์กิวเมนต์ทั้งหมดออกเป็นตัวแปรโลคอลเช่น:

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

(ในทางเทคนิคคุณสามารถใช้ส่วนl:นำหน้าเพื่ออ้างอิงตัวแปรท้องถิ่นภายในฟังก์ชั่นตัวอย่างเช่นl:bazแต่สิ่งนี้ซ้ำซ้อนดังนั้นฉันจะไม่แนะนำมัน)


แต่ฉันขอแนะนำให้คุณใช้แบบฟอร์มนี้ทุกครั้งที่ทำได้:

function! s:FunctionName(...)

!ช่วยให้คุณสามารถที่จะกำหนดฟังก์ชั่นของคุณที่รันไทม์ (เช่นโดยการโหลดสคริปต์) และs:ขีด จำกัด ของการทำงานเพื่อขอบเขตสคริปต์ สิ่งนี้จะช่วยหลีกเลี่ยงการสร้างเนมสเปซส่วนกลาง (และเสี่ยงต่อการชน) หากฟังก์ชันของคุณถูกอ้างอิงจากที่อื่นภายในสคริปต์เท่านั้น โดยทั่วไปแล้วเป็นวิธีที่ต้องการในการกำหนดฟังก์ชั่นเมื่อไม่จำเป็นต้องมองเห็นได้ทั่วโลก ;-)


a:0ไม่รวมพารามิเตอร์ที่มีชื่อคงที่ a:1เป็นพารามิเตอร์แรกภายใน...(เพิ่งทดสอบกับ VIM 8.0)
Boris Brodski

ขอบคุณ @BorisBrodski คุณพูดถูกจับได้ดี ฉันแก้ไขคำตอบแล้ว
joeytwiddle

8

ฉันไม่ชำนาญใน vimscript แต่นี่เป็นวิธีที่ฉันจะทำ:

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

จากนั้นคุณสามารถcall Func("Hello", "World")และเห็นว่ามันพิมพ์ "Hello", "World", "Unspecified baz"

นี่คือการใช้คุณสมบัติ varargs ของฟังก์ชั่นเป็นกลุ่มซึ่งช่วยให้คุณผ่านจำนวนข้อโต้แย้งพิเศษไปยังฟังก์ชั่น ข้อโต้แย้งจะถูกเก็บไว้ในตัวแปรซึ่งขึ้นอยู่กับa:0(ความยาวของรายการอาร์กิวเมนต์พิเศษ) ทั้งสองได้รับการตั้งค่าเป็นอาร์กิวเมนต์ที่สอดคล้องกันหรือค่าเริ่มต้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.