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
- Dired Shell Commands: The find & xargs replacement
(MasteringEmacs.com) : Mickey nous montre comment faire un
find ... -exec
oufind ... | xargs
avecdired-x
(qu’il faudra que j’essaie un de ces quatre…). - Episode 13: multiple-cursors (Emacs Rocks!) : une vidéo dans laquelle Magnar Sveen renomme des fichiers avec multiple-cursors.el (github) (plutôt que d’utiliser un rectangle).
- In Emacs, How to replace only on matching lines
(stackoverflow.com) : un exemple d’utilisation du mode
occur-edit
qui ressemble finalement au mien.
Footnotes:
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).