unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Re: arguments hint
       [not found] <200406010011.16822.pogonyshev@gmx.net>
@ 2004-06-02  3:45 ` Richard Stallman
  2004-06-02  5:58   ` Stefan Monnier
  0 siblings, 1 reply; 11+ messages in thread
From: Richard Stallman @ 2004-06-02  3:45 UTC (permalink / raw)
  Cc: emacs-devel

    Is there a mode for Emacs that gives hints on function
    arguments?  For instance, I type

      int result = function(

    and immediatly after '(' is typed, Emacs shows in a
    small window:

      int
      function(int x, int y, int z)

Whether a feature like this already exists in Emacs, I don't know.
But it sounds useful.

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

* Re: arguments hint
  2004-06-02  3:45 ` arguments hint Richard Stallman
@ 2004-06-02  5:58   ` Stefan Monnier
  2004-06-02  6:30     ` Karl Chen
  2004-06-02 20:11     ` Paul Pogonyshev
  0 siblings, 2 replies; 11+ messages in thread
From: Stefan Monnier @ 2004-06-02  5:58 UTC (permalink / raw)
  Cc: emacs-devel, Paul Pogonyshev

>     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}.


        Stefan

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

* Re: arguments hint
  2004-06-02  5:58   ` Stefan Monnier
@ 2004-06-02  6:30     ` Karl Chen
  2004-06-02 13:42       ` Stefan Monnier
  2004-06-02 22:55       ` Richard Stallman
  2004-06-02 20:11     ` Paul Pogonyshev
  1 sibling, 2 replies; 11+ messages in thread
From: Karl Chen @ 2004-06-02  6:30 UTC (permalink / raw)



Harmonia does this kind of cool language-aware stuff.
Unfortunately it only works with XEmacs.  I've tried to port it
before but it is very involved.

http://harmonia.cs.berkeley.edu/harmonia/projects/harmonia-mode/index.html



-- 
Karl 2004-06-01 23:29

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

* Re: arguments hint
  2004-06-02  6:30     ` Karl Chen
@ 2004-06-02 13:42       ` Stefan Monnier
  2004-06-02 22:55       ` Richard Stallman
  1 sibling, 0 replies; 11+ messages in thread
From: Stefan Monnier @ 2004-06-02 13:42 UTC (permalink / raw)
  Cc: emacs-devel

> Harmonia does this kind of cool language-aware stuff.
> Unfortunately it only works with XEmacs.  I've tried to port it
> before but it is very involved.

> http://harmonia.cs.berkeley.edu/harmonia/projects/harmonia-mode/index.html

I can't find any source code.  Their web page is frustratingly ".com-like".


        Stefan


PS: This said, it also looks like it's runtime loading of .so objects.

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

* Re: arguments hint
  2004-06-02  5:58   ` Stefan Monnier
  2004-06-02  6:30     ` Karl Chen
@ 2004-06-02 20:11     ` Paul Pogonyshev
  2004-06-02 20:51       ` Stefan Monnier
  1 sibling, 1 reply; 11+ messages in thread
From: Paul Pogonyshev @ 2004-06-02 20:11 UTC (permalink / raw)


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  <pogonyshev@gmx.net>

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

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

* Re: arguments hint
  2004-06-02 20:11     ` Paul Pogonyshev
@ 2004-06-02 20:51       ` Stefan Monnier
  2004-06-02 21:22         ` Paul Pogonyshev
  0 siblings, 1 reply; 11+ messages in thread
From: Stefan Monnier @ 2004-06-02 20:51 UTC (permalink / raw)
  Cc: emacs-devel

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

Since we are in feature freeze, I think this patch will have to wait.

> 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'.

I like this idea (even though it is pretty hairy to correctly process
&optional, [OPTARG], or even &key and such which can appear with functions
defined with CL's defun*).
When editing calls to completing-read and other such functions with many
parameters, it's really handy (although I'd prefer to use CL-style &key
parameters for those).

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

That doesn't strike me as terribly useful (the text is pretty different in
the two cases already).

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

I didn't dissect it, but it looks pretty good.


        Stefan

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

* Re: arguments hint
  2004-06-02 20:51       ` Stefan Monnier
@ 2004-06-02 21:22         ` Paul Pogonyshev
  2004-06-04 13:33           ` Paul Pogonyshev
  0 siblings, 1 reply; 11+ messages in thread
From: Paul Pogonyshev @ 2004-06-02 21:22 UTC (permalink / raw)


> > 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.
> 
> Since we are in feature freeze, I think this patch will have to wait.

No problem.  When is the release?

