J'ai souvent des commandes à exécuter lorsque je développe, comme par exemple :

#php symfony phpunit:unit path/to/test/file.php

Jusqu'à récemment, j'avais ajouté la ligne suivante à mon .vimrc pour ne pas avoir à sortir de VIM pour exécuter ce type de commande :

nnoremap <F12> :!php symfony phpunit:unit % 2>&1 \| more<CR> 

Ainsi, en appuyant sur la touche F12 de mon clavier, je déclenchais l'exécution du fichier de tests en cours d'édition.

Cette solution fonctionne, mais à quelques inconvénients induit par le fait que le résultat de la commande n'est pas affiché dans une fenêtre de VIM :

  1. Il n'est pas possible de conserver ou éditer les résultats de la commande.
  2. Si plusieurs tests ne passent pas, la sortie de la commande peut être très longue.

Bref, à l'usage, ce n'est pas le plus pratique.

La solution consiste donc à injecter le résultat de la commande dans un buffer afin de l'avoir dans une fenêtre et ainsi disposer de l'ensemble des commandes de VIM pour le manipuler.

Sur la base de cette astuce, j'ai donc ajouté à mon .vimrc le code suivant :

let s:_ = ''

function! s:ExecuteInShell(command, bang)
let _ = a:bang != '' ? s:_ : a:command == '' ? '' : join(map(split(a:command), 'expand(v:val)'))

if (_ != '')
let s:_ = _
let bufnr = bufnr('%')
let winnr = bufwinnr('^' . _ . '$')
silent! execute winnr < 0 ? 'new ' . fnameescape(_) : winnr . 'wincmd w'
setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile nowrap number
silent! :%d
let message = 'Execute ' . _ . '...'
call append(0, message)
echo message
silent! redraw
silent! execute 'silent! %!'. _
silent! execute 'resize ' . line('$')
silent! execute 'au BufUnload <buffer> execute bufwinnr(' . bufnr . ') . ''wincmd w'''
silent! execute 'nnoremap <silent> <buffer> <LocalLeader>r :call <SID>ExecuteInShell(''' . _ . ''', '''')<CR>'
silent! execute 'nnoremap <silent> <buffer> <LocalLeader>g :execute bufwinnr(' . bufnr . ') . ''wincmd w''<CR>'
endif
endfunction

command! -complete=shellcmd -nargs=* -bang Shell call s:ExecuteInShell(<q-args>, '<bang>')

La commande suivante me permet donc maintenant d'exécuter la commande de mon choix et d'en obtenir le résultat dans une fenêtre :

:Shell php symfony phpunit:unit %

Cerise sur le gâteau, s'il existe déjà une fenêtre de résultat pour cette commande, elle sera réutilisée, afin de ne pas multiplier inutilement les fenêtres de résultat.

Et enfin, il est possible d'exécuter à nouveau la commande à partir de la fenêtre de résultat en tapant <localleader>r en mode normal, ou bien à l'aide de la commande :Shell!.

Et comme le code évolue rapidement, à tel point que je suis en train de me dire qu'en faire une extension serait intéressant, je vous conseille d'aller consulter mon .vimrc.