Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

query-replace-regexp-swap ?

8 réponses
Avatar
Bastien
(Pas de réponse sur g.emacs.help, je tente ici.)

J'ai souvent besoin d'intervertir deux chaînes de caractères dans un
buffer. Par exemple faire que #000 devienne #FFF - et inversement.

Le problème est que ça doit être fait d'un coup, sinon on ne sait plus
quelle chaîne est d'origine et quelle chaîne vient d'être modifiée.

Donc pour l'instant j'utilise ça:

===%<=================================================================
(defun query-replace-regexp-swap (regexp-a regexp-b beg end)
"Swap A and B strings in current buffer."
(interactive
(let ((regexp-a (read-string "Regexp A: "))
(regexp-b (read-string "Regexp B: ")))
(list regexp-a regexp-b (region-beginning) (region-end))))
(save-match-data
(save-excursion
(goto-char beg)
(let* ((regexp (concat "\\(" regexp-a "\\)\\|"
"\\(" regexp-b "\\)"))
(match-a (save-excursion
(re-search-forward regexp-a end t)
(match-string 0)))
(match-b (save-excursion
(re-search-forward regexp-b end t)
(match-string 0))))
(while (re-search-forward regexp nil t)
(cond ((match-string 1)
(when (y-or-n-p (format "Replace with %s? " match-b))
(replace-match match-b t t)))
((match-string 2)
(when (y-or-n-p (format "Replace with %s? " match-a))
(replace-match match-a t t)))))))))
===%<=================================================================

... mais c'est assez affreux.

Le problème est que je voudrais reproduire le comportement général des
query-replace*, mais il faudrait pour cela que ma fonction fasse appel
à la fonction `perform-replace' qui n'est pas clairement documentée.

Est-ce que quelqu'un a une idée ?

--
Bastien

8 réponses

Avatar
drkm
Bastien writes:

la fonction `perform-replace' qui n'est pas clairement documentée.



(info "(elisp)Search and Replace") me semble plutôt clair.
Non ?

Est-ce que quelqu'un a une idée ?



Quelque chose comme ceci ?

(defun query-replace-regexp-swap (regexp-a regexp-b beg end)
"Swap A and B strings in current buffer."
(interactive "sRegexp A: nsRegexp B: nr")
(save-match-data
(save-excursion
(goto-char beg)
(perform-replace (concat "(" regexp-a ")|" "(" regexp-b ")")
(cons (lambda (data pos)
(if (match-string 1) (car data) (cdr data)))
(cons (save-excursion
(re-search-forward regexp-b end t)
(match-string 0))
(save-excursion
(re-search-forward regexp-a end t)
(match-string 0))))
t t nil nil nil beg end))))

Attention, code non vraiment testé, adaptation rapide du tien.

--drkm
Avatar
Bastien
drkm writes:

Quelque chose comme ceci ?

