2010-04-04 4 views
7

Lorsque j'utilise:%! pour exécuter le contenu d'un fichier à travers un filtre et le filtre échoue (il renvoie un autre code que 0) et imprime un message d'erreur à stderr Je reçois mon fichier remplacé par ce message d'erreur. Existe-t-il un moyen d'indiquer à vim d'ignorer le filtrage si le filtre renvoie un code d'état qui indique une erreur et/ou ignore la sortie que le programme de filtre écrit sur stderr?Filtres vim et stdout/stderr

Il y a des cas où vous voulez que votre fichier soit remplacé par la sortie du filtre mais le plus souvent, ce comportement est incorrect. Bien sûr, je peux tout simplement annuler le filtrage avec une seule touche, mais ce n'est pas optimal.

J'ai également un problème similaire lors de l'écriture d'un script vim personnalisé pour effectuer le filtrage. J'ai un script qui appelle un programme de filtrage avec system() et remplace le fichier dans le buffer par sa sortie mais il ne semble pas y avoir un moyen de détecter si les lignes retournées par system() ont été écrites sur stdout ou sur stderr . Y a-t-il un moyen de les différencier dans un script vim?

Répondre

3

Vous pouvez utiliser Python pour distinguer entre stdout et stderr:

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

Bien sûr! Avec chaque "vrai" langage de script, ce n'est pas un problème du tout. N'a pas pensé à ça. Bien que je préférerais vim script si possible parce que je ne veux pas avoir plus de dépendances sur mon script que nécessaire. – ahe

+1

Je ne connais qu'une autre façon: utiliser 'system()', rediriger stderr vers un fichier temporaire (ou '/ dev/null'), sauvegarder stdout dans une variable et utiliser' v: shell_error' pour déterminer si une commande a échoué avant tampon d'écrasement. Notez que les filtres ':!' Remplacent «!» Par la commande précédente et «%» par le nom de fichier actuel, alors que 'system()' ne le fait pas. – ZyX

3

:!{cmd}{cmd} avec la Exécute shell et définit v:shell_error.

Si vous arrivez à mettre en place les correspondances pour appeler vos filtres, vous pouvez faire quelque chose comme ce qui suit:

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

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

Belle astuce :). En fait j'espérais un pendentif sensible à l'erreur pour la syntaxe:! {Cmd} que j'ai juste oubliée. Mais de plus en plus je crains qu'il n'existe pas de telle syntaxe alternative. – ahe

1

Une alternative serait d'exécuter la commande de filtre tel qu'il modifie le fichier sur le disque.

Par exemple, pour gofmt (www.golang.org) J'ai ces correspondances en place:

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

Explication: : w - fichier de sauvegarde : silencieux - éviter d'appuyer entrer à la fin % - passe le fichier à gofmt -w = true - tells gofmt d'écrire dans le fichier : e - dit vim pour reload fichier modifié

0

C'est ce que je fini par faire:

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. 

Vous pouvez voir mon code complet à http://vim.wikia.com/wiki/Perl_compatible_regular_expressions

Il est compliqué, mais ça fonctionne et quand il est utilisé, il est assez transparent et gracieux. J'espère que cela aide de quelque façon!