2010-04-04 16 views
7

Wenn ich verwende:%! um den Inhalt einer Datei über einen Filter laufen zu lassen und der Filter schlägt fehl (er gibt einen anderen Code als 0 zurück) und druckt eine Fehlermeldung an stderr Ich bekomme meine Datei mit dieser Fehlermeldung ersetzt. Gibt es eine Möglichkeit, vim zu sagen, die Filterung zu überspringen, wenn der Filter einen Statuscode zurückgibt, der einen Fehler anzeigt und/oder Ausgaben ignoriert, die das Filterprogramm in stderr schreibt?vim filter und stdout/stderr

Es gibt Fälle, in denen Ihre Datei durch die Ausgabe des Filters ersetzt werden soll, aber meistens ist dieses Verhalten falsch. Natürlich kann ich die Filterung nur mit einem Tastendruck rückgängig machen, aber es ist nicht optimal.

Auch ich habe ein ähnliches Problem beim Schreiben eines benutzerdefinierten vim-Skript, um die Filterung zu tun. Ich habe ein Skript, das ein Filterprogramm mit system() aufruft und die Datei im Puffer mit seiner Ausgabe ersetzt, aber es scheint keine Möglichkeit zu geben, festzustellen, ob die von system() zurückgegebenen Zeilen in stdout oder stderr geschrieben wurden . Gibt es eine Möglichkeit, sie in vim script voneinander zu unterscheiden?

Antwort

3

können Sie Python verwenden, um zwischen stdout und stderr zu unterscheiden:

python import vim, subprocess 
python b=vim.current.buffer 
python line=vim.current.range.start 
python p=subprocess.Popen(["command", "argument", ...], stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) 
python returncode=p.poll() 
python if not returncode: b.append(("STDOUT:\n"+p.stdout.read()+"\nSTDERR:\n"+p.stderr.read()).split("\n"), line) 
+0

Natürlich! Mit jeder "echten" Skriptsprache ist das überhaupt kein Problem. Daran habe ich nicht gedacht. Obwohl ich vim Skript bevorzugen würde, wenn möglich, weil ich nicht mehr Abhängigkeiten zu meinem Skript als nötig haben möchte. – ahe

+1

Ich kenne nur einen anderen Weg: benutze 'system()', leite stderr in eine temporäre Datei um (oder '/ dev/null'), speichere stdout in eine Variable und benutze' v: shell_error', um festzustellen, ob ein Befehl fehlgeschlagen ist Puffer überschreiben. Beachten Sie, dass ':!' -Filter «!» Durch den vorherigen Befehl und «%» durch den aktuellen Dateinamen ersetzen, während 'system()' dies nicht tut. – ZyX

3

:!{cmd} Führen {cmd} mit der Schale und setzt v:shell_error.

function! UndoIfShellError() 
    if v:shell_error 
     undo 
    endif 
endfuntion 

nmap <leader>filter :%!/path/to/filter<CR>:call UndoIfShellError()<CR> 
+0

Netter Trick :). Eigentlich habe ich auf ein fehlerempfindliches Pendant für die:! {Cmd} -Syntax gehofft, die ich gerade übersehen habe. Aber mehr und mehr befürchte ich, dass keine solche alternative Syntax existiert. – ahe

1

Eine Alternative wäre, den Filterbefehl wie sie modifiziert, um die Datei auf der Festplatte auszuführen:

Wenn Sie Zuordnungen passieren, um Ihren Filter zu nennen, könnten Sie so etwas wie die folgenden tun.

Zum Beispiel für gofmt (www.golang.org) Ich habe diese Zuordnungen in Ort:

map <f9> :w<CR>:silent !gofmt -w=true %<CR>:e<CR> 
imap <f9> <ESC>:w<CR>:silent !gofmt -w=true %<CR>:e<CR> 

Erläuterung: : w - Datei speichern : silent - vermeiden Drücken der Eingabetaste am Ende % - übergibt die Datei gofmt -w = true - gofmt Tells in die Datei zu schreiben zurück : e - sagt vim geändert reload-Datei

0

Dies ist, was ich am Ende tun:

function MakeItAFunction(line1, line2, args) 
    let l:results=system() " call filter via system or systemlist 
    if v:shell_error 
    "no changes were ever actually made! 
    echom "Error with etc etc" 
    echom results 
    endif 
    "process results if anything needed? 

    " delete lines but don't put in register: 
    execute a:line1.",".a:line2." normal \"_dd" 
    call append(a:line1-1, l:result) " add lines 
    call cursor(a:line1, 1) " back to starting place 
    " echom any messages 
endfunction 
command -range <command keys> MakeItAFunction(<line1>,<line2>,<q-args>) 
"           or <f-args>, etc. 

Sie können meinen vollständigen Code bei http://vim.wikia.com/wiki/Perl_compatible_regular_expressions

Es ist kompliziert, aber es funktioniert und wenn es verwendet wird, ist es ziemlich transparent und anmutig zu sehen. Hoffe das hilft in keiner Weise!