query-replace-regexp personnel

4 réponses
Avatar
JJ. Rétorré
Bonjour,

J'ai parfois à éditer un bulletin d'association que je mets en forme
en LaTeX.
Je reçois les articles en texte brut, et leurs auteurs ont l'habitude
d'écrire les nombres en chiffre. Je les convertis en lettre, du moins
pour les nombres qui s'écrivent normalement en un seul mot.
Comme il s'agit d'un travail assez important, j'ai écrit une fonction
personnelle pour gagner un peu de temps (et accessoirement en perdre
pas mal à l'écrire, mais c'est aussi pour apprendre).

;-------------------------------------
(defun query-replace-number-in-words()
(interactive)
(while (re-search-forward "\\(\\<[0-9]+\\)\\([ ~\t\n]+\\)" nil t)
(let ((match-number(string-to-int (match-string 1)))
(chiffres '((0 . "zero")(1 . "un")(2 . "deux")(3 . "trois")
(4 . "quatre")(5 . "cinq")(6 . "six")(7 . "sept")
(8 . "huit")(9 . "neuf")(10 . "dix")(11 . "onze")
(12 . "douze")(13 . "treize")(14 . "quatorze")
(15 . "quinze")(16 . "seize")) )
newtext)
(if (and(setq newtext(assoc-default match-number chiffres))
(y-or-n-p "Remplacer ? "))
(replace-match (concat newtext (match-string 2)) nil nil)))))
;-----------------------------------------------------------------------

Ça marche plutôt de manière satisfaisante, sauf pour un détail : les
parties susceptibles d'être remplacées sont pas mises en surbrillance
comme pour un query-replace-regexp «normal». Or je préfère laisser les
nombres qui sont des dates (2 février 2012) et quelques autres cas en
chiffre.
J'ai essayé une autre stratégie en utilisant un regex-replace et en
plaçant le test dans la chaîne de remplacement, mais ça ne marche pas
mieux.
Si vous avez des idées...

--
JJR.

4 réponses

Avatar
vincent.belaiche
JJ. Rétorré <jj.r&torr&@gmail.com> writes:

Bonjour,

J'ai parfois à éditer un bulletin d'association que je mets en forme
en LaTeX.
Je reçois les articles en texte brut, et leurs auteurs ont l'habitude
d'écrire les nombres en chiffre. Je les convertis en lettre, du moins
pour les nombres qui s'écrivent normalement en un seul mot.
Comme il s'agit d'un travail assez important, j'ai écrit une fonction
personnelle pour gagner un peu de temps (et accessoirement en perdre
pas mal à l'écrire, mais c'est aussi pour apprendre).

;-------------------------------------
(defun query-replace-number-in-words()
(interactive)
(while (re-search-forward "(<[0-9]+)([ ~tn]+)" nil t)
(let ((match-number(string-to-int (match-string 1)))
(chiffres '((0 . "zero")(1 . "un")(2 . "deux")(3 . "trois")
(4 . "quatre")(5 . "cinq")(6 . "six")(7 . "sept")
(8 . "huit")(9 . "neuf")(10 . "dix")(11 . "onze")
(12 . "douze")(13 . "treize")(14 . "quatorze")
(15 . "quinze")(16 . "seize")) )
newtext)
(if (and(setq newtext(assoc-default match-number chiffres))
(y-or-n-p "Remplacer ? "))
(replace-match (concat newtext (match-string 2)) nil nil)))))
;-----------------------------------------------------------------------

Ça marche plutôt de manière satisfaisante, sauf pour un détail : les
parties susceptibles d'être remplacées sont pas mises en surbrillance
comme pour un query-replace-regexp «normal». Or je préfère laisser les
nombres qui sont des dates (2 février 2012) et quelques autres cas en
chiffre.
J'ai essayé une autre stratégie en utilisant un regex-replace et en
plaçant le test dans la chaîne de remplacement, mais ça ne marche pas
mieux.
Si vous avez des idées...



