commit b97947b2033e33eb5fddb71ec840a3221b27e87c
parent c87f865c7a3c15ed0c049099694ee6cc4643b684
Author: Wilfred Hughes <me@wilfred.me.uk>
Date: Thu, 10 May 2018 08:42:18 +0100
Don't highlight very large code snippets
This stops big code excerpts hanging Emacs when using helpful.
Fixes #107.
Diffstat:
2 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
@@ -14,6 +14,10 @@ Function signatures are now correct when a function uses
Fixed an issue where escaped backticks were confused with unescaped
backticks in docstrings.
+Fixed an issue with very large code snippets making helpful hang due
+to slow syntax highlighting. This was particularly problematic for C
+functions and variables.
+
# v0.9
Much better handling of aliases: show aliases differently to their
diff --git a/helpful.el b/helpful.el
@@ -82,6 +82,14 @@ To disable cleanup entirely, set this variable to nil. See also
:type 'function
:group 'helpful)
+;; TODO: explore whether more basic highlighting is fast enough to
+;; handle larger functions. See `c-font-lock-init' and its use of
+;; font-lock-keywords-1.
+(defconst helpful-max-highlight 5000
+ "Don't highlight code with more than this many characters.
+This is particularly important for large pieces of C code, such
+as describing `this-command'.")
+
(defun helpful--kind-name (symbol callable-p)
"Describe what kind of symbol this is."
(cond
@@ -905,25 +913,26 @@ hooks.")
(with-temp-buffer
(insert source)
- ;; Switch to major-mode MODE, but don't run any hooks.
- (delay-mode-hooks (funcall mode))
-
- ;; `delayed-mode-hooks' contains mode hooks like
- ;; `emacs-lisp-mode-hook'. Build a list of functions that are run
- ;; when the mode hooks run.
- (let (hook-funcs)
- (dolist (hook delayed-mode-hooks)
- (let ((funcs (symbol-value hook)))
- (setq hook-funcs (append hook-funcs funcs))))
-
- ;; Filter hooks to those that relate to highlighting, and run them.
- (setq hook-funcs (-intersection hook-funcs helpful--highlighting-funcs))
- (-map #'funcall hook-funcs))
-
- (if (fboundp 'font-lock-ensure)
- (font-lock-ensure)
- (with-no-warnings
- (font-lock-fontify-buffer)))
+ (when (< (length source) helpful-max-highlight)
+ ;; Switch to major-mode MODE, but don't run any hooks.
+ (delay-mode-hooks (funcall mode))
+
+ ;; `delayed-mode-hooks' contains mode hooks like
+ ;; `emacs-lisp-mode-hook'. Build a list of functions that are run
+ ;; when the mode hooks run.
+ (let (hook-funcs)
+ (dolist (hook delayed-mode-hooks)
+ (let ((funcs (symbol-value hook)))
+ (setq hook-funcs (append hook-funcs funcs))))
+
+ ;; Filter hooks to those that relate to highlighting, and run them.
+ (setq hook-funcs (-intersection hook-funcs helpful--highlighting-funcs))
+ (-map #'funcall hook-funcs))
+
+ (if (fboundp 'font-lock-ensure)
+ (font-lock-ensure)
+ (with-no-warnings
+ (font-lock-fontify-buffer))))
(buffer-string)))
(defun helpful--source (sym callable-p)