:!<command>
pode ser usado para executar um comando no shell. Mas isso "assume" meu terminal e o preenche com stdout
esse comando específico.
Como executo um comando em segundo plano que só me notifica em um código de saída diferente de zero?
:!<command>
pode ser usado para executar um comando no shell. Mas isso "assume" meu terminal e o preenche com stdout
esse comando específico.
Como executo um comando em segundo plano que só me notifica em um código de saída diferente de zero?
Respostas:
:silent exec "!command"
Observe que sua sessão vim ainda estará ocupada enquanto seu comando estiver em execução. Isso se deve à natureza síncrona do Vim. Você ainda pode voltar ao seu shell pressionando CTRL + z (para enviar o Vim para o segundo plano) e depois retomar o vim com o comando fg
normalmente.
Para fazer as coisas de forma assíncrona, dê uma olhada no plugin vim-dispatch de Tim Pope ou no projeto NeoVim, que possui suporte nativo para execução de comandos assíncronos, que você pode aproveitar facilmente usando o plugin NeoMake. A versão mais recente do Vim também oferece suporte para tarefas assíncronas.
Veja : h: silencioso
:silent !ls
) ... Ele também não 't dar saída apropriada em um-0 não código de saída ... Então eu tenho medo é um pouco mais envolvido do que apenas usando :silent
...
:silent exec "!ls"
nem :silent !ls
mostro nenhuma saída na minha versão do Vim, 7.4 com os patches 1-213.
:silent !ls
: i.stack.imgur.com/1XvS6.png ... Preciso pressionar ^L
para corrigi-lo novamente ...
Para executar um comando sem acionar a mensagem Enter, como:
Pressione ENTER ou digite o comando para continuar
tente o seguinte exemplo simples:
:silent !echo Hello
Em seguida, pressione Ctrl+ L(ou :redraw!
) para atualizar a tela quando voltar ao Vim.
Para evitar a necessidade de atualização, você pode definir seu próprio comando personalizado, como:
:command! -nargs=1 Silent execute ':silent !'.<q-args> | execute ':redraw!'
Agora, você pode usar o novo comando Vim para executar um comando shell (nota: sem ! E com S maiúsculo ):
:Silent ps
Fonte: Evitando os avisos "Pressione ENTER para continuar" no site da Vim Wikia
:Silent ctags -R . > /dev/null &
sejam executados em segundo plano. Enviar stdout para / dev / null impede que a saída apareça no buffer do vim.
Isso pode iniciar um processo em segundo plano:
:!slow_command_here > /tmp/output 2>&1 &
Mas o Vim precisa de uma maneira de descobrir quando o processo foi concluído e como, então, vamos usar um arquivo de marcador:
:!(rm -f /tmp/finished; slow_command_here > /tmp/output 2>&1; echo "$?" > /tmp/finished) &
Agora, podemos pedir ao Vim para verificar de vez em quando se o processo foi concluído:
: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
Ei, não é bonito, mas funciona!
Infelizmente, o autocmd acima não será acionado até você mover o cursor. E se você deseja executar mais de um processo em segundo plano por vez, precisará adicionar IDs exclusivos a esses arquivos e ao nome do grupo autocmd.
Portanto, se você puder lidar com uma dependência extra, é melhor usar uma solução testada e comprovada, como o plug-in vim-dispatch mencionado em outra resposta.
Se você deseja ver a saída do processo, em vez de apenas o código de saída , substitua a final echo
acima por:
silent botright pedit /tmp/output
Isso abriria a janela de visualização. Para usar a lista de erros do quickfix:
silent cget /tmp/output | copen
A lista de correções rápidas permite navegar facilmente para erros usando :cnext
. No entanto, copen
move o cursor para a janela do quickfix quando ela é aberta, o que provavelmente será surpreendente / irritante.
(Uma solução alternativa seria abrir a janela QF :copen
ao iniciar o processo inicialmente, para que você não precise chamá-lo no final.)
Eu estava executando um comando que bloqueou um pouco e realmente não me importei com a saída. Isso pode ser resolvido iniciando o processo anexado não ao terminal / emulador, mas ao sistema e redirecionando toda a saída para / dev / null. Por exemplo:
:silent exec "!(espeak 'speaking in background'&) > /dev/null"
o (...&)
executa em segundo plano e > /dev/null
redireciona toda a saída para /dev/null
(nada).
Os parênteses prendem a saída em um subshell (ou algo assim), mas tem o efeito colateral de não ser anexado ao shell atual (não é grande coisa).
Acabei de perceber que, se você estiver mapeando, pode fazer algo como
nnoremap <silent> <leader>e :!$(espeak 'speaking in the background'&) > /dev/null
O item acima não exibirá nada na barra de comando e, além disso, não exibirá nada no terminal fora do vim. Será mapeado para <leader>
e, que é \ epor padrão.
(Outra edição - e talvez a melhor). Este mostrará a saída de um comando se você escolher:
DENTRO DE UMA NOVA TAB:
silent exec "!(echo 'hello. I'm a process! :)') > /tmp/vim_process" | :tabedit /tmp/vim_process
DENTRO DE UMA DIVISÃO VERTICAL:
silent exec "!(echo 'hello. I'm a process :)') > /tmp/vim_process" | :vs /tmp/vim_process
DENTRO DE UMA FENDA HORIZONTAL:
silent exec "!(echo 'hello. I'm a process :)') > /tmp/vim_process" | :sp /tmp/vim_process
... faça o que você quiser
Se você não se importa com o código de saída, pode fazer isso:
:call system('/usr/bin/zathura using-docker.pdf &')
v:shell_error
variável informará
Não tenho certeza se isso atende às suas necessidades (não lida com processos em segundo plano como em foo &
- não tenho certeza se é isso que você quer dizer com "em segundo plano" ), mas um comando personalizado pode ser usado como em:
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>)
Então use como por exemplo:
:PT ls -l
:PT foobar
ERROR #127
/bin/bash: foobar: command not found
Se você não precisa / deseja que a mensagem de erro seja system()
suficiente, verifique v:shell_error
e relate por exemplo echo Error!
.
Na ajuda 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 &
…” . A partir do texto Q como um todo, eu o interpretei como sendo um ou outro. Ou “Executar como comando externo AKA background” ou “Executar como comando externo _e_ como processo em background” . Eu respondi principalmente com base no título de Q etc. - e adicionei um comentário sobre "Não tenho certeza ..." - e deixei para o OP esclarecer se é ou não.
O Vim 8 introduziu o suporte a trabalhos. Pode-se executar comandos externos em segundo plano sem depender de plug-ins. Por exemplo, para executar um servidor de descontos ( markserv ) no local atual e não bloquear a sessão do vim:
:call job_start('markserv .')
Isso inicia o processo markserv como um subprocesso do processo vim atual. Você pode verificar isso com pstree
.
Consulte job_start
Eu uso o seguinte código:
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
Agora você pode digitar o seguinte
:Silent !your_command
Isso parece quase com o silent !
comando interno do Vim , exceto a capital S
. Ele ainda permite um opcional !
para torná-lo ainda mais semelhante. A chamada para system()
torna o comando shell verdadeiramente silencioso: nenhuma tela pisca e não é redesenhada.
(e se você precisar de um código de status, pode verificar a v:shell_error
variável, consulte a ajuda para obter mais informações)
O plug- in AsyncRun, se projetado para isso, permite executar comandos do shell em segundo plano no Vim8 / NeoVim e exibir a saída na janela do quickfix.
Apenas como uma substituição do !
comando:
:AsyncRun ls -la /
Você também pode ocultar completamente a saída na janela do quickfix:
:AsyncRun -mode=3 ls -la /
Quando o trabalho for concluído, o AsyncRun o notificará passando uma opção -post
:
:AsyncRun -post=some_vim_script ls -la /
O script vim definido por -post
será executado após a conclusão do trabalho.