:!<command>
可用于在Shell中执行命令。但这会“接管”我的终端,并用该命令的stdout
填充它。 我如何在后台执行仅在非零退出代码时通知我的命令?
#1 楼
:silent exec "!command"
请注意,执行命令时,vim会话仍将被占用。这是由于Vim的同步特性。您仍然可以通过按CTRL + z(将Vim发送到后台)返回外壳,然后像往常一样使用命令
fg
恢复vim。要异步执行操作,请看一下Tim Pope的插件vim-dispatch或项目NeoVim具有对异步命令执行的本机支持,您可以使用插件NeoMake轻松利用它。 Vim的最新版本还支持异步任务。
请参见:h:silent
评论
这也是我看到问题时尝试的第一件事:-)但是,如果您使用输出到stdout(或stderr)的命令,它将“占据”您的Vim主窗口(try:silent!ls).. 。它也不会在非0退出代码上提供正确的输出...因此,我担心它比仅仅使用:silent ...要涉及的更多。
–马丁·图尔诺伊(Martin Tournoij)
2015年2月19日在11:07
哦对不起。在编写注释时添加了一些有关异步执行的注释。不知道如何解决退出状态问题。您可能想在Freenode上的#vim中尝试。
– OliverUv
2015年2月19日在11:11
我还要注意::silent exec“!ls”或:silent!ls都没有在我的Vim 7.4版本(带有补丁1-213)上显示任何输出。
– OliverUv
2015年2月19日在11:14
嗯,这就是我得到的:silent!ls:i.stack.imgur.com/1XvS6.png ...我需要再次按^ L来解决...
–马丁·图尔诺伊(Martin Tournoij)
15年2月19日在11:35
vim-dispatch当然看起来像是解决给定问题的方法。
– joeytwiddle
15年2月19日在11:56
#2 楼
要在不触发Enter消息的情况下执行命令,例如:按ENTER或键入命令以继续
尝试以下简单示例:
:silent !echo Hello
然后返回到Vim时,按Ctrl + L(或
:redraw!
)刷新屏幕。定义您自己的自定义命令,例如: :command! -nargs=1 Silent execute ':silent !'.<q-args> | execute ':redraw!'
来源:避免在Vim Wikia网站上出现“点击ENTER继续”提示
评论
如何获得非零退出代码的通知?
–马丁·图尔诺伊(Martin Tournoij)
2015年2月25日在16:26
这不是非零退出代码的解决方案,但是,作为补充,此Silent命令允许使用诸如:Silent ctags -R之类的命令。 > / dev / null&在后台运行。将stdout发送到/ dev / null可以防止输出出现在vim缓冲区中。
– ftvs
16年5月29日在18:02
#3 楼
快速而肮脏的解决方案(使用纯Vimscript)这可以在后台启动进程:
:!slow_command_here > /tmp/output 2>&1 &
但是Vim需要一种方法来找出过程何时完成以及如何完成,所以让我们使用标记文件: :
:!(rm -f /tmp/finished; slow_command_here > /tmp/output 2>&1; echo "$?" > /tmp/finished) &
嘿,虽然不漂亮,但是可以正常工作!
缺点
不幸的是,autocmd在您移动光标之前,以上内容不会触发。而且,如果您想一次运行多个后台进程,则需要向这些文件以及autocmd组名称添加唯一的ID。
因此,如果您可以处理额外的依赖项,使用另一个答案中提到的vim-dispatch插件等经过测试的解决方案可能会更好。
显示输出
如果要查看输出该过程,而不只是退出代码,然后将上面的最终
echo
替换为::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
这将打开预览窗口。要改用快速修复错误列表,请执行以下操作:
silent botright pedit /tmp/output
通过快速修复列表,您可以使用
:cnext
轻松导航至错误。但是,copen
打开时会将光标移到quickfix窗口中,这可能令人惊讶/烦恼。(一种解决方法是,在最初开始该过程时使用
:copen
打开QF窗口,因此您无需在结尾处调用它。)评论
这是实际上回答问题的唯一答案:“在后台执行仅通知我非零退出代码的命令”……我不知道为什么其他答案甚至全都赞成...
–马丁·图尔诺伊(Martin Tournoij)
2015年2月25日在16:19
我相信他们会投票,因为他们可以完美回答问题的标题,这就是将访问者带到此页面的原因。 “如何以静默方式执行shell命令?”常见的SE现象!访客很感激,但也许没有纪律。
– joeytwiddle
16-4-12在2:43
在理想的世界中,我们可能会有两个独立的问题:“如何以静默方式执行Shell命令?”和“如何在后台执行shell命令?”以便Google员工可以找到他们想要的东西。
– joeytwiddle
16年4月12日在2:45
#4 楼
在后台运行命令我正在运行的命令被阻塞了一段时间,而我实际上并不关心输出。可以通过启动不是附加到终端/仿真器而是附加到系统的进程并将所有输出重定向到/ dev / null来解决此问题。例如:
:silent exec "!(espeak 'speaking in background'&) > /dev/null"
(...&)
在后台运行它,而> /dev/null
将所有输出重定向到/dev/null
(什么都没有)。输出到子shell(或类似的东西)中,但是它确实具有不附加到当前shell的副作用(没什么大不了的)。映射我只是意识到,实际上,如果您正在映射它,则可以执行类似的操作
nnoremap <silent> <leader>e :!$(espeak 'speaking in the background'&) > /dev/null
上面将不显示任何内容在命令栏中,并且不会在vim之外的终端中不显示任何内容。它将被映射到
<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
...随你所愿
#5 楼
如果您不关心退出代码,可以使用以下代码::call system('/usr/bin/zathura using-docker.pdf &')
评论
如果您关心退出代码,则v:shell_error变量会告诉您
–杰罗姆·达伯特(Jerome Dalbert)
18年3月18日在22:22
#6 楼
不确定是否满足您的需求((不能像q4312079q一样处理后台进程–不确定这是否意味着您在“后台”)),但是可以使用自定义命令,例如: />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
如果不需要/不需要错误消息,那么简单的
foo &
就足够了,然后检查system()
并通过v:shell_error
进行报告。评论
这并不是在后台真正运行它。您仍然需要等待它完成。
–马丁·图尔诺伊(Martin Tournoij)
2015年2月25日在16:26
@Carpetsmoker:是的,因此我的评论“……不像foo&…那样处理后台进程”。从整个Q文本中,我将其解释为“或”。 “以外部命令AKA后台执行”或“以外部命令_and_作为后台进程执行”。我主要根据Q等标题回答-并对“不确定…”添加了评论-并留给OP来说明是或否。
– Runium
15年2月26日在20:30
#7 楼
我使用以下代码: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
Vim的内置
silent !
命令,但大写S
除外。它甚至允许使用可选的!
,使其看起来更加相似。调用system()
会使shell命令真正静音:不闪烁屏幕也不重绘。(如果需要状态码,则可以检查
v:shell_error
变量,有关更多信息,请参阅帮助)#8 楼
Vim 8引入了工作支持。无需依赖插件即可在后台运行外部命令。例如,要在当前位置运行markdown服务器(markserv)而不阻塞vim会话,请执行以下操作: 。您可以使用pstree
对此进行验证。请参见job_start
#9 楼
如果为此设计了AsyncRun插件,则它允许您在Vim8 / NeoVim中在后台运行shell命令,并在quickfix窗口中显示输出。代替
!
命令: > :AsyncRun ls -la /
您还可以将输出完全隐藏在quickfix窗口中:
:AsyncRun -mode=3 ls -la /
作业完成后,AsyncRun将通知您通过传递一个选项
-post
::AsyncRun -post=some_vim_script ls -la /
-post
定义的vim脚本将在作业完成后执行。
评论
您愿意使用+ python界面还是其他语言界面之一?@joeytwiddle是