unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#61877: [PATCH] Extract Lisp function examples from shortdoc information
       [not found] <m14jr5v2na.fsf.ref@yahoo.es>
@ 2023-02-28 22:36 ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-03-02 21:38   ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 8+ messages in thread
From: Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-28 22:36 UTC (permalink / raw)
  To: 61877

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


Shortdoc contains a lot of useful examples about how to use common ELisp
functions.  This patch explores a new Emacs feature where those examples
are identified and extracted so they can be displayed, perhaps, in
*Help* buffers (via an additional help-fns-describe-function-functions
hook).

After you install the attached patch, take a look at the *Help* buffer
produced by C-h f assq RET, or C-h f match-string RET, etc.

What do you think of having this new Lisp feature in Emacs 30?  I can
send later another patch with tests, relevant NEWS entries and
documentation changes.

Thanks.


[-- Attachment #2: 0001-Extract-Lisp-function-examples-from-shortdoc-informa.patch --]
[-- Type: text/x-patch, Size: 6732 bytes --]

From da859693ba9fafd0ba43107bc99dba5464ac3ab6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= <mardani29@yahoo.es>
Date: Tue, 28 Feb 2023 23:15:40 +0100
Subject: [PATCH] Extract Lisp function examples from shortdoc information

* lisp/emacs-lisp/shortdoc.el (shortdoc--display-function): Add a new
shortdoc-example text property so that ELisp examples can be searched
for later.
(shortdoc--insert-group-in-buffer): New function extracted from the
buffer insertion code in shortdoc-display-group.
(shortdoc-display-group): Implement in terms of
shortdoc--insert-group-in-buffer.
* lisp/help-fns.el (help-fns--shortdoc-example): Add a new
help-fns-describe-function-functions hook that displays example code
for functions documented in shortdoc groups.
---
 lisp/emacs-lisp/shortdoc.el | 80 ++++++++++++++++++++-----------------
 lisp/help-fns.el            | 28 +++++++++++++
 2 files changed, 72 insertions(+), 36 deletions(-)

diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index c49960c2ee6..4e19cd04c9e 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -1443,45 +1443,51 @@ shortdoc-display-group
     (setq group (intern group)))
   (unless (assq group shortdoc--groups)
     (error "No such documentation group %s" group))
