9 votes

Emacs : comment remplacer-regexp par une fonction lisp dans un defun ?

Par exemple, je veux que tout le texte entre parenthèses, (), soit en majuscules. Il est trivial de faire ce qui suit de manière interactive :

M-x query-replace-regexp
replace: "(\(.+?\))"
with   : "(\,(upcase \1))"

Au lieu de cela, je veux écrire un defun qui le fera :

(defun upcs ()
  (interactive)
  (goto-char 1)
  (while (search-forward "(\\(.+?\\))" nil t) (replace-match "(\\,(upcase \\1))" t nil)))

mais ça ne marche pas ! Alors que la méthode suivante fonctionne (elle ajoute foo y bar aux textes entre parenthèses) :

(defun HOOK ()
  (interactive)
  (goto-char 1)
  (while (search-forward-regexp "(\\(.+?\\))" nil t) (replace-match "(foo \\1 bar)" t nil)))

7voto

zev Points 2412

La réponse de Luc fait presque l'affaire, mais pas tout à fait. L'expéditeur initial voulait que tout le texte entre parenthèses soit converti en majuscules, alors que le code de Luke convertit le code en majuscules ET supprime AUSSI les parenthèses. Une légère modification de l'expression rationnelle fournit la solution correcte :

(defun upcs ()
(interactive)
(goto-char 1)
    (while (search-forward-regexp "\\([^\\)]+\\)" nil t) 
        (replace-match (upcase (match-string 1)) t nil)))

6voto

Luke Girvin Points 8270

Tout d'abord, vous utilisez search-forward dans votre première fonction. Celle-ci prend une chaîne littérale plutôt qu'une expression régulière. Vous devriez utiliser search-forward-regexp comme vous le faites dans votre deuxième fonction.

Deuxièmement, bien que ce code soit valable en tant que valeur de remplacement de query-replace-regexp je ne pense pas que tu puisses le passer à replace-match :

(\\,(upcase \\1))

Vous pouvez obtenir la valeur de la correspondance trouvée par search-forward-regexp en utilisant le match-string fonction.

Enfin, je ne suis pas sûr que votre expression régulière de recherche soit correcte.

Je pense que vous avez besoin de quelque chose de ce genre :

(defun upcs ()
    (interactive)
    (goto-char 1)
        (while (search-forward-regexp "(\\([^\\)]+\\))" nil t) 
            (replace-match (upcase (match-string 1)) t nil)))

6voto

Adobe Points 1592

Cela résout donc le problème.

(defun put-in-par (str)
  (concat "(" str ")"))

(defun upcs-luke ()
    (interactive)
    (goto-char 1)
        (while (search-forward-regexp "(\\([^\\)]+\\))" nil t) 
            (replace-match (put-in-par (upcase (match-string 1))) t nil)))

Merci à BillC et Luke Girvin pour leur aide.

3voto

girnigoe Points 51

C'était très utile, merci à tous.

Dans l'intérêt de mettre plus d'exemples sur le web, je suis parti de ceci :

(replace-regexp "\([\%\)\”\"]\..?\)[0-9]+" "\1")

(qui n'a pas fonctionné, mais qui a utilisé les regexps qui ont fonctionné en mode interactif)

à ça :

(while (re-search-forward "\\([\\%\\\"\\”]\\)\\.?[0-9]+" nil t)
    (replace-match (match-string 1) t nil))

J'avais besoin de trois antislashes avant le guillemet interne.

0voto

ctietze Points 128

Les fonctions de remplacement interactives basées sur l'expression rationnelle ne peuvent pas modifier la casse mais fonctionnent bien par défaut : la fonction case-replace doit être définie comme suit nil (par défaut : t ). Les remplacements interactifs fonctionneront alors correctement avec ,(upcase \1) et des amis.

Référence : Voir la discussion sur la liste de diffusion emacs-berlin : https://mailb.org/pipermail/emacs-berlin/2021/000840.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X