branch: scratch/editorconfig commit 25f45dc3b506558087a312ceda98192195612adf Author: Stefan Monnier <monn...@iro.umontreal.ca> Commit: Stefan Monnier <monn...@iro.umontreal.ca>
(editorconfig-fnmatch-p): Speed up * editorconfig-fnmatch.el: Change copyright to the FSF since all the contributors have signed the corresponding paperwork. (editorconfig-fnmatch-p): Remove autoload cookie since all users do `require` anyway. (editorconfig-fnmatch--do-translate): Push in reverse order and `reverse` at the end to avoid the usual O(N²) complexity. --- editorconfig-fnmatch.el | 124 ++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/editorconfig-fnmatch.el b/editorconfig-fnmatch.el index 520aeb16c2..374c814394 100644 --- a/editorconfig-fnmatch.el +++ b/editorconfig-fnmatch.el @@ -1,27 +1,29 @@ -;;; editorconfig-fnmatch.el --- Glob pattern matching in Emacs lisp -*- lexical-binding: t -*- +;;; editorconfig-fnmatch.el --- Glob pattern matching -*- lexical-binding: t -*- -;; Copyright (C) 2011-2024 EditorConfig Team +;; Copyright (C) 2011-2024 Free Software Foundation, Inc. ;; Author: EditorConfig Team <editorcon...@googlegroups.com> +;; Package: editorconfig ;; See -;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors -;; or the CONTRIBUTORS file for the list of contributors. +;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors or +;; https://github.com/editorconfig/editorconfig-emacs/blob/master/CONTRIBUTORS +;; for the list of contributors. ;; This file is part of EditorConfig Emacs Plugin. ;; EditorConfig Emacs Plugin is free software: you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or (at your -;; option) any later version. +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. ;; EditorConfig Emacs Plugin is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -;; Public License for more details. +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +;; See the GNU General Public License for more details. -;; You should have received a copy of the GNU General Public License along with -;; EditorConfig Emacs Plugin. If not, see <https://www.gnu.org/licenses/>. +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. ;;; Commentary: @@ -83,7 +85,6 @@ string (substring string (match-end 0)))) num)) -;;;###autoload (defun editorconfig-fnmatch-p (string pattern) "Test whether STRING match PATTERN. @@ -128,7 +129,7 @@ translation is found for PATTERN." (length (length pattern)) (brace-level 0) (in-brackets nil) - ;; List of strings of resulting regexp + ;; List of strings of resulting regexp, in reverse order. (result ()) (is-escaped nil) (matching-braces (= (editorconfig-fnmatch--match-num @@ -146,14 +147,15 @@ translation is found for PATTERN." (while (< index length) (if (and (not is-escaped) - (string-match "[^]\\*?[{},/\\-]+" + (string-match "[^]\\*?[{},/-]+" ;;(string-match "[^]\\*?[{},/\\-]+" "?.a") pattern index) (eq index (match-beginning 0))) - (setq result `(,@result ,(regexp-quote (match-string 0 pattern))) - index (match-end 0) - is-escaped nil) + (progn + (push (regexp-quote (match-string 0 pattern)) result) + (setq index (match-end 0) + is-escaped nil)) (setq current-char (aref pattern index) index (1+ index)) @@ -163,19 +165,20 @@ translation is found for PATTERN." (setq pos index) (if (and (< pos length) (= (aref pattern pos) ?*)) - (setq result `(,@result ".*")) - (setq result `(,@result "[^/]*")))) + (push ".*" result) + (push "[^/]*" result))) (?? - (setq result `(,@result "[^/]"))) + (push "[^/]" result)) (?\[ (if in-brackets - (setq result `(,@result "\\[")) + (push "\\[" result) (if (= (aref pattern index) ?/) ;; Slash after an half-open bracket - (setq result `(,@result "\\[/") - index (+ index 1)) + (progn + (push "\\[/" result) + (setq index (+ index 1))) (setq pos index has-slash nil) (while (and (< pos length) @@ -186,28 +189,31 @@ translation is found for PATTERN." (setq has-slash t) (setq pos (1+ pos)))) (if has-slash - (setq result `(,@result ,(concat "\\[" - (substring pattern - index - (1+ pos)) - "\\]")) - index (+ pos 2)) + (progn + (push (concat "\\[" + (substring pattern + index + (1+ pos)) + "\\]") + result) + (setq index (+ pos 2))) (if (and (< index length) (memq (aref pattern index) '(?! ?^))) - (setq index (1+ index) - result `(,@result "[^")) - (setq result `(,@result "["))) + (progn + (setq index (1+ index)) + (push "[^" result)) + (push "[" result)) (setq in-brackets t))))) (?- (if in-brackets - (setq result `(,@result "-")) - (setq result `(,@result "\\-")))) + (push "-" result) + (push "\\-" result))) (?\] - (setq result `(,@result "]") - in-brackets nil)) + (push "]" result) + (setq in-brackets nil)) (?{ (setq pos index @@ -233,52 +239,56 @@ translation is found for PATTERN." pattern-sub))) (number-end (string-to-number (match-string 2 pattern-sub)))) - (setq result `(,@result ,(concat "\\(?:" - (mapconcat #'number-to-string - (cl-loop for i from number-start to number-end - collect i) - "\\|") - "\\)")))) + (push (concat "\\(?:" + (mapconcat #'number-to-string + (cl-loop for i from number-start to number-end + collect i) + "\\|") + "\\)") + result)) (let ((inner (editorconfig-fnmatch--do-translate pattern-sub t))) - (setq result `(,@result ,(format "{%s}" inner))))) + (push (format "{%s}" inner) result))) (setq index (1+ pos))) (if matching-braces - (setq result `(,@result "\\(?:") - brace-level (1+ brace-level)) - (setq result `(,@result "{"))))) + (progn + (push "\\(?:" result) + (setq brace-level (1+ brace-level))) + (push "{" result)))) (?, (if (and (> brace-level 0) (not is-escaped)) - (setq result `(,@result "\\|")) - (setq result `(,@result "\\,")))) + (push "\\|" result) + (push "\\," result))) (?} (if (and (> brace-level 0) (not is-escaped)) - (setq result `(,@result "\\)") - brace-level (- brace-level 1)) - (setq result `(,@result "}")))) + (progn + (push "\\)" result) + (setq brace-level (- brace-level 1))) + (push "}" result))) (?/ (if (and (<= (+ index 3) (length pattern)) (string= (substring pattern index (+ index 3)) "**/")) - (setq result `(,@result "\\(?:/\\|/.*/\\)") - index (+ index 3)) - (setq result `(,@result "/")))) + (progn + (push "\\(?:/\\|/.*/\\)" result) + (setq index (+ index 3))) + (push "/" result))) (t (unless (= current-char ?\\) - (setq result `(,@result ,(regexp-quote (char-to-string current-char))))))) + (push (regexp-quote (char-to-string current-char)) result)))) (if (= current-char ?\\) (progn (when is-escaped - (setq result `(,@result "\\\\"))) + (push "\\\\" result)) (setq is-escaped (not is-escaped))) (setq is-escaped nil)))) (unless nested - (setq result `("^" ,@result "\\'"))) - (apply #'concat result))) + (setq result `("\\'" ,@result "\\`"))) + (apply #'concat (reverse result)))) (provide 'editorconfig-fnmatch) ;;; editorconfig-fnmatch.el ends here