From: Lars Ingebrigtsen Date: Fri, 17 Sep 2021 15:54:21 +0000 (+0200) Subject: Stop imenu indexing after a certain number of seconds X-Git-Tag: emacs-28.0.90~893 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=a8103cf9e08cdc159c4824d2b3b08cc5882fae76;p=emacs.git Stop imenu indexing after a certain number of seconds * doc/emacs/programs.texi (Imenu): Document it. * lisp/imenu.el (imenu-max-index-time): New user option. (imenu-default-create-index-function, imenu--generic-function): Use it (bug#18696). --- diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi index 37a15b6d5f6..ec11b0c00f2 100644 --- a/doc/emacs/programs.texi +++ b/doc/emacs/programs.texi @@ -275,8 +275,10 @@ a non-@code{nil} value. There is no need to rescan because of small changes in the text. @vindex imenu-auto-rescan-maxout +@vindex imenu-max-index-time @code{imenu-auto-rescan} will be disabled in buffers that are larger -than @code{imenu-auto-rescan-maxout} in bytes. +than @code{imenu-auto-rescan-maxout} in bytes, and scanning is +stopped if it takes more than @code{imenu-max-index-time} seconds. @vindex imenu-sort-function You can customize the way the menus are sorted by setting the diff --git a/etc/NEWS b/etc/NEWS index 9606eded505..2201dd7a3b9 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2929,6 +2929,13 @@ This previously used to align subsequent lines with the last sibling, but it now aligns with the first sibling (which is the preferred style in Ruby). +** Imenu + ++++ +*** New user option 'imenu-max-index-time'. +If creating the imenu index takes longer than specified by this +variable (default 5 seconds), imenu indexing is stopped. + * New Modes and Packages in Emacs 28.1 diff --git a/lisp/imenu.el b/lisp/imenu.el index 2024bb1e066..788755a2d7e 100644 --- a/lisp/imenu.el +++ b/lisp/imenu.el @@ -85,7 +85,8 @@ This might not yet be honored by all index-building functions." :type 'boolean) (defcustom imenu-auto-rescan-maxout 600000 - "Imenu auto-rescan is disabled in buffers larger than this size (in bytes)." + "Imenu auto-rescan is disabled in buffers larger than this size (in bytes). +Also see `imenu-max-index-time'." :type 'integer :version "26.2") @@ -153,6 +154,11 @@ uses `imenu--generic-function')." :type 'boolean :version "24.4") +(defcustom imenu-max-index-time 5 + "Max time to use when creating imenu indices." + :type 'number + :version "28.1") + ;;;###autoload (defvar-local imenu-generic-expression nil "List of definition matchers for creating an Imenu index. @@ -520,10 +526,13 @@ The alternate method, which is the one most often used, is to call (cond ((and imenu-prev-index-position-function imenu-extract-index-name-function) (let ((index-alist '()) (pos (point-max)) + (start (float-time)) name) (goto-char pos) ;; Search for the function - (while (funcall imenu-prev-index-position-function) + (while (and (funcall imenu-prev-index-position-function) + ;; Don't use an excessive amount of time. + (< (- (float-time) start) imenu-max-index-time)) (unless (< (point) pos) (error "Infinite loop at %s:%d: imenu-prev-index-position-function does not move point" (buffer-name) pos)) (setq pos (point)) @@ -576,6 +585,7 @@ depending on PATTERNS." (not (local-variable-p 'font-lock-defaults))) imenu-case-fold-search (nth 2 font-lock-defaults))) + (start-time (float-time)) (old-table (syntax-table)) (table (copy-syntax-table (syntax-table))) (slist imenu-syntax-alist)) @@ -618,7 +628,13 @@ depending on PATTERNS." (not invis)))))) ;; Exit the loop if we get an empty match, ;; because it means a bad regexp was specified. - (not (= (match-beginning 0) (match-end 0)))) + (not (= (match-beginning 0) (match-end 0))) + ;; Don't take an excessive amount of time. + (or (< (- (float-time) start-time) + imenu-max-index-time) + (progn + (message "`imenu-max-index-time' exceeded") + nil))) (setq start (point)) ;; Record the start of the line in which the match starts. ;; That's the official position of this definition.