Thursday, September 2, 2010

Vim, PHP, TagList, and Ctags

I spent a good bit of time figuring out how to get vim to play nice with the spectacular TagList plugin, Ctags and PHP, so I've decided to sum up everything I did to get it working perfectly for the next person who comes along.

Installing TagList itself is simple---just follow the instructions, standard to installing any vim plugin. However, getting Exuberant Ctags, which is TagList's workhorse, to work properly with PHP is another matter. Ctags doesn't understand PHP very well. It picks up on variables (which is sorta useless in PHP, anyway) but not functions whose definitions specify access ("public", "protected", etc.), interfaces or abstract classes. How useless!

Creating a useful Ctags file for PHP is not difficult, thanks to the info at these two resources. Just use these flags:

ctags -R --exclude=.svn --tag-relative=yes --PHP-kinds=+cf-v --regex-PHP='/abstract\s+class\s+([^ ]+)/\1/c/' --regex-PHP='/interface\s+([^ ]+)/\1/c/' --regex-PHP='/(public\s+|static\s+|abstract\s+|protected\s+|private\s+)function\s+\&?\s*([^ (]+)/\2/f/' lib/

Notice that I exclude variables via the --PHP-kinds option. This isn't C, tyvm.

What I didn't understand, at first, is that TagList calls Ctags every single time it's opened so that it generates an up-to-date temporary tags file. This makes perfect sense, but when Ctags is called by TagList, it doesn't have all of our required command-line options. Enter the Ctags config file. Put the following in your ~/.ctags file:

--regex-PHP=/abstract\s+class\s+([^ ]+)/\1/c/
--regex-PHP=/interface\s+([^ ]+)/\1/c/
--regex-PHP=/(public\s+|static\s+|abstract\s+|protected\s+|private\s+)function\s+\&?\s*([^ (]+)/\2/f/

And, amazingly, TagList becomes useful for PHP development. The last step is to tweak TagList to work in a way that's most convenient for you. Personally, I like these options:

" set the names of flags
let tlist_php_settings = 'php;c:class;f:function;d:constant'
" close all folds except for current file
let Tlist_File_Fold_Auto_Close = 1
" make tlist pane active when opened
let Tlist_GainFocus_On_ToggleOpen = 1
" width of window
let Tlist_WinWidth = 40
" close tlist when a selection is made
let Tlist_Close_On_Select = 1

TagList has a ton of options, so check them out. You may also be interested in my most up-to-date .ctags and .vimrc.


Heikki Naski said...

Thank you. I've put those options in directly in the taglist.vim plugin file. Which is quite annoying once you have several computers.

And the options you recommend are excellent.

Aaron said...

Hi! Great article. I notice in your latest .ctags file that you no longer use the kind '-v' and you've added the kind 'p'. Using your .ctags, I get a warning:

ctags: Warning: Unsupported parameter 'p' for --PHP-kinds option

Moving the --PHP-kinds statement after the --regex-PHP removes the warning for me, but I wondered if you are experiencing the same issue, or if you are using a different version of Exuberant Ctags. ( I'm using 5.8)

I got to your article from this SO Question:

Lucas Oman said...

Hey Aaron, thanks for the info! You're right, I was getting the same error, and I've implemented your fix in my file on GitHub.

Aaron said...

Good to know I'm not crazy and there is no secret ctags out there with different support. =D

So, you seemed pretty viament in your original post about not looking for variables in php. I was curious if you found them more useful than you originally thought, or just not as distracting as they could be.

I notice that I'm getting quite a few duplicate matches in my tags files, I suspect that I'm getting a match for the built in regular expressions and the supplied regular expressions on the same file. I was wondering if you have this issue also, or if this is just not an issue.

Lucas Oman said...

Hey Aaron, I'm haven't noticed any duplication in mine.

I wonder if it's possible that you have a newer version of ctags than I do, so the private/public/protected regexes are no longer necessary.

Regarding variables, I think I've sorted them down to the bottom, so they're not in my way, but the list of vars is still searchable in the TagList window if I happen to be looking for one in particular.

Aaron said...

Have you tried gnu global as an alternative to etags? Looks pretty promising..

Anonymous said...

Hey Aaron, I had a same problem with seeing all definitions twice in TagList. My ctags says that the version is:
$ ctags --version
Exuberant Ctags 5.9~svn20110310, Copyright (C) 1996-2009 Darren Hiebert

Here's my current ~/.ctags:
$ cat ~/.ctags
--regex-PHP=/interface\s+([^ ]+)/\1/c/
--regex-PHP=/(abstract\s+|final\s+).*function\s+\&?\s*([^ (]+)/\2/f/

Now all works like a charm=)

andi said...

Hi, i also added


Then it ignores all files other than .php so you won't have any .js tags in your tags file.

matason said...

Thanks so much, really makes ctags useful in Vim!

ANU said...

Really nice information you had posted. Its very informative and definitely it will be useful for many people
iOS Training in Chennai
Android Training in Chennai
php Training in Chennai