Thread: [CEDET-devel] completion in semantic
Brought to you by:
zappo
From: Eric M. L. <er...@si...> - 2003-04-26 02:37:38
|
Hi, I've checked in an experimental file `semantic-complete.el' as a proposal to a framework for performing completion. The test function is simply `semantic-completion-test'. I've implemented only one completion mechanism which is a minibuffer prompt for selecting a tag out of the current buffer. The architecture is discussed in the commentary. I started from scratch with the minibuffer prompt instead of using `completing-read', so it is missing a bit of the fluff associated with prompts such as history, help, defaults and the like. I expect all will appear over time. My hope is that the framework will support prompts, inline completion, widgets, or anything else where a user interacts to select a tag. The prompt is organized to return an actual tag, not just a string. I sort of went overboard attempting to abstract out key pieces to make a flexible system so I'd appreciate any insights folks may have. Have fun Eric -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: Masatake Y. <je...@gy...> - 2003-04-26 03:08:25
|
> I've checked in an experimental file `semantic-complete.el' as a > proposal to a framework for performing completion. The test function > is simply `semantic-completion-test'. I've implemented only one > completion mechanism which is a minibuffer prompt for selecting a tag > out of the current buffer. The architecture is discussed in the > commentary. Is this code snippet fro GNU Emacs useful? (I've tried this code on 21.3.50 at emacs CVS repository.) (defun tooltip-show-at-point (text) (require 'tooltip) (require 'avoid) (let* ((P (mouse-avoidance-point-position)) (frame (car P)) (x (cadr P)) (y (cddr P)) (oP (mouse-position)) (oframe (car oP)) (ox (cadr oP)) (oy (cddr oP))) (set-mouse-position frame x y) (tooltip-show text) (set-mouse-position oframe ox oy))) (tooltip-show-at-point "setString(char* x)\nsetInt(int x)b\nsetPtr(void *x)") Masatake YAMATO |
From: Masatake Y. <je...@gy...> - 2003-04-26 16:36:53
|
> > I've checked in an experimental file `semantic-complete.el' as a > > proposal to a framework for performing completion. The test function > > is simply `semantic-completion-test'. I've implemented only one > > completion mechanism which is a minibuffer prompt for selecting a tag > > out of the current buffer. The architecture is discussed in the > > commentary. > > Is this code snippet fro GNU Emacs useful? > (I've tried this code on 21.3.50 at emacs CVS repository.) I've tried what I wrote here by myself. How do you think about popup menu? Masatake YAMATO Index: semantic/semantic-complete.el =================================================================== RCS file: /cvsroot/cedet/cedet/semantic/semantic-complete.el,v retrieving revision 1.2 diff -u -r1.2 semantic-complete.el --- semantic/semantic-complete.el 26 Apr 2003 12:07:32 -0000 1.2 +++ semantic/semantic-complete.el 26 Apr 2003 16:32:36 -0000 @@ -470,14 +470,30 @@ () "Traditional display mechanism for a list of possible completions.") +(defun tooltip-show-at-point (text) + (require 'tooltip) + (require 'avoid) + (let* ((P (mouse-avoidance-point-position)) + (frame (car P)) + (x (cadr P)) + (y (cddr P)) + (oP (mouse-position)) + (oframe (car oP)) + (ox (cadr oP)) + (oy (cddr oP))) + (set-mouse-position frame x y) + (tooltip-show text) + (set-mouse-position oframe ox oy))) + (defmethod semantic-displayor-show-request ((obj semantic-displayor-abstract)) "A request to show the current tags table." - (with-output-to-temp-buffer "*Completions*" - (display-completion-list - (mapcar semantic-completion-displayor-format-tag-function - (oref obj table))) - ) - ) + (let* ((l (mapcar semantic-completion-displayor-format-tag-function + (oref obj table))) + (ll (length l))) + (if (and (<= 0 ll) (< ll 10)) + (tooltip-show-at-point (concat " " (mapconcat 'identity l "\n "))) + (with-output-to-temp-buffer "*Completions*" + (display-completion-list l))))) ;;; Testing |
From: Eric M. L. <er...@si...> - 2003-04-26 17:18:32
|
>>> Masatake YAMATO <je...@gy...> seems to think that: >> > I've checked in an experimental file `semantic-complete.el' as a >> > proposal to a framework for performing completion. The test function >> > is simply `semantic-completion-test'. I've implemented only one >> > completion mechanism which is a minibuffer prompt for selecting a tag >> > out of the current buffer. The architecture is discussed in the >> > commentary. >> >> Is this code snippet fro GNU Emacs useful? >> (I've tried this code on 21.3.50 at emacs CVS repository.) > >I've tried what I wrote here by myself. >How do you think about popup menu? > >Masatake YAMATO > >Index: semantic/semantic-complete.el >=================================================================== >RCS file: /cvsroot/cedet/cedet/semantic/semantic-complete.el,v >retrieving revision 1.2 >diff -u -r1.2 semantic-complete.el >--- semantic/semantic-complete.el 26 Apr 2003 12:07:32 -0000 1.2 >+++ semantic/semantic-complete.el 26 Apr 2003 16:32:36 -0000 >@@ -470,14 +470,30 @@ > () > "Traditional display mechanism for a list of possible completions.") > >+(defun tooltip-show-at-point (text) >+ (require 'tooltip) >+ (require 'avoid) >+ (let* ((P (mouse-avoidance-point-position)) >+ (frame (car P)) >+ (x (cadr P)) >+ (y (cddr P)) >+ (oP (mouse-position)) >+ (oframe (car oP)) >+ (ox (cadr oP)) >+ (oy (cddr oP))) >+ (set-mouse-position frame x y) >+ (tooltip-show text) >+ (set-mouse-position oframe ox oy))) >+ > (defmethod semantic-displayor-show-request ((obj semantic-displayor-abstract)) > "A request to show the current tags table." >- (with-output-to-temp-buffer "*Completions*" >- (display-completion-list >- (mapcar semantic-completion-displayor-format-tag-function >- (oref obj table))) >- ) >- ) >+ (let* ((l (mapcar semantic-completion-displayor-format-tag-function >+ (oref obj table))) >+ (ll (length l))) >+ (if (and (<= 0 ll) (< ll 10)) >+ (tooltip-show-at-point (concat " " (mapconcat 'identity l "\n "))) >+ (with-output-to-temp-buffer "*Completions*" >+ (display-completion-list l))))) > > > ;;; Testing [ ... ] That's an interesting idea. A good way to do it is to make a subclass of `semantic-displayor-abstract', and add your method there. I'm hoping to have several displayors, and allow the user to select their favorite. Yours would be a viable option there. Thanks! Eric -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: Masatake Y. <je...@gy...> - 2003-05-01 06:51:02
|
> That's an interesting idea. A good way to do it is to make a > subclass of `semantic-displayor-abstract', and add your method there. > > I'm hoping to have several displayors, and allow the user to select > their favorite. Yours would be a viable option there. I've tried. I'm new to eieio, so I'm afraid I've taken stupid mistake. I've change semantic-complete-read-tag-buffer-deep to test tooltip. I've tested on GNU Emacs at the HEAD of subversions.gnu.org CVS repository. BTW, eieio is really cool. How do you think to add GtkObject/GObject's signal like mechanism to eieio? (We will call it `hook'.) Regards, Masatake YAMATO Index: semantic-complete.el =================================================================== RCS file: /cvsroot/cedet/cedet/semantic/semantic-complete.el,v retrieving revision 1.4 diff -u -r1.4 semantic-complete.el --- semantic-complete.el 26 Apr 2003 18:51:06 -0000 1.4 +++ semantic-complete.el 1 May 2003 06:41:37 -0000 @@ -309,7 +309,7 @@ HISTORY is a symbol representing a variable to story the history in." (semantic-complete-read-tag-engine (semantic-collector-buffer-deep prompt :buffer (current-buffer)) - (semantic-displayor-traditional "simple") + (semantic-displayor-tooltip "simple") prompt default-tag initial-input @@ -542,6 +542,87 @@ (oref obj table))) ) ) + +(defclass semantic-displayor-tooltip (semantic-displayor-abstract) + ((max-tags :type integer + :initarg :max-tags + :initform 10 + :custom integer + :documentation + "Max number of tags displayed on tooltip at once. +If `force-show' is 1, this value is ignored with typing tab or space twice continuously. +if `force-show' is 0, this value is always ignored.") + (force-show :type integer + :initarg :force-show + :initform 1 + :custom (choice (const + :tag "Show when double typing" + 1) + (const + :tag "Show always" + 0) + (const + :tag "Show if the number of tags is less than `max-tags'." + -1)) + :documentation + "Control the behavior of the number of tags is greater than `max-tags'. +-1 means tags are never shown. +0 means the tags are always shown. +1 means tags are shown if space or tab is typed twice continuously.") + (typing-count :type integer + :initform 0 + :documentation + "Counter holding how many times the user types space or tab continuously before showing tags.") + (shown :type boolean + :initform nil + :documentation + "Flag representing whether tags is shown once or not.") + ) + "Display mechanism using tooltip for a list of possible completions.") + +(defmethod semantic-displayor-show-request ((obj semantic-displayor-tooltip)) + "A request to show the current tags table." + (let* ((l (mapcar semantic-completion-displayor-format-tag-function + (oref obj table))) + (ll (length l)) + (typing-count (oref obj typing-count)) + (force-show (oref obj force-show)) + msg) + (if (or (oref obj shown) + (< ll (oref obj max-tags)) + (and (<= 0 force-show) + (< (1- force-show) typing-count))) + (progn + (oset obj typing-count 0) + (oset obj shown t) + (if (eq 1 ll) + (setq msg "SOLE COMPLETION") + (setq msg (mapconcat 'identity l "\n")) + (if (eq 0 (length msg)) + (setq msg "NO MORE COMPLETION"))) + (semantic-displayor-tooltip-show msg)) + (oset obj typing-count (1+ typing-count)) + (cond + ((= force-show -1) + (semantic-displayor-tooltip-show "TOO MANY")) + ((= force-show 1) + (semantic-displayor-tooltip-show + "TOO MANY (Type TAB or SPACE again to show force)")))))) + +(defun semantic-displayor-tooltip-show (text) + (require 'tooltip) + (require 'avoid) + (let* ((P (mouse-avoidance-point-position)) + (frame (car P)) + (x (cadr P)) + (y (cddr P)) + (oP (mouse-position)) + (oframe (car oP)) + (ox (cadr oP)) + (oy (cddr oP))) + (set-mouse-position frame x y) + (tooltip-show text) + (set-mouse-position frame (1+ x) y))) ;;; Testing |
From: Eric M. L. <er...@si...> - 2003-05-01 16:00:41
|
>>> Masatake YAMATO <je...@gy...> seems to think that: >> That's an interesting idea. A good way to do it is to make a >> subclass of `semantic-displayor-abstract', and add your method there. >> >> I'm hoping to have several displayors, and allow the user to select >> their favorite. Yours would be a viable option there. > >I've tried. I'm new to eieio, so I'm afraid I've taken stupid mistake. >I've change semantic-complete-read-tag-buffer-deep to test tooltip. Great stuff. I will try it out when I get back on an X console. I'm adding a focusing displayor to semantic-complete.el right now. When I finish it, I will merge your changes. In particular, I need to add a configuration variable so you can choose your favorite display mechanism. I think this displayor will be perfect for in-buffer completion of symbols. >I've tested on GNU Emacs at the HEAD of subversions.gnu.org CVS >repository. > >BTW, eieio is really cool. How do you think to add GtkObject/GObject's >signal like mechanism to eieio? (We will call it `hook'.) [ ... ] EIEIO is a port of CLOS, and extended where appropriate for Emacs facilities like custom, or lack of appropriate CL constructs. I am unaware of any signaling type mechanisms, nor am I too familiar with them. I commonly add hooks by just having a slot with a ":type 'function" specifier and call it where appropriate. Eric -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: Masatake Y. <je...@gy...> - 2003-05-08 07:18:30
|
> >BTW, eieio is really cool. How do you think to add GtkObject/GObject's > >signal like mechanism to eieio? (We will call it `hook'.) > [ ... ] > > EIEIO is a port of CLOS, and extended where appropriate for Emacs > facilities like custom, or lack of appropriate CL constructs. > > I am unaware of any signaling type mechanisms, nor am I too familiar > with them. > > I commonly add hooks by just having a slot with a ":type 'function" > specifier and call it where appropriate. > > Eric Gtk's signal is similar to emacs's hook. However, in some aspects Gtk's signal is more powerful than emacs's hook. As you wrote ":type 'function" does what I want a bit. But not enough. 1) The is no agreement about number of arguments between hook and callback functions. (defun hook-func0 ()) (add-hook 'test-hook 'hook-func0) (run-hook-with-args 'test-hook "xxx") 2) Client arguments are not supported. You cannot pass hook function private data. In above text, I call client arguments extra arguments. I've extended hook mechanisms that overcome above limits. Simple example: (defhook message-broadcast-hook (func) "Just an example") (defun hook-func (func msg) (funcall func msg) (sit-for 1)) (connect-hook 'message-broadcast-hook 'hook-func "E") (connect-hook 'message-broadcast-hook 'hook-func "EI") (connect-hook 'message-broadcast-hook 'hook-func "EIE") (connect-hook 'message-broadcast-hook 'hook-func "EIEI") (connect-hook 'message-broadcast-hook 'hook-func "EIEIO") (emit-hook 'message-broadcast-hook 'message) (describe-hook 'message-broadcast-hook) Read comments in the program to know more. What I'd like to do is add this new hook mechanism to eieio. Imaginary code: (defclass testclass nil ((state-changed :type hook :arglist ((obj testclass) n) :documentation "Hook called when the state is changed. N is number.")) "Test class") (defun hook-func (obj n) ...) (oconnect testclass state-changed hook-func) ... (oemit testclass state-changed 42) Masatake YAMATO ;; hook.el --- extended hook mechanism ;; ;; Copyright (C) 2003 Masatake YAMATO ;; ;; Author: Masatake YAMATO <je...@gy...> ;; Created: Thu May 1 19:55:05 2003 ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;; ;;; Commentary: ;; ;; Simple example: ;; (defhook message-broadcast-hook (func) "Just an example") ;; (defun hook-func (func msg) (funcall func msg) (sit-for 1)) ;; ;; (connect-hook 'message-broadcast-hook 'hook-func "E") ;; (connect-hook 'message-broadcast-hook 'hook-func "EI") ;; (connect-hook 'message-broadcast-hook 'hook-func "EIE") ;; (connect-hook 'message-broadcast-hook 'hook-func "EIEI") ;; (connect-hook 'message-broadcast-hook 'hook-func "EIEIO") ;; ;; (emit-hook 'message-broadcast-hook 'message) ;; ;; This program provides following extension for emacs hook mechanism: ;; 1) Unification two run-hook* functions: `run-hooks' and `run-hook-with-args'. ;; Even if a hook takes arguments or not, you need call single new function ;; `emit-hook'. ;; ;; 2) Checking the number of arugments. ;; The number of arugments of a hook and the hook functions are checked. ;; First you can declare how many arguments a hook takes with new macro ;; `defhook'. ;; e.g. (defhook test-hook (filename versoin) "Hook example") ;; ;; This arguments declaration is used in `connect-hook', the replacement ;; of `add-hook' and `emit-hook'. ;; e.g. (defun test-func1 (f v) ...) ;; (connect-hook 'test-hook 'test-func1) ;; ;; Above code may work fine. Because test-func1 takes two arguments; ;; test-hook is defined with the arguments list: (filename versoin). ;; Both are matched. ;; In other hand following code causes an error because the numbers of arguments ;; are not matched. ;; e.g. (defun test-func2 (f) ...) ;; (connect-hook 'test-hook 'test-func2) ;; The number of arguments for `emit-hook' is also checked. ;; e.g. (emit-hook `test-hook "emacs" "21.3.50") ;; ;; This may work well. The number of arguments, "emacs" and "21.3.50" are ;; matched to the declaration of test-hook: (filename versoin). ;; Following causes an error: ;; e.g. (emit-hook `test-hook "emacs" "21.3.50" "something") ;; (emit-hook `test-hook) ;; ;; 3) Hook function side extra arguments ;; When you connect a hook function to a hook with `connect-hook', you can ;; pass extra arguments. The extra arguments are just registered when you ;; call `connect-hook'. But when you call `emit-hook', the registered extra ;; arguments are passed to the hook function. ;; e.g. (defun test-func3 (f v ex)) ;; (connect-hook 'test-hook 'test-func3 "extra" ;; (emit-hook `test-hook "emacs" "21.3.50") ;; When test-func3 is called in `emit-hook', f is bound to "emacs". ;; v is bound to "21.3.50". ex is bound to "extra". ;; Even if you passed extra arguments, 2) the number of arugments checking is ;; done. ;; ;; 4) M-x describe-hook ;; ;;; Code: (require 'help-fns) (require 'advice) (defvar hook-global-hooks-list () "List of hooks defined in defhook.") (defalias 'defhook 'hook-defhook) (defmacro hook-defhook (hook arglist &optional docstring) "Define HOOK as a hook. You are not required to define a hook in order to use it, but the definition can supply documentation and arglist. ARGLIST is used for checking number of arguments, when `connect-hook'(similar to `add-hook'), `emit-hook'(similar to `run-hook-with-args') is called. `describe-hook' shows the document of a hook if it is defined with `defhook'. Example 1. Define two hook functions. `foo' takes one argument. (defun foo (x) (message x)) `bar' takes two arguments. (defun bar (a b) (insert (concat a b))) Define hook that passes one argument to hook functions: MSG. (defhook test-hook (msg)) Connect `foo' and `bar' to `test-hook': (connect-hook 'test-hook 'foo) (connect-hook 'test-hook 'bar \"!\") `bar' takes one extra argument. Emit `test-hook': (emit-hook 'test-hook \"hello, world\") => works fine. Above emission calls (foo \"hello, works\") and (bar \"hello, works\" \"!\") inside. Example 2. Define a hook function that takes two argument. (defun baz (a b) ...) Connect `baz' to `test-hook': (connect-hook 'test-hook 'baz) => error because the number of arguments for `baz' and `test-hook' are not matched. `baz' takes two arguments. `test-hook' passes one argument to the hook function. Example 3. Emit `test-hook' with two arguments: (emit-hook 'test-hook \"hello, world\" \"xxx\")) => error because the number of arguments passed to emit-hook and that for test-hook are not matched. " `(progn (if (not (numberp (length ',arglist))) (error "wrong-type-of-argument")) (prog1 (defconst ,hook nil (format (case (length ',arglist) (0 "A hook with no argument.\n%s") (1 "A hook with one argument.\n%s") (t (format "A hook with %d arguments.\n%%s" (length ',arglist) ))) (if ,docstring ,docstring "Not documented"))) (hook-put-spec ',hook ',arglist ,docstring) (setq hook-global-hooks-list (adjoin ',hook hook-global-hooks-list))))) (put 'defhook 'lisp-indent-function 'defun) (defmacro hook-p (hook) "Non-nil iff HOOK is a type of hook." `(if (hook-get-spec ,hook) t nil)) (defmacro connect-hook (hook function &rest extra-args) `(connect-hook-internal ,hook ,function t nil ,@extra-args)) (defmacro connect-hook-prepend (hook function &rest extra-args) `(connect-hook-internal ,hook ,function nil nil ,@extra-args)) (defmacro connect-to-local-hook (hook function &rest extra-args) `(connect-hook-internal ,hook ,function t t ,@extra-args)) (defmacro connect-to-local-hook-prepend (hook function &rest extra-args) `(connect-hook-internal ,hook ,function nil t ,@extra-args)) (defun connect-hook-internal (hook function append local &rest extra-args) "Similar to add-hook, but checking number of arguments and passing extra arguments to the function. EXTRA-ARGS is passed to function when the hook is emitted. FUNCTION's arglist, the number of EXTRA-ARGS and HOOK's arglist given with `defhook` are compared. The number of FUNCTION arguments must be equal to the number EXTRA-ARGS plus the number of HOOK's argument. If number of arguments are matched, `connect-hook` is the same to `add-hook'. If not, raise an error. This returns a lambda added to HOOK. You can pass the return value to `remove-hook' or `disconnect-hook' to remove the function from the hook." (unless (hook-p hook) (error "%S is not defined as a hook" hook)) (let* ((num (hook-get-number-of-hook-arguments hook)) (arglist (hook-get-hook-arglist hook)) closure) (assert (not (eq arglist t)) "hook.el's internal error") (hook-check-number-of-arguments function (+ num (length extra-args)) "Number of arguments taken by function are not matched with hook") (setq closure (hook-generate-funciton function arglist extra-args)) (add-hook hook closure append local) closure)) (defun disconnect-hook (hook function) (remove-hook hook function nil)) (defun disconnect-local-hook (hook function) (remove-hook hook function t)) (defmacro emit-hook (hook &rest args) "Similar to run-hook-with-args, but checking number and type(not implemented yet) of arguments. ARGS and HOOK's arglist given with `defhook` are compared. If number of arguments and type of them are matched, `emit-hook` is the same to `run-hook-with-args'. If not, raise an error." `(let* ((num (hook-get-number-of-hook-arguments ,hook))) (unless (hook-p ,hook) (error "%S is not defined as a hook" ,hook)) (unless (eq num (length ',args)) (error "Number of arguments are not match with hook")) (run-hook-with-args ,hook ,@args))) (defmacro emit-hook-until-success (hook &rest args) `(let* ((num (hook-get-number-of-hook-arguments ,hook))) (unless (hook-p ,hook) (error "%S is not defined as a hook" ,hook)) (unless (eq num (length ',args)) (error "Number of arguments are not match with hook")) (run-hook-with-args-until-success ,hook ,@args))) (defmacro emit-hook-until-failure (hook &rest args) `(let* ((num (hook-get-number-of-hook-arguments ,hook))) (unless (hook-p ,hook) (error "%S is not defined as a hook" ,hook)) (unless (eq num (length ',args)) (error "Number of arguments are not match with hook")) (run-hook-with-args-until-failure ,hook ,@args))) (defmacro emit-hook (hook &rest args) "Similar to run-hook-with-args, but checking number and type(not implemented yet) of arguments. ARGS and HOOK's arglist given with `defhook` are compared. If number of arguments and type of them are matched, `emit-hook` is the same to `run-hook-with-args'. If not, raise an error." `(let* ((num (hook-get-number-of-hook-arguments ,hook))) (unless (hook-p ,hook) (error "%S is not defined as a hook" ,hook)) (unless (eq num (length ',args)) (error "Number of arguments are not match with hook")) (run-hook-with-args ,hook ,@args))) ;; ;; Helper functions ;; (defvar hook-read-hook nil "History of the function `hook-read-hook' prompt.") (defun hook-build-hook-alist () (mapcar (lambda (x) (list (symbol-name x))) hook-global-hooks-list)) (defun hook-read-hook (prompt &optional histvar) "Return a hook chosen by the user using PROMPT. Optional argument HISTVAR is a variable to use as history." (intern (completing-read prompt (hook-build-hook-alist) nil t nil (or histvar 'hook-read-hook)))) (defun hook-get-function-arglist (func) (help-function-arglist func)) ;; (hook-get-min-number-of-function-arguments 'find-file) ;; (hook-get-min-number-of-function-arguments 'car) ;; (hook-get-min-number-of-function-arguments 'describe-hook) ;; (hook-get-min-number-of-function-arguments 'emit-hook) (defun hook-get-min-number-of-function-arguments (func) ;; autoload and builtin returns nil (let ((arglist (hook-get-function-arglist func)) (min 0)) (unless (listp arglist) (setq arglist nil) (setq min nil)) (dolist (elt arglist min) (cond ((or (eq elt '&optional) (eq elt '&rest)) (return min)) (t (incf min)))))) ;; (hook-get-max-number-of-function-arguments 'find-file) ;; (hook-get-max-number-of-function-arguments 'car) ;; (hook-get-max-number-of-function-arguments 'describe-hook) ;; (hook-get-max-number-of-function-arguments 'emit-hook) (defun hook-get-max-number-of-function-arguments (func) ;; autoload and builtin returns nil ;; &rest returns t (let ((arglist (hook-get-function-arglist func)) (max 0) optional) (unless (listp arglist) (setq arglist nil) (setq max nil)) (dolist (elt arglist max) (cond ((eq elt '&optional) (setq optional t)) ((eq elt '&rest) (setq max t) (return max)) (t (incf max)))))) (defun hook-check-number-of-arguments (func num &optional raise-error) (let* ((min (hook-get-min-number-of-function-arguments func)) (max (hook-get-max-number-of-function-arguments func)) (result (cond ((not min) ;; autoload or builtin t) ((eq max min) (eq min num)) ((and (<= min num) (<= num (if (numberp max) max (1+ num))))) (t nil)))) (if (and raise-error (not result)) (error raise-error)) result)) (defun hook-put-spec (hook num docstring) (put hook 'hook-defhook-spec (list num docstring))) (defun hook-get-spec (hook) (get hook 'hook-defhook-spec)) (defun hook-get-hook-arglist (hook) "Get arguments list from HOOK. Return t if no arguments list is attached to HOOK." (let ((spec (hook-get-spec hook))) (hook-get-hook-arglist-from-spec spec))) (defun hook-get-hook-arglist-from-spec (spec) "Get arguments list from SPEC Return t if SPEC is not list." (if (listp spec) (car spec) t)) (defun hook-get-number-of-hook-arguments (hook) "Get number of arguments of HOOK. Return -1 if no arguments list is attached to HOOK." (let ((arglist (hook-get-hook-arglist hook))) (if (eq arglist t) -1 (length (hook-get-hook-arglist hook))))) (defun hook-get-hook-docstring (hook) (car (cdr (hook-get-spec hook)))) (defvar hook-generate-timestamp 0) (defun hook-generate-funciton (function hook-arglist &optional extra-args) (incf hook-generate-timestamp) (list 'lambda hook-arglist hook-generate-timestamp (list 'apply (list 'quote function) (cons 'list (if extra-args (append hook-arglist extra-args) hook-arglist))))) (defun hook-ungenerate-funciton (function) (let* ((base (cdr (nth 3 function))) (fsymbol (cadar base)) (fargs (cdadr base))) (cons fsymbol fargs))) ;; ;; Help ;; (defun describe-hook (hook) (interactive (list (hook-read-hook "Hook: "))) (unless (hook-p hook) (error "%S is not defined as a hook" hook)) (let ((doc (hook-get-hook-docstring hook)) (arglist (hook-get-hook-arglist hook)) (arglen (hook-get-number-of-hook-arguments hook))) (assert (not (eq arglist t)) "hook.el's internal error") (with-output-to-temp-buffer "*Help*" (prin1 hook) (princ " is a hook that takes ") (cond ((eq 0 arglen) (princ "no argument.")) ((eq 1 arglen) (princ "one argument.")) (t (prin1 arglen) (princ " arguments."))) (terpri) (terpri) (if doc (princ doc) (princ "Not documented as a hook.")) (terpri) (terpri) (princ "Expected argument list: ") (terpri) (princ "\t") (prin1 arglist) (terpri) (terpri) (princ "Hook functions: ") (terpri) (dolist (f (eval hook)) (princ "\t") (prin1 (hook-ungenerate-funciton f)) (terpri)) (buffer-string)))) (defadvice describe-variable (around hook-describe activate) "Display the full documentation of FUNCTION (a symbol). Returns the documentation as a string, also." (if (hook-p (ad-get-arg 0)) (describe-hook (ad-get-arg 0)) ad-do-it)) (provide 'hook) ;; hook.el ends here |
From: Eric M. L. <er...@si...> - 2003-05-08 12:11:21
|
>>> Masatake YAMATO <je...@gy...> seems to think that: >> >BTW, eieio is really cool. How do you think to add GtkObject/GObject's >> >signal like mechanism to eieio? (We will call it `hook'.) >> [ ... ] >> >> EIEIO is a port of CLOS, and extended where appropriate for Emacs >> facilities like custom, or lack of appropriate CL constructs. >> >> I am unaware of any signaling type mechanisms, nor am I too familiar >> with them. >> >> I commonly add hooks by just having a slot with a ":type 'function" >> specifier and call it where appropriate. >> >> Eric > >Gtk's signal is similar to emacs's hook. However, in some aspects >Gtk's signal is more powerful than emacs's hook. > >As you wrote ":type 'function" does what I want a bit. But not enough. > >1) The is no agreement about number of arguments between hook and callback > functions. > > (defun hook-func0 ()) > (add-hook 'test-hook 'hook-func0) > (run-hook-with-args 'test-hook "xxx") > >2) Client arguments are not supported. > You cannot pass hook function private data. > In above text, I call client arguments extra arguments. > >I've extended hook mechanisms that overcome above limits. > >Simple example: > (defhook message-broadcast-hook (func) "Just an example") > (defun hook-func (func msg) (funcall func msg) (sit-for 1)) > > (connect-hook 'message-broadcast-hook 'hook-func "E") > (connect-hook 'message-broadcast-hook 'hook-func "EI") > (connect-hook 'message-broadcast-hook 'hook-func "EIE") > (connect-hook 'message-broadcast-hook 'hook-func "EIEI") > (connect-hook 'message-broadcast-hook 'hook-func "EIEIO") > > (emit-hook 'message-broadcast-hook 'message) > (describe-hook 'message-broadcast-hook) > >Read comments in the program to know more. > >What I'd like to do is add this new hook mechanism to eieio. > >Imaginary code: > (defclass testclass nil > ((state-changed :type hook > :arglist ((obj testclass) n) > :documentation "Hook called when the state is changed. N is number.")) > "Test class") > > (defun hook-func (obj n) > ...) > > (oconnect testclass state-changed hook-func) > > ... > (oemit testclass state-changed 42) > >Masatake YAMATO > >;; hook.el --- extended hook mechanism >;; >;; Copyright (C) 2003 Masatake YAMATO >;; >;; Author: Masatake YAMATO <je...@gy...> >;; Created: Thu May 1 19:55:05 2003 [ ... ] That is an interesting idea for adapting GTK signals to Emacs and EIEIO. Your hook code also looks like it could be quite useful too. As I understand your problem better, I think what you want for EIEIO is what C++ calls functors. Java does something similar for what some widget systems refer to as `callbacks' but I don't recall the name it uses. Here is the basic idea in EIEIO code form. I use the term `signal' in names merely to show it's association to GTK signal: ---- (defclass manly-signal-abstract () () "Base class for the Manly Signal." :abstract t) (defmethod manly-signal-send ((mso manly-signal-abstract)) "Send a manly signal." nil) (defmethod class-that-sends-manly-signals () ((manly :type list :documentation "List of manly signals.") ) "Whatever") (defclass manly-signal (manly-signal-abstract) ((data :initarg :data :initform nil :documentation "Data associated with this signal handler.")) "foo") ... (let ((sighandler (manly-signal :data "moose"))) (object-add-to-list sigsender 'manly sighandler)) ... (if (manlyness-detected-p) (let ((manly (oref sigsender manly))) (while manly (manly-signal-send (car manly)) (setq manly (cdr manly))))) ------ Now in you code, you can instance `manly-signal', with useful `local-data', and methods of `class-that-sends-manly-signals' can call `manly-signal-send' on elements of `manly'. You can use `object-add-to-list' and `object-remove-from-list' as you used connect/disconnect. The :type of `manly' can be just `manly-signal-abstract' for one, but must be 'list for a list of something. This is (as far as I can tell) a limitation of Emacs' `typep' function which cannot handle the type '(list classname). For stronger type-checking, I suppose the type '(satisfies (lambda (a) (manly-signal-abstract-child-p (car a)))) would be closer. I suspect that base classes and conveniences for signal sending/functor type operations could ease the process here. It would be easy to wrap up as a provided EIEIO Base class. One of my first EIEIO projects was a widget system, where I had a base class representing data other objects were interested in. Whenever the data was set, it would send a signal to the list of interested parties. It was vaguely like the NEXT signaling model. Have fun Eric -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: Masatake Y. <je...@gy...> - 2003-05-11 04:17:26
Attachments:
hook.el
eieio-hook.el
|
> That is an interesting idea for adapting GTK signals to Emacs and > EIEIO. Your hook code also looks like it could be quite useful too. I believe hook/signal is a kind of programming paradigm. I've called it observer oriented programming. It may change our coding style. Object oriented programming and the observer oriented programming are not conflicted. There are many way to be combined. You showed one of the way. I'll show another way. > As I understand your problem better, I think what you want for EIEIO > is what C++ calls functors. Java does something similar for what some > widget systems refer to as `callbacks' but I don't recall the name it > uses. You might talk about Observer pattern. About semantics, what you talk and what I talked are the same. But its coding policy is bit different. I'll explain latter. > Here is the basic idea in EIEIO code form. I use the term `signal' > in names merely to show it's association to GTK signal: > > ---- > (defclass manly-signal-abstract () > () > "Base class for the Manly Signal." [...] With your code, I can do what I wanted to do. But I feel it is too large scale to do something small things: to connect to a signal I have to write a class. (Of course you are the primary eieio hacker, so you are feel free to write a class.) Your example shows the way to implement signal UNDER eieio system. My proposal is that making signal a kind of the first class object. My proposal may not be beautiful enough from a view of object oriented programming. But it is easy to write. > One of my first EIEIO projects was a widget system, where I had a > base class representing data other objects were interested > in. Whenever the data was set, it would send a signal to the list of > interested parties. It was vaguely like the NEXT signaling model. NEXT signaling model is called Notification. There are 4 terms: signal, hook, notification, observer. (I don't know well abot Qt.) The term signal is good because the user can know it comes from Gtk/GObject. However, the term, signal is already used in emacs lisp including eieio. The term hook is good because the user can know it comes from emacs. However, the behavior of hook I'm talking now is bit different from that of original emacs hook. Programmers may be confused. Using notification as a type name is not so bad. But I cannot find good method names for connect and emit. emit->notify. connect->subscribe? The term observer implies object oriented programming. I think the term observer is good for your approach. Ok, I'll show my code. I'll use the term hook here. You can M-% "hook" "signal" with you eye. This code works with attached elisp files. - class developer: ;; `testhook' is a slot for `defhook'. (defclass testclass nil ((testhook :type hook-slot)) "A displayor which has the ability to focus in on one tag.") ;; Define above `testhook' arglist. ;; `testhook' passes two arguments: `object' and `file'. ;; This arglist definition is set to `testhook' slot of `testclass`. ;; This class's user can know hook's arglist easily with this `defhook' ;; notation. (defhook testhook ((object testclass) file) "Hook about...") ;; Define a method to emit the hook. (defmethod runtest ((object testclass)) ; ... (oemit object 'testhook "Hello") ; ... ) - class user (defvar testobject (testclass "testobject")) ;; just define a function and connect it to the hook. (defun testcb (object msg) (message "%s" msg)) (oconnect testobject 'testhook 'testcb) - someone ;; fire (runtest testobject) The class user have to write a function only to use the hook. To use hook, the class user don't need to know `defclass'. I think much easier to use. For class user, it is easy to find a hook in a class and its arglist: look at `defhook'. To test my code, load hook.el then load eieio-hook.el. Regards, Masatake YAMATO |
From: Masatake Y. <je...@gy...> - 2003-05-13 04:42:25
|
Just quick report. I found hook.el and eieio-hook.el posted here were broken. I improved. But it is toooo slow to write a real application. My application is named pickmake. Extracking variables information from Makefile without parsing. In the future I'll apply this to project-am.el. Usage: 1. Find a Makefile (and Makefile.am) in a source package. e.g. [jet@station117 var]$ cd autotrace [jet@station117 autotrace]$ ls -l Makefile Makefile.am -rw-rw-r-- 1 jet jet 39709 Feb 12 12:32 Makefile -rw-rw-r-- 1 jet jet 3788 Apr 4 17:51 Makefile.am [jet@station117 autotrace]$ 2. Put pickmake attached to this mail to command search PATH Don't forget chmod u+x pickmake 3. Run emacs at the directory in which the Makefile and Makefile.am are. 3. load closure.el, hook.el, eieio-hook.el and pickmake.el in order. 4. M-x pm-values-show Give any variable name defined in Makefile you want to dump. e.g. SOURCES You'll get the value of the variable. Completing-read is supported in pm-values-show but it take 6 minuets on my PIII 600MHz. I think I have to write data cache mechanism. Other interesting functions: (pm-values VARIABLENAME) e.g. (pm-values "SOURCES") => ("private.h" "strgicmp.h" "getopt1.c" "getopt.h" "getopt.c" ...) If you give the second arguments, SUBDIRS are tracked. e.g. (pm-values "SOURCES" t) Dump in sexp all variable names defined in Makefile: (pm-names) =>("XGETTEXT" "INSTALL_DATA" "LS_COLORS" "JAVA_HOME" "GMSGFMT" "MKINSTALLDIRS" ... These are based on eieio-hook.el. Usage of pickmake itself: - To dump all variables $ pickmake -N -F sxml (pickmake-names (@ (pattern ".*") (makefile "Makefile")) (directory (@ (path "/home/jet/var/autotrace")) (name "DIST_SUBDIRS") (name "distdir") - TO dump value of a variable e.g. SOURCES $ pickmake SOURCES -F sxml (pickmake-values (@ (variable "SOURCES") (pattern ".*") (makefile "Makefile")) (directory (@ (path "/home/jet/var/autotrace")) (value "input-pnm.c") (value "input-pnm.h") You can use xml instead of xml. But broken. Regards, Masatake YAMATO |
From: Eric M. L. <er...@si...> - 2003-05-10 02:45:21
|
>>> Masatake YAMATO <je...@gy...> seems to think that: >> That's an interesting idea. A good way to do it is to make a >> subclass of `semantic-displayor-abstract', and add your method there. >> >> I'm hoping to have several displayors, and allow the user to select >> their favorite. Yours would be a viable option there. > >I've tried. I'm new to eieio, so I'm afraid I've taken stupid mistake. >I've change semantic-complete-read-tag-buffer-deep to test tooltip. > >I've tested on GNU Emacs at the HEAD of subversions.gnu.org CVS >repository. > >BTW, eieio is really cool. How do you think to add GtkObject/GObject's >signal like mechanism to eieio? (We will call it `hook'.) [ ... ] Hi, It's been too long, but I finally integrated this patch and tried it out. It is quite nifty! I checked it into CVS pretty much as is. I have some comments. See below. [ ... ] >+ >+(defclass semantic-displayor-tooltip (semantic-displayor-abstract) >+ ((max-tags :type integer >+ :initarg :max-tags If you do not intend to create this object using an initarg, it is better to not specify the initarg as it gives the slot more privacy. >+ :initform 10 >+ :custom integer If you do not intend for a user to modify this object, definitely do not bother adding a :custom slot. Now, in relation to these last two comments, it would be nifty to have a way for users to customize and save to disk instances of these classes as way of customizing their prompts, but I have no plan ideas for accomplishing that task at this time. >+ :documentation >+ "Max number of tags displayed on tooltip at once. >+If `force-show' is 1, this value is ignored with typing tab or space twice continuously. >+if `force-show' is 0, this value is always ignored.") >+ (force-show :type integer >+ :initarg :force-show >+ :initform 1 >+ :custom (choice (const >+ :tag "Show when double typing" >+ 1) >+ (const >+ :tag "Show always" >+ 0) >+ (const >+ :tag "Show if the number of tags is less than `max-tags'." >+ -1)) >+ :documentation >+ "Control the behavior of the number of tags is greater than `max-tags'. >+-1 means tags are never shown. >+0 means the tags are always shown. >+1 means tags are shown if space or tab is typed twice continuously.") >+ (typing-count :type integer >+ :initform 0 >+ :documentation >+ "Counter holding how many times the user types space >or tab continuously before showing tags.") I think between the time you wrote your code, and now, I have added some new methods for `next-action' and `focus' that you could use to accomplish the same task as your typing count slot. >+ (shown :type boolean >+ :initform nil >+ :documentation >+ "Flag representing whether tags is shown once or not.") >+ ) >+ "Display mechanism using tooltip for a list of possible completions.") [ ... ] >+ >+(defun semantic-displayor-tooltip-show (text) >+ (require 'tooltip) >+ (require 'avoid) >+ (let* ((P (mouse-avoidance-point-position)) >+ (frame (car P)) [ ... ] Always give your functions a doc-string. It is "The Right Thing To Do." There is a nice section on writing doc strings in the Emacs Lisp Reference Manual. Thanks! Eric -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: David P. <dav...@wa...> - 2003-04-26 10:35:34
|
Hi Eric, > I've checked in an experimental file `semantic-complete.el' as a > proposal to a framework for performing completion. The test function > is simply `semantic-completion-test'. I've implemented only one > completion mechanism which is a minibuffer prompt for selecting a tag > out of the current buffer. The architecture is discussed in the > commentary. Good work Eric! I think your new completion framework is a good idea, and I like the formal distinction between "completor" and "displayor". I did a quick try of `semantic-complete-test' on some buffers and noticed the following problems: - the completion engine don't take into account the current buffer, it only completes based on the first buffer where `semantic-complete-test' was used for the first time. Even worse, after killing that buffer, completion test no more work and I get this error: Debugger entered--Lisp error: (error "Selecting deleted buffer") set-buffer(#<killed buffer>) (save-excursion (set-buffer something) (semantic-bovinate-toplevel t)) semantic-something-to-tag-table(#<killed buffer>) semantic-flatten-tags-table(#<killed buffer>) (eieio-oset obj (quote cache) (semantic-flatten-tags-table (oref obj buffer))) (oset obj cache (semantic-flatten-tags-table (oref obj buffer))) eieio-generic-call(semantic-collector-calculate-cache ... semantic-collector-calculate-cache([object semantic-collector-buffer-deep ... semantic-collector-abstract([object semantic-collector-buffer-deep... semantic-collector-calculate-completions([object semantic-collector-buffer-deep... semantic-complete-do-completion() semantic-complete-complete-tab() call-interactively(semantic-complete-complete-tab) read-from-minibuffer("Symbol: " nil (keymap ... semantic-complete-read-tag-engine([object semantic-collector-buffer-deep ... semantic-complete-read-tag-buffer-deep("Symbol: ") (semantic-format-tag-prototype (semantic-complete-read-tag-buffer-deep "Symbol: ")) semantic-completion-test() * call-interactively(semantic-completion-test) execute-extended-command(nil) * call-interactively(execute-extended-command) - when refining the selection, the completion buffer continues to show all the possible names. For example when I enter "xxx" in the minibuffer, then press the TAB key twice, I would like to see only the names that begin with "xxx". - when trying to enter something at first "Symbol:" prompt, I get this error: Debugger entered--Lisp error: (unbound-slot "#<class semantic-collector-buffer-deep>" "#<semantic-collector-buffer-deep Symbol: >" last-all-completions oref) signal(unbound-slot ("#<class semantic-collector-buffer-deep>" ... eieio-default-superclass([object semantic-collector-buffer-deep... eieio-generic-call(slot-unbound ([object semantic-collector-buffer-deep... slot-unbound([object semantic-collector-buffer-deep... eieio-barf-if-slot-unbound(unbound [object semantic-collector-buffer-deep... eieio-oref([object semantic-collector-buffer-deep... (oref obj last-all-completions) semantic-collector-abstract([object semantic-collector-buffer-deep... eieio-generic-call(semantic-collector-all-completions... semantic-collector-all-completions([object semantic-collector-buffer-deep... (semantic-displayor-set-completions semantic-completion-display-engine (semantic-collector-all-completions semantic-completion-collector-engine)) semantic-complete-do-completion() semantic-complete-complete-tab() call-interactively(semantic-complete-complete-tab) read-from-minibuffer("Symbol: " nil ... semantic-complete-read-tag-engine([object semantic-collector-buffer-deep... semantic-complete-read-tag-buffer-deep("Symbol: ") (semantic-format-tag-prototype (semantic-complete-read-tag-buffer-deep "Symbol: ")) semantic-completion-test() * call-interactively(semantic-completion-test) execute-extended-command(nil) call-interactively(execute-extended-command) Hope this will help. Thanks! David |
From: Eric M. L. <er...@si...> - 2003-04-26 12:05:08
|
>>> David Ponce <dav...@wa...> seems to think that: >Hi Eric, > > > I've checked in an experimental file `semantic-complete.el' as a > > proposal to a framework for performing completion. The test function > > is simply `semantic-completion-test'. I've implemented only one > > completion mechanism which is a minibuffer prompt for selecting a tag > > out of the current buffer. The architecture is discussed in the > > commentary. > >Good work Eric! I think your new completion framework is a good >idea, and I like the formal distinction between "completor" and >"displayor". > >I did a quick try of `semantic-complete-test' on some buffers and >noticed the following problems: > >- the completion engine don't take into account the current buffer, it > only completes based on the first buffer where > `semantic-complete-test' was used for the first time. Even worse, > after killing that buffer, completion test no more work and I get > this error: Aha, a typo in the `make-variable-buffer-local' prevented that from working. [ ... ] >- when refining the selection, the completion buffer continues to show > all the possible names. For example when I enter "xxx" in the > minibuffer, then press the TAB key twice, I would like to see only > the names that begin with "xxx". Hmm, I see a premature optimization written incorrectly. I removed it and if we need a speed boost, I can add something back later. >- when trying to enter something at first "Symbol:" prompt, I get this > error: Hmm, unbound slots. I see one possibility I can tidy up. I'll check these changes in. Eric -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |
From: David P. <dav...@wa...> - 2003-04-26 13:04:07
|
Eric, [...] > I'll check these changes in. Thanks! All is working fine now :-) IMO, semantic-complete is close to be able to replace senator completion ;-) A feature it would be nice to have in semantic-complete, is `senator-completion-uniquify-names', very useful to disambiguate tag names. A short example in a Java buffer: Using `semantic-complete-test' on "get" symbol returns the following completion buffer: Possible completions are: getMethod0 getMethod1 getMethod2 getMissingParameters getURL getValue getText getValue getValue You can see that "getValue" is proposed three times, and it is quasi impossible to know which one is the good choice :-( In a such case (for example, using `senator-jump' on "get" symbol) senator completion proposes this: Possible completions are: getMethod0 getMethod1 getMethod2 getMissingParameters getText getURL getValue().Essai getValue().Essai2 getValue().Internal2 It is now easy to distinguish each occurrence of "getValue", and to choose the right one. Maybe would it be possible to reuse the `senator-completion-uniquify-names' code in semantic-complete? Unfortunately, I don't know well enough (yet) your new code to be able to do that myself. Maybe could you give me a starting point, and I could try something? David |
From: Eric M. L. <er...@si...> - 2003-04-26 16:01:28
|
>>> David Ponce <dav...@wa...> seems to think that: >Eric, > >[...] > > I'll check these changes in. > >Thanks! All is working fine now :-) > >IMO, semantic-complete is close to be able to replace senator >completion ;-) > >A feature it would be nice to have in semantic-complete, is >`senator-completion-uniquify-names', very useful to disambiguate tag >names. > >A short example in a Java buffer: > >Using `semantic-complete-test' on "get" symbol returns the following >completion buffer: > >Possible completions are: >getMethod0 getMethod1 >getMethod2 getMissingParameters >getURL getValue >getText getValue >getValue > >You can see that "getValue" is proposed three times, and it is >quasi impossible to know which one is the good choice :-( > >In a such case (for example, using `senator-jump' on "get" symbol) >senator completion proposes this: > >Possible completions are: >getMethod0 getMethod1 >getMethod2 getMissingParameters >getText getURL >getValue().Essai getValue().Essai2 >getValue().Internal2 > >It is now easy to distinguish each occurrence of "getValue", and to >choose the right one. > >Maybe would it be possible to reuse the >`senator-completion-uniquify-names' code in semantic-complete? >Unfortunately, I don't know well enough (yet) your new code to be >able to do that myself. Maybe could you give me a starting point, >and I could try something? [ ... ] Hi, I agree. I was targeting the simplest case just to get the framework up. The correct OO way to do this is to create a new class inheriting from `semantic-collector-buffer-abstract', or `semantic-collector-buffer-deep'. I recommend the second. In the `semantic-collector-calculate-cache' method for your new class, you can use (call-next-method) to do the cache fetching, You can then clone all tags that need the name changed, and set the names in the cloned tags. The rest would then operate normally. The cloned cache has no other support however, so at the end when it comes time to return the actual tag, not the cloned tag, some additional work may need to be done. I don't think senator needs the actual tag for the 'jump' feature though it is likely other applications do. Perhaps the original tag could be added as a property of the clone. I had thought about other options for senator as well. Mostly in the displayor option. The existing collector could stay the same, but the displayor could `focus' in on given tags. For example, once a unique name is chosen, each additional request for the completion list could focus in on one instance by moving the point and highlighting the target in the buffer. This focus feature might be useful even when there is only one option. Anyway, I still need to add history and default support before it could be a full replacement. Have fun Eric -- Eric Ludlam: za...@gn..., er...@si... Home: http://www.ludlam.net Siege: www.siege-engine.com Emacs: http://cedet.sourceforge.net GNU: www.gnu.org |