Comment rechercher un mot arabe dans un texte sans ses signes diacritiques / accents?

11

En arabe comme dans certaines autres langues, il existe ce qu'on appelle des diacritiques pour améliorer la prononciation. Il n'y a pas de convention sur le nombre de signes diacritiques à écrire pour un seul mot. Certains utilisent le minimum (que je préfère) juste assez pour lever l'ambiguïté de la prononciation, tandis que certains les utilisent de manière superflue ou simplement à des fins de calligraphie esthétique. Ainsi, il existe une grande variation sur ce que et combien de signes diacritiques sont associés à un mot. Lorsque je le fais isearch-forward/backwarden appuyant sur C-s/r, un problème survient lorsque je le tape dans le mini-tampon de recherche sans signes diacritiques, il ne correspondra pas au même mot dans le texte s'il avait des signes diacritiques, ce qui rend la tâche de rechercher ce mot avec ses signes diacritiques potentiels toujours insatisfaisante.

Existe-t-il un moyen de rendre la recherche / expression rationnelle ignorante des signes diacritiques? J'espère qu'il y aura une réponse qui pourra être étendue pour inclure regexp C-M-s/ret greprechercher que j'utilise assez souvent dans helm-projectile pour rechercher un mot dans un projet multi-fichiers en latex.

Mettre à jour
Il serait agréable de voir qu'Emacs dans toutes ses fonctions de recherche effectue l'étape de suppression du texte (à partir d'accents / diacritiques / vous le nommez) avant de faire correspondre l'étape comme un comportement par défaut qui peut être désactivé par un préfixe à la demande quelle que soit la langue à portée de main. En règle générale, lorsque je recherche quelque chose, je ne m'attends pas à ce que le meilleur éditeur (Emacs) échoue dans cette course simplement à cause de certains signes diacritiques ou accents qui sont rarement, voire jamais, nécessaires pour accomplir des tâches de texte banales.

doctorat
la source
1
Regardez les ucs-normalize-*fonctions dans lisp/international/ucs-normalize.el. Il n'y a pas de pliage de recherche prédéfini pour ceux-ci, comme c'est le cas avec le pliage de cas, mais vous pouvez au moins normaliser une région avant de la rechercher. Une bonne mise en œuvre est probablement une tâche assez complexe.
Ted Zlatanov
Superuser.com/a/675172/233868 peut-il aider?
Nom
@Name, l'arabe a beaucoup plus de possibilités de combinaisons de lettres (26) avec des accents / diacritiques, donc ce n'est pas pour l'arabe. Il semble qu'il n'y ait pas de substitut aux bibliothèques spécifiques aux langues. Je ne peux pas croire que cela a déjà été implémenté dans Microsoft Word et pas dans Emacs toutes ces années.
doctorat
1
L'arabe compte environ 80 signes diacritiques et 26 lettres, faire toutes les combinaisons est une tâche intimidante. Il doit y avoir un moyen de supprimer le texte de ses signes diacritiques, comme ce qui est phpimplémenté: stackoverflow.com/a/25563250/1288722 - également implémenté dans Javascript: stackoverflow.com/a/7193622/1288722
doctorat du
Réflexion: n'est-il pas possible d'exécuter la chaîne via cette fonction de nettoyage php, puis de passer le résultat à quelque chose de similaire helm-swoop?
Sean Allred

Réponses:

5

Voici un début approximatif, basé sur la liste des caractères de combinaison dans cette réponse (puis étendue). (Marquer ceci comme wiki communautaire - veuillez le modifier et l'améliorer!)

(defconst arabic-diacritics '(#x064b #x064c #x064d #x064e #x064f #x0650 #x0651 #x0652 #x0653 #x0654 #x0655 #x0670)
  "Unicode codepoints for Arabic combining characters.")
(defconst arabic-diacritics-regexp (regexp-opt (mapcar #'string arabic-diacritics)))

(defconst arabic-equivalents
  '(
    ;; "alef" is equivalent to "alef with hamza above" etc
    (#x0627 #x0623 #x0625 #x0622)))

;; (require 'cl-lib)    
;; (defun arabic-strip-diacritics (string)
;;   (cl-reduce (lambda (s c) (remove c s)) arabic-diacritics :initial-value string))

(defun arabic-search-without-diacritics (string)
  (interactive (list (read-string "Search for: " nil nil nil t)))
  (let ((regexp
         (apply #'concat
                (mapcar (lambda (c)
                          (let ((equivalents (assq c arabic-equivalents)))
                            (concat
                             (if equivalents
                                 (regexp-opt (mapcar #'string equivalents))
                               (regexp-quote (string c)))
                             arabic-diacritics-regexp "*")))
                        string))))
    (search-forward-regexp regexp)))

Donc, si un tampon contient "الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ", et j'évalue (arabic-search-without-diacritics "الحمد لله رب العالمين"), il trouve le texte. Il fonctionne également de manière interactive, comme M-x arabic-search-without-diacritics.

Approche alternative:

Voici un exemple de code complet qui montre comment les marques diacritiques et autres marques non espacées ( Mnpropriété) peuvent être supprimées des chaînes normalisées dans les correspondances d'expression régulière. Cela fonctionne avec les exemples donnés et l'OMI est la bonne approche.

(defun kill-marks (string)
  (concat (loop for c across string
                when (not (eq 'Mn (get-char-code-property c 'general-category)))
                collect c)))

(let* ((original1 "your Arabic string here")
      (normalized1 (ucs-normalize-NFKD-string original1))
      (original2 "your other Arabic string here")
      (normalized2 (ucs-normalize-NFKD-string original2)))
  (equal
   (replace-regexp-in-string "." 'kill-marks normalized1)
   (replace-regexp-in-string "." 'kill-marks normalized2)))
legoscia
la source
J'ai ajouté deux autres signes diacritiques couramment utilisés en arabe à votre belle liste. Ceci est la liste triée complète 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1648- mise à jour gratuite.
doctorat
La première fonction arabic-search-without-diacriticsfonctionne bien mais rompt avec quelques mots, je ne sais pas pourquoi comme celle-ci الأَ. Autre mise en garde, je dois toujours définir la méthode d'entrée en arabe lorsque j'entre ma chaîne dans un mini-tampon, tandis qu'en isearch-forward/backwardfonction, elle y reste.
doctorat
kill-marksest la meilleure approche pour fournir un texte sans tracas prêt pour toutes sortes de recherches. Ce qui n'est pas clair pour moi, c'est comment implémenter cela sur un tampon entier, puis sur plusieurs fichiers?
doctorat
1
Merci! est-il possible de le faire comme isearch-forward/backwardmettre en évidence toutes les occurrences et l'actuelle différemment et en invoquant sva avancer et rreculer?
doctorat
2
Discussion sur emacs-devel: thread.gmane.org/gmane.emacs.devel/182483
Ted Zlatanov