:!<command>
może być użyty do wykonania polecenia w powłoce. Ale to „przejmuje” mój terminal i wypełnia go stdout
tym konkretnym poleceniem.
Jak wykonać polecenie w tle, które powiadamia mnie tylko o niezerowym kodzie wyjścia?
:!<command>
może być użyty do wykonania polecenia w powłoce. Ale to „przejmuje” mój terminal i wypełnia go stdout
tym konkretnym poleceniem.
Jak wykonać polecenie w tle, które powiadamia mnie tylko o niezerowym kodzie wyjścia?
Odpowiedzi:
:silent exec "!command"
Zauważ, że twoja sesja vim nadal będzie zajęta podczas wykonywania polecenia. Wynika to z synchronicznej natury Vima. Nadal możesz wrócić do powłoki, naciskając CTRL + Z (aby wysłać Vima do tła), a następnie wznowić vim za pomocą polecenia, fg
jak zwykle.
Aby zrobić wszystko asynchronicznie, spójrz na wtyczkę Tima Pope'a vim-dispatch lub projekt NeoVim, który ma natywne wsparcie dla wykonywania poleceń asynchronicznych, które możesz łatwo wykorzystać za pomocą wtyczki NeoMake. Najnowsza wersja Vima obsługuje także zadania asynchroniczne.
Zobacz : h: cichy
:silent !ls
) ... nie daje prawidłowego wyniku dla kodu wyjścia innego niż 0 ... Więc obawiam się, że jest to trochę bardziej zaangażowane niż tylko użycie :silent
...
:silent exec "!ls"
nie :silent !ls
pokazuję żadnych wyników w mojej wersji Vima, 7.4 z łatkami 1-213.
:silent !ls
: i.stack.imgur.com/1XvS6.png ... Muszę nacisnąć, ^L
aby to naprawić ponownie ...
Aby wykonać polecenie bez wyzwalania komunikatu Enter, na przykład:
Naciśnij ENTER lub wpisz polecenie, aby kontynuować
spróbuj następującego prostego przykładu:
:silent !echo Hello
Następnie naciśnij Ctrl+ L(lub :redraw!
), aby odświeżyć ekran po powrocie do Vima.
Aby uniknąć potrzeby odświeżania, możesz zdefiniować własne niestandardowe polecenie, takie jak:
:command! -nargs=1 Silent execute ':silent !'.<q-args> | execute ':redraw!'
Teraz możesz użyć nowego polecenia Vima, aby uruchomić polecenie powłoki (uwaga: bez ! I dużymi literami S ):
:Silent ps
Źródło: Unikanie monitów „Hit ENTER, by kontynuować” na stronie Vim Wikia
:Silent ctags -R . > /dev/null &
na uruchamianie poleceń w tle. Wysłanie standardowego wyjścia do / dev / null zapobiega wyświetlaniu danych wyjściowych w buforze vim.
Może to uruchomić proces w tle:
:!slow_command_here > /tmp/output 2>&1 &
Ale Vim potrzebuje sposobu, aby dowiedzieć się, kiedy proces się zakończy i jak, więc użyjmy pliku znaczników:
:!(rm -f /tmp/finished; slow_command_here > /tmp/output 2>&1; echo "$?" > /tmp/finished) &
Teraz możemy prosić Vima, aby sprawdzał co jakiś czas, czy proces się zakończył:
: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
Hej, to nie jest ładne, ale to trochę działa!
Niestety powyższy autocmd nie uruchomi się, dopóki nie przesuniesz kursora. A jeśli chcesz uruchomić więcej niż jeden proces w tle, musisz dodać unikalne identyfikatory do tych plików i do nazwy grupy autocmd.
Jeśli więc poradzisz sobie z dodatkową zależnością, lepiej byłoby użyć sprawdzonego rozwiązania, takiego jak wtyczka vim-dispatch wspomniana w innej odpowiedzi.
Jeśli chcesz zobaczyć wynik procesu, a nie tylko kod zakończenia , zamień ostatni echo
z powyższych na:
silent botright pedit /tmp/output
To otworzy okno podglądu. Aby zamiast tego użyć listy błędów szybkiej poprawki:
silent cget /tmp/output | copen
Lista poprawek pozwala łatwo nawigować do błędów za pomocą :cnext
. Jednak copen
przesuwa kursor do okna szybkiego dostępu, gdy zostanie otwarte, co prawdopodobnie będzie zaskakujące / denerwujące.
(Obejściem tego problemu byłoby otwarcie okna QF :copen
przy początkowym uruchomieniu procesu, więc nie trzeba będzie wywoływać go na końcu.)
Uruchomiłem polecenie, które zablokowało się na chwilę, i tak naprawdę nie obchodziło mnie wyjście. Można temu zaradzić, uruchamiając proces podłączony nie do terminala / emulatora, lecz do systemu i przekierowując wszystkie dane wyjściowe do / dev / null. Na przykład:
:silent exec "!(espeak 'speaking in background'&) > /dev/null"
(...&)
uruchamia go w tle i > /dev/null
przekierowuje wszystkie dane wyjściowe do /dev/null
(nic).
Nawias przechwytuje dane wyjściowe do podpowłoki (lub czegoś w tym rodzaju), ale ma taki efekt uboczny, że nie jest dołączony do bieżącej powłoki (nic wielkiego).
Właśnie zdałem sobie sprawę, że jeśli są w rzeczywistości, przyporządkowując je, można zrobić coś takiego
nnoremap <silent> <leader>e :!$(espeak 'speaking in the background'&) > /dev/null
Powyższe nie wyświetli nic na pasku poleceń i dodatkowo nie wyświetli niczego w terminalu poza vimem. Zostanie on zamapowany <leader>
e, co jest \ edomyślnie.
(Kolejna edycja - i może najładniejsza). Ten będzie wyświetlany na wyjście komendy jeśli więc wybrać:
WEWNĄTRZ NOWEJ ZAKŁADKI:
silent exec "!(echo 'hello. I'm a process! :)') > /tmp/vim_process" | :tabedit /tmp/vim_process
WEWNĄTRZ PIONOWEGO ROZDZIELENIA:
silent exec "!(echo 'hello. I'm a process :)') > /tmp/vim_process" | :vs /tmp/vim_process
WEWNĄTRZ HORYZONTALNEGO ROZDZIELENIA:
silent exec "!(echo 'hello. I'm a process :)') > /tmp/vim_process" | :sp /tmp/vim_process
... rób co chcesz
Jeśli nie obchodzi Cię kod wyjścia, możesz przejść z tym:
:call system('/usr/bin/zathura using-docker.pdf &')
v:shell_error
zmienna powie ci
Nie jestem pewien, czy odpowiada to twoim potrzebom (nie obsługuje procesów w tle jak w foo &
- nie jestem pewien, czy to właśnie rozumiesz przez „w tle” ), ale niestandardowe polecenie może być użyte jak w:
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>)
Następnie użyj jako np .:
:PT ls -l
:PT foobar
ERROR #127
/bin/bash: foobar: command not found
Jeśli nie potrzebujesz / nie chcesz, aby komunikat o błędzie system()
wystarczył, wystarczy sprawdzić v:shell_error
i zgłoś np echo Error!
.
Z pomocy 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 &
…” . Z całego tekstu Q zinterpretowałem go jako albo. Albo „Wykonaj jako zewnętrzne polecenie AKA w tle” lub „Wykonaj jako zewnętrzne polecenie _ i_ jako proces w tle” . Odpowiedziałem głównie na podstawie tytułu Q itp. - dodałem komentarz do „Nie jestem pewien…” - i zostawiłem OP, aby wyjaśnić, czy któryś lub.
Vim 8 wprowadził obsługę miejsc pracy. Można uruchamiać zewnętrzne polecenia w tle, nie polegając na wtyczkach. Na przykład, aby uruchomić serwer Markdown ( markserv ) w bieżącej lokalizacji i nie blokować sesji vim:
:call job_start('markserv .')
To uruchamia proces markserv jako podproces bieżącego procesu vim. Możesz to zweryfikować za pomocą pstree
.
Zobacz job_start
Używam następującego kodu:
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
Teraz możesz wpisać następujące
:Silent !your_command
Wygląda to prawie jak wbudowane silent !
polecenie Vima , z wyjątkiem stolicy S
. Pozwala nawet na opcjonalne, !
aby wyglądał jeszcze bardziej podobnie. Wezwanie do system()
tego, aby polecenie powłoki było naprawdę ciche: żaden ekran nie miga i nie przerysowuje.
(a jeśli kiedykolwiek potrzebujesz kodu stanu, możesz sprawdzić v:shell_error
zmienną, zobacz pomoc, aby uzyskać więcej informacji)
AsyncRun wtyczki jeśli przeznaczone do tego, że pozwala na uruchomienie poleceń powłoki w tle w Vim8 / NeoVim i wyświetla dane wyjściowe w quickfix okna.
Podobnie jak zamiana !
polecenia:
:AsyncRun ls -la /
Możesz również całkowicie ukryć dane wyjściowe w oknie szybkiej poprawki:
:AsyncRun -mode=3 ls -la /
Po zakończeniu zadania AsyncRun powiadomi Cię, przekazując opcję -post
:
:AsyncRun -post=some_vim_script ls -la /
Zdefiniowany przez skrypt vim -post
zostanie wykonany po zakończeniu zadania.