From 35c7dc06ed1bd27fc69b2a79e88a8cfb2a6b3dae Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Sat, 28 Nov 2015 10:32:46 +0000 Subject: [PATCH] * lisp/character-fold.el: Code simplifications (character-fold-table): Reduce the scope of a variable. (character-fold-to-regexp): Change logic to work directly on the input string. It's a little easier to understand, probably faster, and sets us up for implementing multi-char matches. * test/automated/character-fold-tests.el (character-fold--test-fold-to-regexp): New test. --- lisp/character-fold.el | 51 ++++++++++++-------------- test/automated/character-fold-tests.el | 10 +++++ 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/lisp/character-fold.el b/lisp/character-fold.el index 4b526c2027..749d1135ce 100644 --- a/lisp/character-fold.el +++ b/lisp/character-fold.el @@ -25,13 +25,14 @@ (defconst character-fold-table (eval-when-compile - (let* ((equiv (make-char-table 'character-fold-table)) - (table (unicode-property-table-internal 'decomposition)) - (func (char-table-extra-slot table 1))) + (let ((equiv (make-char-table 'character-fold-table)) + (table (unicode-property-table-internal 'decomposition))) ;; Ensure the table is populated. - (map-char-table - (lambda (char v) (when (consp char) (funcall func (car char) v table))) - table) + (let ((func (char-table-extra-slot table 1))) + (map-char-table (lambda (char v) + (when (consp char) + (funcall func (car char) v table))) + table)) ;; Compile a list of all complex characters that each simple ;; character should match. @@ -126,9 +127,10 @@ Any character in STRING that has an entry in `character-fold-table' is replaced with that entry (which is a regexp) and other characters are `regexp-quote'd." - (let* ((spaces 0) - (chars (mapcar #'identity string)) - (out chars)) + (let ((spaces 0) + (i 0) + (end (length string)) + (out nil)) ;; When the user types a space, we want to match the table entry ;; for ?\s, which is generally a regexp like "[ ...]". However, ;; the `search-spaces-regexp' variable doesn't "see" spaces inside @@ -137,24 +139,19 @@ regexp) and other characters are `regexp-quote'd." ;; search engine acts on a bunch of spaces, not on individual ;; spaces, so if the string contains sequential spaces like " ", we ;; need to keep them grouped together like this: "\\( \\|[ ...][ ...]\\)". - (while chars - (let ((c (car chars))) - (setcar chars - (cond - ((eq c ?\s) - (setq spaces (1+ spaces)) - nil) - ((> spaces 0) - (prog1 (concat (character-fold--make-space-string spaces) - (or (aref character-fold-table c) - (regexp-quote (string c)))) - (setq spaces 0))) - (t (or (aref character-fold-table c) - (regexp-quote (string c)))))) - (setq chars (cdr chars)))) - (concat (apply #'concat out) - (when (> spaces 0) - (character-fold--make-space-string spaces))))) + (while (< i end) + (pcase (aref string i) + (`?\s (setq spaces (1+ spaces))) + (c (when (> spaces 0) + (push (character-fold--make-space-string spaces) out) + (setq spaces 0)) + (push (or (aref character-fold-table c) + (regexp-quote (string c))) + out))) + (setq i (1+ i))) + (when (> spaces 0) + (push (character-fold--make-space-string spaces) out)) + (apply #'concat (nreverse out)))) ;;; Commands provided for completeness. diff --git a/test/automated/character-fold-tests.el b/test/automated/character-fold-tests.el index 2b1a15c9e7..40f0aecf44 100644 --- a/test/automated/character-fold-tests.el +++ b/test/automated/character-fold-tests.el @@ -54,5 +54,15 @@ (concat w1 "\s\n\s\t\f\t\n\r\t" w2) (concat w1 (make-string 90 ?\s) w2))))) +(ert-deftest character-fold--test-fold-to-regexp () + (let ((character-fold-table (make-char-table 'character-fold-table))) + (aset character-fold-table ?a "abc") + (aset character-fold-table ?1 "123") + (aset character-fold-table ?\s "-!-") + (should (equal (character-fold-to-regexp "a1a1") + "abc123abc123")) + (should (equal (character-fold-to-regexp "a1 a 1") + "abc123\\(?: \\|-!--!-\\)abc\\(?: \\|-!-\\)123")))) + (provide 'character-fold-tests) ;;; character-fold-tests.el ends here -- 2.39.2