unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#35689: Customizable char-fold
@ 2019-05-11 21:22 Juri Linkov
  2019-05-12 19:12 ` Juri Linkov
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Juri Linkov @ 2019-05-11 21:22 UTC (permalink / raw)
  To: 35689

[-- Attachment #1: Type: text/plain, Size: 74 bytes --]

Tags: patch

This patch adds long-awaited customization to char-fold.el:


[-- Attachment #2: char-fold-defcustom.patch --]
[-- Type: text/x-diff, Size: 3040 bytes --]

diff --git a/lisp/char-fold.el b/lisp/char-fold.el
index e61bc3edc6..24882008a4 100644
--- a/lisp/char-fold.el
+++ b/lisp/char-fold.el
@@ -24,6 +24,30 @@
 
 (eval-and-compile (put 'char-fold-table 'char-table-extra-slots 1))
 \f
+(defcustom char-fold-include-base nil
+  "Include mappings from composite character to base letter."
+  :type 'boolean
+  :group 'matching
+  :version "27.1")
+
+(defcustom char-fold-include-alist
+  '((?\" """ "“" "”" "”" "„" "⹂" "〞" "‟" "‟" "❞" "❝" "❠" "“" "„" "〝" "〟" "🙷" "🙶" "🙸" "«" "»")
+    (?' "❟" "❛" "❜" "‘" "’" "‚" "‛" "‚" "󠀢" "❮" "❯" "‹" "›")
+    (?` "❛" "‘" "‛" "󠀢" "❮" "‹"))
+  "Additional character mappings to include."
+  :type '(alist :key-type (character :tag "From")
+                :value-type (repeat (string :tag "To")))
+  :group 'lisp
+  :version "27.1")
+
+(defcustom char-fold-exclude-alist nil
+  "Character mappings to exclude from default setting."
+  :type '(alist :key-type (character :tag "From")
+                :value-type (character :tag "To"))
+  :group 'lisp
+  :version "27.1")
+
+\f
 (defconst char-fold-table
   (eval-when-compile
     (let ((equiv (make-char-table 'char-fold-table))
@@ -76,7 +106,11 @@ char-fold-table
                                       (aref equiv-multi (car decomp))))
                         (aset equiv (car decomp)
                               (cons (char-to-string char)
-                                    (aref equiv (car decomp))))))))
+                                    (aref equiv (car decomp))))
+                        (when char-fold-include-base
+                          (aset equiv char
+                                (cons (char-to-string (car decomp))
+                                      (aref equiv (car decomp)))))))))
                (funcall make-decomp-match-char decomp char)
                ;; Do it again, without the non-spacing characters.
                ;; This allows 'a' to match 'ä'.
@@ -98,13 +132,18 @@ char-fold-table
        table)
 
       ;; Add some manual entries.
