From 50c623de5e4ac3a101a2fa19de97f75132063554 Mon Sep 17 00:00:00 2001 From: Morgan Willcock Date: Sat, 5 Oct 2024 18:33:51 +0100 Subject: [PATCH 1/2] Rewrite speedbar expansion for all descendants Rewrite 'speedbar-expand-line-descendants' to avoid getting into an infinite loop by reaching max-lisp-eval-depth. The new method avoids querying and displaying information for every movement, instead using a single message to indicate that expansion is in progress, and so is significantly faster. The narrowing per item introduced by the fix for bug#35014 is removed because it prevented expanded descendant items when the top-level item was already expanded. * lisp/speedbar.el (speedbar--get-line-indent-level): New function to return the indentation level of the current line. (speedbar-expand-line-descendants): Use simpler line motion and no recursion. Output messages indicating when expansion is in progress and when it is completed. Fix expansion of descendants where the top-level item was already expanded. --- lisp/speedbar.el | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/lisp/speedbar.el b/lisp/speedbar.el index c13c977938b..38fb641acf7 100644 --- a/lisp/speedbar.el +++ b/lisp/speedbar.el @@ -3168,25 +3168,32 @@ speedbar-toggle-line-expansion (speedbar-do-function-pointer)) (error (speedbar-position-cursor-on-line)))) +(defun speedbar--get-line-indent-level () + "Return the indentation level of the current line." + (save-excursion + (beginning-of-line) + (if (looking-at "[0-9]+:") + (string-to-number (match-string 0)) + 0))) + (defun speedbar-expand-line-descendants (&optional arg) "Expand the line under the cursor and all descendants. Optional argument ARG indicates that any cache should be flushed." (interactive "P") - (save-restriction - (narrow-to-region (line-beginning-position) - (line-beginning-position 2)) - (speedbar-expand-line arg) - ;; Now, inside the area expanded here, expand all subnodes of - ;; the same descendant type. - (save-excursion - (speedbar-next 1) ;; Move into the list. - (let ((err nil)) - (while (not err) - (condition-case nil - (progn - (speedbar-expand-line-descendants arg) - (speedbar-restricted-next 1)) - (error (setq err t)))))))) + (dframe-message "Expanding all descendants...") + (save-excursion + (let ((top-depth (speedbar--get-line-indent-level))) + ;; Attempt to expand the top-level item. + (speedbar-expand-line arg) + ;; Move forwards, either into the newly expanded list, onto an + ;; already expanded list, onto a sibling item, or to the end of + ;; the buffer. + (while (and (zerop (forward-line 1)) + (not (eobp)) + (> (speedbar--get-line-indent-level) top-depth) + (speedbar-expand-line arg))))) + (dframe-message "Expanding all descendants...done") + (speedbar-position-cursor-on-line)) (defun speedbar-contract-line-descendants () "Expand the line under the cursor and all descendants." -- 2.39.5