Edit dans dired/occured = awesome

Voici des exemples qui font que je ne pourrais pas me passer d’Emacs tant il me facilite la vie. (Attention, certaines des fonctionnalités que je vais utiliser ne marchent qu’avec Emacs > 24.)

dired mode

Mise en place des exemples

Dans une console, tapez les commandes

mkdir -p /tmp/testEmacs{1..2} && cd /tmp/testEmacs1
for i in {01..10};do dd if=/dev/urandom count=$((RANDOM%10+1)) bs=1024 | base64 > fic$i;done
touch /tmp/testEmacs2/fic{{01..10},{03..05}.bck}

qui vont créer dix fichiers contenant du texte aléatoire dans le dossier /tmp/testEmacs1 et des fichiers dont certains possèdent une sauvegarde.

Dans Emacs, en tapant C-x f /tmp/testEmacs1 on se trouve dans le dossier en mode Dired.

Le mode édition ou wdired mode

Renommer les gros fichiers

Le but ici va être de renommer les fichiers de taille supérieur à 10000, pour par exemple vérifier plus tard leur contenu, effectuer des remplacements à l’intérieur des fichiers, ou juste pour l’exemple en fait…

Dans un buffer en mode dired, il est possible de passer en mode édition avec C-x C-q (en fait on passe en wdired-mode (pour Writable Dired)). Cela permet entre autres choses de renommer les fichiers ou changer leur permission.

Pour marquer nos fichiers, il est plus simple de les trier par taille. Pour cela un petit C-u s nous permet de spécifier comment trier les fichiers. En ajoutant S aux options du ls qui s’affichent, on a donc les plus gros fichiers en premiers.

En mode édition (C-x C-q donc), on se met à la fin du premier fichier, C-spc, on descend jusqu’au fichier voulu, on insère un rectangle avec C-x r t .aVerifier et les fichiers sont renommés. Il ne reste plus qu’à valider avec un C-c C-c.

Remplacer les .bck

Pour ce deuxième exemple (C-x f /tmp/testEmacs2), on a un certain nombre de fichiers qui possède une sauvegarde (un fichier .bck). On veut les changer : le fichier ficXY deviendra ficXY.bck et inversement.

Pour ça, je propose la macro suivante :

  • C-x C-q on passe en mode édition
  • F3 début d’enregistrement de la macro
  • C-s .bck pour chercher la prochaine sauvegarde
  • C-p .bck pour renommer le fichier sans extension
  • C-n C-u BCKSPC pour renommer la sauvegarde
  • F4 pour terminer la macro
  • M-0 F4 pour exécuter la macro sur les autres fichiers
  • C-c C-c pour valider

Le .bck ne nous plait pas et on veut renommer en .save ?

  • C-x C-q on passe en mode édition
  • M-< on remonte au début du fichier
  • C-M-% .bck$ .save pour modifier l’extension .bck en .save
  • ! pour renommer tous les fichiers
  • C-c C-c pour valider

occur mode

(C’est cette partie qui nécessite un Emacs récent.)

Présentation

Vu que je n’ai pas encore parlé d’occur, je fais une rapide présentation :

M-s o lance la commande occur et demande une regexp. Elle affiche dans un buffer *Occur* les lignes qui contiennent la regexp. Un argument permet de définir le contexte (comme grep -C2 par exemple).

multi-occur, respectivement multi-occur-in-matching-buffers, permet de montrer les lignes dans les buffers que l’on a renseigné un par un, resp. par une regexp (utilisez . pour tous les buffers donc). Pour faire pareil avec les buffers marqués dans la liste des buffers (C-x C-b), il existe Buffer-menu-multi-occur.

Dans la fenêtre qui s’ouvre, on a le nombre de concordances avec le nom du buffer. Si on clique sur la ligne, on va dans le buffer d’origine.

C’est donc pratique pour par exemple avoir un index des fonctions d’un fichier (M-s o function), lister tous les endroits où l’on a une adresse http (M-s o http), etc.

Le mode édition ou occur-edit mode

À partir de la version 24, un appui sur e perment de passer en mode Occur-Edit. Dans ce mode, les changements dans le buffer sont aussi appliqués dans le buffer d’origine. C’est un bon moyen plus visuel pour faire du remplacement sélectif.

Par exemple, dans un buffer, on a les lignes suivantes :

[...]
variable 1
valeur: chose 2
[...]
variable x
valeur: chose y
[...]
variable 3
valeur: chose 4
[...]
variable x
valeur: chose y
[...]
variable 4
valeur: chose 4
[...]

