emacs-devel
[Top][All Lists]
Advanced

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

Re: arguments hint


From: Paul Pogonyshev
Subject: Re: arguments hint
Date: Wed, 2 Jun 2004 23:11:41 +0300
User-agent: KMail/1.6.52

Stefan Monnier wrote:
> >     Is there a mode for Emacs that gives hints on function
> >     arguments?  For instance, I type
> 
> For the Elisp language, there is eldoc-mode which does exactly that.
> For other languages like C, I think there are various packages roaming the
> net trying to do that in various ways.  I'd be surprised if CEDET didn't
> do that, for example, and I know someone posted a package that does it for
> C recently to gnu.emacs.{sources,help}.

Thank you, I'll try to find something for C.

Meanwhile, I decided to practice with Elisp for a bit and came up with the
following patch for eldoc-mode.  I assigned copyright to FSF, so if you like
the patch, you can include it in Emacs.

The patch makes eldoc-mode highlight the current argument with bold face.
Thus one can immediatly see which argument he stopped his point on.  This is
maybe not very useful when typing new code, but should be helpful when
editing something.  I took care to handle special cases like `&optional' or
`&rest'.

As another, minor, change it highlights function/variable name with
appropriate face.  This should help distinguishing between function and
variable hints.

I'm not very familiar with Elisp, so maybe you'd like to review the patch.
I will appreciate any feedback :)

Paul



Is this change log entry too elaborate?

2004-06-02  Paul Pogonyshev  <address@hidden>

        * emacs-lisp/eldoc.el (eldoc-get-fnsym-args-string): Fontify the
        argument under point with bold face.
        (eldoc-docstring-format-sym-doc): Fontify function/variable name
        with `font-lock-function-name-face' or
        `font-lock-variable-name-face' correspondingly.
        (eldoc-fnsym-in-current-sexp, eldoc-beginning-of-sexp): Return
        index of argument under point.