> > 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'.
> 
> I like this idea (even though it is pretty hairy to correctly process
> &optional, [OPTARG], or even &key and such which can appear with functions
> defined with CL's defun*).
> When editing calls to completing-read and other such functions with many
> parameters, it's really handy (although I'd prefer to use CL-style &key
> parameters for those).

Well, I'm not familiar with Common Lisp, so I just handled Elisp cases.
I can try to look into this especially since the patch is delayed.

> > As another, minor, change it highlights function/variable name with
> > appropriate face.  This should help distinguishing between function and
> > variable hints.
> 
> That doesn't strike me as terribly useful (the text is pretty different in
> the two cases already).

I can remove this.  The largest part is about arguments anyway.

Paul


P.S.  I'm now subscribed to `emacs-devel', so you can reply to the list.

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

* Re: arguments hint
  2004-06-02  6:30     ` Karl Chen
  2004-06-02 13:42       ` Stefan Monnier
@ 2004-06-02 22:55       ` Richard Stallman
  2004-06-03 15:33         ` Karl Chen
  1 sibling, 1 reply; 11+ messages in thread
From: Richard Stallman @ 2004-06-02 22:55 UTC (permalink / raw)
  Cc: emacs-devel

    Harmonia does this kind of cool language-aware stuff.

Is Harmonia a self-contained combination of many different features?
(I don't know, I am guessing, so please tell me if I'm wrong.)

Such packages are not a good way to add features to Emacs, because in
effect they make an alternate editor.  The right way to add multiple
features is to add each feature separately, making it fit in as much
as possible with all the rest of Emacs.  Then users can use them all,
or use just one of them.

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

* Re: arguments hint
  2004-06-02 22:55       ` Richard Stallman
@ 2004-06-03 15:33         ` Karl Chen
  0 siblings, 0 replies; 11+ messages in thread
From: Karl Chen @ 2004-06-03 15:33 UTC (permalink / raw)


