Hi,
well, sounds good - such a semantic-go-to-tag would be fine for me.
But i have another case which is not considered in your new =
implementation:
Faux-groups created by semantic-adopt-external-members (e.g. with c++
where the methods of a class are defined in another file as the class =
itself -
same for eieio).
Well, i makes also sense calling semantic-go-to-tag withsuch a faux-tag =
-
and i'm not sure if this is already handled by the new implementation?
ECB currently does the following:
(when (ecb-faux-group-tag-p tag)
(set-buffer (get-file-buffer ecb-path-selected-source))
(let ((faux-group (ecb-semanticdb-get-type-definition
(ecb--semantic-tag-name data))))
(when faux-group
(set-buffer (find-file-noselect (car faux-group)))
(goto-char (semantic-tag-start (cdr faux-group))))))
I think we could add such a algorithm also into your new
semantic-go-to-tag.
Here comes the definition of ecb-semanticdb-get-type-definition
(all functions ecb--semantic-X are just aliases to semantic-X!):
(defun ecb-semanticdb-get-type-definition-list (typename &optional
=
search-system-dbs)
"Search with semanticdb for the definition of the type with name =
TYPENAME.
The value of SEARCH-SYSTEM-DBS is propagated to the semanticdb variable
`semanticdb-search-system-databases'. Return-value is an alist where =
each
element represents a found location for TYPENAME. The car of an element =
is the
full filename and the cdr is the tag in this file. If no type-definition =
can
be found or if the semanticdb is not active then nil is returned."
(when (and (featurep 'semanticdb) (ecb--semanticdb-minor-mode-p))
(if (not ecb-semantic-2-loaded)
;; With semantic 1.X we just run a very simplified database =
search.
(let ((search-result (ecb--semanticdb-find-tags-by-name =
typename)))
(when search-result
(list (cons (ecb--semanticdb-full-filename (caar =
search-result))
(cdar search-result)))))
;; With semantic 2.X we do a full featured database-search.
(let* ((semanticdb-search-system-databases search-system-dbs)
(search-result (ecb--semanticdb-find-tags-by-name =
typename))
(result-tags (and search-result
(ecb--semanticdb-strip-find-results =
search-result)))
(type-tag-numbers nil))
(when (and result-tags
;; some paranoia
(=3D (length result-tags)
(ecb--semanticdb-find-result-length =
search-result)))
;; First we check which tags in the stripped search-result
;; (result-tags) are types with positions (means associated =
with a
;; file) and collect their sequence-positions in =
type-tag-numbers.
(dotimes (i (length result-tags))
(if (and (equal (ecb--semantic-tag-class (nth i =
result-tags))
'type)
(ecb--semantic-tag-with-position-p (nth i =
result-tags)))
(setq type-tag-numbers
(cons i type-tag-numbers))))
(setq type-tag-numbers (nreverse type-tag-numbers))
;; Now we get for each element in type-tag-numbers the related
;; filename (where the tag is defined) and collect them in an =
alist
;; where each element is a cons-cell where car is the filename =
and
;; cdr is the tag in this file. Especially with scoped =
languages
;; like C++ or Java a type with the same name can be defined =
in more
;; than one file - each of these files belonging to another
;; package/library.
(delq nil
(mapcar (function (lambda (n)
(let ((r =
(ecb--semanticdb-find-result-nth-with-file
search-result n)))
(if (and (cdr r)
(stringp (cdr r))
(ecb-file-readable-p (cdr =
r)))
(cons (cdr r) (car r))))))
type-tag-numbers)))))))
(defun ecb-semanticdb-get-type-definition (typename &optional
search-system-dbs)
"Runs `ecb-semanticdb-get-type-definition-list' for TYPENAME and
SEARCH-SYSTEM-DBS and return exactly one type-definition cons-cell where =
car
is a full filename and cdr is a tag for TYPENAME. "
(let ((type-definition-alist (ecb-semanticdb-get-type-definition-list
typename search-system-dbs)))
(when type-definition-alist
;; if we got more than one file for TYPENAME then the user has to
;; choose one.
(if (> (length type-definition-alist) 1)
(assoc (ecb-offer-choices "Select a definition-file: "
(mapcar #'car =
type-definition-alist))
type-definition-alist)
(car type-definition-alist)))))
What did you think??
Ciao,
Klaus
Eric M. Ludlam wrote:
> Having looked at this a little bit more, I think I have an issue with
> going in this direction. semantic-go-to-tag is not supposed to switch
> to the found buffer, it is just supposed to set the buffer to that
> location. It's up to the app in question to to do the switch-buffer.
> As such, the find-file is actually a bug, and should be (set-buffer
> (find-file-noselect ...)).
>=20
> This function is also missing a few things. It isn't taking advantage
> of `semantic-tag-filename' for tags not currently hooked into a tag
> cache. This will happen if you clone tags, or use the class browser
> data structure.
>=20
> The proper way to use this functin is like this:
>=20
> (semantic-go-to-tag tag)
> (do-something-that-depends-on-that-tags-environment ...)
>=20
> which doesn't change any visible buffers. Here is the way speedbar
> uses it (or, is supposed to use it, and now does that I fixed
> semantic-sb.el)
>=20
> (select-window (some-window))
> (semantic-go-to-tag tag parent)
> (switch-to-buffer (current-buffer))
>=20
> which should be exactly what ECB needs.
>=20
> Here is a re-written version that also uses `semantic-tag-file-name'
> to make it more robust.
>=20
> (define-overload semantic-go-to-tag (tag &optional parent)
> "Go to the location of TAG.
> TAG may be a stripped element, in which case PARENT specifies a
> parent tag that has position information.
> Different behaviors are provided depending on the type of tag.
> For example, dependencies (includes) will seek out the file that is
> depended on (see `semantic-dependency-tag-file'."
> (:override
> (unless (and (eq (semantic-tag-class tag) 'include)
> (let ((f (semantic-dependency-tag-file tag)))
> (when f
> (set-buffer (find-file-noselect f))
> (point))))
> (cond ((semantic-tag-buffer tag)
> ;; If the tag has no buffer, it may be deoverlayed.
> ;; Assume the tool doing the finding knows that we came
> ;; in from a database, and use the current buffer.
> (set-buffer (semantic-tag-buffer tag)))
> ((semantic-tag-file-name tag)
> ;; If it didn't have a buffer, but does have a file
> ;; name, then we need to get to that file so the tag
> ;; location is made accurate.
> (set-buffer (find-file-noselect (semantic-tag-file-name tag))))
> ((and parent (semantic-tag-p parent) (semantic-tag-buffer parent))
> ;; The tag had nothing useful, but we have a parent with
> ;; a buffer, then go there.
> (set-buffer (semantic-tag-buffer parent)))
> ((and parent (semantic-tag-p parent) (semantic-tag-file-name
> parent)) ;; Tag had nothing, and the parent only has a
> file-name, then ;; find that file, and switch to that buffer.
> (set-buffer (find-file-noselect (semantic-tag-file-name
> parent)))) (t
> ;; Well, just assume things are in the current buffer.
> nil
> ))
> ;; We should be in the correct buffer now, try and figure out
> ;; where the tag is.
> (cond ((semantic-tag-with-position-p tag)
> ;; If it's a number, go there
> (goto-char (semantic-tag-start tag)))
> ((semantic-tag-with-position-p parent)
> ;; Otherwise, it's a trimmed vector, such as a parameter,
> ;; or a structure part. If there is a parent, we can use it
> ;; as a bounds for searching.
> (goto-char (semantic-tag-start parent))
> ;; Here we make an assumption that the text returned by
> ;; the parser and concocted by us actually exists
> ;; in the buffer.
> (re-search-forward (semantic-tag-name tag)
> (semantic-tag-end parent)
> t))
> (t
> ;; Take a guess that the tag has a unique name, and just
> ;; search for it from the beginning of the buffer.
> (goto-char (point-min))
> (re-search-forward (semantic-tag-name tag) nil t)))
> ))
> )
>=20
> Eric
>=20
>>>> <klaus.berndl@...> seems to think that:
>> Eric M. Ludlam wrote:
>>> Hi,
>>>=20
>>> I was about to send you a response with a similar suggestion for
>>> semantic-go-to-tag, though I was going to suggest something like
>>> `semantic-retrieve-tag-buffer' which used `find-file-noselect'
>>> instead of find-file. The perfect name would be
>>> `semantic-tag-buffer' but that's been used.
>>=20
>> Well, `semantic-retrieve-tag-buffer' would be fine if it returns
>> the buffer of the tag and the position of the tag in this buffer. Or
>> which signature of this new function you had in mind?
>> Do you include this new function before releasing 1.0 or should i
>> write=20
>> a first version derived from current semantic-go-to-tag and send it
>> to=20
>> you for review?
>>=20
>>>=20
>>> As far as layers are concerned, there are a lot of layers in
>>> semantic. There's the parser, the primitive tag layer, a set of
>>> file finding layers. Search layers. Analysis layers. Mode layers.
>>> And finally, some applications, like imenu support. I doubt there
>>> is a black and white rule for determining which is which, except via
>>> experimentation and discovery.
>>=20
>> Of course but all of these layers are in my opinion part of a
>> superlayer "semantic" which offers a
>> parsing-and-tag-retrieving/analysing-engine=20
>> to an arbitrary display-layer on top of this "semantic"-layer. This
>> display- layer can be something like imenu, speedbar, ECB or
>> senator....=20
>>=20
>> This means no sublayer (analysis-support, mode-layers, search-layers
>> etc..)=20
>> of the layer "semantic" creates new windows, devides windows,
>> displays files=20
>> in any window, moves point to some tag-location but all these
>> sublayers just offer a well-defined API so a display-layer can get
>> all necessary-informations to display the result of the
>> analysis-support, the search-result, the tag-buffer and tag-position
>> etc.... Only the display layer decides in which window/frame an
>> information should be displayed. Of course cedet can contain such a
>> display- layer for itself, e.g. senator... or some other special
>> display but the underlaying sublayers should only return buffers and
>> buffer-positions or should at least offer also functions which just
>> return these informations. =20
>>=20
>> Ciao,
>> Klaus
>>=20
>>>=20
>>> Of course, the speedbar use of `semantic-go-to-tag' means that it
>>> does exactly what speedbar wants. ;)
>>>=20
>>> Eric
>>>=20
>>>>>> <klaus.berndl@...> seems to think that: Hi,
>>>>=20
>>>> after spending some minutes more for the solution i came down with
>>>> the idea that the best would be if semantic-go-to-tag would be
>>>> renamed into something like semantic-tag-location whic would just
>>>> return a cons-cell where the car is the full pathfile-name of the
>>>> tag-definition and the cdr the position with in this file where
>>>> TAG starts. But it should not perform file-opening or some
>>>> cursor-moving. Of course semantic-tag-location should be
>>>> overloadable too.=20
>>>>=20
>>>> With such a function tools like ECB would get all what they need
>>>> and can then use the informations (file-name and position of
>>>> tag-start) in any manner they need/want.
>>>>=20
>>>> If we see tools like ECB and semantic as 2 layers of a software
>>>> then semantic is the server which just supplies informations and
>>>> ECB is the client which uses this informations and displays them
>>>> suitable. IMHO it would be the best if both tools would not cross
>>>> this responsibility-frontier. For speedbar and senator the same
>>>> arguments as for ECB are applicable.=20
>>>>=20
>>>> semantic-go-to-tag is a good example how things should not be done
>>>> with respect of the responsibilities i described above. For
>>>> semantic-imenu-goto-function the situation is a little bit
>>>> different because this function just hooks
>>>> into imenu and makes it working with semantic, so maybe calling
>>>> find-file or stuff like this could be ok here.
>>>>=20
>>>> I have not checked the whole semantic-API but i suspect that there
>>>> are other semantic function which perform some display-jobs which
>>>> should be done by layers above semantic.
>>>>=20
>>>> Strict disjuncture of responsibilities is one of the best and most
>>>> important design principles in software-development - at least
>>>> IMHO ;-)=20
>>>>=20
>>>> Thoughts?
>>>>=20
>>>> Ciao,
>>>> Klaus
>>>>=20
>>>> klaus.berndl@... wrote:
>>>>> Hi Eric, David,
>>>>>=20
>>>>> i just found semantic-go-to-tag which does some things ECB
>>>>> currently implements for itself. But in general i think ECB
>>>>> should throw away its own implementation of this job and use
>>>>> instead this function because its overloadable - which is most
>>>>> important advantage. Currently ECB implements quite the same
>>>>> stuff as the default-code of semantic-go-to-tag but of course ECB
>>>>> could not profite from overloaded versions...=20
>>>>>=20
>>>>> But to become useable by ECB `semantic-go-to-tag' has to be
>>>>> changed slightly, especially concerning finding files. ECB needs
>>>>> the full controll which function is used for finding files wheres
>>>>> semantic-go-to-tag currently uses hard-coded `find-file' - but ECB
>>>>> sometimes wants files to being openend in the other window etc...
>>>>>=20
>>>>> So i have patched `semantic-go-to-tag' and also
>>>>> `semantic-imenu-goto-function'
>>>>> as follows (these functions are currently the only ones using
>>>>> `find-file'...):=20
>>>>>=20
>>>>> First i have introduced a new option:
>>>>>=20
>>>>> ;; TODO: Klaus Berndl <klaus.berndl@...>: Where to put this
>>>>> option?? ;; currently used by semantic-imenu-goto-function and
>>>>> semantic-go-to-tag (defcustom semantic-find-file-function
>>>>> 'find-file "*Function used by semantic to find and display a
>>>>> file." :group 'semantic :type 'function)=20
>>>>>=20
>>>>> This option is currently placed in semantic.el - maybe there is a
>>>>> better place?=20
>>>>>=20
>>>>> Then i have ajusted `semantic-go-to-tag' and also
>>>>> `semantic-imenu-goto-function' (i have only replaced the calls to
>>>>> find-file by a more flexible solution):
>>>>>=20
>>>>> (define-overload semantic-go-to-tag (&optional tag parent) "Go
>>>>> to the location of TAG. TAG may be a stripped element, in which
>>>>> case PARENT specifies a parent tag that has position information.
>>>>> Different behaviors are provided depending on the type of tag.
>>>>> For example, dependencies (includes) will seek out the file that
>>>>> is depended on (see `semantic-dependency-tag-file'."
>>>>> (or tag (setq tag (car (semantic-find-tag-by-overlay nil))))
>>>>> (unless (and (eq (semantic-tag-class tag) 'include)
>>>>> (let ((f (semantic-dependency-tag-file tag))
>>>>> (find-file-function (or (and (fboundp
>>>>>=20
>>>>>=20
>>>>> semantic-find-file-function)
>>>>> semantic-find-file-function) 'find-file))) (if f (funcall
>>>>> find-file-function f)))) (:override (if (semantic-tag-buffer
>>>>> tag) ;; If the tag has no buffer, it may be deoverlayed.
>>>>> ;; Assume the tool doing the finding knows that we came
>>>>> ;; in from a database, and use the current buffer.
>>>>> (set-buffer (semantic-tag-buffer tag)))
>>>>> (if (semantic-tag-with-position-p tag)
>>>>> ;; If it's a number, go there
>>>>> (goto-char (semantic-tag-start tag))
>>>>> ;; Otherwise, it's a trimmed vector, such as a parameter,
>>>>> ;; or a structure part.
>>>>> (if (not parent)
>>>>> nil
>>>>> (if (semantic-tag-with-position-p parent)
>>>>> (progn
>>>>> (if (semantic-tag-buffer parent)
>>>>> ;; If this parent tag has no buffer, then it
>>>>> ;; may be deoverlayed.
>>>>> (set-buffer (semantic-tag-buffer parent)))
>>>>> (goto-char (semantic-tag-start parent))
>>>>> ;; Here we make an assumption that the text
>>>>> returned by ;; the parser and concocted by us
>>>>> actually exists ;; in the buffer.
>>>>> (re-search-forward (semantic-tag-name tag) nil
>>>>> t))))))))=20
>>>>>=20
>>>>> (defun semantic-imenu-goto-function (name position &optional rest)
>>>>> "Move point associated with NAME to POSITION.
>>>>> Used to override function `imenu-default-goto-function' so that we
>>>>> can continue to use overlays to maintain the current position.
>>>>> Optional argument REST is some extra stuff."
>>>>> (if (semantic-overlay-p position)
>>>>> (let ((os (semantic-overlay-start position))
>>>>> (ob (semantic-overlay-buffer position)))
>>>>> (if os
>>>>> (progn
>>>>> (if (not (eq ob (current-buffer)))
>>>>> (switch-to-buffer ob))
>>>>> (imenu-default-goto-function name os rest))
>>>>> ;; This should never happen, but check anyway.
>>>>> (message "Imenu is out of date, try again. (internal bug)")
>>>>> (setq imenu--index-alist nil)))
>>>>> ;; When the POSITION is actually a pair of numbers in an
>>>>> array, then ;; the file isn't loaded into the current buffer.
>>>>> (let ((find-file-function (or (and (fboundp
>>>>> =20
>>>>> semantic-find-file-function)
>>>>> semantic-find-file-function) 'find-file))) (if (vectorp
>>>>> position) (let ((file (aref position 0))
>>>>> (pos (aref position 1)))
>>>>> (and file (funcall find-file-function file))
>>>>> (imenu-default-goto-function name pos rest))
>>>>> ;; When the POSITION is the symbol 'file-only' it means
>>>>> that this ;; is a directory index entry and there is no
>>>>> tags in this ;; file. So just jump to the beginning of
>>>>> the file. (if (eq position 'file-only)
>>>>> (progn
>>>>> (funcall find-file-function name)
>>>>> (imenu-default-goto-function name (point-min) rest))
>>>>> ;; Probably POSITION don't came from a semantic imenu.
>>>>> Try ;; the default imenu goto function.
>>>>> (condition-case nil
>>>>> (imenu-default-goto-function name position rest)
>>>>> (error (message "Semantic Imenu override problem.
>>>>> (Internal bug)") (setq imenu--index-alist nil)))))
>>>>> )))=20
>>>>>=20
>>>>>=20
>>>>> Maybe there are additional function where this new option could
>>>>> be used - don't know?=20
>>>>>=20
>>>>> With this new option and the changed functions tools like ECB
>>>>> could have full-controll in which window (or even frame) semantic
>>>>> would "find" files! What do you think?
>>>>>=20
>>>>> Ciao,
>>>>> Klaus
>>>>>=20
>>>>>=20
>>>>> -------------------------------------------------------
>>>>> SF email is sponsored by - The IT Product Guide
>>>>> Read honest & candid reviews on hundreds of IT Products from real
>>>>> users. Discover which products truly live up to the hype. Start
>>>>> reading now. http://ads.osdn.com/?ad_ide95&alloc_id=14396&op=3Dick
>>>>> _______________________________________________
>>>>> Cedet-devel mailing list
>>>>> Cedet-devel@...
>>>>> https://lists.sourceforge.net/lists/listinfo/cedet-devel
|