--- eldoc.el    10 Apr 2004 08:55:47 +0300      1.28
+++ eldoc.el    02 Jun 2004 23:09:28 +0300      
@@ -253,7 +253,7 @@ Emacs Lisp mode) that support Eldoc.")
             (let* ((current-symbol (eldoc-current-symbol))
                    (current-fnsym  (eldoc-fnsym-in-current-sexp))
                    (doc (cond
-                         ((eq current-symbol current-fnsym)
+                         ((eq current-symbol (car current-fnsym))
                           (or (eldoc-get-fnsym-args-string current-fnsym)
                               (eldoc-get-var-docstring current-symbol)))
                          (t
@@ -267,22 +267,59 @@ Emacs Lisp mode) that support Eldoc.")
 ;; Return a string containing the function parameter list, or 1-line
 ;; docstring if function is a subr and no arglist is obtainable from the
 ;; docstring or elsewhere.
-(defun eldoc-get-fnsym-args-string (sym)
-  (let ((args nil)
+(defun eldoc-get-fnsym-args-string (sym-cons)
+  (let ((sym (car sym-cons))
+       (argument-index (cdr sym-cons))
+       (args nil)
         (doc nil))
     (cond ((not (and sym (symbolp sym) (fboundp sym))))
           ((and (eq sym (aref eldoc-last-data 0))
                 (eq 'function (aref eldoc-last-data 2)))
-           (setq doc (aref eldoc-last-data 1)))
+           (setq args (aref eldoc-last-data 1)))
          ((setq doc (help-split-fundoc (documentation sym t) sym))
           (setq args (car doc))
           (string-match "\\`[^ )]* ?" args)
           (setq args (concat "(" (substring args (match-end 0)))))
           (t
            (setq args (eldoc-function-argstring sym))))
-    (cond (args
-           (setq doc (eldoc-docstring-format-sym-doc sym args))
-           (eldoc-last-data-store sym doc 'function)))
+    (when args
+      (let ((argument-start nil)
+           (argument-end 0)
+           (argument-string))
+       ;; Find the current argument in the argument string.  We need
+       ;; to handle `&rest' and informal `...' properly.
+       ;;
+       ;; FIXME: What to do with optional arguments, like in
+       ;;        (defun NAME ARGLIST [DOCSTRING] BODY...) case?
+       (while (>= argument-index 1)
+         (if (string-match "[^ ()]+" args argument-end)
+             (progn (setq argument-start  (match-beginning 0)
+                          argument-end    (match-end 0)
+                          argument-string (substring args
+                                                     argument-start
+                                                     argument-end))
+                    (if (not (string= argument-string "&rest"))
+                        (unless (string= argument-string "&optional")
+                          (setq argument-index (1- argument-index)))
+                      (string-match "[^ ()]+" args argument-end)
+                      (setq argument-start (match-beginning 0)
+                            argument-end   (match-end 0)
+                            argument-index 0)))
+           (setq argument-index 0)
+           (unless (and argument-start
+                        (string= (substring args
+                                            (- argument-end 3)
+                                            argument-end)
+                            "..."))
+             (setq argument-start nil))))
+
+       (when argument-start
+         (add-text-properties argument-start argument-end '(face bold) args))
+       (setq doc (eldoc-docstring-format-sym-doc
+                  sym args 'font-lock-function-name-face))
+       (when argument-start
+         (set-text-properties argument-start argument-end nil args))
+       (eldoc-last-data-store sym args 'function)))
     doc))
 
 ;; Return a string containing a brief (one-line) documentation string for
@@ -296,7 +333,8 @@ Emacs Lisp mode) that support Eldoc.")
           (let ((doc (documentation-property sym 'variable-documentation t)))
             (cond (doc
                    (setq doc (eldoc-docstring-format-sym-doc
-                              sym (eldoc-docstring-first-line doc)))
+                              sym (eldoc-docstring-first-line doc)
+                              'font-lock-variable-name-face))
                    (eldoc-last-data-store sym doc 'variable)))
             doc)))))
 
@@ -320,7 +358,7 @@ Emacs Lisp mode) that support Eldoc.")
 ;; If the entire line cannot fit in the echo area, the symbol name may be
 ;; truncated or eliminated entirely from the output to make room for the
 ;; description.
-(defun eldoc-docstring-format-sym-doc (sym doc)
+(defun eldoc-docstring-format-sym-doc (sym doc face)
   (save-match-data
     (let* ((name (symbol-name sym))
            (ea-multi eldoc-echo-area-use-multiline-p)
@@ -332,7 +370,7 @@ Emacs Lisp mode) that support Eldoc.")
       (cond ((or (<= strip 0)
                  (eq ea-multi t)
                  (and ea-multi (> (length doc) ea-width)))
-             (format "%s: %s" sym doc))
+             (format "%s: %s" (propertize name 'face face) doc))
             ((> (length doc) ea-width)
              (substring (format "%s" doc) 0 ea-width))
             ((>= strip (length name))
@@ -342,27 +380,38 @@ Emacs Lisp mode) that support Eldoc.")
              ;; than the beginning, since the former is more likely
              ;; to be unique given package namespace conventions.
              (setq name (substring name strip))
-             (format "%s: %s" name doc))))))
+             (format "%s: %s" (propertize name 'face face) doc))))))
 
  
 (defun eldoc-fnsym-in-current-sexp ()
-  (let ((p (point)))
-    (eldoc-beginning-of-sexp)
+  (let ((p (point))
+       (argument-index (1- (eldoc-beginning-of-sexp))))
     (prog1
         ;; Don't do anything if current word is inside a string.
         (if (= (or (char-after (1- (point))) 0) ?\")
             nil
-          (eldoc-current-symbol))
+          (cons (eldoc-current-symbol) argument-index))
       (goto-char p))))
 
 (defun eldoc-beginning-of-sexp ()
-  (let ((parse-sexp-ignore-comments t))
+  (let ((parse-sexp-ignore-comments t)
+       (p (point))
+       (num-skipped-sexps 0))
     (condition-case err
-        (while (progn
-                 (forward-sexp -1)
-                 (or (= (char-before) ?\")
-                     (> (point) (point-min)))))
-      (error nil))))
+       (progn
+         ;; FIXME: Can this be done nicer?
+         (forward-sexp -1)
+         (forward-sexp 1)
+         (when (< (point) p)
+           (setq num-skipped-sexps 1))
+         (goto-char p)
+         (while (progn
+                  (forward-sexp -1)
+                  (setq num-skipped-sexps (1+ num-skipped-sexps))
+                  (or (= (char-before) ?\")
+                      (> (point) (point-min))))))
+      (error num-skipped-sexps))
+    num-skipped-sexps))
 
 ;; returns nil unless current word is an interned symbol.
 (defun eldoc-current-symbol ()




reply via email to

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