LBSNDD : le blog sans nom de dimitri

Aller au contenu | Aller au menu | Aller à la recherche

vendredi 26 janvier 2007

Se déplacer de mot en mot

J'ai beau utiliser Vim depuis 5 ans je découvre toujours des nouvelles fonctionnalités/approches/astuces qui me conforte dans mon choix. L'astuce du jour[1] est presque banale, mais je ne connaissais pas ces raccourcis clavier.

Pour passer d'un mot à l'autre, dans Vim comme dans Vi, ce sont les touches w (vers le mot suivant) et b (vers le mot précédent). Évidemment, seulement en mode commande.

J'ai découvert par hasard[2] que l'on pouvait faire de même avec Ctrl combiné aux flèches droite et gauche. Aussi bien en mode commande qu'en insertion. L'est pas belle la vie !

Notes

[1] Qui ne signifie pas « une astuce par jour », pas que je n'aurais pas assez de matière...

[2] En fait, je viens de comprendre pourquoi je ne l'ai pas trouvé avant. Depuis toujours j'utilise la touche Ctrl combinée aux flèches pour changer de bureau virtuel. Aujourd'hui, nouveau window manager (ou plutôt desktop shell), nouvelles habitudes. Rââhh, Enlightenment c'est beau...

vendredi 4 août 2006

Le Vi(m)seur ou mettre en surbrillance la ligne et la colonne courante

Vim 7 uniquement !

J'ai parfois pesté contre Vim (bah oui, nul logiciel n'est parfait, mais les imperfections sont parfois liées aux usages) lorsque, faisant une recherche de mot (/mot) je ne retrouvais pas mon curseur au milieu d'un tas de texte. Voici donc comment le repérer plus facilement.

Les options cursorline et cursorcolumn, lorqu'elles sont activées, mettent en surbrillance respectivement la ligne et la colonne courante. Pour supprimer cette surbrillance il suffit d'activer les options inverses que sont nocursorline et nocursorcolumn.

Voici une macro pour activer et désactiver les deux options en même temps :

map _ :set cursorline! cursorcolumn!<bar>set cursorline? cursorcolumn?<CR><CR>

Je vous renvoie à un futur billet sur la permutation des options que j'écrirai bien un jour.

Cependant il est possible de modifier les schémas de coloration de ces deux options pour que la mise en valeur soit vraiment immanquables

highlight CursorLine term=reverse cterm=reverse
highlight CursorColumn term=reverse cterm=reverse

Après cela vous pouvez activer cette surbrillance originale par la touche underscore '_'.

Prochain épisode... heu, c'est déjà pas mal là, non ? Si vous en voulez plus essayez Emacs !

jeudi 3 août 2006

Afficher la taille du fichier courant

Et zou, encore un gadget pour notre barre de status, l'affichage de la taille du fichier courant.

Là encore une fonction interne de Vim nous donne cette information : getfsize renvoie la taille du fichier dont le nom est passé en paramètre.

Bien sûr, pas question de spécifier le nom du fichier en dur ou à la volée, c'est Vim qui va nous le donner. Le motif % contient cette information. Cependant elle n'est pas utilisable directement par la fonction getfsize, elle est prévue pour les macros commandes.

On doit donc utiliser la fonction expand pour transformer le mot-clé en une chaîne de caractères. Un petit essai avant de modifier notre .vimrc :

:echo getfsize(expand('%'))

Attention, si votre fichier n'existe pas, c'est-à-dire, un nouveau fichier pas encore sauvé, la fonction getfsize renvoie -1. D'ailleurs, la valeur que nous allons afficher est celle du fichier sauvé. Elle n'est pas mise à jour en temps réel au fur et à mesure que vous tapez.

Voici donc notre statusline après cet ultime ajout :

set statusline=%a\ %t%1*%m%*%10l/%2*%L%*%6c%V/%2*%{strlen(getline('.'))}%*%10{getfsize(expand('%'))}o

Prochain épisode, on active le viseur !

mercredi 2 août 2006

Calculer le nombre de caractères dans une ligne

