all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Gregory Heytings <gregory@heytings.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: yantar92@posteo.net, 60568@debbugs.gnu.org, mardani29@yahoo.es
Subject: bug#60568: [FR] 30.0.50; Help buffers and function bodies for generated functions
Date: Thu, 05 Jan 2023 20:44:21 +0000	[thread overview]
Message-ID: <8dea9f3e0ea1de84c49a@heytings.org> (raw)
In-Reply-To: <83mt6xvsct.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 459 bytes --]


>>> Well, searching for the regexp "defun .*org-babel-execute:" would have 
>>> done that, right?
>>
>> In this specific case, yes.  But in general?
>
> I hope that in a more general case we could use something similar, since 
> every definition of a function should start from "defun " followed by 
> some part of its name, right?
>

Not always, I can imagine functions defined with fset for example.

What about the attached patch?  It seems to work well.

[-- Attachment #2: Try-to-find-where-dynamically-defined-functions-were.patch --]
[-- Type: text/x-diff, Size: 5424 bytes --]

From 38d0941bb87c0b46f27eb4cf496f24bba071d982 Mon Sep 17 00:00:00 2001
From: Gregory Heytings <gregory@heytings.org>
Date: Thu, 5 Jan 2023 20:41:37 +0000
Subject: [PATCH] Try to find where dynamically defined functions were defined

* lisp/help-mode.el
(help-function-def--find-probable-definition-place): New function.
(help-function-def--button-function): Use it.  See bug#60568.
---
 lisp/help-mode.el | 94 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 93 insertions(+), 1 deletion(-)

diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index bf64d032b6..542c477789 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -252,6 +252,87 @@ 'help-customize-face
 		   (customize-face v))
   'help-echo (purecopy "mouse-2, RET: customize face"))
 
