Kabuk komutları sessizce nasıl yürütülür?


70

:!<command>Kabukta bir komut çalıştırmak için kullanılabilir. Fakat bu benim terminalimi “devraldı” ve onu stdoutbu özel komutla doldurdu .

Arka planda yalnızca sıfır olmayan bir çıkış kodunda beni bilgilendiren bir komutu nasıl uygularım?


1
+ Python arayüzünü veya diğer dil arayüzlerinden birini kullanmaya istekli misiniz?
joeytwiddle

1
@joeytwiddle Evet
OrangeTux

Yanıtlar:


52

:silent exec "!command"

Komutunuz yürütülürken vim oturumunuzun hala meşgul olacağını unutmayın. Bu Vim'in senkron doğasından kaynaklanmaktadır. CTRL + z tuşlarına basarak (arka plana Vim göndermek için) kabuğuna geri dönebilir ve daha sonra fgher zamanki komutla vim'e devam edebilirsin .

Eşzamansız işleri yapmak için, eklenti NeoMake'i kullanarak kolayca yararlanabileceğiniz Tim Papa'nın eklenti vim-dispatch veya eşzamansız komut yürütme için yerel desteği olan NeoVim projesine bakın. Vim'in en son sürümü, zaman uyumsuz görevleri de desteklemektedir.

Bakınız : h: sessiz


5
Bu aynı zamanda soruyu gördüğümde denediğim ilk şeydi :-) Ama stdout (veya stderr) komutunu veren bir komut kullanırsanız, ana Vim pencerenizi "clobber" eder (dener :silent !ls) ... 0 olmayan bir çıkış kodunun düzgün bir çıktısını vermeyin ... Korkarım ki kullanmaktan biraz daha fazlası :silent...
Martin Tournoij

Ah özür dilerim. Yorumunuzu yazarken eşzamansız yürütme hakkında bazı notlar eklendi. Çıkış durumu sorununun nasıl ele alınacağını bilmiyorum. Freenode'da #vim denemek isteyebilirsiniz.
OliverUv

Ayrıca Vim, 7.4 versiyonunda 1-213 yamaları olan herhangi bir çıktının gösterilmediğini :silent exec "!ls"ve :silent !lsgösterilmediğini de belirtmek isterim.
OliverUv

3
Hm, işte ne alacağım :silent !ls: i.stack.imgur.com/1XvS6.png ... ^LTekrar düzeltmek için basmam gerekiyor ...
Martin Tournoij

vim-sevk kesinlikle verilen soruna bir çözüm gibi görünüyor.
joeytwiddle

30

Enter mesajını tetiklemeden bir komut uygulamak için,

Devam etmek için ENTER tuşuna basın veya command yazın

aşağıdaki basit örneği deneyin:

:silent !echo Hello

Sonra Vim'e geri döndüğünde ekranı yenilemek için Ctrl+ L(veya :redraw!) düğmesine basın .

Yenileme ihtiyacını önlemek için, aşağıdakiler gibi kendi özel komutunuzu tanımlayabilirsiniz:

:command! -nargs=1 Silent execute ':silent !'.<q-args> | execute ':redraw!'

Şimdi, bir kabuk komutu çalıştırmak için yeni Vim komutunu kullanabilirsiniz (not: olmadan ! Ve büyük S ile ):

:Silent ps

Kaynak: Vim Wikia sitesinde " Devam etmek için Vur" komutunu kullanmaktan kaçınmak


1
Sıfır olmayan bir çıkış kodunda nasıl bildirim alırsınız?
Martin Tournoij

1
Sıfır olmayan çıkış koduna bir çözüm değil, buna ek olarak, bu Sessiz komutu :Silent ctags -R . > /dev/null &arka planda çalışacak gibi komutlara izin verir . Stdout komutunu / dev / null öğesine göndermek, çıkışın vim arabelleğinde görünmesini önler.
ftvs

10