-  (funcall (if same-window
-               #'pop-to-buffer-same-window
-             #'pop-to-buffer)
-           (format "*Shortdoc %s*" group))
-  (let ((inhibit-read-only t)
-        (prev nil))
-    (erase-buffer)
-    (shortdoc-mode)
-    (button-mode)
-    (mapc
-     (lambda (data)
-       (cond
-        ((stringp data)
-         (setq prev nil)
-         (unless (bobp)
-           (insert "\n"))
-         (insert (propertize
-                  (substitute-command-keys data)
-                  'face 'shortdoc-heading
-                  'shortdoc-section t
-                  'outline-level 1))
-         (insert (propertize
-                  "\n\n"
-                  'face 'shortdoc-heading
-                  'shortdoc-section t)))
-        ;; There may be functions not yet defined in the data.
-        ((fboundp (car data))
-         (when prev
-           (insert (make-separator-line)
-                   ;; This helps with hidden outlines (bug#53981)
-                   (propertize "\n" 'face '(:height 0))))
-         (setq prev t)
-         (shortdoc--display-function data))))
-     (cdr (assq group shortdoc--groups))))
+  (let ((buf (get-buffer-create (format "*Shortdoc %s*" group))))
+    (shortdoc--insert-group-in-buffer group buf)
+    (funcall (if same-window
+                 #'pop-to-buffer-same-window
+               #'pop-to-buffer)
+             buf))
   (goto-char (point-min))
   (when function
     (text-property-search-forward 'shortdoc-function function t)
     (beginning-of-line)))
 
+(defun shortdoc--insert-group-in-buffer (group &optional buf)
+  "Insert a short documentation summary for functions in GROUP in buffer BUF."
+  (with-current-buffer (or buf (current-buffer))
+    (let ((inhibit-read-only t)
+          (prev nil))
+      (erase-buffer)
+      (shortdoc-mode)
+      (button-mode)
+      (mapc
+       (lambda (data)
+         (cond
+          ((stringp data)
+           (setq prev nil)
+           (unless (bobp)
+             (insert "\n"))
+           (insert (propertize
+                    (substitute-command-keys data)
+                    'face 'shortdoc-heading
+                    'shortdoc-section t
+                    'outline-level 1))
+           (insert (propertize
+                    "\n\n"
+                    'face 'shortdoc-heading
+                    'shortdoc-section t)))
+          ;; There may be functions not yet defined in the data.
+          ((fboundp (car data))
+           (when prev
+             (insert (make-separator-line)
+                     ;; This helps with hidden outlines (bug#53981)
+                     (propertize "\n" 'face '(:height 0))))
+           (setq prev t)
+           (shortdoc--display-function data))))
+       (cdr (assq group shortdoc--groups))))))
+
 ;;;###autoload
 (defalias 'shortdoc #'shortdoc-display-group)
 
@@ -1521,7 +1527,8 @@ shortdoc--display-function
                           "=>"))
           (single-arrow (if (char-displayable-p ?→)
                             "→"
-                          "->")))
+                          "->"))
+          (start-example (point)))
       (cl-loop for (type value) on data by #'cddr
                do
                (cl-case type
@@ -1572,7 +1579,8 @@ shortdoc--display-function
                  (:eg-result-string
                   (insert "    e.g. " double-arrow " ")
                   (princ value (current-buffer))
-                  (insert "\n")))))
+                  (insert "\n"))))
+      (add-text-properties start-example (point) `(shortdoc-example ,function)))
     ;; Insert the arglist after doing the evals, in case that's pulled
     ;; in the function definition.
     (save-excursion
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 50e60b68e17..843de957a5f 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -954,6 +954,34 @@ help-fns--mention-shortdoc-groups
         (fill-region-as-paragraph (point-min) (point-max))
         (goto-char (point-max))))))
 
+(add-hook 'help-fns-describe-function-functions
+          #'help-fns--shortdoc-example)
+(defun help-fns--shortdoc-example (object)
+  (require 'shortdoc)
+  (when-let ((groups (and (symbolp object)
+                          (shortdoc-function-groups object)))
+             (times 0))
+    (mapc
+     (lambda (group)
+       (let ((buf (current-buffer)))
+         (with-temp-buffer
+           (shortdoc--insert-group-in-buffer group)
+           (goto-char (point-min))
+           (setq match (text-property-search-forward
+                        'shortdoc-example object t))
+           (let ((temp-buffer (current-buffer)))
+             (with-current-buffer buf
+               (when (zerop times)
+                 (if (eq (length groups) 1)
+                     (insert "  Example:\n\n")
+                   (insert "  Examples:\n\n")))
+               (setq times (1+ times))
+               (insert-buffer-substring temp-buffer
+                                        (prop-match-beginning match)
+                                        (prop-match-end match))
+               (insert "\n"))))))
+     groups)))
+
 (defun help-fns-short-filename (filename)
   (let* ((abbrev (abbreviate-file-name filename))
          (short abbrev))
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* bug#61877: [PATCH] Extract Lisp function examples from shortdoc information
  2023-02-28 22:36 ` bug#61877: [PATCH] Extract Lisp function examples from shortdoc information Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-03-02 21:38   ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-03-11  8:37     ` Eli Zaretskii
  0 siblings, 1 reply; 8+ messages in thread
From: Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-02 21:38 UTC (permalink / raw)
  To: 61877

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

Daniel Martín <mardani29@yahoo.es> writes:

> Shortdoc contains a lot of useful examples about how to use common ELisp
> functions.  This patch explores a new Emacs feature where those examples
> are identified and extracted so they can be displayed, perhaps, in
> *Help* buffers (via an additional help-fns-describe-function-functions
> hook).
>
> After you install the attached patch, take a look at the *Help* buffer
> produced by C-h f assq RET, or C-h f match-string RET, etc.
>
> What do you think of having this new Lisp feature in Emacs 30?  I can
> send later another patch with tests, relevant NEWS entries and
> documentation changes.
>
> Thanks.

I attach a second version of the patch.  I've confined the
implementation to shortdoc.el, added a test, and documented the new
functions.

The NEWS entry explains how users could show this information in their
*Help* buffers, if they want.

Thanks.


[-- Attachment #2: 0001-Add-functions-to-query-Emacs-Lisp-examples-registere.patch --]
[-- Type: text/x-patch, Size: 10707 bytes --]

From 709f3605c84e6a0948c30753011e366f5caaace9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= <mardani29@yahoo.es>
Date: Tue, 28 Feb 2023 23:15:40 +0100
Subject: [PATCH] Add functions to query Emacs Lisp examples registered in
 shortdoc

* lisp/emacs-lisp/shortdoc.el (shortdoc--display-function): Add a new
shortdoc-example text property so that ELisp examples can be searched
for later.
(shortdoc--insert-group-in-buffer): New function extracted from the
buffer insertion code in shortdoc-display-group.
(shortdoc-display-group): Implement in terms of
shortdoc--insert-group-in-buffer.
(shortdoc-function-examples): New function that returns an alist of
Emacs Lisp examples from shortdoc.
(shortdoc-help-fns-examples-function): New function to insert Emacs
Lisp function examples in *Help* buffers, if added to
help-fns-describe-function-functions.
*
test/lisp/emacs-lisp/shortdoc-tests.el (shortdoc-function-examples-test):
Test it.
* doc/lispref/help.texi (Documentation Groups): Document it.
* etc/NEWS: Advertise it. (Bug#61877)
---
 doc/lispref/help.texi                  |  20 ++++
 etc/NEWS                               |  18 ++++
 lisp/emacs-lisp/shortdoc.el            | 122 +++++++++++++++++--------
 test/lisp/emacs-lisp/shortdoc-tests.el |  10 ++
 4 files changed, 134 insertions(+), 36 deletions(-)

diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi
index 59b6b6dab1d..b4c3b0eed5f 100644
--- a/doc/lispref/help.texi
+++ b/doc/lispref/help.texi
@@ -989,3 +989,23 @@ Documentation Groups
 If @var{group} doesn't exist, it will be created.  If @var{section}
 doesn't exist, it will be added to the end of the function group.
 @end defun
+
+You can also query the examples of use of functions defined in
+shortdoc groups.
+
+@defun shortdoc-function-examples function
+This function returns all shortdoc examples for @var{function}.  The
+result is an alist with items of the form
+
+@example
+(@var{group} . @var{examples})
+@end example
+
+@noindent
+where @var{group} is a documentation group where @var{function}
+appears in and @var{examples} is a string with the examples of use of
+@var{function} defined in @var{group}.
+
+@code{shortdoc-function-examples} returns @code{nil} if @var{function}
+is not a function or if it doesn’t contain shortdoc information.
+@end defun
diff --git a/etc/NEWS b/etc/NEWS
index 31fb22fc1e2..a0934b7d7d0 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -201,6 +201,24 @@ This command adds a docstring comment to the current defun.  If a
 comment already exists, point is only moved to the comment.  It is
 bound to 'C-c C-d' in 'go-ts-mode'.
 
+** Shortdoc
+
++++
+*** New function 'shortdoc-function-examples'.
+This function queries the registered documentation groups and returns
+examples of use of a given Emacs Lisp function.
+
++++
+*** New function 'shortdoc-help-fns-examples-function'.
+This function queries the registered documentation groups and inserts
+examples of use of a given Emacs Lisp function into the current
+buffer.  If you want to insert Emacs Lisp function examples into
+regular *Help* buffers when you use 'describe-function', add the
+following to you init file:
+
+(add-hook 'help-fns-describe-function-functions
+           #'shortdoc-help-fns-examples-function)
+
 \f
 * New Modes and Packages in Emacs 30.1
 
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index c49960c2ee6..cf66a43fc35 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -1443,45 +1443,51 @@ shortdoc-display-group
     (setq group (intern group)))
   (unless (assq group shortdoc--groups)
     (error "No such documentation group %s" group))
-  (funcall (if same-window
-               #'pop-to-buffer-same-window
-             #'pop-to-buffer)
-           (format "*Shortdoc %s*" group))
-  (let ((inhibit-read-only t)
-        (prev nil))
-    (erase-buffer)
-    (shortdoc-mode)
-    (button-mode)
-    (mapc
-     (lambda (data)
-       (cond
-        ((stringp data)
-         (setq prev nil)
-         (unless (bobp)
-           (insert "\n"))
-         (insert (propertize
-                  (substitute-command-keys data)
-                  'face 'shortdoc-heading
-                  'shortdoc-section t
-                  'outline-level 1))
-         (insert (propertize
-                  "\n\n"
-                  'face 'shortdoc-heading
-                  'shortdoc-section t)))
-        ;; There may be functions not yet defined in the data.
-        ((fboundp (car data))
-         (when prev
-           (insert (make-separator-line)
-                   ;; This helps with hidden outlines (bug#53981)
-                   (propertize "\n" 'face '(:height 0))))
-         (setq prev t)
-         (shortdoc--display-function data))))
-     (cdr (assq group shortdoc--groups))))
+  (let ((buf (get-buffer-create (format "*Shortdoc %s*" group))))
+    (shortdoc--insert-group-in-buffer group buf)
+    (funcall (if same-window
+                 #'pop-to-buffer-same-window
+               #'pop-to-buffer)
+             buf))
   (goto-char (point-min))
   (when function
     (text-property-search-forward 'shortdoc-function function t)
     (beginning-of-line)))
 
+(defun shortdoc--insert-group-in-buffer (group &optional buf)
+  "Insert a short documentation summary for functions in GROUP in buffer BUF."
+  (with-current-buffer (or buf (current-buffer))
+    (let ((inhibit-read-only t)
+          (prev nil))
+      (erase-buffer)
+      (shortdoc-mode)
+      (button-mode)
+      (mapc
+       (lambda (data)
+         (cond
+          ((stringp data)
+           (setq prev nil)
+           (unless (bobp)
+             (insert "\n"))
+           (insert (propertize
+                    (substitute-command-keys data)
+                    'face 'shortdoc-heading
+                    'shortdoc-section t
+                    'outline-level 1))
+           (insert (propertize
+                    "\n\n"
+                    'face 'shortdoc-heading
+                    'shortdoc-section t)))
+          ;; There may be functions not yet defined in the data.
+          ((fboundp (car data))
+           (when prev
+             (insert (make-separator-line)
+                     ;; This helps with hidden outlines (bug#53981)
+                     (propertize "\n" 'face '(:height 0))))
+           (setq prev t)
+           (shortdoc--display-function data))))
+       (cdr (assq group shortdoc--groups))))))
+
 ;;;###autoload
 (defalias 'shortdoc #'shortdoc-display-group)
 
@@ -1521,7 +1527,8 @@ shortdoc--display-function
                           "=>"))
           (single-arrow (if (char-displayable-p ?→)
                             "→"
-                          "->")))
+                          "->"))
+          (start-example (point)))
       (cl-loop for (type value) on data by #'cddr
                do
                (cl-case type
@@ -1572,7 +1579,8 @@ shortdoc--display-function
                  (:eg-result-string
                   (insert "    e.g. " double-arrow " ")
                   (princ value (current-buffer))
-                  (insert "\n")))))
+                  (insert "\n"))))
+      (add-text-properties start-example (point) `(shortdoc-example ,function)))
     ;; Insert the arglist after doing the evals, in case that's pulled
     ;; in the function definition.
     (save-excursion
@@ -1582,6 +1590,48 @@ shortdoc--display-function
         (insert " " (symbol-name param)))
       (add-face-text-property arglist-start (point) 'shortdoc-section t))))
 
+(defun shortdoc-function-examples (function)
+  "Return all shortdoc examples for FUNCTION.
+The result is an alist with items of the form (GROUP . EXAMPLES),
+where GROUP is a shortdoc group where FUNCTION appears in and
+EXAMPLES is a string with the usage examples of FUNCTION defined
+in GROUP.  Return nil if FUNCTION is not a function or if it
+doesn't contain shortdoc information."
+  (let ((groups (and (symbolp function)
+                     (shortdoc-function-groups function)))
+        (examples nil))
+    (mapc
+     (lambda (group)
+       (with-temp-buffer
+         (shortdoc--insert-group-in-buffer group)
+         (goto-char (point-min))
+         (setq match (text-property-search-forward
+                      'shortdoc-example function t))
+         (push `(,group . ,(string-trim
+                            (buffer-substring-no-properties
+                             (prop-match-beginning match)
+                             (prop-match-end match))))
+               examples)))
+     groups)
+    examples))
+
+(defun shortdoc-help-fns-examples-function (function)
+  "Insert Emacs Lisp examples for FUNCTION into the current buffer.
+You can add this function to the
+`help-fns-describe-function-functions' list to show function
+example documentation in *Help* buffers."
+  (let ((examples (shortdoc-function-examples function))
+        (times 0))
+    (dolist (example examples)
+      (when (zerop times)
+        (if (eq (length examples) 1)
+            (insert "  Example:\n\n")
+          (insert "  Examples:\n\n")))
+      (setq times (1+ times))
+      (insert "  ")
+      (insert (cdr example))
+      (insert "\n\n"))))
+
 (defun shortdoc-function-groups (function)
   "Return all shortdoc groups FUNCTION appears in."
   (cl-loop for group in shortdoc--groups
diff --git a/test/lisp/emacs-lisp/shortdoc-tests.el b/test/lisp/emacs-lisp/shortdoc-tests.el
index 516d095767f..a65a4a5ddc3 100644
--- a/test/lisp/emacs-lisp/shortdoc-tests.el
+++ b/test/lisp/emacs-lisp/shortdoc-tests.el
@@ -65,6 +65,16 @@ shortdoc-all-groups-work
         (when buf
           (kill-buffer buf))))))
 
+(ert-deftest shortdoc-function-examples-test ()
+  "Test the extraction of usage examples of some Elisp functions."
+  (should (equal '((list . "(delete 2 (list 1 2 3 4))\n    => (1 3 4)\n  (delete \"a\" (list \"a\" \"b\" \"c\" \"d\"))\n    => (\"b\" \"c\" \"d\")"))
+                 (shortdoc-function-examples 'delete)))
+  (should (equal '((alist . "(assq 'foo '((foo . bar) (zot . baz)))\n    => (foo . bar)")
+		   (list . "(assq 'b '((a . 1) (b . 2)))\n    => (b . 2)"))
+                 (shortdoc-function-examples 'assq)))
+  (should (equal '((regexp . "(string-match-p \"^[fo]+\" \"foobar\")\n    => 0"))
+                 (shortdoc-function-examples 'string-match-p))))
+
 (provide 'shortdoc-tests)
 
 ;;; shortdoc-tests.el ends here
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* bug#61877: [PATCH] Extract Lisp function examples from shortdoc information
  2023-03-02 21:38   ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-03-11  8:37     ` Eli Zaretskii
  2023-03-11 14:27       ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2023-03-11  8:37 UTC (permalink / raw)
  To: Daniel Martín; +Cc: 61877

> Date: Thu, 02 Mar 2023 22:38:42 +0100
> From:  Daniel Martín via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
> 
> Daniel Martín <mardani29@yahoo.es> writes:
> 
> > Shortdoc contains a lot of useful examples about how to use common ELisp
> > functions.  This patch explores a new Emacs feature where those examples
> > are identified and extracted so they can be displayed, perhaps, in
> > *Help* buffers (via an additional help-fns-describe-function-functions
> > hook).
> >
> > After you install the attached patch, take a look at the *Help* buffer
> > produced by C-h f assq RET, or C-h f match-string RET, etc.
> >
> > What do you think of having this new Lisp feature in Emacs 30?  I can
> > send later another patch with tests, relevant NEWS entries and
> > documentation changes.
> >
> > Thanks.
> 
> I attach a second version of the patch.  I've confined the
> implementation to shortdoc.el, added a test, and documented the new
> functions.

Thanks.  This no longer applies to the current master, so please
resubmit, and I will install.

> The NEWS entry explains how users could show this information in their
> *Help* buffers, if they want.

Maybe this part should be also in the user manual?





^ permalink raw reply	[flat|nested] 8+ messages in thread

* bug#61877: [PATCH] Extract Lisp function examples from shortdoc information
  2023-03-11  8:37     ` Eli Zaretskii
@ 2023-03-11 14:27       ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-03-12  8:30         ` Eli Zaretskii
  0 siblings, 1 reply; 8+ messages in thread
From: Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-11 14:27 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 61877

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

Eli Zaretskii <eliz@gnu.org> writes:

>
> Thanks.  This no longer applies to the current master, so please
> resubmit, and I will install.
>

Thanks, I've rebased the patch.

>> The NEWS entry explains how users could show this information in their
>> *Help* buffers, if they want.
>
> Maybe this part should be also in the user manual?

I've added some information to the user manual.  I see we don't document
help-fns-describe-function-functions in the user manual at all, should
we do it?  Customizing what is displayed in describe-function buffers
may be something that users want to do.  But perhaps we need to make the
hook part of the Customize interface first, I don't know.


[-- Attachment #2: 0001-Add-functions-to-query-Emacs-Lisp-examples-registere.patch --]
[-- Type: text/x-patch, Size: 11816 bytes --]

From e1cfca117c7c757fd87bdd76eb612ada682d0f00 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= <mardani29@yahoo.es>
Date: Tue, 28 Feb 2023 23:15:40 +0100
Subject: [PATCH] Add functions to query Emacs Lisp examples registered in
 shortdoc

* lisp/emacs-lisp/shortdoc.el (shortdoc--display-function): Add a new
shortdoc-example text property so that ELisp examples can be searched
for later.
(shortdoc--insert-group-in-buffer): New function extracted from the
buffer insertion code in shortdoc-display-group.
(shortdoc-display-group): Implement in terms of
shortdoc--insert-group-in-buffer.
(shortdoc-function-examples): New function that returns an alist of
Emacs Lisp examples from shortdoc.
(shortdoc-help-fns-examples-function): New function to insert Emacs
Lisp function examples in *Help* buffers, if added to
help-fns-describe-function-functions.
*
test/lisp/emacs-lisp/shortdoc-tests.el (shortdoc-function-examples-test):
Test it.
* doc/emacs/help.texi (Name Help): Document in the user manual.
* doc/lispref/help.texi (Documentation Groups): Document it.
* etc/NEWS: Advertise it. (Bug#61877)
---
 doc/emacs/help.texi                    |   9 ++
 doc/lispref/help.texi                  |  26 ++++++
 etc/NEWS                               |  18 ++++
 lisp/emacs-lisp/shortdoc.el            | 122 +++++++++++++++++--------
 test/lisp/emacs-lisp/shortdoc-tests.el |  10 ++
 5 files changed, 149 insertions(+), 36 deletions(-)

diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi
index 2513e6be271..10c007eb635 100644
--- a/doc/emacs/help.texi
+++ b/doc/emacs/help.texi
@@ -316,6 +316,15 @@ Name Help
 by using the @kbd{M-x shortdoc} command.  This will prompt you for an
 area of interest, e.g., @code{string}, and pop you to a buffer where
 many of the functions relevant for handling strings are listed.
+Here's an example you can include in your initialization file
+(@pxref{Init File}) that uses @code{shortdoc} to insert Emacs Lisp
+function examples into regular @file{*Help*} buffers when you use
+@kbd{C-h f}:
+
+@example
+(add-hook 'help-fns-describe-function-functions
+          #'shortdoc-help-fns-examples-function)
+@end example
 
 @kindex C-h v
 @findex describe-variable
diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi
index 59b6b6dab1d..3175f66122e 100644
--- a/doc/lispref/help.texi
+++ b/doc/lispref/help.texi
@@ -989,3 +989,29 @@ Documentation Groups
 If @var{group} doesn't exist, it will be created.  If @var{section}
 doesn't exist, it will be added to the end of the function group.
 @end defun
+
+You can also query the examples of use of functions defined in
+shortdoc groups.
+
+@defun shortdoc-function-examples function
+This function returns all shortdoc examples for @var{function}.  The
+result is an alist with items of the form
+
+@example
+(@var{group} . @var{examples})
+@end example
+
+@noindent
+where @var{group} is a documentation group where @var{function}
+appears in and @var{examples} is a string with the examples of use of
+@var{function} defined in @var{group}.
+
+@code{shortdoc-function-examples} returns @code{nil} if @var{function}
+is not a function or if it doesn’t contain shortdoc information.
+@end defun
+
+@defun shortdoc-help-fns-examples-function function
+This function queries the registered documentation groups and inserts
+examples of use of a given Emacs Lisp function into the current
+buffer.
+@end defun
diff --git a/etc/NEWS b/etc/NEWS
index 13d073c7fb8..5f51b801774 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -220,6 +220,24 @@ asynchronously (which is the default behavior).
 *** New face 'doc-view-svg-face'.
 This replaces 'doc-view-svg-foreground' and 'doc-view-svg-background'.
 
+** Shortdoc
+
++++
+*** New function 'shortdoc-function-examples'.
+This function queries the registered documentation groups and returns
+examples of use of a given Emacs Lisp function.
+
++++
+*** New function 'shortdoc-help-fns-examples-function'.
+This function queries the registered documentation groups and inserts
+examples of use of a given Emacs Lisp function into the current
+buffer.  If you want to insert Emacs Lisp function examples into
+regular *Help* buffers when you use 'describe-function', add the
+following to you init file:
+
+    (add-hook 'help-fns-describe-function-functions
+              #'shortdoc-help-fns-examples-function)
+
 \f
 * New Modes and Packages in Emacs 30.1
 
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index c49960c2ee6..cf66a43fc35 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -1443,45 +1443,51 @@ shortdoc-display-group
     (setq group (intern group)))
   (unless (assq group shortdoc--groups)
     (error "No such documentation group %s" group))
-  (funcall (if same-window
-               #'pop-to-buffer-same-window
-             #'pop-to-buffer)
-           (format "*Shortdoc %s*" group))
-  (let ((inhibit-read-only t)
-        (prev nil))
-    (erase-buffer)
-    (shortdoc-mode)
-    (button-mode)
-    (mapc
-     (lambda (data)
-       (cond
-        ((stringp data)
-         (setq prev nil)
-         (unless (bobp)
-           (insert "\n"))
-         (insert (propertize
-                  (substitute-command-keys data)
-                  'face 'shortdoc-heading
-                  'shortdoc-section t
-                  'outline-level 1))
-         (insert (propertize
-                  "\n\n"
-                  'face 'shortdoc-heading
-                  'shortdoc-section t)))
-        ;; There may be functions not yet defined in the data.
-        ((fboundp (car data))
-         (when prev
-           (insert (make-separator-line)
-                   ;; This helps with hidden outlines (bug#53981)
-                   (propertize "\n" 'face '(:height 0))))
-         (setq prev t)
-         (shortdoc--display-function data))))
-     (cdr (assq group shortdoc--groups))))
+  (let ((buf (get-buffer-create (format "*Shortdoc %s*" group))))
+    (shortdoc--insert-group-in-buffer group buf)
+    (funcall (if same-window
+                 #'pop-to-buffer-same-window
+               #'pop-to-buffer)
+             buf))
   (goto-char (point-min))
   (when function
     (text-property-search-forward 'shortdoc-function function t)
     (beginning-of-line)))
 
+(defun shortdoc--insert-group-in-buffer (group &optional buf)
+  "Insert a short documentation summary for functions in GROUP in buffer BUF."
+  (with-current-buffer (or buf (current-buffer))
+    (let ((inhibit-read-only t)
+          (prev nil))
+      (erase-buffer)
+      (shortdoc-mode)
+      (button-mode)
+      (mapc
+       (lambda (data)
+         (cond
+          ((stringp data)
+           (setq prev nil)
+           (unless (bobp)
+             (insert "\n"))
+           (insert (propertize
+                    (substitute-command-keys data)
+                    'face 'shortdoc-heading
+                    'shortdoc-section t
+                    'outline-level 1))
+           (insert (propertize
+                    "\n\n"
+                    'face 'shortdoc-heading
+                    'shortdoc-section t)))
+          ;; There may be functions not yet defined in the data.
+          ((fboundp (car data))
+           (when prev
+             (insert (make-separator-line)
+                     ;; This helps with hidden outlines (bug#53981)
+                     (propertize "\n" 'face '(:height 0))))
+           (setq prev t)
+           (shortdoc--display-function data))))
+       (cdr (assq group shortdoc--groups))))))
+
 ;;;###autoload
 (defalias 'shortdoc #'shortdoc-display-group)
 
@@ -1521,7 +1527,8 @@ shortdoc--display-function
                           "=>"))
           (single-arrow (if (char-displayable-p ?→)
                             "→"
-                          "->")))
+                          "->"))
+          (start-example (point)))
       (cl-loop for (type value) on data by #'cddr
                do
                (cl-case type
@@ -1572,7 +1579,8 @@ shortdoc--display-function
                  (:eg-result-string
                   (insert "    e.g. " double-arrow " ")
                   (princ value (current-buffer))
-                  (insert "\n")))))
+                  (insert "\n"))))
+      (add-text-properties start-example (point) `(shortdoc-example ,function)))
     ;; Insert the arglist after doing the evals, in case that's pulled
     ;; in the function definition.
     (save-excursion
@@ -1582,6 +1590,48 @@ shortdoc--display-function
         (insert " " (symbol-name param)))
       (add-face-text-property arglist-start (point) 'shortdoc-section t))))
 
+(defun shortdoc-function-examples (function)
+  "Return all shortdoc examples for FUNCTION.
+The result is an alist with items of the form (GROUP . EXAMPLES),
+where GROUP is a shortdoc group where FUNCTION appears in and
+EXAMPLES is a string with the usage examples of FUNCTION defined
+in GROUP.  Return nil if FUNCTION is not a function or if it
+doesn't contain shortdoc information."
+  (let ((groups (and (symbolp function)
+                     (shortdoc-function-groups function)))
+        (examples nil))
+    (mapc
+     (lambda (group)
+       (with-temp-buffer
+         (shortdoc--insert-group-in-buffer group)
+         (goto-char (point-min))
+         (setq match (text-property-search-forward
+                      'shortdoc-example function t))
+         (push `(,group . ,(string-trim
+                            (buffer-substring-no-properties
+                             (prop-match-beginning match)
+                             (prop-match-end match))))
+               examples)))
+     groups)
+    examples))
+
+(defun shortdoc-help-fns-examples-function (function)
+  "Insert Emacs Lisp examples for FUNCTION into the current buffer.
+You can add this function to the
+`help-fns-describe-function-functions' list to show function
+example documentation in *Help* buffers."
+  (let ((examples (shortdoc-function-examples function))
+        (times 0))
+    (dolist (example examples)
+      (when (zerop times)
+        (if (eq (length examples) 1)
+            (insert "  Example:\n\n")
+          (insert "  Examples:\n\n")))
+      (setq times (1+ times))
+      (insert "  ")
+      (insert (cdr example))
+      (insert "\n\n"))))
+
 (defun shortdoc-function-groups (function)
   "Return all shortdoc groups FUNCTION appears in."
   (cl-loop for group in shortdoc--groups
diff --git a/test/lisp/emacs-lisp/shortdoc-tests.el b/test/lisp/emacs-lisp/shortdoc-tests.el
index 516d095767f..a65a4a5ddc3 100644
--- a/test/lisp/emacs-lisp/shortdoc-tests.el
+++ b/test/lisp/emacs-lisp/shortdoc-tests.el
@@ -65,6 +65,16 @@ shortdoc-all-groups-work
         (when buf
           (kill-buffer buf))))))
 
+(ert-deftest shortdoc-function-examples-test ()
+  "Test the extraction of usage examples of some Elisp functions."
+  (should (equal '((list . "(delete 2 (list 1 2 3 4))\n    => (1 3 4)\n  (delete \"a\" (list \"a\" \"b\" \"c\" \"d\"))\n    => (\"b\" \"c\" \"d\")"))
+                 (shortdoc-function-examples 'delete)))
+  (should (equal '((alist . "(assq 'foo '((foo . bar) (zot . baz)))\n    => (foo . bar)")
+		   (list . "(assq 'b '((a . 1) (b . 2)))\n    => (b . 2)"))
+                 (shortdoc-function-examples 'assq)))
+  (should (equal '((regexp . "(string-match-p \"^[fo]+\" \"foobar\")\n    => 0"))
+                 (shortdoc-function-examples 'string-match-p))))
+
 (provide 'shortdoc-tests)
 
 ;;; shortdoc-tests.el ends here
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* bug#61877: [PATCH] Extract Lisp function examples from shortdoc information
  2023-03-11 14:27       ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-03-12  8:30         ` Eli Zaretskii
  2023-03-12 12:55           ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2023-03-12  8:30 UTC (permalink / raw)
  To: Daniel Martín; +Cc: 61877

> From: Daniel Martín <mardani29@yahoo.es>
> Cc: 61877@debbugs.gnu.org
> Date: Sat, 11 Mar 2023 15:27:54 +0100
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> >
> > Thanks.  This no longer applies to the current master, so please
> > resubmit, and I will install.
> >
> 
> Thanks, I've rebased the patch.
> 
> >> The NEWS entry explains how users could show this information in their
> >> *Help* buffers, if they want.
> >
> > Maybe this part should be also in the user manual?
> 
> I've added some information to the user manual.  I see we don't document
> help-fns-describe-function-functions in the user manual at all, should
> we do it?  Customizing what is displayed in describe-function buffers
> may be something that users want to do.  But perhaps we need to make the
> hook part of the Customize interface first, I don't know.

I added an index entry for help-fns-describe-function-functions in the
ELisp manual; I think this is enough for now.

Now installed on master.

Btw, something seems amiss: "C-h f" for string-fill, which has 2
examples in shortdoc, still says "Example:", not "Examples:", as I'd
expect.  Can you take a look?





^ permalink raw reply	[flat|nested] 8+ messages in thread

* bug#61877: [PATCH] Extract Lisp function examples from shortdoc information
  2023-03-12  8:30         ` Eli Zaretskii
@ 2023-03-12 12:55           ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-03-12 13:25             ` Eli Zaretskii
  0 siblings, 1 reply; 8+ messages in thread
From: Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-12 12:55 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 61877

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

Eli Zaretskii <eliz@gnu.org> writes:

> Btw, something seems amiss: "C-h f" for string-fill, which has 2
> examples in shortdoc, still says "Example:", not "Examples:", as I'd
> expect.  Can you take a look?

That is because some functions have more than one example per group (for
example, string-lessp is documented in the "comparison" and "string"
groups), but the "s" is added when a function is documented in _more
than one group_.

I think a more accurate logic to add the "s" is to count the number of
"arrow characters" that separate the form from the example.

Could you give a try to the attached patch, and install it for me if all
works correctly?  Thanks.


[-- Attachment #2: 0001-Fix-pluralization-in-shortdoc-help-fns-examples-func.patch --]
[-- Type: text/x-patch, Size: 4515 bytes --]

From c3ca21707f38f1bc82939fc05e381dfc1131026d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= <mardani29@yahoo.es>
Date: Sun, 12 Mar 2023 13:38:34 +0100
Subject: [PATCH] Fix pluralization in shortdoc-help-fns-examples-function

* lisp/emacs-lisp/shortdoc.el (shortdoc-help-fns-examples-function):
Implement a better logic to pluralize "Example", by counting the
number of arrow characters in the example string. (Bug#61877)
* test/lisp/emacs-lisp/shortdoc-tests.el
(shortdoc-help-fns-examples-function-test): Add a test.
---
 lisp/emacs-lisp/shortdoc.el            | 35 ++++++++++++++++++++++----
 test/lisp/emacs-lisp/shortdoc-tests.el | 15 +++++++++++
 2 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index 6e3ebc7c6a2..9a6f5dd12ce 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -1621,13 +1621,38 @@ shortdoc-help-fns-examples-function
 You can add this function to the `help-fns-describe-function-functions'
 hook to show examples of using FUNCTION in *Help* buffers produced
 by \\[describe-function]."
-  (let ((examples (shortdoc-function-examples function))
-        (times 0))
+  (let* ((examples (shortdoc-function-examples function))
+         (num-examples (length examples))
+         (times 0))
     (dolist (example examples)
       (when (zerop times)
-        (if (eq (length examples) 1)
-            (insert "\n  Example:\n\n")
-          (insert "\n  Examples:\n\n")))
+        (if (> num-examples 1)
+            (insert "\n  Examples:\n\n")
+          ;; Some functions have more than one example per group.
+          ;; Count the number of arrows to know if we need to
+          ;; pluralize "Example".
+          (let* ((text (cdr example))
+                 (count 0)
+                 (pos 0)
+                 (end (length text))
+                 (double-arrow (if (char-displayable-p ?⇒)
+                                   "    ⇒"
+                                 "    =>"))
+                 (double-arrow-example (if (char-displayable-p ?⇒)
+                                           "    e.g. ⇒"
+                                         "    e.g. =>"))
+                 (single-arrow (if (char-displayable-p ?→)
+                                   "    →"
+                                 "    ->")))
+            (while (and (< pos end)
+                        (or (string-match double-arrow text pos)
+                            (string-match double-arrow-example text pos)
+                            (string-match single-arrow text pos)))
+              (setq count (1+ count)
+                    pos (match-end 0)))
+            (if (> count 1)
+                (insert "\n  Examples:\n\n")
+              (insert "\n  Example:\n\n")))))
       (setq times (1+ times))
       (insert "  ")
       (insert (cdr example))
diff --git a/test/lisp/emacs-lisp/shortdoc-tests.el b/test/lisp/emacs-lisp/shortdoc-tests.el
index a65a4a5ddc3..d2dfbc66864 100644
--- a/test/lisp/emacs-lisp/shortdoc-tests.el
+++ b/test/lisp/emacs-lisp/shortdoc-tests.el
@@ -75,6 +75,21 @@ shortdoc-function-examples-test
   (should (equal '((regexp . "(string-match-p \"^[fo]+\" \"foobar\")\n    => 0"))
                  (shortdoc-function-examples 'string-match-p))))
 
+(ert-deftest shortdoc-help-fns-examples-function-test ()
+  "Test that `shortdoc-help-fns-examples-function' correctly prints ELisp function examples."
+  (with-temp-buffer
+    (shortdoc-help-fns-examples-function 'string-fill)
+    (should (equal "\n  Examples:\n\n  (string-fill \"Three short words\" 12)\n    => \"Three short\\nwords\"\n  (string-fill \"Long-word\" 3)\n    => \"Long-word\"\n\n"
+                   (buffer-substring-no-properties (point-min) (point-max))))
+    (erase-buffer)
+    (shortdoc-help-fns-examples-function 'assq)
+    (should (equal "\n  Examples:\n\n  (assq 'foo '((foo . bar) (zot . baz)))\n    => (foo . bar)\n\n  (assq 'b '((a . 1) (b . 2)))\n    => (b . 2)\n\n"
+                   (buffer-substring-no-properties (point-min) (point-max))))
+    (erase-buffer)
+    (shortdoc-help-fns-examples-function 'string-trim)
+    (should (equal "\n  Example:\n\n  (string-trim \" foo \")\n    => \"foo\"\n\n"
+                   (buffer-substring-no-properties (point-min) (point-max))))))
+
 (provide 'shortdoc-tests)
 
 ;;; shortdoc-tests.el ends here
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* bug#61877: [PATCH] Extract Lisp function examples from shortdoc information
  2023-03-12 12:55           ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-03-12 13:25             ` Eli Zaretskii
  2023-09-06  0:03               ` Stefan Kangas
  0 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2023-03-12 13:25 UTC (permalink / raw)
  To: Daniel Martín; +Cc: 61877

> From: Daniel Martín <mardani29@yahoo.es>
> Cc: 61877@debbugs.gnu.org
> Date: Sun, 12 Mar 2023 13:55:49 +0100
> 
> > Btw, something seems amiss: "C-h f" for string-fill, which has 2
> > examples in shortdoc, still says "Example:", not "Examples:", as I'd
> > expect.  Can you take a look?
> 
> That is because some functions have more than one example per group (for
> example, string-lessp is documented in the "comparison" and "string"
> groups), but the "s" is added when a function is documented in _more
> than one group_.
> 
> I think a more accurate logic to add the "s" is to count the number of
> "arrow characters" that separate the form from the example.
> 
> Could you give a try to the attached patch, and install it for me if all
> works correctly?  Thanks.

It works here; I installed it.

Thanks.





^ permalink raw reply	[flat|nested] 8+ messages in thread

* bug#61877: [PATCH] Extract Lisp function examples from shortdoc information
  2023-03-12 13:25             ` Eli Zaretskii
@ 2023-09-06  0:03               ` Stefan Kangas
  0 siblings, 0 replies; 8+ messages in thread
From: Stefan Kangas @ 2023-09-06  0:03 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 61877-done, Daniel Martín

Eli Zaretskii <eliz@gnu.org> writes:

>> Could you give a try to the attached patch, and install it for me if all
>> works correctly?  Thanks.
>
> It works here; I installed it.

I'm therefore closing this bug report.





^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2023-09-06  0:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <m14jr5v2na.fsf.ref@yahoo.es>
2023-02-28 22:36 ` bug#61877: [PATCH] Extract Lisp function examples from shortdoc information Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-02 21:38   ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-11  8:37     ` Eli Zaretskii
2023-03-11 14:27       ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-12  8:30         ` Eli Zaretskii
2023-03-12 12:55           ` Daniel Martín via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-12 13:25             ` Eli Zaretskii
2023-09-06  0:03               ` Stefan Kangas

Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).