:!<command>
สามารถใช้เพื่อรันคำสั่งในเชลล์ แต่นี่ "ใช้เวลา" terminal ของฉันและเติมด้วยstdout
คำสั่งเฉพาะที่
ฉันจะรันคำสั่งในพื้นหลังที่แจ้งให้ฉันทราบเฉพาะรหัสทางออกที่ไม่เป็นศูนย์ได้อย่างไร
:!<command>
สามารถใช้เพื่อรันคำสั่งในเชลล์ แต่นี่ "ใช้เวลา" terminal ของฉันและเติมด้วยstdout
คำสั่งเฉพาะที่
ฉันจะรันคำสั่งในพื้นหลังที่แจ้งให้ฉันทราบเฉพาะรหัสทางออกที่ไม่เป็นศูนย์ได้อย่างไร
คำตอบ:
:silent exec "!command"
โปรดทราบว่าเซสชันเสียงเรียกเข้าของคุณจะยังคงถูกครอบครองขณะที่คำสั่งของคุณกำลังดำเนินการ นี่เป็นเพราะธรรมชาติของ Vim คุณยังสามารถกลับไปที่เชลล์ของคุณได้โดยกด CTRL + z (เพื่อส่ง Vim ไปที่พื้นหลัง) จากนั้นกลับมา vim ด้วยคำสั่งfg
ตามปกติ
ในการทำสิ่งต่าง ๆ แบบอะซิงโครนัสลองดูที่ปลั๊กอินvim-dispatchของ Tim Pope หรือโครงการ NeoVim ที่มีการสนับสนุนพื้นเมืองสำหรับการดำเนินการคำสั่งแบบอะซิงโครนัสซึ่งคุณสามารถใช้ประโยชน์จากปลั๊กอิน NeoMake ได้อย่างง่ายดาย เวอร์ชั่นล่าสุดของ Vim ยังรองรับการทำงานแบบอะซิงโครนัส
:silent !ls
) ... t' ให้ผลผลิตที่เหมาะสมใน-0 ไม่ใช่รหัสทางออก ... ดังนั้นผมเกรงว่ามันเป็นบิตที่เกี่ยวข้องมากขึ้นกว่าเพียงแค่ใช้:silent
...
:silent exec "!ls"
หรือไม่:silent !ls
แสดงผลลัพธ์ใด ๆ เลยในเวอร์ชัน Vim ของฉัน 7.4 ด้วยแพตช์ 1-213
:silent !ls
: i.stack.imgur.com/1XvS6.png ... ฉันต้องกด^L
เพื่อแก้ไขอีกครั้ง ...
เพื่อรันคำสั่งโดยไม่ทริกเกอร์ข้อความ Enter เช่น:
กด ENTER หรือพิมพ์คำสั่งเพื่อดำเนินการต่อ
ลองตัวอย่างง่ายๆดังต่อไปนี้:
:silent !echo Hello
จากนั้นกดCtrl+ L(หรือ:redraw!
) เพื่อรีเฟรชหน้าจอเมื่อกลับไปเป็นกลุ่ม
เพื่อหลีกเลี่ยงความต้องการรีเฟรชคุณสามารถกำหนดคำสั่งที่คุณกำหนดเองเช่น:
:command! -nargs=1 Silent execute ':silent !'.<q-args> | execute ':redraw!'
ตอนนี้คุณสามารถใช้คำสั่ง Vim ใหม่เพื่อรันคำสั่ง shell (หมายเหตุ: ไม่มี!และด้วย capital S ):
:Silent ps
แหล่งที่มา: การหลีกเลี่ยงข้อความแจ้ง "Hit ENTER to Continue"
:Silent ctags -R . > /dev/null &
รันในพื้นหลัง การส่ง stdout ไปที่ / dev / null ป้องกันไม่ให้เอาต์พุตปรากฏในบัฟเฟอร์ vim
สิ่งนี้สามารถเริ่มต้นกระบวนการในพื้นหลัง:
:!slow_command_here > /tmp/output 2>&1 &
แต่เป็นกลุ่มต้องการวิธีการค้นหาเมื่อกระบวนการเสร็จสมบูรณ์และอย่างไรดังนั้นลองใช้ไฟล์มาร์กเกอร์:
:!(rm -f /tmp/finished; slow_command_here > /tmp/output 2>&1; echo "$?" > /tmp/finished) &
ตอนนี้เราสามารถขอให้กลุ่มตรวจสอบทุก ๆ ครั้งว่ากระบวนการเสร็จสมบูรณ์แล้วหรือไม่:
:augroup WaitForCompletion
:autocmd!
:autocmd CursorHold * if filereadable('/tmp/finished') | exec "augroup WaitForCompletion" | exec "au!" | exec "augroup END" | echo "Process completed with exit code ".readfile('/tmp/finished')[0] | end
:augroup END
เฮ้มันไม่สวย แต่เรียงลำดับจากผลงาน!
น่าเสียดายที่ autocmd ด้านบนไม่ทำงานจนกว่าคุณจะเลื่อนเคอร์เซอร์ และถ้าคุณต้องการเรียกใช้กระบวนการพื้นหลังมากกว่าหนึ่งครั้งคุณจะต้องเพิ่ม ID เฉพาะให้กับไฟล์เหล่านั้นและไปยังชื่อกลุ่ม autocmd
ดังนั้นหากคุณสามารถรับมือกับการพึ่งพาพิเศษคุณอาจจะดีกว่าโดยใช้โซลูชันที่ทดลองและทดสอบแล้วเช่นปลั๊กอิน vim-dispatch ที่กล่าวถึงในคำตอบอื่น
หากคุณต้องการที่จะเห็นผลลัพธ์ของกระบวนการแทนที่จะเป็นเพียงแค่รหัสออกจากนั้นแทนที่สุดท้ายecho
ข้างต้นด้วย:
silent botright pedit /tmp/output
ที่จะเปิดหน้าต่างแสดงตัวอย่าง หากต้องการใช้รายการข้อผิดพลาด quickfix แทน:
silent cget /tmp/output | copen
รายการ QuickFIX :cnext
ช่วยให้คุณสามารถนำทางไปยังข้อผิดพลาดโดยใช้ อย่างไรก็ตามcopen
เลื่อนเคอร์เซอร์ของคุณไปที่หน้าต่าง Quickfix เมื่อมันเปิดขึ้นซึ่งอาจจะแปลกใจ / น่ารำคาญ
(วิธีแก้ปัญหาสำหรับสิ่งนั้นคือการเปิดหน้าต่าง QF ด้วย:copen
เมื่อเริ่มต้นกระบวนการดังนั้นคุณจะไม่ต้องเรียกมันในตอนท้าย)
ฉันกำลังรันคำสั่งที่บล็อกไว้เล็กน้อยและฉันไม่สนใจเกี่ยวกับผลลัพธ์ สิ่งนี้สามารถได้รับการดูแลโดยเริ่มต้นกระบวนการที่แนบมาไม่ใช่กับเทอร์มินัล / อีมูเลเตอร์ แต่ไปที่ระบบและเปลี่ยนทิศทางเอาต์พุตทั้งหมดไปยัง / dev / null ตัวอย่างเช่น:
:silent exec "!(espeak 'speaking in background'&) > /dev/null"
(...&)
ทำงานในพื้นหลังและ> /dev/null
เปลี่ยนเส้นทางการส่งออกทั้งหมดไป/dev/null
(อะไร)
วงเล็บจะดักเอาท์พุทไปไว้ที่ subshell (หรืออะไรทำนองนั้น) แต่มันมีผลข้างเคียงที่ไม่ได้ติดอยู่กับเปลือกปัจจุบัน (ไม่ใช่เรื่องใหญ่)
ฉันเพิ่งรู้ว่าหากคุณเป็นจริงในการทำแผนที่คุณสามารถทำสิ่งที่ชอบ
nnoremap <silent> <leader>e :!$(espeak 'speaking in the background'&) > /dev/null
ด้านบนจะไม่แสดงผลใด ๆ ในแถบคำสั่งและจะไม่แสดงสิ่งใด ๆ ในเทอร์มินัลนอกเสียงเรียกเข้า มันจะถูกแมปไป<leader>
eซึ่ง\ eโดยค่าเริ่มต้น
(การแก้ไขอื่น - และอาจเป็นสิ่งที่ประณีตที่สุด) หนึ่งนี้จะแสดงการส่งออกของคำสั่งดังนั้นหากคุณเลือก:
ภายในแท็บใหม่:
silent exec "!(echo 'hello. I'm a process! :)') > /tmp/vim_process" | :tabedit /tmp/vim_process
ภายในแยกแนวตั้ง:
silent exec "!(echo 'hello. I'm a process :)') > /tmp/vim_process" | :vs /tmp/vim_process
ภายในแยก HORIZONTAL:
silent exec "!(echo 'hello. I'm a process :)') > /tmp/vim_process" | :sp /tmp/vim_process
... ทำสิ่งที่คุณต้องการ
หากคุณไม่สนใจรหัสออกคุณสามารถไปกับสิ่งนี้:
:call system('/usr/bin/zathura using-docker.pdf &')
v:shell_error
ตัวแปรจะบอกคุณ
ไม่แน่ใจว่าสิ่งนี้เหมาะสมกับความต้องการของคุณหรือไม่ (ไม่จัดการกระบวนการพื้นหลังในfoo &
- ไม่แน่ใจว่านั่นคือสิ่งที่คุณหมายถึงโดย"ในพื้นหลัง" ) แต่คำสั่งที่กำหนดเองสามารถนำมาใช้ใน:
fun! s:PraeceptumTacet(cmd)
silent let f = systemlist(a:cmd)
if v:shell_error
echohl Error
echom "ERROR #" . v:shell_error
echohl WarningMsg
for e in f
echom e
endfor
echohl None
endif
endfun
command! -nargs=+ PT call s:PraeceptumTacet(<q-args>)
จากนั้นใช้เป็นเช่น:
:PT ls -l
:PT foobar
ERROR #127
/bin/bash: foobar: command not found
ถ้าคุณไม่จำเป็นต้อง / ต้องการให้ข้อความแสดงข้อผิดพลาดง่าย system()
จะพอเพียงแล้วตรวจสอบและรายงานเช่นv:shell_error
echo Error!
จากวิธีใช้v: shell_error :
v:shell_error shell_error-variable
v:shell_error Result of the last shell command. When non-zero, the last
shell command had an error. When zero, there was no problem.
This only works when the shell returns the error code to Vim.
The value -1 is often used when the command could not be
executed. Read-only.
Example: >
:!mv foo bar
:if v:shell_error
: echo 'could not rename "foo" to "bar"!'
:endif
"shell_error" also works, for backwards compatibility.
foo &
...” จากข้อความ Q โดยรวมฉันตีความว่ามันเป็นอย่างใดอย่างหนึ่งหรือ อย่างใดอย่างหนึ่ง“ดำเนินการเป็นพื้นหลัง AKA คำสั่งภายนอก”หรือ“ดำเนินการเป็น _and_ คำสั่งภายนอกเป็นกระบวนการพื้นหลัง.” ฉันตอบส่วนใหญ่ขึ้นอยู่กับชื่อของคำถาม ฯลฯ - และเพิ่มความคิดเห็นใน“ ไม่แน่ใจ…” - และปล่อยไว้ที่ OP เพื่อชี้แจงหากมีหรือ
เป็นกลุ่มที่ 8 แนะนำงานสนับสนุน หนึ่งสามารถเรียกใช้คำสั่งภายนอกในพื้นหลังโดยไม่ต้องพึ่งพาปลั๊กอิน ตัวอย่างเช่นการรันเซิร์ฟเวอร์ markdown ( markserv ) ที่ตำแหน่งปัจจุบันและไม่บล็อกเซสชัน vim:
:call job_start('markserv .')
สิ่งนี้เริ่มต้นกระบวนการ markserv เป็นกระบวนการย่อยของกระบวนการ vim ปัจจุบัน pstree
คุณสามารถตรวจสอบกับ
ฉันใช้รหัสต่อไปนี้:
command! -nargs=1 Silent call SilentExec(<q-args>)
function! SilentExec(cmd)
let cmd = substitute(a:cmd, '^!', '', '')
let cmd = substitute(cmd, '%', shellescape(expand('%')), '')
call system(cmd)
endfunction
ตอนนี้คุณสามารถพิมพ์ดังต่อไปนี้
:Silent !your_command
นี้มีลักษณะเกือบจะเหมือนในตัวเป็นกลุ่มของคำสั่งยกเว้นสำหรับเงินทุนsilent !
S
มันยังช่วยให้ตัวเลือก!
เพื่อให้ดูคล้ายกันมากขึ้น การเรียกเพื่อให้system()
คำสั่งเชลล์เงียบอย่างแท้จริง: ไม่มีหน้าจอกะพริบและไม่มีการวาดซ้ำ
(และหากคุณต้องการรหัสสถานะคุณสามารถตรวจสอบv:shell_error
ตัวแปรดูวิธีใช้สำหรับข้อมูลเพิ่มเติม)
AsyncRunปลั๊กอินถ้าออกแบบมาสำหรับการนี้จะช่วยให้คุณสามารถเรียกใช้คำสั่งเชลล์ในพื้นหลังใน Vim8 / NeoVim และแสดงผลในหน้าต่าง QuickFIX
เช่นเดียวกับการเปลี่ยน!
คำสั่ง:
:AsyncRun ls -la /
คุณยังสามารถซ่อนผลลัพธ์ในหน้าต่าง quickfix ได้อย่างสมบูรณ์:
:AsyncRun -mode=3 ls -la /
เมื่องานเสร็จ AsyncRun จะแจ้งให้คุณทราบโดยผ่านตัวเลือก-post
:
:AsyncRun -post=some_vim_script ls -la /
สคริปต์กลุ่มที่กำหนดโดย-post
จะถูกดำเนินการหลังจากงานเสร็จสิ้น