+(defun help-function-def--find-probable-definition-place (fun)
+  "Find the function in which FUN was likely defined.
+FUN is the body of a function, returned by `symbol-function'.
+The current buffer must be visiting the file in which the
+function was defined (see `symbol-file').
+If the function is found, return a cons with its name and its
+beginning position.
+Otherwise, return nil."
+  (save-excursion
+    ;; Build a list of strings with the symbols (and strings) of FUN.
+    (let ((names
+           (mapcar (lambda (el)
+                     (concat
+                      "\\_<"
+                      (regexp-quote (format "%s" el))
+                      "\\_>"))
+                   (flatten-tree (symbol-function fun))))
+          results)
+      (delete-dups names)
+      (when names
+        ;; Build an alist with all functions in which each symbol is
+        ;; found.
+        (dolist (el names)
+          ;; Exclude symbols that are 3 characters or less.
+          (when (> (length el) 9)
+            (let (result)
+              (goto-char (point-min))
+              (while (re-search-forward el nil t)
+                (push (lisp-current-defun-name) result))
+              (delete-dups result)
+              (when result
+                (push (cons el result) results)))))
+        (when results
+          ;; First check if one of the symbols is found in a single
+          ;; function.
+          (let ((el (catch 'found
+                      (mapcar
+                       (lambda (el)
+                         (if (= (length el) 2)
+                             (throw 'found (car el))))
+                       results))))
+            (if (stringp el)
+                ;; If one such function was found, it's the function
+                ;; we are after.
+                (progn
+                  (goto-char (point-min))
+                  (re-search-forward el nil t)
+                  (beginning-of-defun)
+                  (cons (lisp-current-defun-name) (point)))
+              ;; Otherwise, find which function contains the most
+              ;; symbols in FUN.
+              (let (places)
+                (dolist (el results)
+                  (dolist (e (cdr el))
+                    (push e places)))
+                (let* ((sorted-places (sort places #'string<))
+                       (ptr sorted-places)
+                       (count 1)
+                       (max 0)
+                       result)
+                  (while ptr
+                    (if (string= (car ptr) (cadr ptr))
+                        (setq count (1+ count))
+                      (when (> count max)
+                        (setq max count)
+                        (setq result (car ptr)))
+                      (setq count 1))
+                    (setq ptr (cdr ptr)))
+                  (when result
+                    ;; Determine the beginning position of that
+                    ;; function.
+                    (goto-char (point-min))
+                    (catch 'found
+                      (while (re-search-forward
+                              (concat "\\_<" (regexp-quote result) "\\_>"))
+                        (when (string= (lisp-current-defun-name)
+                                       result)
+                          (throw 'found nil))))
+                    (beginning-of-defun)
+                    (cons result (point))))))))))))
+
 (defun help-function-def--button-function (fun &optional file type)
   (or file
       (setq file (find-lisp-object-file-name fun type)))
@@ -281,7 +362,18 @@ help-function-def--button-function
             (unless (= (point) position)
               (push-mark nil t))
             (goto-char position))
-        (message "Unable to find location in file")))))
+        (let ((probable-definition-place
+               (help-function-def--find-probable-definition-place fun)))
+          (when probable-definition-place
+            (goto-char (cdr probable-definition-place)))
+	  (with-help-window (help-buffer)
+	    (insert (format "Function %s could not be found in %s.\n\n"
+                            fun (file-name-nondirectory file)))
+            (when probable-definition-place
+              (insert (format "It was probably defined by %s.\n\n"
+                              (car probable-definition-place))))
+	    (insert "Function definition:\n\n")
+	    (insert (pp-to-string (symbol-function fun)))))))))
 
 (define-button-type 'help-function-def
   :supertype 'help-xref
-- 
2.39.0


  reply	other threads:[~2023-01-05 20:44 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-05  7:56 bug#60568: [FR] 30.0.50; Help buffers and function bodies for generated functions Ihor Radchenko
2023-01-05  8:09 ` Eli Zaretskii
2023-01-05  8:20   ` Ihor Radchenko
2023-01-05  8:32     ` Eli Zaretskii
2023-01-05 17:04       ` Jean Louis
2023-01-05 17:03   ` Jean Louis
2023-01-05  9:40 ` Gregory Heytings
2023-01-05  9:52   ` Gregory Heytings
2023-01-05 10:45 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-01-05 10:52   ` Ihor Radchenko
2023-01-05 11:20   ` Eli Zaretskii
2023-01-05 12:33     ` Gregory Heytings
2023-01-05 14:16       ` Eli Zaretskii
2023-01-05 14:27         ` Gregory Heytings
2023-01-05 15:10           ` Eli Zaretskii
2023-01-05 15:13             ` Gregory Heytings
2023-01-05 16:49               ` Eli Zaretskii
2023-01-05 20:44                 ` Gregory Heytings [this message]
2023-01-06  6:35                   ` Eli Zaretskii
2023-01-06  9:11                     ` Gregory Heytings
2023-01-06 17:27                       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-01-06 22:52                         ` Gregory Heytings
2023-01-07  0:36                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-01-07  6:55                             ` Eli Zaretskii
2023-01-07  9:42                               ` Gregory Heytings
2023-01-07 13:38                                 ` Ihor Radchenko
2023-01-07 14:00                                   ` Eli Zaretskii
2023-01-07 14:04                                   ` Gregory Heytings
2023-01-07 15:07                                     ` Ihor Radchenko
2023-01-07 15:14                                       ` Eli Zaretskii
2023-01-07 15:19                                         ` Ihor Radchenko
2023-01-07 15:23                                           ` Eli Zaretskii
2023-01-07 17:59                                             ` Eli Zaretskii
2023-01-07 13:14                               ` Ihor Radchenko
2023-01-07 13:55                                 ` Eli Zaretskii
2023-01-05 17:00 ` Jean Louis
2023-01-06  8:39   ` Ihor Radchenko
2023-01-06 16:44 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-01-07 11:32   ` Ihor Radchenko
2023-01-07 15:44     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-01-12 10:40       ` Ihor Radchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8dea9f3e0ea1de84c49a@heytings.org \
    --to=gregory@heytings.org \
    --cc=60568@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    --cc=mardani29@yahoo.es \
    --cc=yantar92@posteo.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.