Lorsque nous avons personnalisé la ligne de status il nous manquait l'information du nombre de caractères par lignes. Il n'existe pas de motif pour statusline donnant cette information. Cependant, il y a possibilité d'appeler une fonction Vim et d'en afficher le résultat.

En fait nous utilisons deux fonctions. La première, strlen(), tout comme en C, donne la taille d'une chaîne de caractères. Il nous faut donc donner à cette fonction une chaîne composée de toute la ligne courante.

Cette chaîne est obtenue grâce à la fonction getline() appelée avec le paramètre '.'. Rappelez-vous, le point sert à désigner la ligne courante.

Avant d'aller plus loin vous pouvez tester que je ne vous dis pas de bétises. Tapez cette commande pour afficher le nombre de caractères de la ligne courante :

:echo strlen(getline('.'))

Nous pouvons maintenant compléter notre statusline comme ceci :

set statusline=%a\ %t%1*%m%*%10l/%2*%L%*%6c%V/%2*%{strlen(getline('.'))}%*

L'ajout a été fait à la fin. La syntaxe pour afficher le résultat d'une fonction consiste à encadrer cette dernière de %{ et }. Pour les autres options je vous renvoie au billet précédent.

Prochain épisode, afficher la taille du fichier dans la statusline.

mardi 1 août 2006

Utiliser la ligne de status

Dans Vim vous avez sans doute remarqué l'avant dernière ligne de la fenêtre (du terminal), celle juste au dessus de celle utilisée pour saisir des commandes. Quand vous ouvrez un fichier, elle vous informe du nom de ce fichier, du nombre de lignes. Ensuite n'apparaissent que la position courante du curseur (ligne, colonne et colonne virtuelle).

Dans aucun de ces deux cas ce n'est la statusline dont il s'agit. Cette dernière n'apparaît par défaut que lorsque vous avez plus d'un buffer ouvert dans la même fenêtre. Par exemple, lorsque vous ouvrez l'aide en ligne. Tapez :help statusline.

J'ai ressenti le besoin de faire apparaître cette barre en permanence afin d'y afficher les informations dont j'ai besoin. Pour cela ajoutez l'option suivante dans votre .vimrc :

set laststatus=2

Nous allons ensuite remplir cette statusline. Je ne vais pas vous détailler tous les paramètres utilisables, vous les trouverez dans l'aide en ligne. Voici ceux que j'utilise :

set statusline=%a\ %t%1*%m%*%10l/%2*%L%*%6c%V

