[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Improved help from minibuffer prompts

From: Juanma Barranquero
Subject: Re: Improved help from minibuffer prompts
Date: Sat, 01 May 2004 04:17:46 +0200

On 30 Apr 2004 18:49:42 -0400, Stefan Monnier <address@hidden> wrote:

> Instead, you could hook into describe-function-1 at the place where the
> corresponding text is inserted, at which point you know exactly where that
> text is, without needing any heuristic.

I agree, in principle, and as I said that's what I first tried.

The problem is, describe-function-1 is a big hairy function with a
complex program flow. For starters, there's not a single place where
help-split-fundoc is called inside describe-function-1, but two. There's
also a call to help-make-usage, which, to add fun, does not return a
string but a list which must be first converted. Additionally,
describe-function-1 uses princ to output data to the current buffer,
which must be changed to (with-current-buffer standard-output (insert...))
or otherwise the text attributes are lost...

All in all, I really doubt the result is easier to understand or
maintain. For example, there's a case I've been unable to test, the one
corresponding to ((stringp arglist) arglist) in the cond, because I
don't know of any such function.

AFAICS, the benefits from doing it your way are small:

 - No heuristics to determine what's a usage doc and what's simply doc.

   OK, but the format of docs is something we control so we can be
   reasonably sure it's working, and we can always adapt
   help-highlight-arguments if necessary.

 - All functions that use describe-function-1 are automatically

   The fact is that describe-function-1 is not a public function (it has
   no docstring and it's not included on the Emacs Lisp reference
   manual); it's only used in describe-function and describe-key. Adding
   my initial implementation to both is a matter of adding one line to
   describe-function and two lines to describe-key.

I've included below a patch doing it your style (it's a bit weird
because I've had to used diff -b to avoid the effects of a reindent of
some code). I honestly don't find it more robust or better that the
other implementation, but I'll be happy to pursue whatever one is deemed
more acceptable.


Index: help-fns.el
RCS file: /cvsroot/emacs/emacs/lisp/help-fns.el,v
retrieving revision 1.40
diff -u -2 -b -r1.40 help-fns.el
--- help-fns.el 29 Apr 2004 18:46:13 -0000      1.40
+++ help-fns.el 1 May 2004 01:59:08 -0000
@@ -131,4 +131,39 @@
 ;; Functions
+(defun help-do-arg-highlight (doc args)
+  (while args
+    (let ((arg (car args)))
+      (setq args (cdr args))
+      (setq doc (replace-regexp-in-string (concat "\\<\\(" arg "\\)e?s?\\>")
+                                          (propertize arg 'face 
+                                          doc))))
+  doc)
+(defun help-highlight-arguments (usage &rest args)
+  (when usage
+    (let* ((case-fold-search nil)
+           (use (car usage))
+           (doc (cdr usage))
+           (next (not args)))
+      ;; Make a list of all arguments
+      (with-temp-buffer
+        (insert use)
+        (goto-char (point-min))
+        ;; Make a list of all arguments
+        (while next
+          (if (not (re-search-forward " \\([\\[(]?\\)\\([^] &)\.]+\\)" nil t))
+              (setq next nil)
+            (setq args (cons (match-string 2) args))
+            (when (string= (match-string 1) "(")
+              ;; A pesky CL-style optional argument with default value,
+              ;; so let's skip over it
+              (search-backward "(")
+              (goto-char (scan-sexps (point) 1)))))
+        ;; Highlight aguments in the USE string
+        (setq use (help-do-arg-highlight (buffer-string) args)))
+      ;; Highlight arguments in the DOC string
+      (setq doc (and doc (help-do-arg-highlight doc args)))
+      (cons use doc))))
 (defun describe-function (function)
@@ -353,10 +390,14 @@
     (let* ((arglist (help-function-arglist def))
           (doc (documentation function))
-          (usage (help-split-fundoc doc function)))
+          (usage (help-highlight-arguments (help-split-fundoc doc function))))
       ;; If definition is a keymap, skip arglist note.
       (unless (keymapp def)
-       (princ (cond
+        (with-current-buffer standard-output
+          (insert (cond
                (usage (setq doc (cdr usage)) (car usage))
-               ((listp arglist) (help-make-usage function arglist))
+                    ((listp arglist)
+                     (setq doc (help-highlight-arguments (cons (format "%s" 
(help-make-usage function arglist))
+                                                               doc)))
+                     (prog1 (car doc) (setq doc (cdr doc))))
                ((stringp arglist) arglist)
                ;; Maybe the arglist is in the docstring of the alias.
@@ -367,10 +408,10 @@
                                                 (documentation fun)
-                  usage)
+                       (setq usage (help-highlight-arguments usage)))
                 (car usage))
                ((or (stringp def)
                     (vectorp def))
                 (format "\nMacro: %s" (format-kbd-macro def)))
-               (t "[Missing arglist.  Please make a bug report.]")))
+                    (t "[Missing arglist.  Please make a bug report.]"))))
       (let ((obsolete (and
@@ -387,5 +428,6 @@
-      (princ (or doc "Not documented.")))))
+      (with-current-buffer standard-output
+        (insert (or doc "Not documented."))))))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]