Bien évidemment, VIM connaît déjà les fichiers CSS. Votre code sera coloriés et vous disposez de
l'auto-complètement des propriétés ET de leurs valeurs par Control-x
Control-o. Mais cet éditeur permet de faire tellement plus pour nous simplifier la
vie qu'il serait dommage de ne pas pousser tout cela un peu plus loin...
Faire ses courses
Avant de commencer à personnaliser, voyons un peu ce qu'offre l'écosystème VIM concernant
les feuilles de style.
-
Pour gagner un peu de temps, vous pouvez utiliser l'incontournable Snipmate pour définir des portions
de code utilisées de manière récurrente.
-
Par défaut, VIM comprend la syntaxe CSS 2.0. Pour monter d'un cran, vous devrez installer
un plugin comme VIM CSS3 Syntax
qui est plutôt complet. Un autre plugin sans doute plus léger, Better CSS Syntax for VIM.
C'est celui que j'utilise. En revanche, cela va upgrader la syntaxe (colorisation), mais pas l'auto-complètement.
-
vim css color va quant à lui
générer dynamiquement le rendu visuel des couleurs que vous
saisissez. Ainsi, sous gVim, #FF0000 apparaîtra en rouge, #00FF00 en vert, etc. Attention
cependant, cela peut vite devenir lourdingue avec des fichiers CSS fleuves ;-). Une version
alternative à ce plugin est Color Highlight qui
lui fonctionne avec tous les types de fichiers. Il suffit de tapper LEADER
cC pour activer/désactiver la colorisation. Et cerise sur le gâteau, il fonctionne
aussi avec Vim en mode terminal (aux approximation prés évidemment).
Configuration d'un plugin pour le type de fichier CSS
Bon tout ceci est bien beau, mais comment aller un peu plus loin et ajouter sa touche
perso là-dedans.
Comme vous le savez peut-être déjà, VIM dispose d'un mécanisme bien pratique permettant de
déclarer un script qui se lancera uniquement à l'ouverture d'un type de fichier donné. Ce
genre de script est à ranger dans le dossier ~/.vim/ftplugin/.
Pour que ceci fonctionne, il faut que vous ayez Proprement configuré
vim avec la ligne suivante dans votre ~/.vimrc
filetype plugin indent on
Définition des mots-clefs
Première chose qui agace, la sélection d'un sélecteur sous le curseur ne prend
pas le # ou le .. La sélection d'un mot en VIM, consiste à
taper la commande viw (v passe en sélection visuelle,
et iw pour Inner Word). Un raccourcis connu de cette sélection
consiste à double-cliquer sur le mot.
Le concept de "mot" en VIM, est régit par le réglage iskeyword. Ce réglage
contient tous les caractères qui définissent un mot. Nous allons donc y ajouter
les caractères -, # et .. Pour cela, nous allons créer
notre fichier ~/.vim/ftplugin/css.vim
setlocal iskeyword+=.,-,#
Notez l'usage de setlocal au lieu du classique set qui
permet d'appliquer le réglage uniquement sur le buffer en cours.
Ensuite le += qui permet non pas d'écraser ce que contient déjà le
réglage mais juste d'y ajouter des choses. Et enfin les 3 caractères séparés
par des virgules.
Une fois le fichier sauvegardé, il vous suffit de retourner sur le fichier CSS
et de forcer sa relecture (commande e!) pour que le
ftplugin/css.vim soit lu et la variable définie pour le buffer. Maintenant si
vous double-cliquez sur un sélecteur, il doit être sélectionné en entier.
Contracter - Décontracter
En bon développeur Java de base, lorsque je voyais des fichiers CSS arriver avec toutes
les propriétés d'un sélecteur sur une seule ligne, je hurlais au scandale. Avec le temps
je me suis rendu compte que c'était finalement bien pratique comme notation, sous réserve
de pouvoir facilement développeur une ligne puis la re-compresser.
/* version compressée */
#mon-selecteur { border:1px solid red; background-color:green }
/* version décompressée */
#mon-selecteur {
border:1px solid red;
background-color:green
}
Nous allons donc créer deux mappings permettant d'effectuer ces opérations. D'abord la
compression :
map <buffer> Œ /}<CR>V?{<CR>J:let @/=""
le choix de Œ (aka Shift-œ) est très personnel. C'est la touche au dessus
du Tab qui ne me sert pas à grand chose en mode "normal".
La commande map permet de définir un mapping, c'est à dire la correspondance
entre une série de touches (ici œ) et un série de commandes. Vous pouvez
voir cela comme une macro car vous pourriez aussi bien taper tout ce qui suit après le
œ à la main.
map s'applique au mode "normal" de VIM. C'est à dire que la touche
œ reste disponible en mode "insertion" (ouf ! ;-).
silent demande à VIM de ne pas afficher chaque séquence composant la macro.
Enfin buffer indique à VIM que ce mapping doit être local au buffer en cours.
Cette macro ne fonctionnera donc que dans un fichier CSS.
Maintenant voyons la macro à proprement parler. /} demande à VIM de chercher
(/) l'accolade qui suit le curseur. Le CR indique un retours
chariot, comme vous le feriez au clavier.
La commande V passe en mode "sélection visuel par ligne". La commande
?{ fonctionne comme /} mais à l'envers. C'est à dire que VIM va
chercher la première accolade ouvrant qui se trouve avant le curseur. Comme on est en
mode visuel, cela revient à sélectionner toutes les lignes entre les deux accolades,
celles-ci comprises.
La commande J va fusionner les lignes de la sélection et tout mettre donc sur
une seule. J a en plus le bon goût de compresser les
espaces de sorte à n'en laisser qu'un seul entre chaque fusion. Ainsi nous compressions
les éventuelles indentations.
Pour finir, la commande :let @/="" affecte une chaine vide au registre de
recherche /. Ce n'est utile que si vous avez activé la colorisation de la
recherche par set hlsearch.
Pour la décompression de la ligne, le travail est un peu plus simple.
map <buffer> œ V:s/\\v[{;]\\s*/\\0\\r<CR>V%=:let @/=""
La commande V passe en mode visuel et sélectionne du coup la ligne à
décompresser. Ensuite une simple commande de remplacement pour rajouter des retours
chariot après les ; et les {. Petites astuces, le \\v
permet de contraindre VIM à ne pas utiliser son mode "magique" pour les expressions
régulières, adoptant ainsi une syntaxe plus classique et plus simple (à mon goût). Enfin
\\0 renvoie ce qui a été trouvé, soit ; ou { selon les
cas.
Pour terminer, V%=. Vous l'aurez maintenant compris, le V passe en
sélection par ligne. La commande % permet de sauter d'une accolade à l'autre.
Comme le traitement précédent s'achève sur l'accolade finale, ça va sélectionner le bloc
de propriétés décompressées. Enfin le = permet de ré-indenter le bloc de code.
Le mapping se termine ici aussi sur un let @/="" pour vider le registre de
recherche.
C'est toujours assez impressionnant de voir le volume de texte nécessaire pour décrire
une simple série de commandes VIM :-).
Gérer les "vendor-prefixes"
Si vous manipulez régulièrement des feuilles de styles, je ne vais pas présenter les
-moz-machin-chose et autre joyeusetés qui les polluent régulièrement. Vous
savez déjà que c'est un petit enfer à gérer car on se retrouve à décrire 10 fois le même
comportement, une fois par navigateur et parfois par version de navigateur.
Pour les vendor prefixes qui correspondent à des propriétés CSS 3.0 (box-shadow,
linear-gradient, etc.), il existe un petit outil bien pratique, cssprefixer, qui permet de
n'avoir QUE le CSS3 à saisir, cette moulinette se chargeant de compléter avec tout le
reste. Magique et bien moins casse-figure que des outils en javascript
comme prefixfree.
CssPrefixer a cependant deux soucis. Le premier est qu'il n'aime pas qu'il y ait déjà
des vendor prefixes avant d'opérer. Le second est qu'il ne bosse que sur des fichiers
css et nom sur des portions.
Nous allons commencer par un petit mapping pour supprimer mes -moz-machin-chose.
map <buffer> - /}<CR>V?{:g/\\v-(moz\\|webkit\\|o)-/d<CR>
Cette fois le mapping est associé à la touche - (pour "supprimer les
préfixes"). Le début est le même que pour la compression. La différence ici est la
commande :g qui au lieu de substituer va appliquer une commande à toutes les
lignes qui vont être trouvées. Ici la commande est d pour "supprimer". Ce
mapping va donc, curseur placé dans un bloc de propriétés contenant des vendor prefixes, les
supprimer sans pitié.
Maintenant pour le mapping qui va faire appel à cssprefixer :
map <buffer> + -:call writefile(split(@*,"\\n"),"/tmp/css-source")<CR>gv!cssprefixer /tmp/css-source<CR>
Bon c'est du lourd, petite explication :-)
Commençons par la commande - qui n'est autre que notre précédent mapping de
suppression de vendor prefixes. On aurait pu faire un seul mapping mais il est pratique
de pouvoir "nettoyer" ainsi les blocs des préfixes parasites, ne serait-ce pour y voir
clair.
Suit la commande :call writefile(split(@*,"\\n"),"/tmp/css-source"). C'est la
fameuse création de fichier (writefile). Les données de ce fichier sont
issues du registre *, celui de la sélection. @* renvoie le contenu
de ce registre (comme @/ vu plus haut). Quelle sélection me direz-vous ? Et
bien celle crée par le mapping - pardi :-)
Ensuite nous faisons appel à la commande gv qui rend à nouveau active cette
fameuse dernière sélection (très pratique !!). Ensuite nous appelons la commande
cssprefixer avec le fichier temporaire en paramètre. Le bang !
utilisé sur une sélection, permet de remplacer la dite sélection par le texte renvoyé
par la commande. Le tour est donc joué.
Conclusion
Vous l'aurez compris, le thème "CSS" de cet article est avant tout un prétexte pour
présenter ce que l'on peut faire avec VIM. Tout ce qui se trouve ici peut être appliqué
à n'importe quel type de fichier pour fluidifier au mieux votre workflow. De même toute
les commandes encapsulées dans mappings peuvent être utilisées individuellement pour
votre édition quotidienne.
Maintenant, je m'arrête un peu avant l'indigestion, mais il y aurait encore pas mal de
chose à dire. Il est ainsi possible de modifier l'auto-complètement de VIM juste pour le
CSS de sorte à déclencher sur une propriété *-color: l'affichage d'un
sélecteur de couleur. Il est aussi possible de connecter VIM et firefox de sorte à ce
qu'en pressant F5 dans une feuille de style, cela recharge juste cette
feuille dans le navigateur. Si cela vous intéresse je pourrais vous en parler une
prochaine fois.