Hızlı ve kirli bir çözüm (saf Vimscript'te)

Bu, arka planda bir işlemi başlatabilir:

:!slow_command_here > /tmp/output 2>&1 &

Fakat Vim'in işlemin ne zaman tamamlandığını ve nasıl bir marker dosyası kullanacağını öğrenmenin bir yoluna ihtiyacı var:

:!(rm -f /tmp/finished; slow_command_here > /tmp/output 2>&1; echo "$?" > /tmp/finished) &

Şimdi Vim'den sürecin tamamlanıp tamamlanmadığını sık sık kontrol etmesini isteyebiliriz:

: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

Hey, hoş değil, ama işe yarıyor!

Dezavantajları

Maalesef yukarıdaki autocmd, siz imleci hareket ettirene kadar tetiklemez. Bir kerede birden fazla arka plan işlemi çalıştırmak istiyorsanız, bu dosyalara ve autocmd grup adına benzersiz kimlikler eklemeniz gerekir.

Dolayısıyla, fazladan bir bağımlılığı kaldırabilirseniz, başka bir cevapta belirtilen vim-dispatch eklentisi gibi denenmiş ve test edilmiş bir çözümü kullanarak daha iyi olabilirsiniz.

Çıkış gösteriliyor

Sadece çıkış kodundan ziyade sürecin çıktısını görmek istiyorsanız , yukarıdaki final ile değiştirin :echo

silent botright pedit /tmp/output

Bu önizleme penceresini açar. Bunun yerine quickfix hata listesini kullanmak için:

silent cget /tmp/output | copen

Hızlı düzeltme listesi, hataları kullanarak kolayca gezinmenizi sağlar :cnext. Ancak copenimleci açıldığında hızlı bir şekilde pencereye götürür, bu muhtemelen şaşırtıcı / can sıkıcı olacaktır.

(Bunun için bir çözüm ile QF penceresini açmak için olacağını :copenbaşlangıçta işlemine başlarken, bu yüzden olacak değil sonunda aramak gerekir.)


2
Buradaki soruya gerçekten cevap veren tek cevap budur: "arka planda yalnızca sıfır olmayan bir çıkış kodunda beni bilgilendiren bir komut yürütün" ... diğer yanıtların neden hiç artırabildiğini bile bilmiyorum.
Martin Tournoij

2
Onları büyütdüklerine inanıyorum, çünkü ziyaretçiyi bu sayfaya getiren soru başlığını mükemmel bir şekilde yanıtlıyorlar . "Kabuk komutları sessizce nasıl yürütülür?" Ortak bir SE fenomeni! Ziyaretçiler minnettar ama disiplinli değil.
joeytwiddle

İdeal bir dünyada, muhtemelen iki ayrı soru soracağız: "Shell komutlarını sessizce nasıl yürütebilirim?" ve "Arka planda kabuk komutları nasıl çalıştırılır?" Böylece Google çalışanları aradıklarını bulabilirler.
joeytwiddle

6

Arka planda bir komut çalıştırma

Bir süreliğine engellenen bir komut çalıştırıyordum ve çıktıyı gerçekten umursamıyordum. Bu, terminale / emülatöre değil, sisteme bağlı işlemi başlatmak ve tüm çıktıyı / dev / null'a yönlendirmekle yapılabilir. Örneğin:

:silent exec "!(espeak 'speaking in background'&) > /dev/null"

(...&)arka planda çalışır ve > /dev/nulltüm çıkış yönlendirir /dev/null(hiçbir şey).

Parantez, çıktıyı bir alt kabuğa (ya da onun gibi bir şeye) hapseder, ancak mevcut kabuğa bağlı olmamanın (büyük bir şey değil) yan etkisi vardır.

Eşleme ile arka planda sessizce bir komut çalıştırma

Sadece eğer fark vardır , aslında, onu haritalama, şöyle bir şey yapabilirsiniz

nnoremap <silent> <leader>e :!$(espeak 'speaking in the background'&) > /dev/null

Yukarıdakiler komut çubuğunda hiçbir şey göstermeyecek ve ek olarak vim dışındaki terminalde hiçbir şey göstermeyecektir. Eşlenir <leader> eolan \ evarsayılan olarak.

Bir komutu çalıştırma, çıktısını yakalama, içeriğini görüntüleme

(Başka bir düzenleme - ve belki de en iyisi). Bu seferki olacak görüntülemek çıktı bunu seçerseniz bir komut:


YENİ BİR SEKME İÇİ:

silent exec "!(echo 'hello. I'm a process! :)') > /tmp/vim_process" | :tabedit /tmp/vim_process

DİKEY BİR ÇARPAN İÇİ:

silent exec "!(echo 'hello. I'm a process :)') > /tmp/vim_process" | :vs /tmp/vim_process

YATAY YAYIN İÇERİĞİ:

silent exec "!(echo 'hello. I'm a process :)') > /tmp/vim_process" | :sp /tmp/vim_process

... ne istersen onu yap


5

Çıkış kodunu umursamıyorsanız, bununla devam edebilirsiniz:

:call system('/usr/bin/zathura using-docker.pdf &')

1
Çıkış kodunu önemsiyorsanız, v:shell_errordeğişken size söyleyecektir
Jerome Dalbert

4

Bunun ihtiyaçlarınızı karşılayıp karşılamadığından emin değilsiniz (arka plan işlemlerinde olduğu gibi işlem yapmaz foo & - “arka planda” derken bunun ne anlama geldiğinden emin değilsiniz ), ancak özel bir komut aşağıdaki gibi kullanılabilir:

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>)

