Timur Fayzrakhmanov
Timur Fayzrakhmanov

Reputation: 19617

How to configure ctags to work with CSS, SCSS, HTML?

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:

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:

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.

Upvotes: 6

Views: 3961

Answers (3)

Timur Fayzrakhmanov
Timur Fayzrakhmanov

Reputation: 19617

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/

Upvotes: 0

romainl
romainl

Reputation: 196781

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/

Upvotes: 5

Ingo Karkat
Ingo Karkat

Reputation: 172698

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.

Upvotes: 1

Related Questions