better generation of vi ctags in ghci

Claus Reinke claus.reinke at
Wed Jun 17 07:02:26 EDT 2009

> I got frustrated with vi tags not working after some unrelated code is 
> edited in a source file. Moreover non-exported top level declarations 
> were not available in vi tags file. Here is an attempt to fix it: 

I'm all in favour of ctags improvements in general! Thanks for investing
the effort. Haven't looked at your patch in detail yet, just a few comments
based on your message:

> Why would you want the new implementation of :ctags ghci command?
> * Tags are searched based on the line content. This is what Exuberant 
> Ctags do for other languages and it is the other posix way to do it. 
> This makes the positioning to work well even when the source code was 
> edited (on places unrelated to the tag location). More complicated Ex 
> statements can be used to improve it even more but then it does not work 
> well with :tselect (it screws up tag kinds, at least with my version of 
> vim 7.2.65).

Haskell isn't like other languages. If you search on source lines of
definitions, that'll break every time you change a pattern, parameter
name, parameter order, clause order, ..; if you search on less than the 
full line, you get additional misleading matches, especially because you
can only search forward or backward, not both (also, the fallback of
/^<tag>/ won't work for infix operators, classes, data, ..).

Ideally, one (well, I at least;-) would like a mixed approach: start with
source line, figure out if the line is right, if yes, done, if not, then search
(starting from the old position). But that seemed to be beyond posix 
tags, so I stuck with line numbers.

If the definition you're looking for isn't close to where it was, you'd
better regenerate the tags anyway; if the definition is still close, line
numbers degrade gracefully; search patterns tend to break completely
(on the other hand, line number changes affect more tags than definition
changes do, so it would be useful to have both options).

Note that emacs always does a search, but it does search outwards
in both directions, from the old location as the start position, so it can 
make do with an underspecified search pattern, such as the tag itself 
(if I recall correctly, the etags position might be off by one anyway; 
emacs doesn't have lines/columns, it counts bytes from the start or 
something like that, which meant that the etags and ctags parts couldn't
share all their code).

> * All top level symbols defined in a module are added to the tags file. 
> Even the non-exported ones. These are marked as static (file:) so the 
> default tag selection (Ctrl-]) works fine based on the file you started 
> the search from.

Thanks, I had meant to do this, don't know why I didn't (you use the new
static tag format, not the old, I assume?).
> * Tags get kinds added so you can select whether you want to get to a 
> type constructor or a data constructor (that is if you share names 
> between the two).

You mean 'kind' in the tags file sense, using it to record namespace, 
similar to haddock's t/v distinction?

The extended tag line format is somewhat underspecified (only file: and 
kind: are mentioned in Vim's docs), so I could not make up my mind
what to use kind: for (namespace? type? kind? type/data/class? package? 
..) and I couldn't figure out whether any editors would actually use the 
extra info if I were to add extra fields to add all the useful info.

In Vim, that info could be accessed via scripts, so it would be useful to 
add all of it, but some standard would help; also some of the info that 
:ctags could record in the tags file can be had by other means, including 
:type and :info output, and those other means will often be more up to 
date than the tags file, so I added no extra info to the tags file.
> * In general it is a nice addition to vim haskellmode. If you search for 
> help on symbols in libraries then opening haddock is cool. If you search 
> for help on a symbol in your project then opening the tag in a preview 
> window (Ctrl-W} or ptselect) is cool.

That's why I suggested the addition in the first place!-) Thanks for
taking it further. The one real show-stopper are files that GHCi can't
handle: because the ctags/etags patch borrowed all the interesting 
functionality from GHCi, it inherited its limitations as well (there is
a ghctags program somewhere which circumvents that issue by not
trying to generate code when generating tags, so it can handle tags
for GHC's sources, which GHCi :ctags couldn't, last time I tried). 
A secondary issue was what to do with non-interpreted modules
(probably: just skip, and rely on them having their own tags files).

(btw, I also use '_si' more since I switched it to open a preview window 
for the :info output, and of course, one can get the types without having 
to record them in the tags file).
> Problems:
> * It needs somebody to check that emacs tags were not broken. I'm not an 
> emacs user but some tag generation code is shared for vim and emacs. I 
> tried to keep emacs tags exactly the way they were (only the exported 
> symbols, original file format).

I'm not an emacs user, either, I just added both versions because I saw
no reason not to (and I had been looking into the curious world of emacs 
terminology for other reasons). Simon M did quite a bit of cleanup on my
original patch, if I recall, perhaps other emacs users care to take a look?

> * If your code happens to have definitions on lines which happen to 
> exist more times in one source file then it may put you at an incorrect 
> location. I doubt it will ever happen but if anybody thinks it is really 
> bad we can keep the original format of vim tags too. Then e.g. :ctags 
> would generate tags with line numbers and :ctags! would generate tags 
> with search expressions.

See above for other things that can go wrong with search-based tags,
so I'd prefer to have both options.

More information about the Glasgow-haskell-users mailing list