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
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.
emacs-lisp-modesuch that they might already contain the correct highlighting? Perhaps it is just a matter of adjusting the extraction method to preserve the highlighting . . . Or, are you actually using
grepto extract the list of results? Perhaps providing a little more details about the extraction method might generate other potential solutions . . .
while (string-match "(defun")loop to walk the current buffer, and
(setq string (concat string (buffer-line-contents) "\n"))to build up the string that is displayed. The main problem is that the help window method strips the font lock info. I can get some font-lock colors by copying and fonting in a temp buffer, and bringing back the fontified string. But then it's lost in the help window process. My guess is that I'll end up using a normal buffer like
buffer-substringpreserves the text-properties, so if you use that function when gathering the results, then it won't be necessary to fontify anything afterwords and there would be no need to use a help-buffer. There is no such animal as
buffer-line-contentsas far as I am aware. You can just use a plain old buffer and add things like a
special-mode-mapto quit the buffer with
qand so forth.
buffer-substringand save it in a variable -- e.g.,
my-variable, and use a simple function like
(defun foo () (insert my-variable))Then, use this:
(let ((temp-buffer-window-setup-hook 'foo)) (help-window-full-frame (help-buffer)))in conjunction with the macro that we wrote together a couple of weeks ago: emacs.stackexchange.com/a/24037/2287 Of course, you can use a list to store the information and populate your help buffer accordingly.
occursource code now, to see if I can figure out how he does it.