ใน zsh เส้นทางการค้นหาฟังก์ชั่น ($ fpath) กำหนดชุดของไดเรกทอรีซึ่งมีไฟล์ที่สามารถทำเครื่องหมายให้โหลดโดยอัตโนมัติเมื่อจำเป็นต้องใช้ฟังก์ชั่นในครั้งแรก
Zsh มีไฟล์การโหลดอัตโนมัติสองโหมด: วิธีดั้งเดิมของ Zsh และโหมดอื่นที่คล้ายกับการโหลดอัตโนมัติของ ksh ส่วนหลังใช้งานได้หากตั้งค่าตัวเลือก KSH_AUTOLOAD โหมดเนทิฟของ Zsh เป็นค่าเริ่มต้นและฉันจะไม่พูดถึงวิธีอื่นที่นี่ (ดู "man zshmisc" และ "man zshoptions" สำหรับรายละเอียดเกี่ยวกับการโหลดอัตโนมัติสไตล์ ksh)
ถูก สมมติว่าคุณมีไดเรกทอรี `~ / .zfunc 'และคุณต้องการให้มันเป็นส่วนหนึ่งของเส้นทางการค้นหาฟังก์ชั่นคุณทำสิ่งนี้:
fpath=( ~/.zfunc "${fpath[@]}" )
ที่เพิ่มไดเรกทอรีส่วนตัวของคุณที่ด้านหน้าของเส้นทางการค้นหา นั่นเป็นสิ่งสำคัญหากคุณต้องการแทนที่ฟังก์ชั่นจากการติดตั้งของ zsh ด้วยตัวคุณเอง (เช่นเมื่อคุณต้องการใช้ฟังก์ชั่นเสร็จสิ้นการอัปเดตเช่น `_git 'จากที่เก็บ CVS ของ zsh ด้วยเชลล์รุ่นเก่าที่ติดตั้ง)
นอกจากนี้ยังเป็นที่น่าสังเกตว่าไดเรกทอรีจาก `$ fpath 'จะไม่ถูกเรียกซ้ำ หากคุณต้องการให้ไดเรกทอรีส่วนตัวของคุณถูกค้นหาซ้ำคุณจะต้องดูแลตัวเองเช่นนี้ (ข้อมูลโค้ดต่อไปนี้ต้องการตัวเลือก `EXTENDED_GLOB '):
fpath=(
~/.zfuncs
~/.zfuncs/**/*~*/(CVS)#(/N)
"${fpath[@]}"
)
มันอาจดูเป็นความลับในสายตาที่ไม่ได้ฝึกฝน แต่จริงๆแล้วมันแค่เพิ่มไดเรกทอรีทั้งหมดที่อยู่ด้านล่าง `~ / .zfunc 'เป็น` $ fpath' ในขณะที่ไม่สนใจไดเรกทอรีที่เรียกว่า "CVS" (ซึ่งมีประโยชน์หากคุณวางแผนจะชำระเงินทั้งหมด ต้นไม้ฟังก์ชั่นจาก CVS ของ zsh ในเส้นทางการค้นหาส่วนตัวของคุณ)
สมมติว่าคุณมีไฟล์ `~ / .zfunc / hello 'ที่มีบรรทัดต่อไปนี้:
printf 'Hello world.\n'
สิ่งที่คุณต้องทำตอนนี้คือทำเครื่องหมายฟังก์ชั่นที่จะโหลดโดยอัตโนมัติตามการอ้างอิงครั้งแรก:
autoload -Uz hello
"-Uz เกี่ยวกับอะไร" คุณถาม? นั่นเป็นเพียงชุดของตัวเลือกที่จะทำให้ 'autoload' ทำสิ่งที่ถูกต้องไม่ว่าตัวเลือกใดจะถูกตั้งค่าเป็นอย่างอื่น `U 'ปิดใช้งานการขยายนามแฝงขณะที่ฟังก์ชันกำลังโหลดและ` z' บังคับให้โหลดอัตโนมัติสไตล์ zsh แม้ว่า `KSH_AUTOLOAD 'จะถูกตั้งค่าด้วยเหตุผลใดก็ตาม
หลังจากนั้นได้รับการดูแลคุณสามารถใช้ฟังก์ชั่น `สวัสดี 'ใหม่ของคุณ:
สวัสดี
สวัสดีชาวโลก.
คำเกี่ยวกับการจัดหาไฟล์เหล่านี้: นั่นเป็นเพียงที่ไม่ถูกต้อง หากคุณต้องการหาไฟล์ `~ / .zfunc / hello 'มันจะพิมพ์" Hello world " ครั้งหนึ่ง ไม่มีอะไรเพิ่มเติม จะไม่มีการกำหนดฟังก์ชั่น นอกจากนี้แนวคิดก็คือให้โหลดโค้ดของฟังก์ชันเมื่อจำเป็นเท่านั้น หลังจากการเรียก 'autoload' ความหมายของฟังก์ชันจะไม่อ่าน ฟังก์ชันถูกทำเครื่องหมายว่าจะโหลดอัตโนมัติในภายหลังตามต้องการ
และสุดท้ายโน้ตเกี่ยวกับ $ FPATH และ $ fpath: Zsh จะรักษาพารามิเตอร์เหล่านั้นไว้เป็นพารามิเตอร์ที่เชื่อมโยง พารามิเตอร์ตัวพิมพ์เล็กคืออาร์เรย์ เวอร์ชันตัวพิมพ์ใหญ่เป็นสเกลาร์สตริงที่มีรายการจากอาร์เรย์ที่เชื่อมโยงซึ่งเชื่อมโยงกันโดยโคลอนในระหว่างรายการ สิ่งนี้เสร็จสิ้นเนื่องจากการจัดการรายการสเกลาร์เป็นวิธีที่เป็นธรรมชาติมากขึ้นโดยใช้อาร์เรย์ในขณะที่ยังคงรักษาความเข้ากันได้แบบย้อนหลังสำหรับโค้ดที่ใช้พารามิเตอร์สเกลาร์ หากคุณเลือกใช้ $ FPATH (scalar one) คุณต้องระวัง:
FPATH=~/.zfunc:$FPATH
จะทำงานในขณะที่สิ่งต่อไปนี้จะไม่:
FPATH="~/.zfunc:$FPATH"
เหตุผลคือการขยายตัวหนอนไม่ได้ดำเนินการภายในเครื่องหมายคำพูดคู่ นี่เป็นสาเหตุของปัญหาของคุณ หากecho $FPATH
พิมพ์เครื่องหมายตัวหนอนและไม่ใช่เส้นทางแบบขยายก็จะไม่ทำงาน เพื่อความปลอดภัยฉันจะใช้ $ HOME แทนตัวหนอนแบบนี้:
FPATH="$HOME/.zfunc:$FPATH"
ที่ถูกกล่าวว่าฉันค่อนข้างจะใช้พารามิเตอร์อาร์เรย์เหมือนที่ฉันได้ที่ด้านบนของคำอธิบายนี้
คุณไม่ควรส่งออกพารามิเตอร์ $ FPATH มันจำเป็นเท่านั้นโดยกระบวนการเชลล์ปัจจุบันและไม่ใช่โดยลูกใด ๆ ของมัน
ปรับปรุง
เกี่ยวกับเนื้อหาของไฟล์ใน `$ fpath ':
ด้วยการโหลดอัตโนมัติสไตล์ zsh เนื้อหาของไฟล์คือส่วนของฟังก์ชั่นที่กำหนด ดังนั้นไฟล์ที่ชื่อ "hello" ที่มีบรรทัดecho "Hello world."
จะกำหนดฟังก์ชันที่เรียกว่า "hello" อย่างสมบูรณ์ คุณมีอิสระที่จะใส่
hello () { ... }
รหัส แต่มันจะไม่จำเป็น
การอ้างสิทธิ์ว่าไฟล์หนึ่งไฟล์อาจมีเพียงหนึ่งฟังก์ชันไม่ถูกต้องทั้งหมด
โดยเฉพาะอย่างยิ่งถ้าคุณดูฟังก์ชั่นบางอย่างจากฟังก์ชั่นการเติมเต็มระบบ (compsys) คุณจะรู้ได้อย่างรวดเร็วว่านั่นเป็นความเข้าใจผิด คุณมีอิสระในการกำหนดฟังก์ชั่นเพิ่มเติมในไฟล์ฟังก์ชั่น คุณมีอิสระที่จะทำการเริ่มต้นประเภทใดก็ได้ซึ่งคุณอาจจำเป็นต้องทำในครั้งแรกที่มีการเรียกใช้ฟังก์ชัน อย่างไรก็ตามเมื่อคุณทำคุณจะกำหนดฟังก์ชั่นที่มีชื่อเหมือนไฟล์ในไฟล์และเรียกใช้ฟังก์ชั่นนั้นในตอนท้ายของไฟล์ดังนั้นมันจะถูกเรียกใช้ในครั้งแรกที่มีการอ้างอิงฟังก์ชัน
ถ้า - ด้วยฟังก์ชั่นย่อย - คุณไม่ได้กำหนดฟังก์ชั่นที่ชื่อเหมือนไฟล์ภายในไฟล์คุณจะท้ายด้วยฟังก์ชั่นที่มีคำนิยามฟังก์ชั่นอยู่ในนั้น (กล่าวคือฟังก์ชั่นย่อยในไฟล์) คุณจะต้องกำหนดฟังก์ชั่นย่อยทั้งหมดอย่างมีประสิทธิภาพทุกครั้งที่คุณเรียกใช้ฟังก์ชันที่มีชื่อเหมือนไฟล์ โดยปกตินั่นไม่ใช่สิ่งที่คุณต้องการดังนั้นคุณจึงต้องกำหนดฟังก์ชันใหม่อีกครั้งซึ่งมีชื่อเหมือนกับไฟล์ภายในไฟล์
ฉันจะรวมโครงกระดูกสั้น ๆ ที่จะทำให้คุณมีความคิดในการทำงาน:
# Let's again assume that these are the contents of a file called "hello".
# You may run arbitrary code in here, that will run the first time the
# function is referenced. Commonly, that is initialisation code. For example
# the `_tmux' completion function does exactly that.
echo initialising...
# You may also define additional functions in here. Note, that these
# functions are visible in global scope, so it is paramount to take
# care when you're naming these so you do not shadow existing commands or
# redefine existing functions.
hello_helper_one () {
printf 'Hello'
}
hello_helper_two () {
printf 'world.'
}
# Now you should redefine the "hello" function (which currently contains
# all the code from the file) to something that covers its actual
# functionality. After that, the two helper functions along with the core
# function will be defined and visible in global scope.
hello () {
printf '%s %s\n' "$(hello_helper_one)" "$(hello_helper_two)"
}
# Finally run the redefined function with the same arguments as the current
# run. If this is left out, the functionality implemented by the newly
# defined "hello" function is not executed upon its first call. So:
hello "$@"
หากคุณเรียกใช้ตัวอย่างที่งี่เง่าการเรียกใช้ครั้งแรกจะมีลักษณะดังนี้:
สวัสดี
initialising ...
สวัสดีชาวโลก.
และการโทรติดต่อกันจะมีลักษณะเช่นนี้:
สวัสดี
สวัสดีชาวโลก.
ฉันหวังว่านี่จะช่วยล้างสิ่งต่างๆ
(หนึ่งในตัวอย่างของโลกแห่งความซับซ้อนที่ใช้กลอุบายทั้งหมดเหล่านี้คือฟังก์ชั่น` _tmux 'ที่กล่าวถึงแล้วจากระบบเสร็จสมบูรณ์ของฟังก์ชันของ zsh)