1

I am using web-mode for javascript files that contain jsx:

(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.js[x]?$" . web-mode))

Is there a way to enable go to symbol with web-mode?

2

for javascript I highly recommend js2-mode. Take a look here https://elpa.gnu.org/packages/js2-mode.html it has function that you are looking for: js2-jump-to-definition which is by default bound to M-.

2

I submit critical patches to both web-mode and js2-mode. Currently as a front end architect, I'm developing a big ReactJS project from the scratch.

The simple answer is: helm-etags+ctags or counsel-etags(based on ivy)+ctags

web-mode is good for handling ReactJS files (JSX). Since ctags uses only regular expression, it can work seamlessly with web-mode.

Another solution is rjsx-mode (https://github.com/felipeochoa/rjsx-mode), it inherits from js2-mode and can handle mixed html/javascript perfectly. But certain js2 commands like js2-jump-to-definition won't work when you try to jump from html tags inside render() method, you got js2-name-node-name accessing a non-js2-name-node error.

One advantage of use rjsx-mode is you could jump to the symbol using js2-mode's imenu commands, it works out of box. Here is the screenshot of my imenu in a React component, enter image description here

Whatever major mode you use, you still need ctags and helm-etags (most people use helm, but some guy prefer ivy). For example, now postcss,es6 are popular in ReactJS developers, if a css class name is embedded inside a es6 template string, ctags is the only solution.

Here is my ~/.ctags:

--exclude=*.hg*
--exclude=*.cvs*
--exclude=*.svn*
--exclude=*.git*
--exclude=*compiled*
--exclude=*public_html*
--exclude=*.idea*
--exclude=*bower_components*
--exclude=*images*
--exclude=*.DS_Store*
--exclude=*log*
--exclude=*target*
--exclude=*deployment*
--exclude=*.war
--exclude=*.jar
--exclude=*.class
--exclude=*flymake*
--exclude=*.min.js
--exclude=*.min.css
--exclude=*.pack.js
--exclude=*.log
--exclude=*vender*
--exclude=*.sql
--exclude=*.sass
--exclude=*.ftl
--exclude=tags
--exclude=TAGS
--exclude=GTAGS
--exclude=GPATH
--exclude=*node_modules*
--exclude=GRTAGS
--exclude=*doc*
--exclude=*tmp*
--exclude=.#*
--tag-relative=yes
--recurse=yes
--c-kinds=+defgpstux

--langmap=html:.htm.html.erb.cmp.page.component
--regex-html=/[ \t]+ng-(controller|click|change|show|if|blur|focus|disabled|repeat)[ \t]*=[ \t]*['"][^a-zA-Z0-9$]*([a-zA-Z0-9$]{4,})/\2/o,object/

--langdef=js
--langmap=js:.js.ts
--regex-js=/\.controller[ \t]*\([ \t]*['"]([A-Za-z0-9_$.]+)['"][ \t]*,/\1/,controller/
--regex-js=/\.controllerAs[ \t]*:[ \t]*['"]([A-Za-z0-9_$.]+)['"][ \t]*,/\1/,controller/
--regex-js=/\.filter[ \t]*\([ \t]*['"]([A-Za-z0-9_$.]+)['"][ \t]*,/\1/,filter/
--regex-js=/\.state[ \t]*\([ \t]*['"]([A-Za-z0-9_$.]+)['"][ \t]*,/\1/,state/
--regex-js=/^[ \t]*state:[ \t]*['"]([A-Za-z0-9_$.]+)['"][ \t]*,/\1/,state/
--regex-js=/\.factory[ \t]*\([ \t]*['"]([A-Za-z0-9_$.]+)['"][ \t]*,/\1/,factory/
--regex-js=/\.constant[ \t]*\([ \t]*['"]([A-Za-z0-9_$.]+)['"][ \t]*,/\1/,constant/
--regex-js=/\.service[ \t]*\([ \t]*['"]([A-Za-z0-9_$.]+)['"][ \t]*,/\1/,service/
--regex-js=/\.directive[ \t]*\([ \t]*['"]([A-Za-z0-9_$.]+)['"][ \t]*,/\1/,directive/
--regex-js=/.*[.][\s]*module\(['"]([a-zA-Z0-9_.-]+)['"], *\[([ ,"'a-zA-Z0-9_.-]+)* *\]\)/\1/m,module/
--regex-js=/[.](when\(['"][a-zA-Z0-9_\/]+['"])/\1/r,ngRoute/
--regex-js=/function[ \t]+([A-Za-z0-9_$]+)[ \t]*\([^)]*\)/\1/,function/
--regex-js=/(,|^|\.)[ \t]*([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*[:=][ \t]*function[ \t]*\(/\2/,function/
--regex-js=/^[ \t]*([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*\([^a-zA-Z0-9, ]*\) *\{ *$/\1/,function/
--regex-js=/^[ \t]*([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*=[ \t]*\(?[a-zA-Z0-9, ]*\)?[ \t]*=>[ \t]*\{/\1/,function/
--regex-js=/^[ \t]*export[ \t]+const[ \t]+([A-Za-z_$][A-Za-z0-9_$]+)[ \t]*=/\1/,function/

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

--langdef=css
--langmap=css:.css
--regex-css=/^[ \t]*(\$[A-Za-z0-9_-]+)[ \t]*:[ \t]*.*;[ \t]*$/\1/c,class/
--regex-css=/^,?[ \t]*#?[ \t]*\.([A-Za-z_][A-Za-z0-9_:"' \t\-]+)[ \t]*[\{,]/\1/c,class/
--regex-css=/^[ \t]*\.([A-Za-z_][A-Za-z0-9_:"' \t\-]+)[ \t]*,/\1/c,class/
--regex-css=/^,?[ \t]*([A-Za-z_][A-Za-z0-9_:()="' \t\-]+)[ \t]*[\{,]/\1/t,tags/

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

This answer just covers the basics. Check my blog http://blog.binchen.org/categories/emacs.html and my js setup https://github.com/redguardtoo/emacs.d/blob/master/lisp/init-javascript.el for advanced skills.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.