-      (dolist (it '((?\" """ "“" "”" "”" "„" "⹂" "〞" "‟" "‟" "❞" "❝" "❠" "“" "„" "〝" "〟" "🙷" "🙶" "🙸" "«" "»")
-                    (?' "❟" "❛" "❜" "‘" "’" "‚" "‛" "‚" "󠀢" "❮" "❯" "‹" "›")
-                    (?` "❛" "‘" "‛" "󠀢" "❮" "‹")))
+      (dolist (it char-fold-include-alist)
         (let ((idx (car it))
               (chars (cdr it)))
           (aset equiv idx (append chars (aref equiv idx)))))
 
+      ;; Remove some entries.
+      (dolist (it char-fold-exclude-alist)
+        (let ((idx (car it))
+              (char (cdr it)))
+          (when (aref equiv idx)
+            (aset equiv idx (remove (char-to-string char) (aref equiv idx))))))
+
       ;; Convert the lists of characters we compiled into regexps.
       (map-char-table
        (lambda (char dec-list)

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-11 21:22 bug#35689: Customizable char-fold Juri Linkov
@ 2019-05-12 19:12 ` Juri Linkov
  2019-05-12 20:30   ` Noam Postavsky
  2019-07-23 20:28 ` Juri Linkov
  2019-07-28 22:46 ` Juri Linkov
  2 siblings, 1 reply; 16+ messages in thread
From: Juri Linkov @ 2019-05-12 19:12 UTC (permalink / raw)
  To: 35689

[-- Attachment #1: Type: text/plain, Size: 399 bytes --]

> This patch adds long-awaited customization to char-fold.el:

I noticed that its compilation fails with:

    ELC      char-fold.elc
  In toplevel form:
  char-fold.el:153:31:Error: Symbol's value as variable is void: char-fold-include-base
  Makefile:296: recipe for target 'char-fold.elc' failed
  make[2]: *** [char-fold.elc] Error 1

So a new patch added 'eval-and-compile' to all defcustoms:


[-- Attachment #2: char-fold-defcustom.2.patch --]
[-- Type: text/x-diff, Size: 3097 bytes --]

diff --git a/lisp/char-fold.el b/lisp/char-fold.el
index e61bc3edc6..a60d49dd8e 100644
--- a/lisp/char-fold.el
+++ b/lisp/char-fold.el
@@ -24,6 +24,30 @@
 
 (eval-and-compile (put 'char-fold-table 'char-table-extra-slots 1))
 \f
+(eval-and-compile (defcustom char-fold-include-base nil
+  "Include mappings from composite character to base letter."
+  :type 'boolean
+  :group 'matching
+  :version "27.1"))
+
+(eval-and-compile (defcustom char-fold-include-alist
+  '((?\" """ "“" "”" "”" "„" "⹂" "〞" "‟" "‟" "❞" "❝" "❠" "“" "„" "〝" "〟" "🙷" "🙶" "🙸" "«" "»")
+    (?' "❟" "❛" "❜" "‘" "’" "‚" "‛" "‚" "󠀢" "❮" "❯" "‹" "›")
+    (?` "❛" "‘" "‛" "󠀢" "❮" "‹"))
+  "Additional character mappings to include."
+  :type '(alist :key-type (character :tag "From")
+                :value-type (repeat (string :tag "To")))
+  :group 'lisp
+  :version "27.1"))
+
+(eval-and-compile (defcustom char-fold-exclude-alist nil
+  "Character mappings to exclude from default setting."
+  :type '(alist :key-type (character :tag "From")
+                :value-type (character :tag "To"))
+  :group 'lisp
+  :version "27.1"))
+
+\f
 (defconst char-fold-table
   (eval-when-compile
     (let ((equiv (make-char-table 'char-fold-table))
@@ -76,7 +109,11 @@ char-fold-table
                                       (aref equiv-multi (car decomp))))
                         (aset equiv (car decomp)
                               (cons (char-to-string char)
-                                    (aref equiv (car decomp))))))))
+                                    (aref equiv (car decomp))))
+                        (when char-fold-include-base
+                          (aset equiv char
+                                (cons (char-to-string (car decomp))
+                                      (aref equiv (car decomp)))))))))
                (funcall make-decomp-match-char decomp char)
                ;; Do it again, without the non-spacing characters.
                ;; This allows 'a' to match 'ä'.
@@ -98,13 +135,18 @@ char-fold-table
        table)
 
       ;; Add some manual entries.
