]> git.eshelyaron.com Git - emacs.git/commitdiff
Stop imenu indexing after a certain number of seconds
authorLars Ingebrigtsen <larsi@gnus.org>
Fri, 17 Sep 2021 15:54:21 +0000 (17:54 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Fri, 17 Sep 2021 15:54:21 +0000 (17:54 +0200)
* 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).

doc/emacs/programs.texi
etc/NEWS
lisp/imenu.el

index 37a15b6d5f699beac344598d5ae5fe83934a864f..ec11b0c00f215d3d10cfddc83c92aa252709a721 100644 (file)
@@ -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
index 9606eded5058228884035ca0adcf0a8f5ca66215..2201dd7a3b9afe70fd53cee5da75fba9ae20e024 100644 (file)
--- 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.
+
 \f
 * New Modes and Packages in Emacs 28.1
 
index 2024bb1e06657d4b8ef545b4479e5a3859866cb1..788755a2d7ee19fd50028e76a3827834d89ce6f9 100644 (file)
@@ -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.