Changer dynamiquement la palette d'URXVT

Changer dynamiquement la palette d'URXVT
Le 29 octobre, 2012 - 00:28 | Ulhume

L'un des avantages de gVIM par rapport à VIM/terminal est sa capacité à charger dynamique un thème de colorisation autonome. Dans un terminal, on est en effet lié à la palette qui ne peut pas être modifiée autrement qu'en passant par le fichier de ressources, et donc un redémarrage du terminal. Impossible donc de basculer de manière fluide d'un thème "light" en journée à un thème "dark" en soirée avec VIM/Terminal ? En fait non, comme souvent, il existe une solution élégante à cette problématique.

Pour quoi faire ?

Comme beaucoup j'ai commencé à utiliser VIM dans sa version graphique (gVIM). Mais n'étant pas un fanatique de menu déroulants et d'icônes, je me suis rapidement retrouvé avec un gVIM qui avait à peu prés la même tête qu'un VIM en console.

Je ne vais pas m'étendre longuement sur l'intérêt de la console. Disons en substance que cela me permet d'avoir le même système en local et en distant, ce qui dans mon métier est un atout énorme.

Il restait cependant deux points lacunaires par rapport à la version graphique : la souris et les couleurs. Le cas de la souris a été rapidement réglé dés que j'ai compris comment paramétrer VIM pour exploiter la gestion de la souris d'URxvt. Aujourd'hui mis à par un double-click un tantinet dure de la feuille, ma version console de VIM exploite la souris strictement de la même manière que sa soeur graphique.

Restait le cas des couleurs. Alors certes un terminal comme URxvt permet d'attaquer une palette de 88 couleurs et de nombreux thèmes VIM exploitent cette option. Malgré cela je me sentais bridé pour la création de mes propres thèmes, bloqué dans des choix de couleurs que je continuais à trouver limité. La vraie bonne solution était pour moi d'avoir possibilité 1/ de modifier dynamiquement la palette du terminal 2/ de pouvoir choisir strictement les couleurs que je désire dans la palette RGB classique, comme pour gVIM.

L'approche par échappement

Tout l'astuce pour résoudre mon problème tient en la capacité de nombreux terminaux à permettre la redéfinition dynamique de nombreux paramètres, dont leur palette, à travers une série de séquence d'échappement appartenant à la catégorie OSC (Operatin System Control). Ce qui suit a été testé sous URxvt mais certaines séquences fonctionnent parfaitement avec XTerm et même avec la tripotée de terminaux basés sur libvte.

Pour commencer par un exemple simple, imaginez vouloir changer la police de votre terminal à la volé en la passant en DejaVu sur 8 Pixels :

gaston$echo -ne '\\033]50;xft:DejaVu Sans Mono:size=8\\007'
Changement dynamique de la police

A partir de là, il suffit de potasser un peu la spécification des séquences XTerm pour trouver comment modifier un élément de palette, mais aussi du fond et de l'encre par défaut. Attention ce qui suit va pourrir proprement votre terminal :)

# Changement de l'encre par défaut en mauve
gaston$echo -ne '\\033]10;#FF00FF\\007'
 
# Changement du fond en bleu pétard
gaston$echo -ne '\\033]11;#0000FF\\007'
 
# Changement de la couleur numéro n°0 (le rouge) en Vert
gaston$echo -ne '\\033]4;0;#00FF00\\007'

Déjà à ce stade il est possible de définir en quelque chose de sympa les 16 couleurs de la palette de base d'un terminal en utilisant une notation classique RGB. Sympa mais pas suffisant pour obtenir un super thème sous VIM. Pas de soucis, car en réalité la dernière séquence peut aller beaucoup plus loin et définir chacune des 88 couleurs de la palette étendue. Si vous décidez donc que vos commentaires sous VIM doivent être en vert mousse (#8BAC56) il me suffit d'émettre la séquence '\\033]4;17;#8BAC56\\007' pour redéfinir la couleur d'index 17. Puis dans mon thème VIM d'utiliser l'index 17 dans mon fichier de syntax VIM (termfg=17) et le tour est joué.

Du coup les 88 couleurs d'URxvt qui peuvent sembler une limitation par rapport au 256 de XTerm, ne le sont en réalité pas si l'on définit chacune à sa convenance.

Après le mode d'initialisation de votre super palette est à votre convenance. Vous pouvez par exemple mettre les echo dans un script que vous lancez à partir de votre ~/.bashrc. Vous pouvez aussi les émettre directement dans le script de votre schéma de couleur VIM.

A noter que l'autre avantage de cette approche est qu'en redéfinissant les couleurs 17 et plus, vous conservez une compatibilité avec la palette des 16 couleurs de base ce qui est utile pour les outils qui ne permettent pas de changer leurs couleurs (htop, alsamixer, etc.).

Enfin, concernant spécifiquement VIM, il est possible de mettre en place cette technique de manière totalement automatisée. Un peu comme le plugin CSApprox, j'ai commencé un plugin qui transforme automatiquement les couleurs d'un schéma prévu pour gVIM et l'adapte en modifiant dynamiquement la palette. C'est plus pour jouer qu'autre chose mais en tout cas le "proof of concept" fonctionne.

Format de spécification de couleurs

Vous ne le trouvez pas encore suffisamment beau votre terminal maintenant qu'il est maquillé comme un camion volé ? Attendez un peu, il y a encore de quoi rigoler avec URxvt. Un truc en effet classiquement bien moche, sont les aplats de couleur lorsque l'on a une image en fond, que ce soit un pixmap custom ou le fond du burea (via inheritPixmap). Et bien figurez-vous qu'en jouant sur le format de spécification des couleurs, il est parfaitement possible d'injecter dans la palette des couleurs avec un niveau de transparence.

# on définir la couleur 17 en vert mousse avec un gentil niveau de transparence
gaston$echo -ne '\\033]4;17;rgba:8B00/AC00/5600/3000\\007'
 
# On imprime un texte avec notre couleur 17 comme fond
gaston$echo -ne '\\033[48;5;17m-----------Coucou---------------\\n'

Et voilà c'est pas zoli ? :)

Conclusion

Décidément j'aime bien ce terminal (URXvt) et cette petite manipulation le rend encore plus agréable à utiliser. Après l'exploitation de ces techniques peut aller assez loin comme définir des palettes par application, les charger/décharger à la demande, etc.

Vus : 2388
Publié par Artisan Numérique : 100