L'autocomplétion C/C++ sous vim

Décembre 2016


Auto-complétion sous ViM






Ce tutoriel s'adresse aux personnes qui utilisent Vim sous windows ou Linux. Ici, je vais plutôt orienter le tutoriel pour les personnes sous Linux.

Introduction


L'auto-complétion est quelque chose de bien connu sous linux puisqu'on l'utilise régulièrement, typiquement dans une console. Toutefois, la seule auto-complétion que propose Vim ne tient pas compte de la sémantique du langage dans lequel on code.

En effet quand on appuie sur Ctrl N (ou Ctrl P) lorsqu'on est en train de taper un mot, Vim cherche dans le fichier un mot qui commence par les mêmes lettres. Malheureusement, le mot proposé n'a pas forcément de sens, car une telle auto-complétion ne tient pas compte de ce que symbolise le mot. Ainsi Vim sera par exemple amené à proposer un "mot" qui correspond à un type là ou une méthode est attendue.
class plop(){
  protected:
   int plopons;
  public:
   plop(){}
   void plopez(){}
};

int main(){
  plop p;
  p. // <-- Ctrl P proposera successivement : plopez, plop... alors que c'est forcément plopons
  return 0;
}

Pour que l'aspect "sémantique" soit pris en compte, on va utilisé un plugin vim basé sur ctags. Ctags permet de "référencer" certains symboles (types, fonctions, classes) pour différents langages, dont le C++.

Lorsque ctags examine une arborescence de fichiers source, celui-ci crée un fichier (appelé tags) qui référence chacun des symboles qui y figurent.

Installation


On commence par installer ctags. Par exemple, sous debian ou une distribution basée sur debian (ubuntu, xandros...) :
sudo aptitude update
sudo aptitude safe-upgrade
sudo aptitude install exuberant-ctags

On récupère également le plugin Vim d'auto-complétion


On va mettre tout ce qui concerne l'auto-complétion dans ~/.vim :
mkdir -p ~/.vim/tags
mv omnicpp*zip ~/.vim
cd ~/.vim
unzip omnicpp*zip
cd -

Ctags est capable d'examiner sans problème les headers des librairies QT, OpenGL, SDL. Toutefois pour la STL, il faut récupérer des headers "simplifiés" ICI

On décompresse l'archive et on crée les tags de la STL :
tar xjvf cpp_src.tar.bz2
ctags -R --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ cpp_src && mv tags ~/.vim/tags/stl

À présent, on génère les tags pour les librairies installées (à adapter si les librairies sont installées ailleurs). Par exemple pour les librairies OpenGL, SDL et QT, il suffit de taper les trois commandes suivantes :
ctags -R --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ /usr/include/GL/  && mv tags ~/.vim/tags/gl

ctags -R --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ /usr/include/SDL/ && mv tags ~/.vim/tags/sdl

ctags -R --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ /usr/include/qt4/ && mv tags ~/.vim/tags/qt4

Configuration


À présent, il faut dire à vim de charger le plugin et les différents fichiers de tags. Pour cela, il suffit de rajouter à la fin du fichier ~/.vimrc les lignes suivantes :
" prérequis tags
set nocp
filetype plugin on

" configure tags - add additional tags here or comment out not-used ones
set tags+=~/.vim/tags/stl
set tags+=~/.vim/tags/gl
set tags+=~/.vim/tags/sdl
set tags+=~/.vim/tags/qt4

" build tags of your own project with CTRL+F12
"map <C-F12> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<CR>
noremap <F12> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<cr>
inoremap <F12> <Esc>:!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<cr>

" OmniCppComplete
let OmniCpp_NamespaceSearch = 1
let OmniCpp_GlobalScopeSearch = 1
let OmniCpp_ShowAccess = 1
let OmniCpp_MayCompleteDot = 1
let OmniCpp_MayCompleteArrow = 1
let OmniCpp_MayCompleteScope = 1
let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD"]

" automatically open and close the popup menu / preview window
au CursorMovedI,InsertLeave * if pumvisible() == 0|silent! pclose|endif
set completeopt=menuone,menu,longest,preview

Si seuls certains fichiers tags ont été générés, commenter les autres en rajoutant le caractère " en début de ligne. Par exemple si on n'a pas généré ~/.vim/tags/gl et ~/.vim/tags/sdl :
set tags+=~/.vim/tags/stl
"set tags+=~/.vim/tags/gl
"set tags+=~/.vim/tags/sdl
set tags+=~/.vim/tags/qt4

Il ne reste plus qu'à sauver ce fichier et (re)lancer vim afin que celui-ci tienne compte des modifications apportées à ~/.vimrc.

Utilisation


Tout ce qui a été taggué au préalable (c'est-à-dire dans ce tutoriel les tags de la STL, de QT, de SDL, et d'OpenGL) est déjà accessible dans l'auto complétion. Il suffit d'appuyer sur ctrl p ou ctrl n. Une fois que la liste apparaît, on peut utiliser les flèches pour mettre en surbrillance la bonne proposition et appuyer sur entrée.

Toutefois, ce n'est pas complètement terminé. Il faut (re)générer les tags des symboles (variables, fonctions, types...) spécifiques au projet que l'on développe. Pour cela, il faudra encore une fois générer un fichier de tags. Et bien entendu, il faudra rafraîchir ce fichier à chaque fois que l'on ajoutera, supprimera, ou modifiera un symbole du projet afin que celui-ci soit à jour.

Comme c'est assez fréquent, il est recommandé de mapper une touche du clavier pour déclencher une passe de ctags. Dans l'exemple de fichier ~/.vimrc que j'ai donné, ceci est assuré par la touche F12.

Liens


http://vim.wikia.com/wiki/C++_code_completion
http://www.vim.org/scripts/script.php?script_id=1520
http://www.vim.org/scripts/script.php?script_id=2358

A voir également :

Ce document intitulé «  L'autocomplétion C/C++ sous vim  » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.