ฉันจะทำให้ Vim ทำการติดตั้งอัตโนมัติในขณะที่ไม่มีโฟกัสได้อย่างไร?


29

ฉันใช้ VIm สำหรับทุกสิ่ง (หรือ gVim ในกรณีนี้) รวมถึงเอาต์พุตการตรวจสอบที่เขียนลงไฟล์ ฉันใช้autoreadเพื่อทำให้ Vim อ่านไฟล์อีกครั้งซึ่งจะทำทุกครั้งที่ฉันสลับโฟกัสของแป้นพิมพ์ไปที่ไฟล์นั้น

มีวิธีใดที่จะทำให้ Vim อัปเดตบัฟเฟอร์แม้ว่าฉันจะไม่เปลี่ยนโฟกัสของแป้นพิมพ์ ฉันลองตั้งค่าแล้วchecktimeแต่ดูเหมือนจะไม่มีผลกระทบใด ๆ ในขณะที่โฟกัสของแป้นพิมพ์อยู่ที่อื่น

เอาท์พุทฉันกำลังตรวจสอบคือการแทนที่ไฟล์ออกอย่างสมบูรณ์ และฉันไม่ได้มองtail -fมัน มีตัวเลือกอื่น ๆ เช่นการlessไพพ์อินสแตนซ์ใหม่ทุกครั้งหรือการไพพ์ลงไปหรือบางสิ่งบางอย่าง แต่มันก็เจ๋งถ้ามันสามารถทำได้ด้วย VIm


@Carpetsmoker แล้วCursorHoldเหตุการณ์ล่ะ? ถ้าเป็นกลุ่มไม่มีโฟกัสควรเรียกทุก n วินาที
muru

1
@muru ไม่CursorHoldถูกดำเนินการเพียงครั้งเดียวนี่เป็นเอกสารอย่างชัดเจนว่า: "ไม่ได้ยิง 'updatetime' ms ทุกครั้งถ้าคุณปล่อยให้ Vim ทำกาแฟ :)"
Martin Tournoij

1
ฉันออกgvimแท็กอีกครั้งผมหวังว่าไม่เป็นไร ;-) ขณะที่ผมเห็นมันคำถามนี้ก็คือไม่จริงเกี่ยวกับ gVim เป็นการเปลี่ยนแปลงโฟกัสเป็นเพียงเหตุการณ์หนึ่งซึ่งเป็นกลุ่มตรวจสอบว่าไฟล์ที่มีการเปลี่ยนแปลง (มีทั้งกลุ่ม, ดูคำตอบของฉันสำหรับรายละเอียด) ส่วนใหญ่หากไม่ได้ทั้งหมดวิธีในการปรับปรุงนี้จะทำงานได้ดีทั้งใน Vim และ gVim
Martin Tournoij

@Carpetsmoker อาฉันอยู่ภายใต้ความประทับใจที่ gVim ตรวจสอบเป็นประจำในขณะที่มีการโฟกัสของแป้นพิมพ์ (จึงทำให้เป็นคำถาม gVim) แต่ดูเหมือนว่าฉันเข้าใจผิด ขอบคุณที่ล้างข้อมูล
falstro

คำตอบ:


20

อัพเดท 2015-06-25 :

  • ฉันได้ทิ้งวิธีการ "เปลือก" เพราะมันผิดปกติเกินไป มันหยุดโหมดแทรกและกระบวนการซอมบี้ทางซ้าย ดูประวัติการแก้ไขของโพสต์นี้คือคุณต้องการเห็นมันจริงๆ
  • ผมได้ทำปลั๊กอินจากนี้auto_autoread.vim ในขณะนี้มันมีประสิทธิภาพเหมือนกับโค้ดด้านล่าง แต่ฉันอยากจะแนะนำให้คุณใช้ปลั๊กอินเพราะมันน่าจะได้รับการอัพเดท

อะไรautoreadทำอย่างไร