Salut,

Tu pourrais faire un test si c'est une date comme ça (pas testé):

;;-----------------------------------------------------------------------------
(defun query-replace-number-in-words()
(interactive)
(while (re-search-forward "(<[0-9]+)([ ~tn]+)" nil t)
(unless (save-match-data
(save-excursion
(goto-char (match-beginning 0))
(or
;; regexp à compléter avec les autres nom de mois
(looking-at "[0-9]{1,2}s-+(janvier|février)s-+[0-9]{4}")
;; ici mets les autres looking-at des cas à éliminer
)))
(let ((match-number(string-to-int (match-string 1)))
(chiffres '((0 . "zero")(1 . "un")(2 . "deux")(3 . "trois")
(4 . "quatre")(5 . "cinq")(6 . "six")(7 . "sept")
(8 . "huit")(9 . "neuf")(10 . "dix")(11 . "onze")
(12 . "douze")(13 . "treize")(14 . "quatorze")
(15 . "quinze")(16 . "seize")) )
newtext)
(if (and(setq newtext(assoc-default match-number chiffres))
(y-or-n-p "Remplacer ? "))
(replace-match (concat newtext (match-string 2)) nil nil))))))
;;-----------------------------------------------------------------------------

Vincent
Avatar
JJ. Rétorré
(Vincent Belaïche) disait le 02/24/12 que :

JJ. Rétorré <jj.r&torr&@gmail.com> writes:

Bonjour,

J'ai parfois à éditer un bulletin d'association que je mets en forme
en LaTeX.





<snip>


Tu pourrais faire un test si c'est une date comme ça (pas testé):

;;-----------------------------------------------------------------------------
(defun query-replace-number-in-words()
(interactive)
(while (re-search-forward "(<[0-9]+)([ ~tn]+)" nil t)
(unless (save-match-data
(save-excursion
(goto-char (match-beginning 0))
(or
;; regexp à compléter avec les autres nom de mois
(looking-at "[0-9]{1,2}s-+(janvier|février)s-+[0-9]{4}")
;; ici mets les autres looking-at des cas à éliminer
)))
(let ((match-number(string-to-int (match-string 1)))
(chiffres '((0 . "zero")(1 . "un")(2 . "deux")(3 . "trois")
(4 . "quatre")(5 . "cinq")(6 . "six")(7 . "sept")
(8 . "huit")(9 . "neuf")(10 . "dix")(11 . "onze")
(12 . "douze")(13 . "treize")(14 . "quatorze")
(15 . "quinze")(16 . "seize")) )
newtext)
(if (and(setq newtext(assoc-default match-number chiffres))
(y-or-n-p "Remplacer ? "))
(replace-match (concat newtext (match-string 2)) nil nil))))))
;;-----------------------------------------------------------------------------




C'est une bonne idée, je pense qu'il faut le faire, mais ça ne résout
pas mon problème.

Je tiens à conserver un contrôle visuel de ce qui
va être modifié, sans quoi je risque de perdre beaucoup de temps en
relecture.
Je pense qu'il faut que je reprenne le code de perform-replace pour
placer un test au bon endroit. Je n'avais pas regardé primitivement car
le commentaire de query-replace-regexp le déconseillait.

Je pense faire évoluer cette fonction vers un mini
correcteur typographique, proposant aussi des espaces insécables entre
les nombres et le mot qui suit (quand cela est pertinent), et sans doute
d'autres tâches de moindre importance. Mais il faut aussi que ça reste
sous contrôle visuel.
J'imagine que les professionnels ont un tel outil, mais je n'ai rien
trouvé pour LaTeX.

J'ai beaucoup de mal à trouver les extensions
d'Emacs, par exemple, j'ai mis un bout de temps pour trouver
spell-number de Vinicius Jose Latorre (qui ne m'a pas vraiment servi
finalement). Dans la liste des extensions sur Emacs wiki, il n'y a pas
de description, c'est un peu rustique.


