Subject: Re: bug#60568: [FR] 30.0.50; Help buffers and function bodies for generated functions

From: Jean Louis <[email-masked]>
Date: Thu, 5 Jan 2023 20:00:50 +0300

* Ihor Radchenko <[email-masked]> [2023-01-05 10:57]:
> Recently, we have stumbled upon a situation when showing function code
> is not only useful, but one of the few sane ways to examine it [3].
> Functions that are not directly written in the source but rather
> generated programmatically cannot currently be easily examined using
> built-in help functionality (using describe-function or other means).
> The help buffer only links to the (point-min) in the library defining
> the generated function - not very helpful. In contrast, helpful extracts
> function body from symbol function slot.

> Would it be possible to provide function body info via *Help* system in
> Emacs?

That would be helpful. 

When there is some on the fly defined function I have used
`symbol-function' function to extract data and save the function in the file for
later examination.

;;; SAVE FUNCTION

(defun save-function ()
  "Saves function at point"
  (interactive)
  (let ((function (function-called-at-point)))
    (when (and (symbolp function)
	       (y-or-n-p (format "Save `%s'" (symbol-name function))))
      (save-function-1 function))))

(defun save-function-1 (function)
  (let* ((fun (symbol-function function))
	 (type (car fun))
	 (file (concat rcd-temp-file-directory
		       "function-" (symbol-name function) ".el")))
    (cond ((eq type 'lambda) (setq fun (append (list 'defun function) (cdr fun))))
	  ((eq type 'closure) (setq fun (append (list 'defun function) (nthcdr 2 fun)))))
    (message (string-to-file-force (prin1-to-string fun) file))))

(defun save-function-delete ()
  (interactive)
  (save-function)
  (beginning-of-line)
  (mark-sexp)
  (delete-active-region))

Then I would get this result, for example:

  -rw-r--r--   1  668 Jan  5 19:54 function-hyperscope-add-new-note-hyperdocument.el

with body being:

(defun hyperscope-add-new-note-hyperdocument nil (interactive) (let* ((parent (hyperscope-set-parent-or-select)) (markup (hyperscope-markup-select)) (related-person-by-parent (if parent (progn (hyperscope-related-person-id parent)))) (related-person (if (and related-person-by-parent (y-or-n-p (format "Is Hyperdocument related to `%s'? " (cf-people-name related-person-by-parent)))) (progn related-person-by-parent))) (prompt (format "New `%s' hyperdocument name: " type-name)) (name (rcd-ask prompt)) (hyperdocument (hyperscope-add-generic name "" markup id nil parent nil nil nil related-person))) (hyperscope-ring hyperdocument) (hyperscope-revert hyperdocument)))

Which I know is not very readable, but is still something useful.

Thus the help buffer shall try to find function in source, but if it
is not there, it shall at least show it's definition by using
`symbol-function'.

Problem is with byte-compiled functions:

(symbol-function 'rcd-iso-date) ➜ #[0 "\300\301!\207" [format-time-string "%Y-%m-%d"] 2]

--
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

In support of Richard M. Stallman
https://stallmansupport.org/