From bfa0cb81ddae6ce3e37f4cc4da4725a2f396d784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?El=C3=ADas=20Gabriel=20P=C3=A9rez?= Date: Tue, 18 Nov 2025 11:02:24 -0600 Subject: [PATCH] hideshow: Fix regressions. (Bug#79857) * lisp/progmodes/hideshow.el (hs-block-positions): Exit the function if 'hs-forward-sexp' fails. (hs-hide-level-recursive): Fix infloop. * test/lisp/progmodes/hideshow-tests.el (hideshow-hide-level-1): (hideshow-hide-level-2): Update tests. --- lisp/progmodes/hideshow.el | 66 +++++++++++++++------------ test/lisp/progmodes/hideshow-tests.el | 8 ++++ 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el index 62bbbe40164..78990993449 100644 --- a/lisp/progmodes/hideshow.el +++ b/lisp/progmodes/hideshow.el @@ -794,34 +794,39 @@ to call with the newly initialized overlay." This returns a list with the current code block beginning and end positions. This does nothing if there is not a code block at current point." - (save-match-data - (save-excursion - (when (funcall hs-looking-at-block-start-predicate) - (let ((mdata (match-data t)) - (header-end (match-end 0)) - block-beg block-end) - ;; `block-start' is the point at the end of the block - ;; beginning, which may need to be adjusted - (save-excursion - (when hs-adjust-block-beginning-function - (goto-char (funcall hs-adjust-block-beginning-function header-end))) - (setq block-beg (line-end-position))) - ;; `block-end' is the point at the end of the block - (hs-forward-sexp mdata 1) - (setq block-end - (cond ((and (stringp hs-block-end-regexp) - (looking-back hs-block-end-regexp nil)) - (match-beginning 0)) - ((functionp hs-block-end-regexp) - (funcall hs-block-end-regexp) - (match-beginning 0)) - (t (point)))) - ;; adjust block end (if needed) - (when hs-adjust-block-end-function + ;; `catch' is used here if the search fails due unbalanced parentheses + ;; or any other unknown error caused in `hs-forward-sexp'. + (catch 'hs-sexp-error + (save-match-data + (save-excursion + (when (funcall hs-looking-at-block-start-predicate) + (let ((mdata (match-data t)) + (header-end (match-end 0)) + block-beg block-end) + ;; `block-start' is the point at the end of the block + ;; beginning, which may need to be adjusted + (save-excursion + (when hs-adjust-block-beginning-function + (goto-char (funcall hs-adjust-block-beginning-function header-end))) + (setq block-beg (line-end-position))) + ;; `block-end' is the point at the end of the block + (condition-case _ + (hs-forward-sexp mdata 1) + (scan-error (throw 'hs-sexp-error nil))) (setq block-end - (or (funcall hs-adjust-block-end-function block-beg) - block-end))) - (list block-beg block-end)))))) + (cond ((and (stringp hs-block-end-regexp) + (looking-back hs-block-end-regexp nil)) + (match-beginning 0)) + ((functionp hs-block-end-regexp) + (funcall hs-block-end-regexp) + (match-beginning 0)) + (t (point)))) + ;; adjust block end (if needed) + (when hs-adjust-block-end-function + (setq block-end + (or (funcall hs-adjust-block-end-function block-beg) + block-end))) + (list block-beg block-end))))))) (defun hs--make-indicators-overlays (beg) "Helper function to make the indicators overlays." @@ -1177,8 +1182,11 @@ region (point MAXP)." (not (nth 8 (syntax-ppss)))) ; not inside comments or strings (if (> arg 1) (hs-hide-level-recursive (1- arg) minp maxp) - (goto-char (match-beginning hs-block-start-mdata-select)) - (hs-hide-block-at-point t)))) + ;; `hs-hide-block-at-point' already moves the cursor, but if it + ;; fails, return to the previous position where we were. + (unless (and (goto-char (match-beginning hs-block-start-mdata-select)) + (hs-hide-block-at-point t)) + (goto-char (match-end hs-block-start-mdata-select)))))) (goto-char maxp)) (defmacro hs-life-goes-on (&rest body) diff --git a/test/lisp/progmodes/hideshow-tests.el b/test/lisp/progmodes/hideshow-tests.el index a6b3ecfbd3d..9cf60c1ec84 100644 --- a/test/lisp/progmodes/hideshow-tests.el +++ b/test/lisp/progmodes/hideshow-tests.el @@ -254,6 +254,8 @@ sub() Comments */ +\"String\" + int main(int argc, char **argv) { @@ -270,6 +272,8 @@ main(int argc, char **argv) Comments */ +\"String\" + int main(int argc, char **argv) {} @@ -284,6 +288,8 @@ main(int argc, char **argv) Comments */ +\"String\" + int main(int argc, char **argv) { @@ -300,6 +306,8 @@ main(int argc, char **argv) Comments */ +\"String\" + int main(int argc, char **argv) {