Allons-y pour les détails :

  • %a si vous avez ouvert plusieurs fichiers, affiche le numéro de buffer sous la forme (1 of 4) pour le premier des quatre fichiers ;
  • %t pour le nom du fichier sans le chemin ;
  • %1* ce qui suit est affiché suivant le schéma de coloration User1 jusqu'au prochain motif %* (idem pour %2* et User2) ;
  • %m affiche [+] lorsque le fichier est modifié et [-] s'il n'est pas modifiable ;
  • %10l le numéro de ligne courante occupant au minimum la place de 10 caractères (c'est juste pour la mise en forme) ;
  • %L le nombre de lignes du fichier ;
  • %6c le numéro de la colonne courante sur 6 caractères ;
  • %V le numéro de colonne virtuelle (tient compte de la place réellement occupée par les multi-caractères comme la tabulation, l'espace insécable, etc.)

Attention, les espaces doivent être protégés par un slash. Vous pouvez inclure du texte pour plus de clarté. Par exemple : Ligne\ %l\ sur\ %L.

Les deux schémas de coloration utilisés ponctuellement sont définis ainsi :

highlight User1 cterm=inverse,bold ctermfg=red
highlight User2 ctermbg=blue ctermfg=red

Par défaut la statusline est affichée en couleurs inverses, ce qui donne une barre gris clair lorsque l'on utilise un terminal sur fond noir comme moi. Trop clair pour mes yeux. J'ai donc redéfini les deux schémas de coloration par défaut. Le deuxième est utilisé lorsque vous avez deux buffers dans la même fenêtre, pour le buffer inactif.

highlight StatusLine term=bold cterm=bold ctermbg=4
highlight StatusLineNC term=none cterm=none ctermfg=4

Prochain épisode, nous verrons comment afficher le nombre de colonnes, c'est-à-dire, le nombre de caractères de la ligne courante.

lundi 17 juillet 2006

Vim contre la canicule

Peu de nouveautés sur ce blog qui semble, comme son auteur, souffrir de la canicule... Allez, juste une petite astuce Vim pour patienter... jusqu'à la prochaine (non, je n'oublie pas que j'avais l'intention de vous présenter plein de jeux en montant ce blog...).

Vous voulez supprimer toutes les lignes d'un fichier contenant un motif (par exemple le mot canicule avec ou sans majuscule au début) :

:g/[Cc]anicule/d

La difficulté (qui m'a fait chercher pendant cinq bonnes minutes) vient ici du fait que c'est le caractère g qui symbolise l'intégralité du fichier, et non % comme c'est le cas par ailleurs (je ne sais pas pourquoi et il fait trop chaud pour chercher). À part cela, ça fonctionne comme avec Sed (et tout le monde sait que Sed c'est bien). Le motif (généralement une expression régulière) est délimité par des slashes /. La commande d (comme delete) efface toute la ligne et non seulement le motif.

Si vous vouliez plutôt effacer le seul motif, il faut faire une substitution par rien. C'est-à-dire, utiliser la commande s comme cela :

:%s/[Cc]anicule//g

Ou encore, pour les plus optimistes :

:%s/[Cc]anicule/fraicheur/g

Mais là je dérive car le motif de la commande d'effacement de ligne n'a pas la même signification que celui de la subsitution. Pour l'effacement on parle d'étiquette. En effet, /canicule/ signifie « toute ligne où se trouve le mot "canicule" ». On pourrait très bien remplacer cela par une plage de lignes. Ici on efface toutes les lignes de la 10 à la 50.

:10,50d

Autre exemple : on efface la ligne courante et les 10 suivantes (soit 11 au total).

:.,+10d

Je vous avais prévenu que c'était de la petite astuce, pas de quoi entretenir ma réputation de fou dangereux.

vendredi 16 juin 2006

Agir sur la ligne courante et les voisines

Que ceux qui trouvent ce titre bizarre regardent la catégorie avant de s'affoler. Une évolution future de ce blog pourrait être l'ajout de petites icônes par catégories. Une évolution de plus sur la liste des choses à faire...

Aujourd'hui rien d'extraordinaire dans cette astuce Vim qui puisse entretenir ma réputation de fou dangereux. Ce sera pour une prochaine fois...

J'ai eu à chercher comment désigner la ligne courante (celle sur laquelle se trouve le curseur) dans Vim. C'est notamment utile dans les macros. Par exemple, je devais réaliser une macro qui déplace la ligne courante et la suivante dans un autre fichier.

La ligne courante est désigné par un point. Les lignes suivantes par une quantité positive (par exemple +4 pour les quatre lignes suivantes) et une valeur négative pour les lignes qui précèdent. Ainsi, si vous voulez appliquer une commande sur la ligne courante et les 4 suivantes, elle doit commencer par :.,+4. La virgule sépare les deux éléments de la plage de valeurs.

La commande pour déplacer deux lignes dans un autre fichier est donc :

:.,+1w >> fichier<CR>2D
  • w écrit dans un fichier
  • >> précise que l'on ajoute des lignes à un fichier existant (sans ce symbole le fichier serait écrasé)
  • <CR> on simule la validation de la commande (pression sur la touche Entrée)
  • 2D on efface deux lignes à partir de la position courante

jeudi 20 avril 2006

Incrémenter lors d'un copier-coller

Petite astuce brute de décoffrage que je viens de mettre en place et qu'il me faudra intégrer dans la prochaine version de spip.vim.

Je voulais pouvoir, d'une simple touche (donc avec macro derrière) insérer un tag <imgXX|center> à l'endroit où se trouve le curseur. Sachant que XX est le numéro de l'image et que je voudrais en prime que le XX inséré soit celui de l'image qui précède dans le fichier incrémenté de 1.

Attention, c'est vraiment du brut. J'utilise la fonction d'incrémentation [Ctrl] + A (notez le pendant [Ctrl] + X pour décrémenter). Pour l'utiliser, placez-vous en mode commande, à proximité (avant) d'une valeur numérique et pressez [Ctrl] + A. Le curseur se déplace automatiquement sur la prochaine valeur et incrémente de 1. Notez que si vous tapez 10[Ctrl] + A, vous incrémentez de 10. S'il y a un tiret devant la valeur, cela sera interprété comme un nombre négatif.

Voici maintenant mes macros (modes commande et insertion) :

map <F8> mz?<img<CR>Y'zP0<C-A>
imap <F8> <ESC>mz?<img<CR>Y'zP0<C-A>o

Détails :

  • mz place un marqueur nommé z à la ligne courante (utile pour y revenir) ;
  • ?<img<CR> recherche le motif « <img » en remontant le fichier ;
  • Y copie toute la ligne ;
  • 'z on revient sur la ligne marquée z ;
  • 0 on se place en début de ligne ;
  • <C-A> on incrémente la valeur numérique la plus proche (celle que l'on veut évidemment).

mercredi 19 avril 2006

Wikipédia dans ton éditeur de texte favori

Où comment arriver à ce que les gens pensent que Vim est plus un OS qu'un éditeur de texte (à non, la place est déjà prise...).

Vous connaissiez peut-être le greffon OOoWikipedia qui permet de rechercher un mot dans Wikipédia, l'encyclopédie libre, depuis OpenOffice.org. Voici comment faire avec Vim.

Cet exemple, assez simple, est également très modulable. En effet, il s'agit d'exécuter une commande externe avec pour argument le mot sous le curseur. Donc, vous pouvez choisir votre navigateur, mais également votre moteur de recherche. Les possibilités s'étendent donc à l'infini (enfin, presque...). Mais limitons-nous à un cas particulier : interroger Wikipédia et afficher le résultat dans Lynx (le site est à l'image du navigateur, très sobre). Oui, je choisis Lynx, car je trouve très classe de pouvoir ouvrir Wikipédia dans la même fenêtre que le texte que je suis en train de taper dans Vim (non, je ne suis pas faché avec ma souris !).

Et hop, la commande :

map <C-W> :!lynx http://fr.wikipedia.org/wiki/<cword><CR><CR>

Ici j'ai choisi de mapper la combinaison [Ctrl] + W sur cette commande. Détails :

  • ! introduit l'appel à une commande externe à Vim
  • <cword> mot-clé désignant le mot situé sous le curseur (je l'ai cherché longtemps, merci à G de me l'avoir souflé)
  • <CR> retour chariot ; deux sont nécessaires pour valider.

La commande précédemment citée est utilisable en mode commande. Voici celle pour le mode insertion.

imap <C-W> <ESC>:!lynx http://fr.wikipedia.org/wiki/<cword><CR><CR>i

La seule différence : on passe en mode commande au début (<ESC>) et on revient en mode insertion à la fin, ni vu ni connu (i).

Une piste de réflexion pour la suite : comment rechercher un groupe de mots (évidemment séparés par des espaces), à priori sélectionnés en mode visuel ?

Un début de troll (?) : on pourrait aisément se servir de Vim comme gestionnaire de fichiers et appeler des commandes externes suivant l'extension (mouais) ou le type Mime. On pourrait aussi afficher la météo de la ville dont le nom se trouve sous le curseur.

samedi 15 avril 2006

Template pour un header

Bonne résolution, je me remets à coder. Arriverais-je à pondre quelque chose de sympa ? Bien sûr que je vous montrerai !

Partir de zéro est toujours difficile. Le fameux syndrome de la page l'écran blanc (ou terminal noir dans mon cas...). Commençons par choisir de bons outils (tout en restant relatif et non trollesque) : Vim pour saisir le code en C.

J'ai vite remarqué que mes headers (fichiers inclus au moyen de la directive #include) avaient tous la même forme de base que voici (ici pour le fichier time.h) :

#ifndef __TIME_H__
#define __TIME_H__
 
#endif 

Vim propose un système de templates ou modèles. Lorsque vous créez un nouveau fichier, il peut ainsi être pré-remplit. Pour cela on utilise le système des autocommandes. Ajoutez cette ligne dans votre fichier .vimrc

au BufNewFile *.h 0r~/.vim/templates/h.h

au est l'abbréviation d'autocmd. On définit ici une commande à exécuter automatiquement lorsque l'événement BufNewFile se produit pour un fichier dont le nom correspondant au motif *.h. Ici, la commande 0r~/.vim/templates/h.h place le curseur au début de la ligne (0) puis lit et copie (r) le fichier ~/.vim/templates/h.h. C'est donc dans ce fichier sobrement nommé h.h (appelez-le comme vous voulez, mais gardez quand même l'extension pour la coloration syntaxique) que l'on va inscrire notre squelette.

Cependant nous n'avons ici qu'un contenu statique, c'est-à-dire que le fichier template est copié dans le nouveau fichier et c'est tout. Or, on aimerait bien, dans le cas des fichiers headers (et c'est d'ailleurs indispensable), pouvoir utiliser le nom du fichier pour nommer la constante qui nous sert à limiter à une l'inclusion dudit fichier. En gros, je voudrais, lorsque je crée toto.h, avoir automatiquement la constante __TOTO_H__ dans mon fichier.

Voici donc le fichier modèle h.h

#ifndef pipo
#define pipo
 
#endif 

On y inscrit un mot quelconque à l'endroit où devra se trouver le nom définitif de la constante. Puis, on complète l'autocommande :

au BufNewFile *.h 0r~/.vim/templates/h.h|exe "%s/pipo/__".substitute(toupper(expand("%")),'\.',"_","")."__/"

Ne partez pas tout de suite, je vous explique !

Le pipe | permet d'enchainer plusieurs commandes. Après avoir recopié le contenu du modèle nous exécutons la commande ci-dessus (tout ce qu'il y a après exe). Cette commande est constituée d'une substitution sur tout le fichier (%s/ancien motif/nouveau motif/). Nous remplaçons donc pipo par une chaîne commençant et finissant par __. Au milieu sera inscrit le résultat des appels imbriqués de trois fonctions.

  • % représente le nom du nouveau fichier.
  • expand("%") est nécessaire pour lire le contenu de la variable %.
  • toupper(str) convertit la chaîne str en majuscules.
  • substitute(str, motif, new, flag) remplace motif par new dans la chaîne str. Ici, on remplace le point (attention, le point est un caractère spécial, il faut le déspécialiser avec '\.') par un underscore.

Ceci devrait vous permettre de faire vos propres modèles interactifs !

jeudi 2 mars 2006

Copier des lignes d'un fichier vers un autre

La situation : j'avais deux Vim ouverts (un en root, l'autre nom). Dans le premier (où j'ai un fichier A ouvert) je voulais copier trois lignes d'un fichier ouvert (appelons-le B) seulement dans le second. Insérer un fichier quelconque se fait par la commande :r fichier. Mais je n'ai pas trouvé comment insérer seulement quelques lignes et non tout le fichier.

Il y a bien la solution d'ouvrir le fichier B dans le Vim où A est déjà ouvert. Mais j'aurais bien aimé une solution plus directe.

Finalement j'ai créé un pipe, un fichier particulier dans lequel je peux écrire des données, et le fait de lire le fichier ultérieurement le vide de son contenu. En gros, j'écris un truc, je le lis une fois, je voie les données que j'ai écrite, je le lis une deuxième fois, il n'y a plus rien. On appelle aussi cela un tuyau (traduction de pipe), ça rentre d'un côté et ça sort de l'autre.

Donc, je crée mon pipe (sachant qu'il pourra me resservir ultérieurement) :

mkfifo ~/tuyau

Puis, dans le Vim où B est ouvert, je sélectionne les lignes à copier (V en mode commande pour passer en mode visuel suivi des flèches pour étendre la zone). Ensuite, j'écris cette sélection dans mon tuyau :

:'<,'>w >> ~/tuyau

La commande w (pour write) écrit du contenu dans un fichier. Le double chevron >> indique que l'on ajoute le contenu à un fichier déjà existant. Le marqueur '<,'> symbolise la sélection visuelle. Il est automatiquement inséré par Vim.

Ensuite, vous allez dans le Vim ouvert sur le fichier A puis vous inséré le contenu du tuyau :

:r /home/d/tuyau

Certes, cette manipulation manque certainement d'élégance, voire même d'utilité. Mais je trouve que le mécanisme des tuyaux est un outil trop peu utilisé.

Cependant, si quelqu'un connait une solution plus simple pour lire une plage de lignes d'un fichier sans l'ouvrir, je suis preneur.

Mise à jour 6 mars

sed c'est bien ! La preuve :

:r !sed -n '3,5p' B

Mais je ne désespère pas de trouver encore plus élégant...

jeudi 16 février 2006

Utiliser les marqueurs

On aimerait parfois pouvoir définir une zone de manière totalement arbitraire dans un fichier texte, et cela sans se soucier des numéros de lignes[1]. Pour cela, dans Vim, on peut placer des marqueurs.

Placer le marqueur c (où c est un caractère pris dans [a-Z] soit une lettre, minuscule ou majuscule[2]) sur la ligne courante :

mc

Se positionner sur la ligne marquée c :

'c

Exemple d'utilisation, effacer toutes les lignes se trouvant entre la position courante et la ligne marquée "a" :

d'a

Notes

[1] Notez que pour afficher les numéros de ligne il faut taper :set number et pour les masquer :set nonumber.

[2] Bien sûr la casse est importante. Ainsi, si vous définissez une marqueur "a", vous ne pourrez le retrouver en cherchant "A".

lundi 23 janvier 2006

Déplacer le curseur dans le vide

On aimerait bien parfois pouvoir déplacer le curseur là où il n'y a aucun caractère. Par exemple, lors d'une sélection rectangulaire faite avec Ctrl + V, si la dernière ligne est plus courte que certaines lignes intermédiaires, on ne peut tracer le rectangle jusqu'au bout. Par exemple, ici, en débutant la sélection dans le coin supérieur gauche, on ne peut pas atteindre le coin opposé car il ne contient pas de caractères (la solution ici serait de partir du bas, mais c'est juste un exemple).

En lisant la doc de Vim j'ai trouvé cette commande qui résout le problème[1] :

:set virtualedit=all

Alors on peut tranquillement sélectionner et aller où bon nous semble !

Dans la doc, cette commande est mentionnée pour éditer facilement des tableaux. Effectivement, plus besoin de rajouter des espaces ou des tabulations à la main pour se rendre dans une colonne précédée de plusieurs colonnes vides. Vim ajoute automatiquement ce qu'il faut si vous tapez du texte dans une zone de vide.

Pour quitter ce mode de déplacement virtuel, exécutez :

:set virtualedit=

Évidemment, si vous utilisez souvent cette technique, vous aurez intérêt à mapper la commande sur un raccourci.

Notes

[1] En fait, on s'aperçoit bien vite qu'il n'y a aucun problème dans Vim, seulement plein de solutions.

lundi 16 janvier 2006

Éditer plusieurs fichiers

Pour ouvrir plusieurs fichiers dans Vim, il suffit de préciser leurs noms sur la ligne de commande, ainsi :

vim un deux trois

On passe de l'un à l'autre avec :next (ou :n), :prev (ou :N), :last et :first.

Si vous n'avez pas sauvé vos modifications avant de passer à un autre fichier, Vim vous rappelle à l'ordre. Vous devez donc, soit rajouter un point d'exclamation à la fin de la commande pour ignorer les modifications (et les perdre), soit écrire le fichier avant (:w). Cette dernière option peut être automatisée en rajoutant dans votre .vimrc la ligne :

:set autowrite

Vous pouvez également redéfinir la liste des fichiers ouverts, c'est-à-dire, remplacer ceux actuellement ouverts par d'autres, et cela, sans fermer puis réouvrir Vim. Il suffit de taper :

:args quatre cinq six

Enfin, pour ajouter des fichiers à ceux déjà ouverts, sans fermer ceux existants :

:arge quatre cinq six

lundi 9 janvier 2006

Les astuces de maître G

G aspire à devenir un maître Vim. D'ailleurs voici une compilation d'astuces qu'il avait griffonées sur un bout de papier.

Quelques « killer tips » pour Vim

J'avoue qu'il se débrouille pas mal...