>>>>> "rms" == Richard Stallman <rms@gnu.org> writes:
    rms> 
    rms>     Harmonia does this kind of cool language-aware stuff.
    rms> Is Harmonia a self-contained combination of many
    rms> different features?  (I don't know, I am guessing, so
    rms> please tell me if I'm wrong.)
    rms> 
    rms> Such packages are not a good way to add features to
    rms> Emacs, because in effect they make an alternate editor.
    rms> The right way to add multiple features is to add each
    rms> feature separately, making it fit in as much as possible
    rms> with all the rest of Emacs.  Then users can use them all,
    rms> or use just one of them.
    rms> 

I agree.  You should write them about improving Emacs itself
rather than creating an alternate editor.


-- 
Karl 2004-06-03 08:29

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

* Re: arguments hint
  2004-06-02 21:22         ` Paul Pogonyshev
@ 2004-06-04 13:33           ` Paul Pogonyshev
  2004-10-10  3:31             ` Stefan
  0 siblings, 1 reply; 11+ messages in thread
From: Paul Pogonyshev @ 2004-06-04 13:33 UTC (permalink / raw)


I made some experiments with `eldoc-mode' for C.  Below are the
results.  The thing is very hackish and has many loose ends,
but is already usable.  It will print hints for the function of
your project (i.e. it doesn't use any special tables for other
functions) based on the tags.  Contrary to what I expected, it
works quite fast.

Btw, as a side effect it opens extra buffers without being asked
for it.  This may be considered a serious drawback.

Comments are welcome.

Paul


;;  To use: eval the below code and then `c-turn-on-eldoc-mode'
;;          in a C buffer.


(defvar c-eldoc-reserved-words
  (list "if" "else" "switch" "while" "for" "sizeof"))

(defun c-turn-on-eldoc-mode ()
  (interactive)
  (set (make-local-variable 'eldoc-print-current-symbol-info-function)
       'c-print-current-symbol-info)
  (turn-on-eldoc-mode))

(defun c-function-and-argument (&optional limit)
  (let* ((return-point   (point))
	 (literal-limits (c-literal-limits))
	 (literal-type   (c-literal-type literal-limits)))
    (prog2
	(when (eq literal-type 'string)
	  (goto-char (car literal-limits))
	  (setq literal-type nil))
	(if literal-type
	    nil
	  (c-save-buffer-state ((argument-index 1))
	    (while (or (eq (c-forward-token-2 -1 t limit) 0)
		       (when (eq (char-before) ?\[)
			 (backward-char)
			 t))
	      (when (eq (char-after) ?,)
		(setq argument-index (1+ argument-index))))
	    (c-backward-syntactic-ws)
	    (when (eq (char-before) ?\()
	      (backward-char)
	      (c-forward-token-2 -1)
	      (when (looking-at "[a-zA-Z_][a-zA-Z_0-9]*")
		(cons (buffer-substring-no-properties
		       (match-beginning 0) (match-end 0))
		      argument-index)))))
      (goto-char return-point))))

(defun c-format-arguments-string (arguments index)
  (let ((paren-pos (string-match "(" arguments))
	(pos       0))
    (when (string-match "(" arguments)
      (setq arguments (replace-regexp-in-string
		       "\\\\?[[:space:]\\\n]" " "
		       (substring arguments paren-pos))
	    arguments (replace-regexp-in-string "\\s-+" " "  arguments)
	    arguments (replace-regexp-in-string " *, *" ", " arguments)
	    arguments (replace-regexp-in-string "( +"   "("  arguments)
	    arguments (replace-regexp-in-string " +)"   ")"  arguments))
      (while (and (> index 1) pos
		  (not (string= (substring arguments (+ pos 2) (+ pos 6))
				"...)")))
	(setq pos (string-match "," arguments (1+ pos))
	      index (1- index)))
      (when (and pos
		 (setq pos (string-match "[^ ,()]" arguments pos)))
	(add-text-properties pos (string-match "[,)]" arguments pos)
			     '(face bold) arguments))
      arguments)))

(defun c-print-current-symbol-info ()
  (let* ((current-function-cons (c-function-and-argument (- (point) 1000)))
	 (current-function      (car current-function-cons))
	 (current-buffer        (current-buffer))
	 (tag-buffer)
	 (function-name-point)
	 (arguments)
	 (type-face             'font-lock-type-face))
    (when (and current-function
	       (not (member current-function c-eldoc-reserved-words)))
      (when (setq tag-buffer (find-tag-noselect current-function))
	(prog2
	    (set-buffer tag-buffer)
	    (when (search-forward current-function (line-end-position) t)
	      (setq function-name-point (point))
	      (forward-sexp)
	      (setq arguments (buffer-substring-no-properties
			       function-name-point (point)))
	      (goto-char function-name-point)
	      (backward-char (length current-function))
	      (c-skip-ws-backward)
	      (setq function-name-point (point))
	      (search-backward-regexp "[};/#]" (point-min) t)
	      (if (= (char-after) ?#)
		  (let ((is-define          (looking-at "#[[:space:]]*define"))
			(preprocessor-point (point)))
		    (while (prog2 (end-of-line)
				  (= (char-before) ?\\)
			     (forward-char)))
		    (when (and is-define (> (point) function-name-point))
		      (goto-char preprocessor-point)
		      (setq type-face 'font-lock-preprocessor-face)))
		(forward-char)
		(when (looking-back "//")
		  (end-of-line)))
	      (c-skip-ws-forward)
	      (concat (propertize (buffer-substring-no-properties
				   (point)
				   function-name-point)
				  'face type-face)
		      "  "
		      (propertize current-function
				  'face 'font-lock-function-name-face)
		      " "
		      (c-format-arguments-string arguments
						 (cdr current-function-cons))))
	  (goto-char (mark t))
	  (set-buffer current-buffer))))))

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

* Re: arguments hint
  2004-06-04 13:33           ` Paul Pogonyshev
@ 2004-10-10  3:31             ` Stefan
  0 siblings, 0 replies; 11+ messages in thread
From: Stefan @ 2004-10-10  3:31 UTC (permalink / raw)
  Cc: emacs-devel

> I made some experiments with `eldoc-mode' for C.  Below are the
> results.  The thing is very hackish and has many loose ends,
> but is already usable.  It will print hints for the function of
> your project (i.e. it doesn't use any special tables for other
> functions) based on the tags.  Contrary to what I expected, it
> works quite fast.

This is neat.  Indeed, it's a bit annoying in that it tends to open many
buffers, but...
I suggest you contact Martin Stjernholm <bug-cc-mode@gnu.org> and see if you
can get it included in CC-mode (where it belongs).


        Stefan

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

end of thread, other threads:[~2004-10-10  3:31 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <200406010011.16822.pogonyshev@gmx.net>
2004-06-02  3:45 ` arguments hint Richard Stallman
2004-06-02  5:58   ` Stefan Monnier
2004-06-02  6:30     ` Karl Chen
2004-06-02 13:42       ` Stefan Monnier
2004-06-02 22:55       ` Richard Stallman
2004-06-03 15:33         ` Karl Chen
2004-06-02 20:11     ` Paul Pogonyshev
2004-06-02 20:51       ` Stefan Monnier
2004-06-02 21:22         ` Paul Pogonyshev
2004-06-04 13:33           ` Paul Pogonyshev
2004-10-10  3:31             ` Stefan

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