Subject: bug#52394: 27.2; Isearch with char folding enabled doesn’t match equivalent strings

From: Juri Linkov <[email-masked]>
Date: Sun, 12 Dec 2021 19:19:14 +0200

> Even better, yes. In addition to simplifying changing the default,
> something like that would make it easy to create different levels of
> folding and switch between them (by writing commands that add or
> remove certain characters from the list).

Thanks for the suggestion,  This is implemented by the following patch:

diff --git a/lisp/char-fold.el b/lisp/char-fold.el
index e3ab7d5b64..12c9d2d4b1 100644
--- a/lisp/char-fold.el
+++ b/lisp/char-fold.el
@@ -26,6 +26,7 @@
 
 (eval-and-compile
   (put 'char-fold-table 'char-table-extra-slots 1)
+  (defconst char-fold--default-override nil)
   (defconst char-fold--default-include
     '((?\" "＂" "“" "”" "”" "„" "⹂" "〞" "‟" "‟" "❞" "❝" "❠" "“" "„" "〝" "〟" "🙷" "🙶" "🙸" "«" "»")
       (?' "❟" "❛" "❜" "‘" "’" "‚" "‛" "‚" "󠀢" "❮" "❯" "‹" "›")
@@ -40,7 +41,8 @@
       ))
   (defconst char-fold--default-symmetric nil)
   (defvar char-fold--previous
-    (list char-fold--default-include
+    (list char-fold--default-override
+          char-fold--default-include
           char-fold--default-exclude
           char-fold--default-symmetric)))
 
@@ -67,6 +69,8 @@
       ;; - A single char of the decomp might be allowed to match the
       ;;   character.
       ;; Some examples in the comments below.
+      (unless (or (bound-and-true-p char-fold-override)
+                  char-fold--default-override)
         (map-char-table
          (lambda (char decomp)
            (when (consp decomp)
@@ -135,7 +139,7 @@
                        (aset equiv (car simpler-decomp)
                              (cons (apply #'string decomp)
                                    (aref equiv (car simpler-decomp)))))))))))
-       table)
+         table))
 
       ;; Add some entries to default decomposition
       (dolist (it (or (bound-and-true-p char-fold-include)
@@ -232,7 +236,9 @@ char-fold-table
 
 (defun char-fold-update-table ()
   "Update char-fold-table only when one of the options changes its value."
-  (let ((new (list (or (bound-and-true-p char-fold-include)
+  (let ((new (list (or (bound-and-true-p char-fold-override)
+                       char-fold--default-override)
+                   (or (bound-and-true-p char-fold-include)
                        char-fold--default-include)
                    (or (bound-and-true-p char-fold-exclude)
                        char-fold--default-exclude)
@@ -242,6 +248,22 @@ char-fold-update-table
       (setq char-fold-table (char-fold--make-table)
             char-fold--previous new))))
 
+(defcustom char-fold-override char-fold--default-override
+  "Non-nil means to override all default folding characters.
+When nil, the equivalence table is populated with the default set
+of equivalent chars, and you can remove unneeded characters using
+`char-fold-exclude', and add own characters using `char-fold-include'.
+But when this variable is customized to non-nil, you start with
+an empty table where you can add only own characters
+using `char-fold-include'."
+  :type 'boolean
+  :initialize #'custom-initialize-default
+  :set (lambda (sym val)
+         (custom-set-default sym val)
+         (char-fold-update-table))
+  :group 'isearch
+  :version "29.1")
+
 (defcustom char-fold-include char-fold--default-include
   "Additional character foldings to include.
 Each entry is a list of a character and the strings that fold into it."