Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace C++ defun-prompt-regexp to fix hang in Emacs #520

Merged
merged 2 commits into from
Apr 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
2024-04-20 Bob Weiner <rsw@gnu.org>

* hui-select.el (hui-c++-defun-prompt-regexp): Add to eliminate an Emacs
hang in c++-mode caused by setting 'defun-prompt-regexp'. Update
provided by Alan Mackenzie. Fixes Emacs bug#61436 from 2023
and gh#rswgnu/hyperbole/issue-518 from 2024.

2024-04-16 Bob Weiner <rsw@gnu.org>

* hyrolo.py: For Org files, create hyrolo match file header from all
Expand All @@ -10,7 +17,7 @@

* hui-select.el (hui-select-initialize): Disable C++ defun selection regexp until
regexp is rewritten to prevent Emacs hangs. See Emacs bug#61436 from 2023
and; gh#rswgnu/hyperbole/issue-518 from 2024.
and gh#rswgnu/hyperbole/issue-518 from 2024.

2024-04-14 Mats Lidell <matsl@gnu.org>

Expand Down
100 changes: 90 additions & 10 deletions hui-select.el
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
;; Author: Bob Weiner
;;
;; Orig-Date: 19-Oct-96 at 02:25:27
;; Last-Mod: 16-Apr-24 at 22:21:45 by Bob Weiner
;; Last-Mod: 20-Apr-24 at 12:02:16 by Bob Weiner
;;
;; SPDX-License-Identifier: GPL-3.0-or-later
;;
Expand Down Expand Up @@ -203,6 +203,90 @@ Used to include a final line when marking indented code.")
:type 'boolean
:group 'hyperbole-commands)

(defconst hui-c++-defun-prompt-regexp
(let* ((space* "[ \t\n\r\f]*")
(space+ "[ \t\n\r\f]+")
(ad-hoc-requires-clause
(concat "\\(?:requires" space* "[][()<> \t\n\r\f_$a-zA-Z0-9&|\"'+=.,*:~-]+" space* "\\)?"))
(id (concat "[_$~a-zA-Z][_$a-zA-Z0-9]*")
;; (concat "\\(\\(~" space* "\\)?" "\\([_$a-zA-Z][_$a-zA-Z0-9]*\\)\\)")
)
(template-brackets "\\(?:<[^;{}]*>\\)")
(id-<> (concat id "\\(?:" space* template-brackets "\\)?"))
(id-:: (concat id-<> "\\(?:" space* "::" space* id-<> "\\)*"))
(paren-exp "([^{};]*)")
(template-exp\? (concat "\\(?:template" space* template-brackets space* "\\)?"))
(type-prefix-modifier* (concat "\\(?:\\(?:"
"\\(?:\\<extern" space+ "\"[^\"]+\"\\)"
"\\|"
(regexp-opt '("auto" "const" "explicit" "extern"
"friend" "inline" "mutable"
"noexcept" "overload"
"register" "static" "typedef"
"virtual" "volatile")
'words)
"\\)"
space+
"\\)*"))
(type-exp (concat
"\\(?:\\(?:" template-brackets space* "\\)?"
type-prefix-modifier*
"\\(?:\\(?:decltype" space* paren-exp space* "\\)"
"\\|"
"\\(?:"
"\\(?:class\\|enum\\|struct\\|typename\\|union\\)"
"\\(?:" space* "\\.\\.\\.\\)?\\)"
space+ id space*
"\\(?::" id-:: space* "\\)?"
"\\|"
id-:: space*
"\\)"
"\\)\\{1,2\\}"))
(type-mid-modifier* (concat "\\(?:"
(regexp-opt
'("auto" "consteval" "constexpr"
"constinit" "explicit"
"extern" "friend" "inline"
"mutable" "noexcept" "register"
"static" "template"
"thread_local" "throw"
"virtual" "volatile")
'words)
space+ "\\)*"))
(operator-exp (concat "\\(?:operator\\>" space*
"\\(?:[][a-z_+*/%^?&|!~<>,:=-]+"
"\\|()\\|\"\""
"\\)" space*
"\\)"))

(name-exp ; matches foo or (* foo), etc.
(concat "\\(?:(" space* "[*&]+" space* id-:: space* "[][()]*" ")"
"\\|\\(?:[*&]+" space* "\\)?" id-::
"\\)" space*))
(type-suffix-modifier* (concat "\\(?:"
(regexp-opt
'("auto" "const" "noexcept"
"requires" "throw" "volatile")
'words)
space+ "\\)*"))
(post-paren-modifier* (concat "\\(?:"
(regexp-opt
'("const" "final" "override"
"mutable")
'words)
space* "\\)*")))

(concat template-exp\?
"\\(?:" ad-hoc-requires-clause "\\)?"
type-exp
type-mid-modifier*
"\\(?:" operator-exp "\\|" name-exp "\\)"
type-suffix-modifier*
paren-exp space*
"\\(?:->" space* type-exp "\\)?"
post-paren-modifier*
"{")))