ในการตอบคำถามนี้เราต้องเข้าใจก่อนว่าautoreadตัวเลือกทำอะไรและที่สำคัญกว่านั้นคือสิ่งที่ไม่ได้ทำ

แต่น่าเสียดายที่:help 'autoread' ไม่ได้มีข้อมูลจำนวนมากเกี่ยวกับเรื่องนี้ก็แค่พูดว่า"ไฟล์ที่ได้รับการตรวจพบจะได้รับการเปลี่ยนแปลงภายนอกที่เป็นกลุ่ม" Vim ตรวจพบว่าไฟล์มีการเปลี่ยนแปลงอย่างไร ในการดำเนินการบางอย่างเป็นกลุ่มจะตรวจสอบเวลาการแก้ไขของไฟล์

เมื่อ:

  • :checktime ถูกนำมาใช้;
  • บัฟเฟอร์ถูกป้อน
  • :diffupdate ถูกนำมาใช้;
  • :e ออกให้สำหรับไฟล์ที่มีบัฟเฟอร์อยู่แล้ว
  • รันคำสั่งภายนอกด้วย!;
  • กลับสู่เบื้องหน้า ( ^Z, fgเฉพาะเมื่อเชลล์มีการควบคุมงาน);

สำหรับ gVim สิ่งนี้จะกระทำเมื่อ:

  • ปิดเมนู "คลิกขวา" (โดยเลือกบางอย่างหรือเพียงแค่ปิด)
  • โฟกัสเปลี่ยนไป (นี่คือสิ่งที่คุณสังเกตเห็นแล้ว);
  • ปิดกล่องโต้ตอบไฟล์ของเบราว์เซอร์ที่ปรากฏขึ้นหากคุณใช้ "ไฟล์ -> เปิด", "ไฟล์ -> บันทึกเป็น" จากเมนู (เช่นเดียวกับที่อื่น ๆ )

ฉันรวบรวมข้อมูลจากแหล่งที่มาเป็นกลุ่มโดยการระบุตำแหน่งทุกสายไป buf_check_timestamp(), check_timestamps()ฟังก์ชั่นและสถานที่ที่ มีการตั้งค่าneed_check_timestampsTRUE

ฉันอาจพลาดเหตุการณ์บางอย่าง แต่สิ่งสำคัญที่ต้องจำคือVim จะตรวจสอบเฉพาะว่าไฟล์นั้นถูกแก้ไขในชุด cirsumstances ที่ จำกัด มากๆ หรือไม่ แน่นอนว่ามันไม่ได้ "สำรวจ" ไฟล์สำหรับการเปลี่ยนแปลงตลอดเวลาnวินาทีซึ่งเป็นสิ่งที่คุณต้องการ

ดังนั้นสำหรับวัตถุประสงค์ของคุณset autoreadไม่เพียงพอ

ใช้ Python

สิ่งนี้จัดตารางเวลาเธรด Python ให้ทำงานในพื้นหลังโดยจะรัน :checktimeทุก ๆnวินาที หากautoreadมีการเปิดใช้งานนี้จะโหลดบัฟเฟอร์จากดิสก์อื่นมันก็จะเตือน

ซึ่งกำหนดให้เป็นกลุ่มมี+pythonหรือใน+python3 :versionควรทำงานได้กับทุกแพลตฟอร์ม (รวมถึง Windows)

fun! AutoreadPython()
python << EOF
import time, vim
try: import thread
except ImportError: import _thread as thread # Py3

def autoread():
    vim.command('checktime')  # Run the 'checktime' command
    vim.command('redraw')     # Actually update the display

def autoread_loop():
    while True:
        time.sleep(1)
        autoread()

thread.start_new_thread(autoread_loop, ())
EOF
endfun

คุณสามารถเริ่มต้นสิ่งนี้ได้โดยใช้:call AutoreadPython(); แน่นอนคุณสามารถทำได้ใน autocmd; ตัวอย่างเช่น:

autocmd *.c call AutoreadPython()

