"Jump to Definition" in Emacs
Navigating from a variable's usage to its definition (or declaration) and back is an important part of any IDE. I haven't found a standard name for this behavior: Visual Studio calls it "Go to Definition"; Xcode calls it "Jump to Definition" (depending on the implementation it can also be called tagging/indexing source code). Emacs has two ways, that I know of, to achieve this feature: etags.el (now deprecated) and its successor xref.el.
etags.el
The standard way to achieve code navigation used to be to generate an index of all source code for your project. The index would basically map a name to a line number of a particular file. ctags was the original program that did this, and was written for Unix in the 90's. I think the origin of its name is that it generates tags for the C language (it also supported Pascal, Fortran, LISP, yacc and lex, but defaulted to C)1. There are two modern implementations of ctags: exuberant-ctags (no longer maintained) and universal-ctags (an active fork of exuberant-ctags).
For some reason, Emacs developed its own version of ctags called etags that generates a tag table in a different format. I'm not sure why emacs didn't just use ctags and its table format. The modern forks of ctags can generate a tags table for Emacs with the -e parameter.
etags.el has been deprecated since Emacs 25.1 in favor of xref. It provides M-x find-tag for jumping to definitions.
I decided to try both ctags and etags with Clojure files. I found a stackoverflow question that suggested using this code to generate tags:
find . \! -name '.*' -name '*.clj' | xargs etags --regex='/[ \t\(]*def[a-z]* \([a-z-!]+\)/\1/' --regex='/[ \t\(]*ns \([a-z.]+\)/\1/'
Running this failed with etags: Invalid range end while compiling pattern. I had to transpose the ! and the - to get it to work:
find . \! -name '.*' -name '*.cljs' | xargs etags --regex='/[ \t\(]*def[a-z]* \([a-z!-]+\)/\1/' --regex='/[ \t\(]*ns \([a-z.]+\)/\1/'
It also provided a way with ctags:
(defvar path-to-ctags "/usr/local/bin/ctags") ;; Recursively generate tags for all *.clj files, ;; creating tags for def* and namespaces (defun create-clj-tags (dir-name) "Create tags file." (interactive "DDirectory: ") (shell-command (format "%s --langdef=Clojure --langmap=Clojure:.clj --regex-Clojure='/[ \t\(]*def[a-z]* \([a-z!-]+\)/\1/' --regex-Clojure='/[ \t\(]*ns \([a-z.]+\)/\1/' -f %s/TAGS -e -R %s" path-to-ctags dir-name (directory-file-name dir-name))))
Now M-x find-tag can use these tables to jump to definitions. Keep in mind that using tags tables for source navigating may require some tuning of your workflow. For example, navigating from a project to its libraries can be complicated2 for some languages (and easy for others3) and you have to plan for the tags table to get invalidated as you edit your code.
xref.el
xref.el uses a backend provided by a major mode to find identifiers (and more). A backend can be implemented using a tags table, language server, or anything else:
Plain old tags table
I tried using xref-find-definitions with the two above tags tables, but only the etags table worked. Not sure why.
Language Servers
CIDER
For Clojure, you can use CIDER which implements an xref backend:
https://github.com/clojure-emacs/cider/commit/15b6d205b6311453349144afc20d7ac4a820b0ab
Once a CIDER connection has been established and a source buffer compiled, xref-find-definitions can accurately jump to symbol definitions regardless of where they are (just as long as they have successfully compiled).