(defconst hui-java-defun-prompt-regexp
(let* ((space* "[ \t\n\r\f]*")
(space+ "[ \t\n\r\f]+")
Expand All @@ -221,15 +305,15 @@ Used to include a final line when marking indented code.")
(concat "^[ \t]*"
modifier*
"\\(?:" generic-exp space* "\\)?"
ids-with-dot-\[\] space+ ; first part of type
ids-with-dot-\[\] space+ ; first part of type
"\\(?:" ids-with-dot-\[\] space+ "\\)?" ; optional second part of type.
"\\(?:[_a-zA-Z][^][ \t:;.,{}()=<>]*" ; defun name
"\\|" ids-with-dots
"\\|" ids-with-dots
"\\)" space*
paren-exp
"\\(?:" space* "]\\)*" ; What's this for?
"\\(?:" space* "\\<throws\\>" space* ids-with-dot-\[\]
"\\(?:," space* ids-with-dot-\[\] "\\)*"
"\\(?:," space* ids-with-dot-\[\] "\\)*"
"\\)?"
space*)))

Expand Down Expand Up @@ -402,12 +486,8 @@ Also, add language-specific syntax setups to aid in thing selection."
(var:add-and-run-hook 'java-mode-hook (lambda ()
(setq defun-prompt-regexp hui-java-defun-prompt-regexp)))

;; !! TODO: defun selection regexp is disabled in C++ until regexp is
;; rewritten as it can hang Emacs; reported in Emacs bug#61436 in
;; 2023 and gh#rswgnu/hyperbole/issue-518 in 2024.
;; (var:add-and-run-hook 'c++-mode-hook (lambda ()
;; (setq defun-prompt-regexp
;; "^[ \t]*\\(template\\s-*<[^>;.{}]+>\\s-*\\)?\\(\\(\\(auto\\|const\\|explicit\\|extern\\s-+\"[^\"]+\"\\|extern\\|friend\\|inline\\|mutable\\|overload\\|register\\|static\\|typedef\\|virtual\\)\\s-+\\)*\\(\\([[<a-zA-Z][]_a-zA-Z0-9]*\\(::[]_a-zA-Z0-9]+\\)?\\s-*<[_<>a-zA-Z0-9 ,]+>\\s-*[*&]*\\|[[<a-zA-Z][]_<>a-zA-Z0-9]*\\(::[[<a-zA-Z][]_<>a-zA-Z0-9]+\\)?\\s-*[*&]*\\)[*& \t\n\r]+\\)\\)?\\(\\(::\\|[[<a-zA-Z][]_a-zA-Z0-9]*\\s-*<[^>;{}]+>\\s-*[*&]*::\\|[[<a-zA-Z][]_~<>a-zA-Z0-9]*\\s-*[*&]*::\\)\\s-*\\)?\\(operator\\s-*[^ \t\n\r:;.,?~{}]+\\(\\s-*\\[\\]\\)?\\|[_~<a-zA-Z][^][ \t:;.,~{}()]*\\|[*&]?\\([_~<a-zA-Z][_a-zA-Z0-9]*\\s-*<[^>;{}]+[ \t\n\r>]*>\\|[_~<a-zA-Z][_~<>a-zA-Z0-9]*\\)\\)\\s-*\\(([^{;]*)\\(\\(\\s-+const\\|\\s-+mutable\\)?\\(\\s-*[=:][^;{]+\\)?\\)?\\)\\s-*")))
(var:add-and-run-hook 'c++-mode-hook (lambda ()
(setq defun-prompt-regexp hui-c++-defun-prompt-regexp)))
;;
;; Match to Lisp symbols with : in their names, often included in help buffers.
(var:add-and-run-hook 'help-mode-hook (lambda () (modify-syntax-entry ?: "_" help-mode-syntax-table)))
Expand Down