:!<command>可用于在Shell中执行命令。但这会“接管”我的终端,并用该命令的stdout填充它。

我如何在后台执行仅在非零退出代码时通知我的命令?

评论

您愿意使用+ python界面还是其他语言界面之一?

@joeytwiddle是

#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 楼

不确定是否满足您的需求((不能像q4​​312079q一样处理后台进程–不确定这是否意味着您在“后台”)),但是可以使用自定义命令,例如: />
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​​脚本将在作业完成后执行。