--
JJR.
Avatar
vincent.belaiche
JJ. Rétorré <jj.r&torr&@gmail.com> writes:

(Vincent Belaïche) disait le 02/24/12 que :

JJ. Rétorré <jj.r&torr&@gmail.com> writes:






[...]


Je tiens à conserver un contrôle visuel de ce qui
va être modifié, sans quoi je risque de perdre beaucoup de temps en
relecture.



[...]

La relecture n'est peut-être pas trop coûteuse si tu fais un M-x ediff
en l'état du fichier avant et après modification.

Je crois que ediff permet d'être configuré pour sauter les différences
qui s'accordent à une expression rationnelle configurable par
l'utilisateur. Perso, je n'ai jamais utilisé ça, mais il me semble
l'avoir lu dans la doc...

Vincent.
Avatar
jackmac
Le jeudi 23 Février 2012 à 18:15 par JJ. Rétorré :
Bonjour,

J'ai parfois à éditer un bulletin d'association que je mets en
forme
en LaTeX.
Je reçois les articles en texte brut, et leurs auteurs ont l'habitude
d'écrire les nombres en chiffre. Je les convertis en lettre, du moins
pour les nombres qui s'écrivent normalement en un seul mot.
Comme il s'agit d'un travail assez important, j'ai écrit une fonction
personnelle pour gagner un peu de temps (et accessoirement en perdre
pas mal à l'écrire, mais c'est aussi pour apprendre).

;-------------------------------------
(defun query-replace-number-in-words()
(interactive)
(while (re-search-forward "(<[0-9]+)([ ~tn]+)" nil
t)
(let ((match-number(string-to-int (match-string 1)))
(chiffres '((0 . "zero")(1 . "un")(2 .
"deux")(3 . "trois")
(4 . "quatre")(5 . "cinq")(6 . "six")(7 .
"sept")
(8 . "huit")(9 . "neuf")(10 . "dix")(11 .
"onze")
(12 . "douze")(13 . "treize")(14 .
"quatorze")
(15 . "quinze")(16 . "seize")) )
newtext)
(if (and(setq newtext(assoc-default match-number chiffres))
(y-or-n-p "Remplacer ? "))
(replace-match (concat newtext (match-string 2)) nil nil)))))
;-----------------------------------------------------------------------

Ça marche plutôt de manière satisfaisante, sauf pour un
détail : les
parties susceptibles d'être remplacées sont pas mises en
surbrillance
comme pour un query-replace-regexp «normal». Or je
préfère laisser les
nombres qui sont des dates (2 février 2012) et quelques autres cas en
chiffre.
J'ai essayé une autre stratégie en utilisant un regex-replace et
en
plaçant le test dans la chaîne de remplacement, mais ça ne
marche pas
mieux.
Si vous avez des idées...

--
JJR.


Bonjour,
j'ai une problématique un peu similaire. J'ai fait un tout petit peu mieux que toi:
J'ai utilisé while + re-search-forward +
(query-replace-regexp from to (not 'delimited) bop eop)
où bop eop sont, en gros le début et la fin du truc à remplacer.
Ceci me permet d'avoir l'interaction standard de query-replace (plutôt que y/n), mais ne fournit le highlight que sur l'unique partie à changer (ce qui n'est déjà pas si mal!) et non partout (ce qui serait mieux).

Je n'ai pas encore complètement trouvé la bonne solution, mais il me semble qu'il faut utiliser perform-replace telle qu'elle est (sans la modifier), mais en positionnant au préalable la variable replace-re-search-function . Je cherche dans cette direction!

Sinon on peut aussi utiliser query-replace-regexp-eval ou la syntaxe "backslash backslash virgule" (cf. http://www.generation-nt.com/reponses/query-replace-regexp-swap-entraide-3786321.html)

HTH
)jack(