How to configure ctags to work with CSS, SCSS, HTML?
Asked Answered
S

3

6

I've already read a lot of blog posts and answers on stackoverflow, but it seems I do something wrong, because I still have the E388: Couldn't find definition error. What I did:

  • Download ctags from here http://ctags.sourceforge.net/
  • Install it by: ./configure && make install
  • Set tags+=tags;$HOME in my .vimrc file
  • Add some lines into ~/.ctags (see below)
  • Do ctags -R . in the project root and get some warnings (see below)
  • Check classes by :tag .<C-D> which gives me a big list of classes (that pleases)

The warnings:

ctags: Warning: regcomp ([A-Za-z0-9._$]+)[ t]*[:=][ t]*{: Unmatched \{
ctags: Warning: regcomp ([A-Za-z0-9._$()]+)[ t]*[:=][ t]*function[ t]*(: Unmatched ( or \(
ctags: Warning: regcomp ([A-Za-z0-9._$]+)[ t]*[:=][ t]*[: Invalid regular expression
ctags: Warning: cannot open source file "static/img/touch/packages" : No such file or directory

My ~/.ctags file looks as follows:

--exclude=*.min.js
--exclude=*.min.css
--exclude=*.map
--exclude=.backup
--exclude=.sass-cache
--exclude=vendors
--exclude=.git

--langdef=css
--langmap=css:.css
--langmap=css:+.sass
--langmap=css:+.styl
--langmap=css:+.less
--regex-css=/^[ \t]*\.([A-Za-z0-9_-]+)/.\1/c,class,classes/
--regex-css=/^[ \t]*#([A-Za-z0-9_-]+)/#\1/i,id,ids/
--regex-css=/^[ \t]*(([A-Za-z0-9_-]+[ \t\n,]+)+)\{/\1/t,tag,tags/
--regex-css=/^[ \t]*@media\s+([A-Za-z0-9_-]+)/\1/m,media,medias/

--langdef=scss
--langmap=scss:.scss
--regex-scss=/^[ \t]*@mixin ([A-Za-z0-9_-]+)/\1/m,mixin,mixins/
--regex-scss=/^[ \t]*\$([A-Za-z0-9_-]+)/\1/v,variable,variables/
--regex-scss=/^([A-Za-z0-9_-]*)*(\.[A-Za-z0-9_-]+) *[,{]/\2/c,class,classes/
--regex-scss=/^[ \t]+(\.[A-Za-z0-9_-]+) *[,{]/\1/c,class,classes/
--regex-scss=/^(.*)*\#([A-Za-z0-9_-]+) *[,{]/\2/i,id,ids/
--regex-scss=/^[ \t]*#([A-Za-z0-9_-]+)/\1/i,id,ids/
--regex-scss=/(^([A-Za-z0-9_-])*([A-Za-z0-9_-]+)) *[,|\{]/\1/t,tag,tags/
--regex-scss=/(^([^\/\/])*)[ \t]+([A-Za-z0-9_-]+)) *[,|\{]/\3/t,tag,tags/
--regex-scss=/(^(.*, *)([A-Za-z0-9_-]+)) *[,|\{]/\3/t,tag,tags/
--regex-scss=/(^[ \t]+([A-Za-z0-9_-]+)) *[,|\{]/\1/t,tag,tags/
--regex-scss=/^[ \t]*@media\s+([A-Za-z0-9_-]+)/\1/d,media,media/

--regex-html=/id="([A-Za-z0-9_-]+)"/\1/i,id,ids/
--regex-html=/class="([A-Za-z0-9_-]+)"/\1/c,class,classes/

--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/

Project structure:

enter image description here

Wherever (static/index.html, static/css/main.scss or static/css/components/set.scss) I try to "jump to definition" using ]^D I always get E388: Couldn't find definition. What happens?

UPDATE

<C-]> pressed at the beginning of _col-2 name:

  • in case of <div class="_col-2">.. gives E426: Tag not found: _col. It looks like vim doesn't detect classname correctly.
  • in case of .class { @extend ._col-2; } gives the same.

As suggest @romainl, after adding set iskeyword+=- in .vimrc to dash be a part of the keyword, pressing on <div class="_col-2">.. throws me at the beginning of the line.

Sheepskin answered 11/11, 2015 at 9:28 Comment(4)
On a side note: you should consider using the less exuberant but maintained universal ctags instead.Briar
I've already see it, but there is no good readme (like "hey, that's reimplementation!" and that all :)), so I skip it. What the benefits using universal ctags over "classic" one?Sheepskin
The "classic" ctags from 1970's is long dead. Exuberant ctags is not that "classic" and not so long dead, but it's still dead. Universal ctags is a fork of Exuberant ctags that is actively maintained. Among other things, it has fixed some long-standing problems in Exuberant ctags, and it added support for more languages. The only regression as far as I can tell is the occasional use of Engrish in the various docs. :)Briar
Good explanation)) By the way, is there any information listing the supported languages? I couldn't find it.Sheepskin
I
5

About E426: Tag not found: txal-center

These lines in your .ctags will index .foo-barwith the leading dot — in *.scss files:

--regex-scss=/^([A-Za-z0-9_-]*)*(\.[A-Za-z0-9_-]+) *[,{]/\2/c,class,classes/
--regex-scss=/^[ \t]+(\.[A-Za-z0-9_-]+) *[,{]/\1/c,class,classes/

When you press <C-]> over a class name in an HTML document, Vim will look for that exact class name, say foo-bar, but it won't find it because you only have .foo-bar in your tags file. That's because Vim does "whole-word" search by default.

The solution to this specific problem is to leave the dot out of the tag:

--regex-scss=/^([A-Za-z0-9_-]*)*\.([A-Za-z0-9_-]+) *[,{]/\2/c,class,classes/
--regex-scss=/^[ \t]+\.([A-Za-z0-9_-]+) *[,{]/\1/c,class,classes/
Icky answered 11/11, 2015 at 11:53 Comment(1)
Hm..I changed it as you suggest, delete old ctags file, generate it again ctags -R . and check it by :tag ^D. However the dots have remained. Here are a lot of classes starting with dot. What's wrong?Sheepskin
B
1

The ]<C-D> motion is for macro definitions, powered by Vim's internal file search and the 'define' option. It doesn't use the tags database, and is mostly for C / C++ macros. What you want is the equivalent to the :tag command (which apparently does work for you). This is <C-]> (or <C-LeftMouse>); you'll find it directly under :help :tag.

Barnet answered 11/11, 2015 at 10:6 Comment(5)
Unfortunately, but when I press <C-]> nothing happens, I just get the message at the bottom of screen: tag 1 of 3 or more.Sheepskin
It doesn't properly detect class name, eg when I press ^] on <div class="_col-3" ... (cursor on _) - I get the error E426: Tag not found: _colSheepskin
@TimurFayzrakhmanov, that's because - is not part of the ìskeyword` option. You can add it with :set iskeyword+=-. This will be useful in both HTML and CSS/LESS/SASS/SCSS files.Icky
Now, when I press on _col-3 it just throw me at the beginning of the line. Pressing on _row still gives the same tag 1 of 3 or more.Sheepskin
@romainl, I've added it already (at my previous comment too). It strange, but despite of running explicitly :tag .txal-center moves me to the right place, pressing ^] at the same class but in HTML gives error: E426: Tag not found: txal-center. It look like vim missing automatic addition of the dot before the class name..Sheepskin
S
0

It seems I find the solution, thanks to @romainl and @IngoKarkat for the tip with excluding dots from regexp. So here are the steps if you haven't tried Ctags with HTML, CSS, SCSS.

  • Download the latest version and extract
  • Go into the extracted folder and run:./configure && make && sudo make install. Now check if ctags installed correctly by running ctags --help
  • Create ~/.ctags file and place the code there (see below)
  • Add the line set tags+=tags;$HOME into your ~/.vimrc, then run :so ~/.vimrc to update the options. tags+=tags;$HOME means search tags file recursively from current folder up to your home directory. If your prefer another
  • Go into your project folder and run ctags -R .. It creates ctags file which is index(database) of the found definitions.
  • Now go to vim vim . and check if tags are available by :tag ^D (press CTRL-D)
  • Now you can list tags, go to definition, back to previous place by b], CTRL-], CTRL-T accordingly.

  • (optionally) You can run ctags -R -f .tags to generate hidden file instead of the default tags name. Don't forget to change the set tags+=tags;$HOME to set tags+=.tags;$HOME

  • (optionally) Add nmap <leader><leader> :!ctags -R -f .tags<CR> to .vimrc if you want to update the index faster. Track you parent directory when you do it by :pwd in order not to pollute each project folder with tags files.

~/.ctags content:

--exclude=*.min.js
--exclude=*.min.css
--exclude=*.map
--exclude=.backup
--exclude=.sass-cache
--exclude=vendors
--exclude=.git

--langdef=css
--langmap=css:.css
--langmap=css:+.styl
--langmap=css:+.less
--regex-css=/^[ \t]*\.([A-Za-z0-9_-]+)/\1/c,class,classes/
--regex-css=/^[ \t]*#([A-Za-z0-9_-]+)/\1/i,id,ids/
--regex-css=/^[ \t]*(([A-Za-z0-9_-]+[ \t\n,]+)+)\{/\1/t,tag,tags/
--regex-css=/^[ \t]*@media\s+([A-Za-z0-9_-]+)/\1/m,media,medias/

--langdef=scss
--langmap=scss:.sass
--langmap=scss:+.scss
--regex-scss=/^[ \t]*@mixin ([A-Za-z0-9_-]+)/\1/m,mixin,mixins/
--regex-scss=/^[ \t]*@function ([A-Za-z0-9_-]+)/\1/f,function,functions/
--regex-scss=/^[ \t]*\$([A-Za-z0-9_-]+)/\1/v,variable,variables/
--regex-scss=/^([A-Za-z0-9_-]*)*\.([A-Za-z0-9_-]+) *[,{]/\2/c,class,classes/
--regex-scss=/^[ \t]+\.([A-Za-z0-9_-]+) *[,{]/\1/c,class,classes/
--regex-scss=/^(.*)*\#([A-Za-z0-9_-]+) *[,{]/\2/i,id,ids/
--regex-scss=/^[ \t]*#([A-Za-z0-9_-]+)/\1/i,id,ids/
--regex-scss=/(^([A-Za-z0-9_-])*([A-Za-z0-9_-]+)) *[,|\{]/\1/t,tag,tags/
--regex-scss=/(^([^\/\/])*)[ \t]+([A-Za-z0-9_-]+)) *[,|\{]/\3/t,tag,tags/
--regex-scss=/(^(.*, *)([A-Za-z0-9_-]+)) *[,|\{]/\3/t,tag,tags/
--regex-scss=/(^[ \t]+([A-Za-z0-9_-]+)) *[,|\{]/\1/t,tag,tags/
--regex-scss=/^[ \t]*@media\s+([A-Za-z0-9_-]+)/\1/d,media,media/
Sheepskin answered 11/11, 2015 at 14:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.