-      (dolist (it '((?\" """ "“" "”" "”" "„" "⹂" "〞" "‟" "‟" "❞" "❝" "❠" "“" "„" "〝" "〟" "🙷" "🙶" "🙸" "«" "»")
-                    (?' "❟" "❛" "❜" "‘" "’" "‚" "‛" "‚" "󠀢" "❮" "❯" "‹" "›")
-                    (?` "❛" "‘" "‛" "󠀢" "❮" "‹")))
+      (dolist (it char-fold-include-alist)
         (let ((idx (car it))
               (chars (cdr it)))
           (aset equiv idx (append chars (aref equiv idx)))))
 
+      ;; Remove some entries.
+      (dolist (it char-fold-exclude-alist)
+        (let ((idx (car it))
+              (char (cdr it)))
+          (when (aref equiv idx)
+            (aset equiv idx (remove (char-to-string char) (aref equiv idx))))))
+
       ;; Convert the lists of characters we compiled into regexps.
       (map-char-table
        (lambda (char dec-list)

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-12 19:12 ` Juri Linkov
@ 2019-05-12 20:30   ` Noam Postavsky
  2019-05-13 20:31     ` Juri Linkov
  0 siblings, 1 reply; 16+ messages in thread
From: Noam Postavsky @ 2019-05-12 20:30 UTC (permalink / raw)
  To: Juri Linkov; +Cc: 35689

Juri Linkov <juri@linkov.net> writes:

>> This patch adds long-awaited customization to char-fold.el:
>
> I noticed that its compilation fails with:
>
>     ELC      char-fold.elc
>   In toplevel form:
>   char-fold.el:153:31:Error: Symbol's value as variable is void: char-fold-include-base
>   Makefile:296: recipe for target 'char-fold.elc' failed
>   make[2]: *** [char-fold.elc] Error 1
>
> So a new patch added 'eval-and-compile' to all defcustoms:

Will it actually work for a user to customize this?  It looks like the
values are used during compile time, so after changing the value the
user would have to recompile char-fold.el?





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-12 20:30   ` Noam Postavsky
@ 2019-05-13 20:31     ` Juri Linkov
  2019-05-13 22:18       ` Noam Postavsky
  0 siblings, 1 reply; 16+ messages in thread
From: Juri Linkov @ 2019-05-13 20:31 UTC (permalink / raw)
  To: Noam Postavsky; +Cc: 35689

[-- Attachment #1: Type: text/plain, Size: 674 bytes --]

>>> This patch adds long-awaited customization to char-fold.el:
>>
>> I noticed that its compilation fails with:
>>
>>     ELC      char-fold.elc
>>   In toplevel form:
>>   char-fold.el:153:31:Error: Symbol's value as variable is void: char-fold-include-base
>>   Makefile:296: recipe for target 'char-fold.elc' failed
>>   make[2]: *** [char-fold.elc] Error 1
>>
>> So a new patch added 'eval-and-compile' to all defcustoms:
>
> Will it actually work for a user to customize this?  It looks like the
> values are used during compile time, so after changing the value the
> user would have to recompile char-fold.el?

Oh, right.  Do you see a problem with a better patch:


[-- Attachment #2: char-fold-defcustom.3.patch --]
[-- Type: text/x-diff, Size: 4139 bytes --]

diff --git a/lisp/char-fold.el b/lisp/char-fold.el
index e61bc3edc6..6c3f809c2b 100644
--- a/lisp/char-fold.el
+++ b/lisp/char-fold.el
@@ -24,8 +24,43 @@
 
 (eval-and-compile (put 'char-fold-table 'char-table-extra-slots 1))
 \f
-(defconst char-fold-table
-  (eval-when-compile
+(eval-and-compile (defcustom char-fold-include-base nil
+  "Include mappings from composite character to base letter."
+  :type 'boolean
+  :set (lambda (sym val)
+         (set sym val)
+         (when (boundp 'char-fold-table)
+           (setq char-fold-table (char-fold-make-table))))
+  :group 'matching
+  :version "27.1"))
+
+(eval-and-compile (defcustom char-fold-include-alist
+  '((?\" """ "“" "”" "”" "„" "⹂" "〞" "‟" "‟" "❞" "❝" "❠" "“" "„" "〝" "〟" "🙷" "🙶" "🙸" "«" "»")
+    (?' "❟" "❛" "❜" "‘" "’" "‚" "‛" "‚" "󠀢" "❮" "❯" "‹" "›")
+    (?` "❛" "‘" "‛" "󠀢" "❮" "‹"))
+  "Additional character mappings to include."
+  :type '(alist :key-type (character :tag "From")
+                :value-type (repeat (string :tag "To")))
+  :set (lambda (sym val)
+         (set sym val)
+         (when (boundp 'char-fold-table)
+           (setq char-fold-table (char-fold-make-table))))
+  :group 'lisp
+  :version "27.1"))
+
+(eval-and-compile (defcustom char-fold-exclude-alist nil
+  "Character mappings to exclude from default setting."
+  :type '(alist :key-type (character :tag "From")
+                :value-type (character :tag "To"))
+  :set (lambda (sym val)
+         (set sym val)
+         (when (boundp 'char-fold-table)
+           (setq char-fold-table (char-fold-make-table))))
+  :group 'lisp
+  :version "27.1"))
+
+(eval-and-compile
+  (defun char-fold-make-table ()
     (let ((equiv (make-char-table 'char-fold-table))
           (equiv-multi (make-char-table 'char-fold-table))
           (table (unicode-property-table-internal 'decomposition)))
@@ -76,7 +123,11 @@ char-fold-table
                                       (aref equiv-multi (car decomp))))
                         (aset equiv (car decomp)
                               (cons (char-to-string char)
-                                    (aref equiv (car decomp))))))))
+                                    (aref equiv (car decomp))))
+                        (when char-fold-include-base
+                          (aset equiv char
+                                (cons (char-to-string (car decomp))
+                                      (aref equiv (car decomp)))))))))
                (funcall make-decomp-match-char decomp char)
                ;; Do it again, without the non-spacing characters.
                ;; This allows 'a' to match 'ä'.
@@ -98,13 +149,18 @@ char-fold-table
        table)
 
       ;; Add some manual entries.
