การใช้ <buffer> นี้ถูกต้องหรือไม่
ฉันคิดว่ามันถูกต้อง แต่คุณเพียงแค่ใส่มันไว้ในกลุ่มและเคลียร์หลังเพื่อให้แน่ใจว่า autocmd จะไม่ซ้ำกันทุกครั้งที่คุณรันคำสั่งที่โหลดบัฟเฟอร์เดียวกัน
ในขณะที่คุณอธิบายรูปแบบพิเศษที่<buffer>
ช่วยให้คุณสามารถที่จะพึ่งพาในตัวกลไกการตรวจสอบ filetype $VIMRUNTIME/filetype.vim
ดำเนินการภายในแฟ้ม
ในไฟล์นี้คุณสามารถค้นหา autocmds ในตัวของ Vim ซึ่งมีหน้าที่รับผิดชอบในการตั้งค่าประเภทไฟล์ที่ถูกต้องสำหรับบัฟเฟอร์ที่กำหนด ตัวอย่างเช่นสำหรับ markdown:
" Markdown
au BufNewFile,BufRead *.markdown,*.mdown,*.mkd,*.mkdn,*.mdwn,*.md setf markdown
ภายในปลั๊กอินชนิดไฟล์ของคุณคุณสามารถคัดลอกรูปแบบเดียวกันสำหรับทุก ๆ autocmd ที่คุณติดตั้ง ตัวอย่างเช่นหากต้องการบันทึกบัฟเฟอร์โดยอัตโนมัติเมื่อเคอร์เซอร์ของคุณไม่ได้ถูกย้ายในช่วงสองสามวินาที:
au CursorHold *.markdown,*.mdown,*.mkd,*.mkdn,*.mdwn,*.md update
แต่<buffer>
ทาง verbose น้อยกว่า:
au CursorHold <buffer> update
นอกจากนี้หากบางวันมีส่วนขยายอื่นที่ถูกต้องและ$VIMRUNTIME/filetype.vim
ได้รับการอัปเดตเพื่อรวมส่วนเติมเงินอัตโนมัติของคุณจะไม่ได้รับแจ้ง และคุณจะต้องอัปเดตรูปแบบทั้งหมดภายในปลั๊กอินชนิดไฟล์ของคุณ
สิ่งต่าง ๆ จะยุ่งถ้าฉันลบบัฟเฟอร์และเปิดอีกครั้ง (หวังว่าตัวเลขจะไม่ชนกัน แต่…)
ฉันไม่แน่ใจ แต่ฉันไม่คิดว่า Vim สามารถใช้หมายเลขบัฟเฟอร์ของบัฟเฟอร์ที่ลบแล้วได้อีก ฉันไม่พบหัวข้อที่เกี่ยวข้องจากความช่วยเหลือ แต่ฉันพบย่อหน้านี้จากvim.wikia.com :
ไม่ Vim จะไม่ใช้หมายเลขบัฟเฟอร์ของบัฟเฟอร์ที่ถูกลบอีกครั้งสำหรับบัฟเฟอร์ใหม่ Vim จะกำหนดหมายเลขลำดับถัดไปสำหรับบัฟเฟอร์ใหม่เสมอ
นอกจากนี้ตามที่@ Tumbler41อธิบายเมื่อคุณล้างบัฟเฟอร์ autocmds ของมันจะถูกลบออก จาก:h autocmd-buflocal
:
เมื่อบัฟเฟอร์ถูกลบออกออโต้คำสั่งบัฟเฟอร์ท้องถิ่นจะหายไปเช่นกัน
หากคุณต้องการตรวจสอบตัวเองคุณสามารถทำได้โดยเพิ่มระดับ verbosity ของ Vim เป็น 6 คุณสามารถทำได้ชั่วคราวเพียงแค่หนึ่งคำสั่งโดยใช้:verbose
ตัวปรับแต่ง ดังนั้นภายในบัฟเฟอร์มาร์คดาวน์ของคุณคุณสามารถดำเนินการได้:
:6verbose bwipe
จากนั้นถ้าคุณตรวจสอบข้อความของ Vim:
:messages
คุณควรเห็นบรรทัดที่มีลักษณะดังนี้:
auto-removing autocommand: CursorHold <buffer=42>
42
จำนวน markdown buffer ของคุณอยู่ที่ไหน
มีข้อผิดพลาดอะไรบ้างที่ฉันควรระวัง?
มี 3 <buffer>
สถานการณ์ที่ผมจะพิจารณาเป็นข้อผิดพลาดและที่เกี่ยวข้องกับรูปแบบพิเศษ ในสองของพวกเขา<buffer>
อาจมีปัญหาในอื่น ๆ มันเป็นทางออก
หลุมพราง 1
ก่อนอื่นคุณควรระวังด้วยวิธีที่คุณล้างข้อมูลกลุ่มของ autocmds บัฟเฟอร์ในเครื่องของคุณ คุณต้องคุ้นเคยกับตัวอย่างนี้:
augroup your_group_name
autocmd!
autocmd Event pattern command
augroup END
ดังนั้นคุณอาจถูกล่อลวงให้ใช้มันสำหรับ autocmds บัฟเฟอร์ท้องถิ่นของคุณไม่มีการแก้ไขเช่นนี้:
augroup my_markdown
autocmd!
autocmd CursorHold <buffer> update
augroup END
แต่สิ่งนี้จะมีผลกระทบที่ไม่พึงประสงค์ ครั้งแรกที่คุณโหลดบัฟเฟอร์ markdown มาเรียกมันว่าA
autocmd นั้นจะถูกติดตั้งอย่างถูกต้อง จากนั้นเมื่อคุณโหลดใหม่A
autocmd จะถูกลบ (เนื่องจากautocmd!
) และติดตั้งใหม่ ดังนั้นกลุ่มจะถูกต้องจะป้องกันการทำซ้ำของ autocmd อย่างถูกต้อง
ทีนี้สมมติว่าคุณโหลดบัฟเฟอร์ markdown ครั้งที่สองเรียกมันว่าB
ในหน้าต่างที่ 2 autocmds ทั้งหมดของ augroup จะถูกล้าง: นั่นคือ autocmd ของA
และหนึ่งในB
นั้น จากนั้น autocmd SINGLE B
จะติดตั้งสำหรับ
ดังนั้นเมื่อคุณทำการเปลี่ยนแปลงB
และรอสักครู่เพื่อCursorHold
ให้ถูกไล่ออกมันจะถูกบันทึกโดยอัตโนมัติ แต่ถ้าคุณกลับไปA
ทำสิ่งเดียวกันบัฟเฟอร์จะไม่ถูกบันทึก นี่เป็นเพราะครั้งสุดท้ายที่คุณโหลดบัฟเฟอร์ markdown มีความไม่สมดุลระหว่างสิ่งที่คุณลบกับสิ่งที่คุณเพิ่ม คุณลบมากกว่าสิ่งที่คุณเพิ่ม
วิธีแก้ไขคือไม่ลบ autocmds ทั้งหมด แต่เฉพาะบัฟเฟอร์ปัจจุบันโดยส่งผ่านรูปแบบพิเศษ<buffer>
ไปที่:autocmd!
:
augroup my_markdown
autocmd! CursorHold <buffer>
autocmd CursorHold <buffer> update
augroup END
โปรดทราบว่าคุณสามารถแทนที่CursorHold
ด้วยดาวเพื่อจับคู่เหตุการณ์ใด ๆ ในบรรทัดที่ลบ autocmds:
augroup my_markdown
autocmd! * <buffer>
autocmd CursorHold <buffer> update
augroup END
ด้วยวิธีนี้คุณไม่จำเป็นต้องระบุเหตุการณ์ทั้งหมดที่ autocmds ของคุณกำลังฟังอยู่เมื่อคุณต้องการล้าง augroup
หลุมพราง 2
มีข้อผิดพลาดอีกอย่างหนึ่ง แต่คราว<buffer>
นี้ไม่ใช่ปัญหามันคือทางออก
เมื่อคุณรวมตัวเลือกโลคัลในปลั๊กอินชนิดไฟล์คุณอาจทำดังนี้:
setlocal option1=value
setlocal option2
สิ่งนี้จะทำงานได้ตามที่คาดไว้สำหรับตัวเลือกบัฟเฟอร์ในเครื่อง แต่ไม่จำเป็นสำหรับตัวเลือกในหน้าต่าง เพื่อแสดงปัญหาคุณสามารถลองการทดสอบต่อไปนี้ สร้างไฟล์~/.vim/after/ftdetect/potion.vim
และข้างในเขียน:
autocmd BufNewFile,BufRead *.pn setfiletype potion
ไฟล์นี้จะตั้ง filetype โดยอัตโนมัติpotion
สำหรับไฟล์ใด ๆ .pn
ที่มีนามสกุลเป็น คุณไม่จำเป็นต้องห่อไว้ในกลุ่มเพราะสำหรับไฟล์ประเภทนี้ Vim จะทำมันโดยอัตโนมัติ (ดู:h ftdetect
)
หากไม่มีไดเรกทอรีกลางในระบบของคุณคุณสามารถสร้างได้
ถัดไปสร้างปลั๊กอินประเภทไฟล์~/.vim/after/ftplugin/potion.vim
และข้างในเขียน:
setlocal list
ตามค่าเริ่มต้นในpotion
ไฟล์การตั้งค่านี้จะทำให้อักขระแท็บแสดงเป็น^I
และสิ้นสุดบรรทัด$
ดังนี้
ตอนนี้สร้างน้อยที่สุดvimrc
; ภายใน/tmp/vimrc
เขียน:
filetype plugin on
... เพื่อเปิดใช้งานปลั๊กอินประเภทไฟล์
นอกจากนี้ยังสร้างแฟ้มยา, และไฟล์แบบสุ่ม/tmp/pn.pn
/tmp/file
ในไฟล์ potion เขียนบางสิ่ง:
foo
bar
baz
ในไฟล์สุ่มเขียนพา ธ ไปยังไฟล์ potion /tmp/pn.pn
:
/tmp/pn.pn
ตอนนี้เริ่ม Vim ด้วยการเริ่มต้นขั้นต่ำเพียงแค่จัดหาvimrc
และเปิดไฟล์ทั้งสองในวิวพอร์ตแนวตั้ง:
$ vim -Nu /tmp/vimrc -O /tmp/pn.pn /tmp/file
คุณควรเห็นวิวพอร์ตแนวตั้ง 2 ตำแหน่ง ไฟล์ potion ทางด้านซ้ายแสดงจุดสิ้นสุดของบรรทัดที่มีเครื่องหมายดอลลาร์ไฟล์สุ่มทางด้านขวาจะไม่แสดงผลเลย
ให้ความสำคัญกับไฟล์แบบสุ่มและกดgf
เพื่อแสดงไฟล์ potion ที่มีพา ธ อยู่ใต้เคอร์เซอร์ ตอนนี้คุณเห็นบัฟเฟอร์ potion เดียวกันในวิวพอร์ตด้านขวา แต่ในตอนนี้จุดสิ้นสุดของบรรทัดจะไม่แสดงด้วยเครื่องหมายดอลลาร์ และถ้าคุณพิมพ์:setlocal list?
เสียงเรียกเข้าควรตอบด้วยnolist
:
ห่วงโซ่ของเหตุการณ์ทั้งหมด:
BufRead event → set 'filetype' option → load filetype plugins
... ไม่ได้เกิดขึ้นเพราะเป็นครั้งแรกของพวกเขาไม่ได้เกิดขึ้นเมื่อคุณกดBufRead
gf
โหลดบัฟเฟอร์แล้ว
อาจดูเหมือนไม่คาดคิดเพราะเมื่อคุณเพิ่มsetlocal list
ในปลั๊กอินประเภทไฟล์ potion คุณอาจคิดว่ามันจะเปิดใช้งาน'list'
ตัวเลือกในหน้าต่างใด ๆ ที่แสดงบัฟเฟอร์ potion
ปัญหาไม่ได้เฉพาะเจาะจงกับpotion
ไฟล์ประเภทใหม่นี้ คุณสามารถสัมผัสกับmarkdown
ไฟล์ได้เช่นกัน
ไม่เฉพาะเจาะจงกับ'list'
ตัวเลือกเช่นกัน คุณจะได้พบกับการตั้งค่าหน้าต่างท้องถิ่นอื่น ๆ เช่น'conceallevel'
, 'foldmethod'
, 'foldexpr'
, 'foldtitle'
...
ไม่เฉพาะเจาะจงกับgf
คำสั่งเช่นกัน คุณสามารถสัมผัสกับมันด้วยคำสั่งอื่น ๆ ซึ่งอาจเปลี่ยนบัฟเฟอร์ที่แสดงในหน้าต่างปัจจุบัน: เครื่องหมายสากลC-o
(เลื่อนไปด้านหลังใน jumplist แบบโลคัลหน้าต่าง) :b {buffer_number}
,, ...
ในการสรุปตัวเลือกในหน้าต่างจะถูกตั้งค่าอย่างถูกต้องถ้าหาก:
- ไฟล์ที่ยังไม่ได้อ่านในช่วง Vim ปัจจุบัน (เพราะ
BufRead
จะต้องถูกไล่ออก)
- ไฟล์กำลังแสดงอยู่ในหน้าต่างที่มีการตั้งค่าตัวเลือกภายในหน้าต่างไว้อย่างถูกต้อง
- หน้าต่างใหม่ถูกสร้างขึ้นด้วยคำสั่งเช่น
:split
(ในกรณีนี้มันควรสืบทอดตัวเลือกหน้าต่างท้องถิ่นจากหน้าต่างที่คำสั่งถูกดำเนินการ)
มิฉะนั้นการตั้งค่าตัวเลือกในหน้าต่างอาจไม่ถูกต้อง
วิธีการแก้ปัญหาที่เป็นไปได้ที่จะตั้งพวกเขาไม่ได้โดยตรงจากปลั๊กอิน filetype แต่จาก autocmd BufWinEnter
ติดตั้งในภายหลังซึ่งจะฟัง เหตุการณ์นี้ควรเริ่มทำงานทุกครั้งที่มีการแสดงบัฟเฟอร์ในหน้าต่าง
ตัวอย่างเช่นแทนที่จะเขียนสิ่งนี้:
setlocal list
คุณจะเขียนสิ่งนี้:
augroup my_potion
au! * <buffer>
au BufWinEnter <buffer> setlocal list
augroup END
<buffer>
และที่นี่คุณจะพบอีกครั้งในรูปแบบพิเศษ
หลุมพราง 3
หากคุณเปลี่ยนประเภทไฟล์ของบัฟเฟอร์ของคุณ autocmds จะยังคงอยู่ หากคุณต้องการลบพวกเขาคุณจะต้องกำหนดค่าb:undo_ftplugin
(ดู:h undo_ftplugin
) และรวมคำสั่งนี้ไว้ในนั้น:
exe 'au! my_markdown * <buffer>'
อย่างไรก็ตามอย่าพยายามลบกลุ่มตัวเองออกเพราะอาจมีบัฟเฟอร์มาร์กอัปที่มี autocmds อยู่ด้านใน
FWIW นี่เป็นข้อมูลโค้ด UltiSnips ที่ฉันใช้เพื่อตั้งค่าb:undo_ftplugin
:
snippet undo "undo ftplugin settings" bm
" teardown {{{1
let b:undo_ftplugin = get(b:, 'undo_ftplugin', '')
\ .(empty(get(b:, 'undo_ftplugin', '')) ? '' : '|')
\ ."${1:
\ setl ${2:option}<}${3:
\ | exe '${4:n}unmap <buffer> ${5:lhs}'}${6:
\ | exe 'au! ${7:group_name} * <buffer>'}${8:
\ | unlet! b:${9:variable}}${10:
\ | delcommand ${11:Cmd}}
\ "
$0
endsnippet
และนี่คือตัวอย่างของค่าที่ฉันมีใน~/.vim/after/ftplugin/awk.vim
:
let b:undo_ftplugin = get(b:, 'undo_ftplugin', '')
\ .(empty(get(b:, 'undo_ftplugin', '')) ? '' : '|')
\ ."
\ setl cms< cocu< cole< fdm< fdt< tw<
\| exe 'nunmap <buffer> K'
\| exe 'au! my_awk * <buffer>'
\| exe 'au! my_awk_format * <buffer>'
\ "
ในฐานะที่เป็นบันทึกด้านข้างฉันเข้าใจว่าทำไมคุณถามคำถามเพราะเมื่อฉันมองหาทุกบรรทัดที่ใช้รูปแบบพิเศษ<buffer>
ในไฟล์เริ่มต้นของ Vim:
:vim /au\%[tocmd!].\{-}<buffer>/ $VIMRUNTIME/**/*
ฉันพบการแข่งขัน 9 รายการเท่านั้น (คุณอาจพบมากขึ้นหรือน้อยลงฉันใช้ Vim เวอร์ชัน 8.0 พร้อมแพตช์ไม่เกิน134
) และในบรรดา 9 แมทช์ 7 รายการอยู่ในเอกสารประกอบการมีเพียง 2 แหล่งเท่านั้น คุณควรพบพวกเขาใน$ VIMRUNTIME / syntax / dircolors.vim :
autocmd CursorMoved,CursorMovedI <buffer> call s:preview_color('.')
autocmd CursorHold,CursorHoldI <buffer> call s:reset_colors()
ผมไม่ทราบว่ามันสามารถทำให้เกิดปัญหา แต่พวกเขาไม่ได้อยู่ภายใน augroup ซึ่งหมายความว่าทุกครั้งที่คุณโหลดบัฟเฟอร์ที่มี filetype คือdircolors
(มันเกิดขึ้นถ้าคุณแก้ไขไฟล์ชื่อ.dircolors
, .dir_colors
หรือมีปลายเส้นทางด้วย/etc/DIR_COLORS
) ปลั๊กอินไวยากรณ์จะเพิ่ม autocmd บัฟเฟอร์ท้องถิ่นใหม่
คุณสามารถตรวจสอบได้ดังนี้:
$ vim ~/.dir_colors
:au * <buffer>
คำสั่งสุดท้ายควรแสดงสิ่งนี้:
CursorHold
<buffer=1>
call s:reset_colors()
CursorHoldI
<buffer=1>
call s:reset_colors()
CursorMoved
<buffer=1>
call s:preview_color('.')
CursorMovedI
<buffer=1>
call s:preview_color('.')
ทีนี้โหลดบัฟเฟอร์ใหม่แล้วถามอีกครั้งว่าบัฟเฟอร์อัตโนมัติในพื้นที่สำหรับบัฟเฟอร์ปัจจุบันคืออะไร:
:e
:au * <buffer>
เวลานี้คุณจะเห็น:
CursorHold
<buffer=1>
call s:reset_colors()
call s:reset_colors()
CursorHoldI
<buffer=1>
call s:reset_colors()
call s:reset_colors()
CursorMoved
<buffer=1>
call s:preview_color('.')
call s:preview_color('.')
CursorMovedI
<buffer=1>
call s:preview_color('.')
call s:preview_color('.')
หลังจากที่ทุกคนโหลดของไฟล์s:reset_colors()
และs:preview_color('.')
จะถูกเรียกว่าเป็นหนึ่งเวลาเพิ่มเติมทุกคนเวลาของเหตุการณ์CursorHold
, CursorHoldI
, CursorMoved
, CursorMovedI
ยิง
อาจไม่ใช่ปัญหาใหญ่เพราะแม้หลังจากโหลดdircolors
ไฟล์ซ้ำหลายครั้งฉันไม่เห็นการชะลอตัวที่เห็นได้ชัดหรือพฤติกรรมที่ไม่คาดคิดจาก Vim
ถ้ามันเป็นปัญหาสำหรับคุณคุณสามารถติดต่อผู้ดูแลปลั๊กอินไวยากรณ์ แต่ในขณะเดียวกันถ้าคุณต้องการที่จะป้องกันไม่ให้เกิดความซ้ำซ้อนในการ autocmds คุณสามารถสร้างปลั๊กอินไวยากรณ์ของคุณเองสำหรับไฟล์โดยใช้ไฟล์dircolors
~/.vim/syntax/dircolors.vim
ภายในนั้นคุณจะต้องนำเข้าเนื้อหาของปลั๊กอินไวยากรณ์ดั้งเดิม:
$ vim ~/.vim/syntax/dircolors.vim
:r $VIMRUNTIME/syntax/dircolors.vim
จากนั้นในตอนท้ายคุณก็แค่ใส่ค่า autocmds ภายในกลุ่มที่คุณจะเคลียร์ ดังนั้นคุณจะแทนที่บรรทัดเหล่านี้:
autocmd CursorMoved,CursorMovedI <buffer> call s:preview_color('.')
autocmd CursorHold,CursorHoldI <buffer> call s:reset_colors()
... กับสิ่งเหล่านี้:
augroup my_dircolors_syntax
autocmd! * <buffer>
autocmd CursorMoved,CursorMovedI <buffer> call s:preview_color('.')
autocmd CursorHold,CursorHoldI <buffer> call s:reset_colors()
augroup END
โปรดทราบว่าถ้าคุณสร้างdircolors
ปลั๊กอินไวยากรณ์ของคุณด้วยไฟล์~/.vim/after/syntax/dircolors.vim
มันจะไม่ทำงานเพราะปลั๊กอินไวยากรณ์เริ่มต้นจะต้องมีที่มาก่อน โดยการใช้~/.vim/syntax/dircolors.vim
ปลั๊กอินไวยากรณ์ของคุณจะได้รับก่อนที่จะเริ่มต้นและมันจะตั้งค่าตัวแปรบัฟเฟอร์ท้องถิ่นb:current_syntax
ซึ่งจะป้องกันไม่ให้ปลั๊กอินไวยากรณ์เริ่มต้นจากแหล่งที่มาเพราะมันมียามนี้:
if exists("b:current_syntax")
finish
endif
กฎทั่วไปดูเหมือนว่า: ใช้~/.vim/ftplugin
และ~/.vim/syntax
ไดเรกทอรีเพื่อสร้างปลั๊กอินประเภทไฟล์ / ไวยากรณ์ที่กำหนดเองและป้องกันปลั๊กอินถัดไป (สำหรับไฟล์ประเภทเดียวกัน) ในพา ธ รันไทม์ที่จะได้รับแหล่งที่มา และการใช้งาน~/.vim/after/ftplugin
, ~/.vim/after/syntax
ไม่ได้ที่จะป้องกันไม่ให้ปลั๊กอินอื่น ๆ ที่มาจากการถูก แต่เพียงแค่มีคำสุดท้ายเกี่ยวกับคุณค่าของการตั้งค่าบางอย่าง