* 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).