One can use Jacinda to generate tags files for vim. This amounts to string processing with regular expressions, which we can do in a functional style, skirting Universal Ctags.

According to :help tags-file-format, the format for a tags file is:

{tagname} {TAB} {tagfile} {TAB} {tagaddress}

In vim, a {tagaddress} can be any ex command, and in fact using regular expressions will ensure our tag files do not become outdated as quickly. For instance:

sum prelude/fn.jac /^fn sum(x) :=$/;

Here is our code:

fn mkEx(s) := '/^' + s + '$/;';

fn processStr(s) := let val line := split s /[ \(]+/ val outLine := sprintf '%s\t%s\t%s' (line.2 . fp . mkEx s) in outLine end;

processStr"{%/fn +[[:lower:]][[:latin:]]*.*:=/}{`0}

This uses implicit syntax for streams, plus some familiar functional programming. /fn +[[:lower:]][[:latin:]]\*.\*:=/ matches only those lines where a function is defined and /[ \\(]+/ splits away the fn to get the function name.

Note also the atypical (as yet undocumented) syntax for tuples; . is the separator rather than ,.

One can run this on all .jac files in a directory with:

fd '.jac$' -x ja run tags.jac -i > tags

This gives:

sum ./prelude/fn.jac /^fn sum(x) :=$/; drop ./prelude/fn.jac /^fn drop(n, str) :=$/; take ./prelude/fn.jac /^fn take(n, str) :=$/; round ./prelude/fn.jac /^fn round(x) := |. (x+0.5);$/; itostring ./prelude/fn.jac /^fn itostring() :=$/; any ./prelude/fn.jac /^fn any(p, xs) :=$/; all ./prelude/fn.jac /^fn all(p, xs) :=$/; id ./prelude/fn.jac /^fn id(x) := x;$/; fromMaybe ./prelude/fn.jac /^fn fromMaybe(a, x) :=$/; replace ./prelude/fn.jac /^fn replace(re, t, str) :=$/; path ./examples/path.jac /^fn path(x) :=$/; printSpan ./examples/span.jac /^fn printSpan(str) :=$/; mkEx ./examples/tags.jac /^fn mkEx(s) :=$/; processStr ./examples/tags.jac /^fn processStr(s) :=$/; ...

I think this would be more useful in awk, since that is more universal than ctags, however, the example is a testament to Jacinda's utility.