Et on veut remettre la valeur correspondant à la variable sauf dans le cas des variables x.

Bien entendu, il est possible de faire ça en utilisant des regexps/macro/fonctions lisp. Mais il y a aussi moins « prise de tête ».

Pour notre problème, M-- M-1 M-s o valeur permet d’afficher les lignes contenant « valeur » et celle d’avant.

En appuyant sur e on passe en mode édition, et il est facile de changer uniquement les lignes qu’il faut (comme on le ferait dans le buffer d’origine).

Pour sortir du mode édition, un C-c C-c, puis q pour quitter le mode occur.

Si l’on veut supprimer « chose » et garder uniquement le numéro (pas quand c’est chose y donc) :

  • M-s o valeur: chose pour afficher les bonnes lignes
  • C-x o pour passer dans le buffer *occur*
  • e pour passer en mode édition
  • M-x flush-lines chose y pour supprimer du buffer *occur* les lignes que l’on ne veut pas changer
  • M-% chose SPC ENTER ENTER ! pour supprimer tous les « chose﹏ »
  • C-c C-c puis q pour sortir du mode étition et quitter occur.

Le buffer ressemble maintenant à :

[...]
variable 1
valeur: 1
[...]
variable x
valeur: chose y
[...]
variable 3
valeur: 3
[...]
variable x
valeur: chose y
[...]
variable 4
valeur:  4
[...]

Autre exemple :

variable 1
valeur: bépo
[...]
variable 2
valeur: auie
[...]
variable 3
valeur: êàyx
[...]
variable 4
valeur: vdlj
[...]
variable 5
valeur: tsrn
[...]

et on veut décaler les valeurs (variable 2 aura pour valeur bépo, etc.).

Pour cela, M-s o valeur: suivi de e pour passer en mode occur-edit. Puis on kill bépo et on se place au début de auie.

On est prêt pour notre macro :

  • F3
  • M-d, on kill le mot (ou C-k si plusieurs mots)
  • C-y M-y on colle le précédent1
  • C-x C-x pour revenir où on était (au début du mot)
  • C-n pour passer à la ligne suivante
  • F4

Alors oui, on peut se passer d’occur-edit en faisant un C-s valeur: SPC ENTER à la place de C-n. Mais souvent, il y a un valeur: dans les [...] que je ne veux pas changer ; plutôt que de faire du F4 au coup par coup (ou de me rendre compte du changement non voulu trop tard), il est plus simple, je trouve, de supprimer la ligne dans *occur*, puis d’appliquer la macro avec un M-0 F4.

À lire

Footnotes:

1

J’aurais pu faire l’inverse : coller le premier, puis killer le second. Mais visiblement, certaines personnes, qui utilisent pourtant souvent Emacs, n’ont pas pris la peine de faire le tuto (C-h t) et ne connaissent pas le kill ring.

Dans Emacs, il existe pour certaines commandes un ring qui permet de retrouver d’anciennes valeurs (C-h v -ring TAB). Par exemple search-ring garde les 16 (search-ring-max) dernière recherche, et quand on fait un C-s, il est possible de faire un M-p ou M-n pour parcourir cette liste. Quand on met une mark avec C-SPC (set-mark-command) elle est mise dans le mark-ring et il est possible de revenir aux précédentes avec C-x C-SPC ou C-u C-SPC (attention, il existe un ring local au buffer, et un global !).

Vous l’avez deviné, c’est la même chose avec le kill-ring : quand on utilise C-k, M-d, C-w, etc. on ajoute la ligne/le mot/la région au kill ring (avec C-M-w on ajoute la région au dernier élément du kill-ring ; si on fait deux C-d à la suite, le deuxième mot coupé est ajouté au premier : le kill-ring n’a qu’un nouvel élément). Quand on colle avec C-y on réinsert le kill le plus récent. Si on fait M-y ensuite, on remonte le kill-ring. (Il est possible d’utiliser un argument pour coller le n-ième élément du kill-ring. (Et j’aurais également pu éviter le C-x C-x avec C-u C-y qui colle en laissant le point (curseur) au début, et la mark à la fin.)

Voir le chapitre Killing and Moving Text (manuel emacs) du manuel pour plus d’infos.

Ce qui est sympa, c’est d’utiliser desktop-save-mode et sa variable desktop-globals-to-save pour enregistrer des rings (par défaut le search-ring est sauvé par exemple).

Autres billets

Date: <2014-05-20>

Generated by Emacs 24.3.1 (Org mode 8.2.4) - Show Org source (htmlized)

CSS inspired by Tontof, colors by Chaotic Soul

Validate