เล่ม

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

PS ฉันพยายามใช้ Ruby ด้วย แต่น่าเสียดายที่ Ruby threads (ใช้Thread) ไม่ทำงานในพื้นหลังเหมือนกับที่ Python ทำดังนั้นฉันจึงไม่สามารถใช้งานได้ (อาจมีวิธีอื่นด้วย)


2

ฉันทำปลั๊กอินvim-autoread เล็กน้อยที่ใช้tail -fในการอัพเดตบัฟเฟอร์ในพื้นหลังแบบอะซิงโครนัส สิ่งนี้ต้องการคุณสมบัติงานของ Vim เวอร์ชัน 8 อย่างชัดเจน

ใช้:AutoReadเพื่อเปิดและ:AutoRead!ปิด


เวอร์ชันที่เข้ากันได้กับ NeoVim จะยอดเยี่ยมมาก!
แอนดรู

@AndrewMacFie ฉันไม่เห็น, ทำไมสิ่งนี้ถึงไม่สามารถใช้ได้กับ Neovim
Christian Brabandt

การขาดงาน Vim 8 สนับสนุนใน NeoVim ฉันคิดอย่างไร
แอนดรู

@AndrewMacFie โอ้ที่อาจเป็นจริง เนื่องจากฉันไม่ได้ใช้ neovim ฉันจึงไม่สามารถเข้ากันได้กับ NeoVim อย่างไรก็ตามการประชาสัมพันธ์ก็ยินดีต้อนรับ :)
Christian Brabandt

พอยุติธรรม)
แอนดรู

1

ใน Neovim คุณสามารถใช้คำสั่งต่อไปนี้ซึ่งจะเปิดเทอร์มินัลบัฟเฟอร์ที่รันคำสั่ง tail

:enew | call termopen('tail --follow=name --retry /path/to/file.log')

สิ่งนี้จะทำงานต่อไปแม้ว่าไฟล์จะถูกลบและสร้างใหม่

หรือเพิ่มสิ่งต่อไปนี้ในของคุณ $MYVIMRC

" :Tail /path/to/file
function! Tail(file)
  enew
  call termopen('tail --follow=name --retry ' . fnameescape(a:file))
endfunction
command! -nargs=1 Tail call Tail(<f-args>)

1

จากคำตอบนี้(อ้างอิงจากคำตอบของPhanHaiQuangและความคิดเห็นโดยflukus )

หนึ่งสามารถเรียกใช้ oneliner นี้จากอดีต (whithin vim) เมื่อต้องการ (หรือใส่คำสั่งแต่ละคำสั่งใน vimrc เมื่อเปิดไฟล์บันทึก)

:set autoread | au CursorHold * checktime | call feedkeys("lh")

คำอธิบาย:
- autoread : อ่านไฟล์เมื่อมีการเปลี่ยนแปลงจากภายนอก (แต่มันไม่ทำงานด้วยตัวของมันเองไม่มีตัวจับเวลาภายในหรืออะไรทำนองนั้นมันจะอ่านไฟล์เมื่อ vim ทำการกระทำเช่นเดียวกับคำสั่งในอดีต:!
- CursorHold * การตรวจสอบเวลา: เมื่อเคอร์เซอร์ไม่ได้ถูกย้ายโดยผู้ใช้ตามเวลาที่ระบุใน 'updatetime' (ซึ่งเป็น 4,000 มิลลิวินาทีโดยค่าเริ่มต้น) เวลาตรวจสอบจะถูกดำเนินการซึ่งจะตรวจสอบการเปลี่ยนแปลงจากภายนอกไฟล์
- ปุ่มฟีดการโทร ("lh") : เคอร์เซอร์ถูกย้ายหนึ่งครั้งขวาและกลับซ้ายจากนั้นไม่มีสิ่งใดเกิดขึ้น (... ซึ่งหมายความว่า CursorHold นั้นถูกกระตุ้นซึ่งหมายความว่าเรามีลูป )

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