In Emacs, how can I use imenu more sensibly with C#?
I've used emacs for a long time, but I haven't been keeping up with a bunch of features. One of these is speedbar, which I just briefly investigated now. Another is imenu. Both of these were mentioned in in-emacs-how-can-i-jump-between-functions-in-the-current-file?
Using imenu, I can jump to particular methods in the module I'm working in. But there is a parse hierarchy that I have to negotiate before I get the option to choose (with autocomplete) the method name.
It goes like this. I type M-x imenu
and then I get to choose Using
or Types
. The Using choice allows me to jump to any of the using statements at the top level of the C# file (something like imports statements in a Java module, for those of you who don't know C#). Not super helpful. I choose Types. Then I have to choose a namespace and a class, even though there is just one of each in the source module. At that point I can choose between variables, types, and methods. If I choose methods I finally get the list of methods to choose from. The hierarchy I traverse looks like this;
Using
Types
Namespace
Class
Types
Variables
Methods
method names
Only after I get to the 5th level do I get to select the thing I really want to jump to: a particular method.
Imenu seems intelligent about the source module, but kind of hard to use. Am I doing it wrong?
The CEDET tools at http://cedet.sf.net includes a C# parser in the 'contrib' area that can parse C# code. CEDET then supports specialized interfaces for both speedbar and imenu, that will shape your menu constructs in a way that code organized, not tag type organized. In c++, for example, code like this:
namespace foo {
class bar {
int somemethod();
}
}
would give you a tree that had "bar" under "foo", and "somemethod" under "bar", so if you know your structure, you just need to unwind by name to the tag you want.
I use the following function, which will use ido and just prompt for the symbols you can jump to. Just call it instead of imenu:
(defun ido-goto-symbol ()
"Will update the imenu index and then use ido to select a symbol to navigate to"
(interactive)
(imenu--make-index-alist)
(let ((name-and-pos '())
(symbol-names '()))
(flet ((addsymbols (symbol-list)
(when (listp symbol-list)
(dolist (symbol symbol-list)
(let ((name nil) (position nil))
(cond
((and (listp symbol) (imenu--subalist-p symbol))
(addsymbols symbol))
((listp symbol)
(setq name (car symbol))
(setq position (cdr symbol)))
((stringp symbol)
(setq name symbol)
(setq position (get-text-property 1 'org-imenu-marker symbol))))
(unless (or (null position) (null name))
(add-to-list 'symbol-names name)
(add-to-list 'name-and-pos (cons name position))))))))
(addsymbols imenu--index-alist)
(let* ((symbol-at-point (symbol-name (symbol-at-point)))
(selected-symbol (ido-completing-read
"Symbol? "
(if (member symbol-at-point symbol-names)
(cons symbol-at-point (remove-if (lambda (x) (string-equal x symbol-at-point))
symbol-names))
symbol-names)))
(position (cdr (assoc selected-symbol name-and-pos))))
(if (markerp position)
(goto-char position) (goto-char (overlay-start position)))))))
(goto-char position) (goto-char (overlay-start position)))))))