-      (dolist (it '((?\" """ "“" "”" "”" "„" "⹂" "〞" "‟" "‟" "❞" "❝" "❠" "“" "„" "〝" "〟" "🙷" "🙶" "🙸" "«" "»")
-                    (?' "❟" "❛" "❜" "‘" "’" "‚" "‛" "‚" "󠀢" "❮" "❯" "‹" "›")
-                    (?` "❛" "‘" "‛" "󠀢" "❮" "‹")))
+      (dolist (it char-fold-include-alist)
         (let ((idx (car it))
               (chars (cdr it)))
           (aset equiv idx (append chars (aref equiv idx)))))
 
+      ;; Remove some entries.
+      (dolist (it char-fold-exclude-alist)
+        (let ((idx (car it))
+              (char (cdr it)))
+          (when (aref equiv idx)
+            (aset equiv idx (remove (char-to-string char) (aref equiv idx))))))
+
       ;; Convert the lists of characters we compiled into regexps.
       (map-char-table
        (lambda (char dec-list)
@@ -113,7 +169,11 @@ char-fold-table
                (set-char-table-range equiv char re)
              (aset equiv char re))))
        equiv)
-      equiv))
+      equiv)))
+
+(defconst char-fold-table
+  (eval-when-compile
+    (char-fold-make-table))
   "Used for folding characters of the same group during search.
 This is a char-table with the `char-fold-table' subtype.
 

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-13 20:31     ` Juri Linkov
@ 2019-05-13 22:18       ` Noam Postavsky
  2019-05-14  6:37         ` Eli Zaretskii
  0 siblings, 1 reply; 16+ messages in thread
From: Noam Postavsky @ 2019-05-13 22:18 UTC (permalink / raw)
  To: Juri Linkov; +Cc: 35689

Juri Linkov <juri@linkov.net> writes:

> Oh, right.  Do you see a problem with a better patch:

> +(eval-and-compile (defcustom char-fold-include-base nil
> +  "Include mappings from composite character to base letter."
> +  :type 'boolean
> +  :set (lambda (sym val)
> +         (set sym val)
> +         (when (boundp 'char-fold-table)
> +           (setq char-fold-table (char-fold-make-table))))

Looks like it could work (though I haven't tested).  The docstrings are
too terse for me easily follow, and they should probably include
something along the lines of "Setting this variable directly does not
take effect; either use M-x customize or ..."





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-13 22:18       ` Noam Postavsky
@ 2019-05-14  6:37         ` Eli Zaretskii
  2019-05-14 20:14           ` Juri Linkov
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2019-05-14  6:37 UTC (permalink / raw)
  To: 35689, npostavs, juri

On May 14, 2019 1:18:18 AM GMT+03:00, Noam Postavsky <npostavs@gmail.com> wrote:
> Juri Linkov <juri@linkov.net> writes:
> 
> > Oh, right.  Do you see a problem with a better patch:
> 
> > +(eval-and-compile (defcustom char-fold-include-base nil
> > +  "Include mappings from composite character to base letter."
> > +  :type 'boolean
> > +  :set (lambda (sym val)
> > +         (set sym val)
> > +         (when (boundp 'char-fold-table)
> > +           (setq char-fold-table (char-fold-make-table))))
> 
> Looks like it could work (though I haven't tested).  The docstrings
> are
> too terse for me easily follow, and they should probably include
> something along the lines of "Setting this variable directly does not
> take effect; either use M-x customize or ..."

We don't gave defcustoms inside eval-and/when-compile anywhere else.  Do we really need this?  For starters, it would defeat cus-dep.el, I think.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-14  6:37         ` Eli Zaretskii
@ 2019-05-14 20:14           ` Juri Linkov
  2019-05-16 14:47             ` npostavs
  0 siblings, 1 reply; 16+ messages in thread
From: Juri Linkov @ 2019-05-14 20:14 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 35689, npostavs

>> > Oh, right.  Do you see a problem with a better patch:
>>
>> > +(eval-and-compile (defcustom char-fold-include-base nil
>> > +  "Include mappings from composite character to base letter."
>> > +  :type 'boolean
>> > +  :set (lambda (sym val)
>> > +         (set sym val)
>> > +         (when (boundp 'char-fold-table)
>> > +           (setq char-fold-table (char-fold-make-table))))
>>
>> Looks like it could work (though I haven't tested).  The docstrings
>> are
>> too terse for me easily follow, and they should probably include
>> something along the lines of "Setting this variable directly does not
>> take effect; either use M-x customize or ..."
>
> We don't gave defcustoms inside eval-and/when-compile anywhere else.
> Do we really need this?  For starters, it would defeat cus-dep.el, I think.

Indeed, better to try and simplify this.  The goal is to pre-compile
the default char-table because its calculation is compute-intensive,
and to recalculate a new value of char-table only in case
when customized values differ from the default values.

I can't find a standard way of doing this.  So instead of using eval-and-compile
I'll try to recalculate the value explicitly when variables are customized:

  (when (or (get 'char-fold-include-base  'customized-value)
            (get 'char-fold-include-alist 'customized-value)
            (get 'char-fold-exclude-alist 'customized-value))
    (setq char-fold-table (char-fold-make-table)))





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-14 20:14           ` Juri Linkov
@ 2019-05-16 14:47             ` npostavs
  2019-05-16 20:13               ` Juri Linkov
  0 siblings, 1 reply; 16+ messages in thread
From: npostavs @ 2019-05-16 14:47 UTC (permalink / raw)
  To: Juri Linkov; +Cc: 35689, npostavs

Juri Linkov <juri@linkov.net> writes:

>> We don't gave defcustoms inside eval-and/when-compile anywhere else.
>> Do we really need this?  For starters, it would defeat cus-dep.el, I think.
>
> Indeed, better to try and simplify this.  The goal is to pre-compile
> the default char-table because its calculation is compute-intensive,
> and to recalculate a new value of char-table only in case
> when customized values differ from the default values.
>
> I can't find a standard way of doing this.  So instead of using eval-and-compile
> I'll try to recalculate the value explicitly when variables are customized:
>
>   (when (or (get 'char-fold-include-base  'customized-value)
>             (get 'char-fold-include-alist 'customized-value)
>             (get 'char-fold-exclude-alist 'customized-value))
>     (setq char-fold-table (char-fold-make-table)))

Instead of looking at symbol property values, which can make for a
confusing time when setting variables outside of customize, I think it
would be nicer to do something like this:

    (eval-and-compile (defconst char-fold--include-base-default ...))

    (defcustom char-fold-include-base char-fold--include-base-default
      :initialize #'custom-initialize-changed
      :set (lambda (sym val)
             (set-default sym val)
             ;; FIXME: Maybe delay this until after-init-time,
             ;; to avoid redundant calls to char-fold-make-table.
             (setq char-fold-table (char-fold-make-table)))
      ...)

    (eval-and-compile
      (defun char-fold-make-table ()
         ...
         (or (bound-and-true-p 'char-fold-include-base)
             char-fold--include-base-default)
         ...))







^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-16 14:47             ` npostavs
@ 2019-05-16 20:13               ` Juri Linkov
  2019-05-21 20:34                 ` Juri Linkov
  0 siblings, 1 reply; 16+ messages in thread
From: Juri Linkov @ 2019-05-16 20:13 UTC (permalink / raw)
  To: npostavs; +Cc: 35689

>> I can't find a standard way of doing this.  So instead of using eval-and-compile
>> I'll try to recalculate the value explicitly when variables are customized:
>>
>>   (when (or (get 'char-fold-include-base  'customized-value)
>>             (get 'char-fold-include-alist 'customized-value)
>>             (get 'char-fold-exclude-alist 'customized-value))
>>     (setq char-fold-table (char-fold-make-table)))
>
> Instead of looking at symbol property values, which can make for a
> confusing time when setting variables outside of customize, I think it
> would be nicer to do something like this:
>
>     (eval-and-compile (defconst char-fold--include-base-default ...))
>
>     (defcustom char-fold-include-base char-fold--include-base-default
>       :initialize #'custom-initialize-changed

I tried different possible values of :initialize,
but not custom-initialize-changed.  I'll try this now.

The problem I encountered with the previous solution it that
calling `(setq char-fold-table (char-fold-make-table))' above
while loading char-fold.el by autoload, garbled data returned
from `(unicode-property-table-internal 'decomposition)',
it just returned garbage, maybe due to a broken coding.
I was busy debugging unidata-get-decomposition to
understand where this data corruption occurs.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-16 20:13               ` Juri Linkov
@ 2019-05-21 20:34                 ` Juri Linkov
  2019-05-21 21:45                   ` npostavs
  2019-06-24 17:33                   ` Lars Ingebrigtsen
  0 siblings, 2 replies; 16+ messages in thread
From: Juri Linkov @ 2019-05-21 20:34 UTC (permalink / raw)
  To: npostavs; +Cc: 35689

[-- Attachment #1: Type: text/plain, Size: 1315 bytes --]

>>> I can't find a standard way of doing this.  So instead of using eval-and-compile
>>> I'll try to recalculate the value explicitly when variables are customized:
>>>
>>>   (when (or (get 'char-fold-include-base  'customized-value)
>>>             (get 'char-fold-include-alist 'customized-value)
>>>             (get 'char-fold-exclude-alist 'customized-value))
>>>     (setq char-fold-table (char-fold-make-table)))
>>
>> Instead of looking at symbol property values, which can make for a
>> confusing time when setting variables outside of customize, I think it
>> would be nicer to do something like this:
>>
>>     (defcustom char-fold-include-base char-fold--include-base-default
>>       :initialize #'custom-initialize-changed
>>       :set (lambda (sym val)
>>              (set-default sym val)
>>              ;; FIXME: Maybe delay this until after-init-time,
>>              ;; to avoid redundant calls to char-fold-make-table.
>
> I tried different possible values of :initialize,
> but not custom-initialize-changed.  I'll try this now.

I see no problems other than redundant calls to char-fold-make-table
when more than one variable is customized.  char-fold.el is autoloaded
when isearch calls char-fold-to-regexp for the first time, so I'm not
sure how after-init-hook could help in this case.


[-- Attachment #2: char-fold-defcustom.4.patch --]
[-- Type: text/x-diff, Size: 5387 bytes --]

diff --git a/lisp/char-fold.el b/lisp/char-fold.el
index 426b1a9f84..16d6d484f0 100644
--- a/lisp/char-fold.el
+++ b/lisp/char-fold.el
@@ -21,13 +21,22 @@
 
 ;;; Code:
 
-(eval-and-compile (put 'char-fold-table 'char-table-extra-slots 1))
+(eval-and-compile
+  (put 'char-fold-table 'char-table-extra-slots 1)
+  (defconst char-fold--symmetric-default nil)
+  (defconst char-fold--include-alist-default
+    '((?\" """ "“" "”" "”" "„" "⹂" "〞" "‟" "‟" "❞" "❝" "❠" "“" "„" "〝" "〟" "🙷" "🙶" "🙸" "«" "»")
+      (?' "❟" "❛" "❜" "‘" "’" "‚" "‛" "‚" "󠀢" "❮" "❯" "‹" "›")
+      (?` "❛" "‘" "‛" "󠀢" "❮" "‹")))
+  (defconst char-fold--exclude-alist-default nil))
+
 \f
-(defconst char-fold-table
-  (eval-when-compile
-    (let ((equiv (make-char-table 'char-fold-table))
-          (equiv-multi (make-char-table 'char-fold-table))
-          (table (unicode-property-table-internal 'decomposition)))
+(eval-and-compile
+  (defun char-fold-make-table ()
+    (let* ((equiv (make-char-table 'char-fold-table))
+           (equiv-multi (make-char-table 'char-fold-table))
+           (search-spaces-regexp nil) ; bug#35802
+           (table (unicode-property-table-internal 'decomposition)))
       (set-char-table-extra-slot equiv 0 equiv-multi)
 
       ;; Ensure the table is populated.
@@ -75,7 +84,12 @@ char-fold-table
                                       (aref equiv-multi (car decomp))))
                         (aset equiv (car decomp)
                               (cons (char-to-string char)
-                                    (aref equiv (car decomp))))))))
+                                    (aref equiv (car decomp))))
+                        (when (or (bound-and-true-p char-fold-symmetric)
+                                  char-fold--symmetric-default)
+                          (aset equiv char
+                                (cons (char-to-string (car decomp))
+                                      (aref equiv (car decomp)))))))))
                (funcall make-decomp-match-char decomp char)
                ;; Do it again, without the non-spacing characters.
                ;; This allows 'a' to match 'ä'.
@@ -97,13 +111,20 @@ char-fold-table
        table)
 
       ;; Add some manual entries.
-      (dolist (it '((?\" """ "“" "”" "”" "„" "⹂" "〞" "‟" "‟" "❞" "❝" "❠" "“" "„" "〝" "〟" "🙷" "🙶" "🙸" "«" "»")
-                    (?' "❟" "❛" "❜" "‘" "’" "‚" "‛" "‚" "󠀢" "❮" "❯" "‹" "›")
-                    (?` "❛" "‘" "‛" "󠀢" "❮" "‹")))
+      (dolist (it (or (bound-and-true-p char-fold-include-alist)
+                      char-fold--include-alist-default))
         (let ((idx (car it))
               (chars (cdr it)))
           (aset equiv idx (append chars (aref equiv idx)))))
 
+      ;; Remove some entries.
+      (dolist (it (or (bound-and-true-p char-fold-exclude-alist)
+                      char-fold--exclude-alist-default))
+        (let ((idx (car it))
+              (char (cdr it)))
+          (when (aref equiv idx)
+            (aset equiv idx (remove (char-to-string char) (aref equiv idx))))))
+
       ;; Convert the lists of characters we compiled into regexps.
       (map-char-table
        (lambda (char dec-list)
@@ -112,7 +133,11 @@ char-fold-table
                (set-char-table-range equiv char re)
              (aset equiv char re))))
        equiv)
-      equiv))
+      equiv)))
+
+(defconst char-fold-table
+  (eval-when-compile
+    (char-fold-make-table))
   "Used for folding characters of the same group during search.
 This is a char-table with the `char-fold-table' subtype.
 
@@ -135,6 +160,40 @@ char-fold-table
 
 Exceptionally for the space character (32), ALIST is ignored.")
 
+(defcustom char-fold-symmetric char-fold--symmetric-default
+  "Include symmetric mappings from composite character back to base letter."
+  :type 'boolean
+  :initialize #'custom-initialize-changed
+  :set (lambda (sym val)
+         (set-default sym val)
+         ;; FIXME: Maybe delay this until after-init-hook,
+         ;; to avoid redundant calls to char-fold-make-table.
+         (setq char-fold-table (char-fold-make-table)))
+  :group 'matching
+  :version "27.1")
+
+(defcustom char-fold-include-alist char-fold--include-alist-default
+  "Additional character mappings to include."
+  :type '(alist :key-type (character :tag "From")
+                :value-type (repeat (string :tag "To")))
+  :initialize #'custom-initialize-changed
+  :set (lambda (sym val)
+         (set-default sym val)
+         (setq char-fold-table (char-fold-make-table)))
+  :group 'lisp
+  :version "27.1")
+
+(defcustom char-fold-exclude-alist char-fold--exclude-alist-default
+  "Character mappings to exclude from default setting."
+  :type '(alist :key-type (character :tag "From")
+                :value-type (character :tag "To"))
+  :initialize #'custom-initialize-changed
+  :set (lambda (sym val)
+         (set-default sym val)
+         (setq char-fold-table (char-fold-make-table)))
+  :group 'lisp
+  :version "27.1")
+
 (defun char-fold--make-space-string (n)
   "Return a string that matches N spaces."
   (format "\\(?:%s\\|%s\\)"

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-21 20:34                 ` Juri Linkov
@ 2019-05-21 21:45                   ` npostavs
  2019-06-06 20:49                     ` Juri Linkov
  2019-06-24 17:33                   ` Lars Ingebrigtsen
  1 sibling, 1 reply; 16+ messages in thread
From: npostavs @ 2019-05-21 21:45 UTC (permalink / raw)
  To: Juri Linkov; +Cc: 35689, npostavs

Juri Linkov <juri@linkov.net> writes:

>>>       :set (lambda (sym val)
>>>              (set-default sym val)
>>>              ;; FIXME: Maybe delay this until after-init-time,
>>>              ;; to avoid redundant calls to char-fold-make-table.
>>
>> I tried different possible values of :initialize,
>> but not custom-initialize-changed.  I'll try this now.
>
> I see no problems other than redundant calls to char-fold-make-table
> when more than one variable is customized.  char-fold.el is autoloaded
> when isearch calls char-fold-to-regexp for the first time, so I'm not
> sure how after-init-hook could help in this case.

Ah, sorry, I had somehow got it into my head that char-fold.el is
preloaded.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-21 21:45                   ` npostavs
@ 2019-06-06 20:49                     ` Juri Linkov
  0 siblings, 0 replies; 16+ messages in thread
From: Juri Linkov @ 2019-06-06 20:49 UTC (permalink / raw)
  To: npostavs; +Cc: 35689

>>>>       :set (lambda (sym val)
>>>>              (set-default sym val)
>>>>              ;; FIXME: Maybe delay this until after-init-time,
>>>>              ;; to avoid redundant calls to char-fold-make-table.
>>>
>>> I tried different possible values of :initialize,
>>> but not custom-initialize-changed.  I'll try this now.
>>
>> I see no problems other than redundant calls to char-fold-make-table
>> when more than one variable is customized.  char-fold.el is autoloaded
>> when isearch calls char-fold-to-regexp for the first time, so I'm not
>> sure how after-init-hook could help in this case.
>
> Ah, sorry, I had somehow got it into my head that char-fold.el is
> preloaded.

I still haven't found a way to avoid calling char-fold-make-table
3 times when 3 variables are customized.  Maybe this is not possible
because currently customizable variables have no dependency on each other.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-21 20:34                 ` Juri Linkov
  2019-05-21 21:45                   ` npostavs
@ 2019-06-24 17:33                   ` Lars Ingebrigtsen
  2019-06-24 20:40                     ` Juri Linkov
  1 sibling, 1 reply; 16+ messages in thread
From: Lars Ingebrigtsen @ 2019-06-24 17:33 UTC (permalink / raw)
  To: Juri Linkov; +Cc: 35689, npostavs

Juri Linkov <juri@linkov.net> writes:

> -(defconst char-fold-table

[...]

> +(defcustom char-fold-symmetric char-fold--symmetric-default
> +  "Include symmetric mappings from composite character back to base letter."
> +  :type 'boolean
> +  :initialize #'custom-initialize-changed
> +  :set (lambda (sym val)
> +         (set-default sym val)
> +         ;; FIXME: Maybe delay this until after-init-hook,
> +         ;; to avoid redundant calls to char-fold-make-table.
> +         (setq char-fold-table (char-fold-make-table)))

OK, here's an uninformed suggestion -- instead of doing all this to
ensure that we have an updated char-fold-table when the user changes
these defaults, why not call char-fold-make-table when needed?

That is, instead of the char-fold-table variable, you'd have a
char-fold-data, which could be, say, something like this:

(defvar char-fold-data :uninitialized)

`char-fold-to-regexp' (and others) would then start with a call to
char-fold-update which would 

be

(let ((new (list :additional char-fold--include-alist-default
                 :exclude char-fold--exclude-alist-default
                 ...)))
  (unless (equal char-fold-data new)
    (setq char-fold-table (char-fold-make-table)
          char-fold-data new)))

or something along those lines.  That is, check whether anything has
changed, and if not, do nothing, but if it has, recompute?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-06-24 17:33                   ` Lars Ingebrigtsen
@ 2019-06-24 20:40                     ` Juri Linkov
  0 siblings, 0 replies; 16+ messages in thread
From: Juri Linkov @ 2019-06-24 20:40 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 35689, npostavs

>> +(defcustom char-fold-symmetric char-fold--symmetric-default
>> +  "Include symmetric mappings from composite character back to base letter."
>> +  :type 'boolean
>> +  :initialize #'custom-initialize-changed
>> +  :set (lambda (sym val)
>> +         (set-default sym val)
>> +         ;; FIXME: Maybe delay this until after-init-hook,
>> +         ;; to avoid redundant calls to char-fold-make-table.
>> +         (setq char-fold-table (char-fold-make-table)))
>
> OK, here's an uninformed suggestion -- instead of doing all this to
> ensure that we have an updated char-fold-table when the user changes
> these defaults, why not call char-fold-make-table when needed?
>
> That is, instead of the char-fold-table variable, you'd have a
> char-fold-data, which could be, say, something like this:
>
> (defvar char-fold-data :uninitialized)
>
> `char-fold-to-regexp' (and others) would then start with a call to
> char-fold-update which would
>
> be
>
> (let ((new (list :additional char-fold--include-alist-default
>                  :exclude char-fold--exclude-alist-default
>                  ...)))
>   (unless (equal char-fold-data new)
>     (setq char-fold-table (char-fold-make-table)
>           char-fold-data new)))
>
> or something along those lines.  That is, check whether anything has
> changed, and if not, do nothing, but if it has, recompute?

Thanks for the idea, I'll try to use such composite value to detect
updates in one of three variables.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-11 21:22 bug#35689: Customizable char-fold Juri Linkov
  2019-05-12 19:12 ` Juri Linkov
@ 2019-07-23 20:28 ` Juri Linkov
  2019-07-28 22:46 ` Juri Linkov
  2 siblings, 0 replies; 16+ messages in thread
From: Juri Linkov @ 2019-07-23 20:28 UTC (permalink / raw)
  To: 35689-done

Thanks to everyone who helped!  Pushed to master as 376f5df3cc.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#35689: Customizable char-fold
  2019-05-11 21:22 bug#35689: Customizable char-fold Juri Linkov
  2019-05-12 19:12 ` Juri Linkov
  2019-07-23 20:28 ` Juri Linkov
@ 2019-07-28 22:46 ` Juri Linkov
  2 siblings, 0 replies; 16+ messages in thread
From: Juri Linkov @ 2019-07-28 22:46 UTC (permalink / raw)
  To: 35689

[-- Attachment #1: Type: text/plain, Size: 403 bytes --]

tags 35689 + fixed
close 35689 27.0.50
quit

I'm closing this customization feature request.

More default values for char-folding could be added depending on user's locale.
But this is another feature that could be implemented within i18n efforts.

PS: As a demonstration what the current customization feature can achieve,
I'm attaching a short snippet that allows searching using Cyrillic translit:


[-- Attachment #2: char-fold-translit.el --]
[-- Type: application/emacs-lisp, Size: 1808 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2019-07-28 22:46 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-11 21:22 bug#35689: Customizable char-fold Juri Linkov
2019-05-12 19:12 ` Juri Linkov
2019-05-12 20:30   ` Noam Postavsky
2019-05-13 20:31     ` Juri Linkov
2019-05-13 22:18       ` Noam Postavsky
2019-05-14  6:37         ` Eli Zaretskii
2019-05-14 20:14           ` Juri Linkov
2019-05-16 14:47             ` npostavs
2019-05-16 20:13               ` Juri Linkov
2019-05-21 20:34                 ` Juri Linkov
2019-05-21 21:45                   ` npostavs
2019-06-06 20:49                     ` Juri Linkov
2019-06-24 17:33                   ` Lars Ingebrigtsen
2019-06-24 20:40                     ` Juri Linkov
2019-07-23 20:28 ` Juri Linkov
2019-07-28 22:46 ` Juri Linkov

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).