branch: scratch/editorconfig commit c70df617723d1bf06ad390089e6a7bc7395a9eca Author: Stefan Monnier <monn...@iro.umontreal.ca> Commit: Stefan Monnier <monn...@iro.umontreal.ca>
(editorconfig-core-handle--parse-file): Streamline * editorconfig-core-handle.el: Change copyright to the FSF since all the contributors have signed the corresponding paperwork. (editorconfig-core-handle--parse-file): Directly return a `editorconfig-core-handle`; parse the buffer directly rather than matching on strings extracted from the buffer; avoid O(N²) complexity by constructing the lists in reverse and using `nreverse` at the end. (editorconfig-core-handle): Simplify accordingly. (editorconfig-core-handle--string-trim): Delete function, not used any more. --- editorconfig-core-handle.el | 130 ++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 77 deletions(-) diff --git a/editorconfig-core-handle.el b/editorconfig-core-handle.el index 20f52a3b97..8ab8a5b191 100644 --- a/editorconfig-core-handle.el +++ b/editorconfig-core-handle.el @@ -1,27 +1,29 @@ ;;; editorconfig-core-handle.el --- Handle Class for EditorConfig File -*- 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: @@ -75,8 +77,7 @@ Slots: Last modified time of .editorconfig file. `path' - Absolute path to .editorconfig file.' -" + Absolute path to .editorconfig file." (top-props nil) (sections nil) (mtime nil) @@ -94,12 +95,7 @@ If CONF does not exist return nil." (equal (editorconfig-core-handle-mtime cached) mtime)) cached (let ((parsed (editorconfig-core-handle--parse-file conf))) - (puthash conf - (make-editorconfig-core-handle :top-props (plist-get parsed :top-props) - :sections (plist-get parsed :sections) - :mtime mtime - :path conf) - editorconfig-core-handle--cache-hash)))))) + (puthash conf parsed editorconfig-core-handle--cache-hash)))))) (defun editorconfig-core-handle-root-p (handle) "Return non-nil if HANDLE represent root EditorConfig file. @@ -153,21 +149,10 @@ This function is a fnmatch with a few modification for EditorConfig usage." (or (editorconfig-fnmatch-p name pattern) (editorconfig-fnmatch-p name (concat "**/" pattern))))) -(defsubst editorconfig-core-handle--string-trim (str) - "Remove leading and trailing whitespaces from STR." - (replace-regexp-in-string "[[:space:]]+\\'" - "" - (replace-regexp-in-string "\\`[[:space:]]+" - "" - str))) - (defun editorconfig-core-handle--parse-file (conf) "Parse EditorConfig file CONF. -This function returns cons of its top properties alist and -alist of patterns and its properties alist. -The list returned will be ordered by the lines they appear. - +This function returns a `editorconfig-core-handle'. If CONF is not found return nil." (when (file-readable-p conf) (with-temp-buffer @@ -175,12 +160,9 @@ If CONF is not found return nil." ;; code conversion (insert-file-contents conf) (goto-char (point-min)) - (let ((point-max (point-max)) - (sections ()) + (let ((sections ()) (top-props nil) - ;; String of current line - (line "") ;; nil when pattern not appeared yet, "" when pattern is empty ("[]") (pattern nil) ;; Alist of properties for current PATTERN @@ -188,58 +170,52 @@ If CONF is not found return nil." ;; Current line num (current-line-number 1)) - (while (not (eq (point) point-max)) - (setq line - (buffer-substring-no-properties (line-beginning-position) - (line-end-position))) - (setq line - (replace-regexp-in-string "\\(^\\| \\)\\(#\\|;\\).*$" - "" - (editorconfig-core-handle--string-trim line))) - + (while (not (eobp)) + (skip-chars-forward " \t\f") (cond - ((string-equal "" line) + ((looking-at "\\(?:[#;].*\\)?$") nil) ;; Start of section - ((string-match "^\\[\\(.*\\)\\]$" - line) - (when pattern - (setq sections - `(,@sections ,(make-editorconfig-core-handle-section - :name pattern - :props props))) - (setq pattern nil) - (setq props nil)) - (setq pattern (match-string 1 line))) - - (t - (let ((idx (string-match "=\\|:" line))) - (unless idx - (error "Error while reading config file: %s:%d:\n %s\n" - conf current-line-number line)) - (let ((key (downcase (editorconfig-core-handle--string-trim - (substring line 0 idx)))) - (value (editorconfig-core-handle--string-trim - (substring line (1+ idx))))) - (when (and (< (length key) 51) - (< (length value) 256)) - (if pattern - (when (< (length pattern) 4097) - (setq props - `(,@props (,key . ,value)))) - (setq top-props - `(,@top-props (,key . ,value))))))))) + ((looking-at "\\[\\(.*\\)\\][ \t]*$") + (let ((newpattern (match-string 1))) + (when pattern + (push (make-editorconfig-core-handle-section + :name pattern + :props (nreverse props)) + sections)) + (setq props nil) + (setq pattern newpattern))) + + ((looking-at "\\([^=: \t]+\\)[ \t]*[=:][ \t]*\\(.*?\\)[ \t]*$") + (let ((key (downcase (match-string 1))) + (value (match-string 2))) + (when (and (< (length key) 51) + (< (length value) 256)) + (if pattern + (when (< (length pattern) 4097) ;;FIXME: 4097? + (push `(,key . ,value) + props)) + (push `(,key . ,value) + top-props))))) + + (t (error "Error while reading config file: %s:%d:\n %s\n" + conf current-line-number + (buffer-substring-no-properties (line-beginning-position) + (line-end-position))))) (setq current-line-number (1+ current-line-number)) (goto-char (point-min)) (forward-line (1- current-line-number))) (when pattern - (setq sections - `(,@sections ,(make-editorconfig-core-handle-section - :name pattern - :props props)))) - (list :top-props top-props - :sections sections))))) + (push (make-editorconfig-core-handle-section + :name pattern + :props (nreverse props)) + sections)) + (make-editorconfig-core-handle + :top-props (nreverse top-props) + :sections (nreverse sections) + :mtime (nth 5 (file-attributes conf)) + :path conf))))) (provide 'editorconfig-core-handle) ;;; editorconfig-core-handle.el ends here