Ardından, örneğin:

:PT ls -l
:PT foobar
ERROR #127
/bin/bash: foobar: command not found

Basit bir işlemin system()yapabileceği bir hata mesajına ihtiyacınız yoksa / istemiyorsanız, v:shell_errorörneğin kontrol edin ve rapor verin echo Error!.

Gönderen yardım 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.

Bu gerçekten arka planda çalışan değil; Hala bitirmesini beklemelisin.
Martin Tournoij

@Carpetsmoker: Evet, bu yüzden benim yorumum “…… gibi arka plan işlemlerini gerçekleştirmiyor foo & . Q metninden bir bütün olarak onu ya da diye yorumladım. Ya “dış komut AKA arka plan olarak çalıştır” veya “arka plan işlemi olarak dış komut _and_ olarak yürütün.” . Ağırlıklı olarak Q vb. Başlığına dayanarak cevap verdim - ve “Emin değilim…” üzerine bir yorum ekledim .
Runium

3

Vim 8 iş desteği sundu. Biri, eklentilere güvenmeden arka planda harici komutu çalıştırabilir. Örneğin, geçerli konumda bir markdown sunucusu ( markserv ) çalıştırmak ve vim oturumunu engellememek için:

:call job_start('markserv .')

Bu, mevcut vim işleminin bir alt süreci olarak markserv işlemini başlatır. İle bunu doğrulayabilirsiniz pstree.

Job_start'ı görün


2

Aşağıdaki kodu kullanıyorum:

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

Şimdi aşağıdakileri yazabilirsiniz

:Silent !your_command

Bu silent !, sermaye hariç, neredeyse Vim'in yerleşik emri gibi görünüyor S. İsteğe bağlı !olarak daha da benzer görünmesini sağlar. system()Kabuk komutunu tamamen susturmak için yapılan çağrı : ekran yanıp sönmez ve yeniden çizilmez.

(ve bir durum koduna ihtiyacınız olursa, v:shell_errordeğişkeni kontrol edebilirsiniz , daha fazla bilgi için yardıma bakın)


1

AsyncRun bunun için tasarlanmış eğer eklenti, bu Vim8 / NeoVim arka planda kabuk komutları çalıştırın ve QuickFix pencerede görüntü çıkışı sağlar.

Sadece !komutun yerine :

:AsyncRun ls -la /

Çıktıyı tamamen quickfix penceresinde gizleyebilirsiniz:

:AsyncRun -mode=3 ls -la /

İş bittiğinde, AsyncRun bir seçeneği ileterek sizi bilgilendirecektir -post:

:AsyncRun -post=some_vim_script   ls -la /

Tarafından tanımlanan vim betiği -postiş bittikten sonra çalıştırılacak.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.