(defun query-replace-regexp-swap (regexp-a regexp-b beg end)



Merci.

Après une réponse dans g.e.help, j'ai fait ça - qui utilise
query-replace-regexp directement:

,----
| (defun query-regexp-swap (regexp-a regexp-b)
| "Swap A and B strings in current buffer."
| (interactive "sRegexp A: nsRegexp B: ")
| (let ((match-a (save-excursion
| (re-search-forward regexp-a nil t)
| (match-string 0)))
| (match-b (save-excursion
| (re-search-forward regexp-b nil t)
| (match-string 0))))
| (query-replace-regexp
| (concat "((" regexp-a ")|" regexp-b ")")
| `(replace-eval-replacement
| replace-quote
| (if (match-string 2) ,match-b ,match-a))
| nil
| (if (and transient-mark-mode mark-active) (region-beginning))
| (if (and transient-mark-mode mark-active) (region-end)))))
`----

ATTENTION: ne doit marcher qu'avec une version CVS d'Emacs.

--
Bastien
Avatar
Sébastien Kirche
Le 28 novembre 2005 à 14:11, Bastien a formulé :

Après une réponse dans g.e.help, j'ai fait ça - qui utilise
query-replace-regexp directement:



Personnellement j'ai beaucoup plus la version de David Kastrup :
C-M-% #((000)|FFF) RET ,(if 2 "FFF" "000") RET

C'est quand même plus compact :)
--
Sébastien Kirche
Avatar
Sébastien Kirche
Le 28 novembre 2005 à 17:11, drkm a formulé :

Sébastien Kirche wrote:

> Personnellement j'ai beaucoup plus la version de David Kastrup :
> C-M-% #((000)|FFF) RET ,(if 2 "FFF" "000") RET

C'est quoi "," ? Un echappement vers une sexp ? Waouw, je ne
connaissais pas ca :-)



Ouaip, je connais pas depuis longtemps, c'est qu'avec cvs.

Je m'en sers par exemple quand je dois faire des décalages dans des
offsets de structures en C pour pas m'embêter.

Par exemple : si je veux rajouter 42 à certaines valeurs :
C-M-% <[[:digit:]]+> RET ,(+ #& 42) RET

et je n'ai plus qu'à répondre SPC ou n sur chaque valeur trouvée, emacs
m'affiche même la valeur calcule qui va être utilisée. C'est génial.

À propos du #& : la valeur trouvée par la regexp est accessible par &
mais avec # en plus elle est convertie directement en valeur, sans
nécessiter string-to-number :)

--
Sébastien Kirche
Avatar
Bastien
Sébastien Kirche writes:

Personnellement j'ai beaucoup plus la version de David Kastrup :
C-M-% #((000)|FFF) RET ,(if 2 "FFF" "000") RET



Euh... oui, mais une fois la fonction écrite, il est plus rapide de
l'utiliser - non ?

--
Bastien
Avatar
Sébastien Kirche
Le 28 novembre 2005 à 23:11, Bastien s'est exprimé ainsi :

Sébastien Kirche writes:

> Personnellement j'ai beaucoup plus la version de David Kastrup :
> C-M-% #((000)|FFF) RET ,(if 2 "FFF" "000") RET

Euh... oui, mais une fois la fonction écrite, il est plus rapide de
l'utiliser - non ?



Si. C'est une question de besoin en fait.

Si tu fais souvent ce genre de remplacement c'est très bien. Avec une
fonction, tu as un outil facile à mettre en ½uvre mais spécialisé : il
faut modifier le code si ton besoin se modifie. Alors que l'autre
solution est plus souple seulement il faut re-saisir les critères de
recherche et de remplacement à chaque fois (rien n'empêche de les
conserver pour une prochaine fois).

C'est un peu comme si tu n'avais qu'un tournevis pour serrer un seul
type de vis. Avec le query-replace-regexp et la possibilité d'utiliser
un bout de code pour calculer le remplacement tu as une boîte à cliquets
et tout un jeu de douilles et d'embouts :o)

--
Sébastien Kirche
Avatar
Bastien
Sébastien Kirche writes:

C'est un peu comme si tu n'avais qu'un tournevis pour serrer un seul
type de vis.



Oui, mais tout dépend de la taille de ton tournevis: 10 lignes de
fonction et je sors ce tournevis quand j'en ai besoin! Evidemment, si
c'était un tournevis électrique demandant du 1000 watts et pesant 130
kgs je dis pas...

En fait, c'était le genre de fonction dont je m'attendais à ce qu'elle
fasse partie de la trousse à outil par défaut d'Emacs.

--
Bastien
Avatar
Bastien
"drkm" writes:

En fait, c'était le genre de fonction dont je m'attendais à ce qu'elle
fasse partie de la trousse à outil par défaut d'Emacs.



Pour ce qui est d'echanger deux chaines de caracteres, je suis
d'accord. Je me demande d'ailleurs si ce n'est pas le cas.



Pas à ma connaissance. Mais ce serait bien!

Pour ce qui est d'echanger deux regexps, je ne sais pas. J'ai
l'impression que cela pose des problemes au niveaux des
specifications, notamment par quoi remplacer un match ?



Oui, tu as raison. C'une une bizarrerie de la fonction que j'ai
postée (mais j'en avais besoin un moment), et on peut s'en passer
facilement :

,----[ query-string-swap ]
| (defun query-string-swap (string-a string-b)
| "Swap A and B strings in current buffer."
| (interactive "sString A: nsString B: ")
| (query-replace-regexp
| (concat "((" string-a ")|" string-b ")")
| `(replace-eval-replacement
| replace-quote
| (if (match-string 2) ,string-b ,string-a))
| nil
| (if (and transient-mark-mode mark-active) (region-beginning))
| (if (and transient-mark-mode mark-active) (region-end))))
`----

--
Bastien