Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make vim's taglist plugin show useful information for javascript?

I've recently abandoned mouse-driven, platform-specific GUI editors and committed entirely to vim. The experience so far has been fantastic, but I'm stuck when it comes to Javascript.

The ever-popular taglist utility (using Exuberant Ctags) has been great for everything but Javascript. With the language's overly-free form and structure, taglist could only pick up a handful of functions when I opened it up -- only those defined in the format:

function FUNCNAME (arg1, arg2) {

but no variables or function objects defined like:

var myFunc = function (arg1, arg2) {

So I googled a bit and found the following definition set for ctags, which I put in my ~/.ctags file:

--langdef=js
--langmap=js:.js
--regex-js=/([A-Za-z0-9._$]+)[ \t]*[:=][ \t]*\{/\1/,object/
--regex-js=/([A-Za-z0-9._$()]+)[ \t]*[:=][ \t]*function[ \t]*\(/\1/,function/
--regex-js=/function[ \t]+([A-Za-z0-9._$]+)[ \t]*([^])])/\1/,function/
--regex-js=/([A-Za-z0-9._$]+)[ \t]*[:=][ \t]*\[/\1/,array/
--regex-js=/([^= ]+)[ \t]*=[ \t]*[^""]'[^'']*/\1/,string/
--regex-js=/([^= ]+)[ \t]*=[ \t]*[^'']"[^""]*/\1/,string/

After that, running ctags from the command line was fantastic. It found every function and object that I needed it to find.

The problem is that the taglist.vim plugin isn't seeing those new results. When I open my javascript file in vim and hit :TlistToggle, I get the exact same meager handful of functions I got before. I hit 'u' to update the list, with no effect.

Digging into taglist.vim, I found this:

" java language
let s:tlist_def_java_settings = 'java;p:package;c:class;i:interface;' .
                               \ 'f:field;m:method'

" javascript language
let s:tlist_def_javascript_settings = 'javascript;f:function'

...which implies we're only looking at one specific kind of output from the ctags utility for javascript. Unfortunately, I'm not savvy enough with taglist or vim in general (yet) to discover what change I can make to get all those wonderful ctags command-line results to show up in vim.

Help appreciated!

like image 800
Tom Frost Avatar asked Nov 24 '09 14:11

Tom Frost


2 Answers

Got it! I dove into the taglist.vim code for awhile, and this is what I found:

taglist.vim forces ctags to use the same filetype that vim is using. So even though the ~/.ctags snippet I found via google is assigning my much-needed definitions to the new "js" language and applying it to files that end in .js, taglist is forcing ctags into using the "JavaScript" filetype that vim is using -- which is built right into ctags already.

The solution is to change the ~/.ctags file from what I've posted above to this:

--regex-JavaScript=/([A-Za-z0-9._$]+)[ \t]*[:=][ \t]*new[ \t]+Object\(/\1/o,object/
--regex-JavaScript=/([A-Za-z0-9._$]+)[ \t]*[:=][ \t]*\{/\1/o,object/
--regex-JavaScript=/([A-Za-z0-9._$()]+)[ \t]*[:=][ \t]*function[ \t]*\(/\1/f,function/
--regex-JavaScript=/function[ \t]+([A-Za-z0-9._$]+)[ \t]*\([^\]\)]*\)/\1/f,function/
--regex-JavaScript=/([A-Za-z0-9._$]+)[ \t]*[:=][ \t]*new[ \t]+Array\(/\1/a,array/
--regex-JavaScript=/([A-Za-z0-9._$]+)[ \t]*[:=][ \t]*\[/\1/a,array/
--regex-JavaScript=/([^= ]+)[ \t]*=[ \t]*[^""]'[^'']*/\1/s,string/
--regex-JavaScript=/([^= ]+)[ \t]*=[ \t]*[^'']"[^""]*/\1/s,string/

which alters the pre-existing JavaScript language definition directly, rather than creating a new language definition within ctags. Now, when taglib forces vim's registered filetype, the new definitions are used. Also missing from the previously posted ~/.ctags lines was the "kind" letter that Al mentioned in his answer, so those are included in my updated version as well.

From there, drop the following into your ~/.vimrc to activate the new types:

let g:tlist_javascript_settings = 'javascript;s:string;a:array;o:object;f:function'

All-in-all, the new regex lines aren't perfect -- they'll definitely need some tweaking to avoid a lot of false positives, and it might be nice to separate out constants and such. But now, at least, I have the ability to do that :).

Edit: Added instructions on how to activate types without editing the plugin, and vastly improved the main ctags function regex to avoid some false-positives.

Edit 2: Added more array and object definitions to the ctags regex.

like image 121
Tom Frost Avatar answered Sep 17 '22 15:09

Tom Frost


I ran into this post on a google search, and although your findings are excellent, I think we can improve them. This is the results of a bit of hacking on your solution:

.ctags

--regex-JavaScript=/^var[ \t]+([a-zA-Z0-9_$]+) = \[/\1/a,array/
--regex-JavaScript=/^var[ \t]+([a-zA-Z0-9_$]+) = \{/\1/o,object/
--regex-JavaScript=/^var[ \t]+([a-zA-Z0-9_$]+) = (^{^[)+/\1/r,var/
--regex-JavaScript=/^[ \t]*(this\.)?([A-Za-z0-9_$()]+)[ \t]*[:=][ \t]*function[ \t]*\(\)/\2/u,function/
--regex-JavaScript=/^[ \t]*function ([a-z0-9]+[A-Za-z0-9_]*)/\1/u,function/
--regex-JavaScript=/^[ \t]*([A-Za-z0-9]+)\.prototype\.([a-z0-9]+[A-Za-z0-9_]*)/\1 : \2/u,function/
--regex-JavaScript=/^[ \t]*function ([A-Z]+[A-Za-z0-9_]*)/\1/o,object/

.vimrc

let g:tlist_javascript_settings = 'javascript;r:var;s:string;a:array;o:object;u:function'

This gets rid of a few more false positives, and adds some more features in, as a tradeoff for getting rid of some of the more problematic regexes. I'll keep updating if I find I need more.

Edit: I've gotten everything working really nicely now; I feel like this result is solid. The only major deficiency is that it doesn't work on comma separated variable definitions. That seems particularly nasty. Maybe another day. :)

Note also that I changed the .vimrc. This isn't because I'm a freak; it's because somehow taglist or ctags or something has some default values set, and if you don't change it, then you get a lot of doubles where functions and vars are concerned, which really drives me insane (I pay super attention to detail.. :P )

Edit: More tweaks. It picks up on prototype function declarations now, and doesn't do some other stupid stuff.

like image 24
thedayturns Avatar answered Sep 20 '22 15:09

thedayturns