I wrote a function to show me a list of all defuns in the current buffer. The output is syntactically incorrect Lisp code (if you can even call it Lisp code, being syntactically a mess). Here's what the output looks like in the help window:
List of results:
(defvar var-one nil "Var one doc")
(defvar var-two nil "Var two doc")
(defun foobar (one two)
(defmacro mymacro (body)
If possible, I would like to fontify the display a bit, to color the defun words and the function names in some way.
I tried to do what org-mode does (suggested on another thread on SO). That is, copy my results to a temp buffer, enable Lisp mode, run font-lock-fontify-buffer
in Lisp mode on the temp buffer, and copy the fontified results back. But that didn't work, for two reasons. First, Lisp mode tried to indent my results like a mess of cascaded, nested defuns (ugh).
The main problem seems to be that with-help-window
loses or blocks all font locking. Maybe it's because of the princ
statements used to generate output into the help window?
Here's my display code (which does not work for keeping font info):
(with-help-window (help-buffer)
(princ (concat title "\n\n"))
(princ alldefuns)
(lisp-mode) ; doesn't help, in or out
(font-lock-fontify-buffer))
My questions are:
Is it possible to display fontified text using with-help-window
?
Or is there an alternate route that I should try? (I suppose I could go study the occur
source, which displays the same kind of results in a normal buffer. But I'd like to stick with with-help-window
approach if I could...)
Update for @lawlist comments below:
Here is the code that generates the list of defuns from the current buffer. The code looks like it should correctly collect and preserve font-lock info from the current buffer because it uses buffer-substring
to extract the lines.
(defun ct-u-buffer-defuns-list ()
"Return a stringlist of defuns in current buffer."
(let (result buf-contents tmp regex)
(setq buf-contents (buffer-string))
(with-temp-buffer
(insert buf-contents)
(goto-char (point-min))
(setq regex "^(defun")
(while (re-search-forward regex nil t)
(let (bol eol)
(setq bol (line-beginning-position))
(setq eol (line-end-position))
(setq tmp (buffer-substring bol eol))
(setq result (concat result tmp "\n")))))
result))
But on a 20 line display displayed in a normal buffer using the code below executed in the scratch buffer, only the first 10 lines retain their font-lock info. Or sometimes it's another 5 or 10 lines in a 30 line display. I don't know why.
(let (alldefuns)
(switch-to-buffer "ct-utils.el")
(setq alldefuns (ct-u-buffer-defuns-list))
(switch-to-buffer (get-buffer-create "foobar"))
(insert "List of results:\n")
(insert alldefuns))
So it seems that at least part of the font-lock properties are collected and preserved by the extraction (search) code, and at least part of the font-lock properties are preserved by inserting the collected string into a temp buffer (Fundamental mode is active in the temporary buffer).
Further, when I try the following bits of code in the *scratch*
buffer as suggested in the comments (alldefuns
is a variable that contains the lines extracted from the code buffer), I get the following results:
(defun foo ()
"Insert a string of defun lines in the current buffer."
(insert alldefuns))
;;works perfectly in Lisp mode scratch buffer
(foo)
;; only displays 10 of 30 lines with font lock info
(let ((temp-buffer-window-setup-hook 'foo))
(help-window-full-frame (help-buffer)
(princ "This title appears last in output.\n")))
It's a puzzle why displaying in (1) a temporary help buffer, or (2) in a temporary Fundamental mode buffer, only shows 1 chunk of 10 lines or so of font-lock info.