Giter Club home page Giter Club logo

elisp-def's Introduction

elisp-def MELPA Build Status Coverage Status

Go to the definition of the symbol at point. Supports global definitions, local definitions, and even macro-heavy code!

screenshot

elisp-def statically analyses your code, and falls back to heuristics where that's not possible. It should work 99% of the time, so please file bugs if it can't find definitions for your code.

Installation

Install from MELPA, then add the following to your Emacs configuration:

(dolist (hook '(emacs-lisp-mode-hook ielm-mode-hook))
  (add-hook hook #'elisp-def-mode))

Global Definitions

elisp-def will find the definition of global functions and global variables at point.

(defun demo/foo ()
  1)

(defun demo/bar ()
  ;; M-x eval-buffer, then elisp-def on this:
  (demo/foo))

It will also use edebug information to find function definitions, so it finds definitions more often than xref.

Lisp-2 Awareness

elisp-def understands the difference between symbols and functions and jumps to the correct definition.

(require 'cc-mode)

;; `c-version' is both a variable and a function.

(defun demo/foo ()
  ;; `elisp-def` will find the function here.
  (c-version))

(defun demo/foo ()
  ;; `elisp-def` will find the variable here.
  (setq c-version t))

Macro Awareness

elisp-def understands macros, so it can accurately detect function references.

(require 'dash)

(defvar demo/foo nil)

(defun demo/foo (x)
  x)

(defun demo/bar ()
  (->> 123
       ;; `elisp-def' knows that this is a function, even though there are
       ;; no parens.
       demo/foo))

It can also understand macros that define functions or variables.

(define-derived-mode demo/foo-mode fundamental-mode "demo")

;; `elisp-def' will expand macros to discover where major mode hooks
;; are defined.
demo/foo-mode-hook

(cl-defstruct demo/point x y)

;; `elisp-def' can find this function even though the defstruct
;; call doesn't contain this symbol name.
(make-demo/point 1 2)

Find Libraries

elisp-def will find libraries, displaying the provide declarations if possible.

;; `elisp-def' will open python.el here.
(require 'python)

;; Unlike `xref-find-definition', `elisp-def' will not confuse this
;; library name with the macro named `use-package'.
(require 'use-package)

;; `elisp-def' will even find python.el here, because the macro
;; expands to a call to `require'.
(use-package python
  :config
  (setq python-indent-guess-indent-offset-verbose nil))

Local Bindings

elisp-def understands local bindings and parameters.

(defun demo/foo (bar)
  (let ((foo 1))
    ;; `elisp-def' on the FOO below will move point to the let
    ;; binding.
    (setq foo 2)
    ;; `elisp-def' on the BAR below will move point to the function
    ;; parameters line.
    (setq bar 3)))

(defun demo/bar ()
  (let* ((foo 1)
         (bar 2)
         (foo 3)
         ;; `elisp-def' on the second FOO on the following line will
         ;; move point to the relevant binding, which is the line
         ;; immediately above.
         (foo (+ foo 1))
         (foo 5))
    nil))

This even works with macros that introduce bindings.

(require 'dash)
(eval-when-compile
  (require 'cl-lib))

(defun demo/foo (items)
  (cl-destructuring-bind (first second) items
    ;; `elisp-def' knowns that FIRST is bound on line above.
    (message "first is %s" first))
  (-let [(first . rest) items]
    ;; `elisp-def' knowns that FIRST is bound on line above.
    (message "first is %s" first)))

Ergonomics

elisp-def allows you to put point on quoted symbols, docstring symbols or backquoted symbols.

(defun demo/foo (x)
  ;; `elisp-def' on X in the docstring will find the parameter.
  "Adds one to X and returns it."
  (1+ x))

(defun demo/bar ()
  ;; `elisp-def' can find demo/foo even when point is on the #.
  (funcall #'demo/foo 1)
  ;; `elisp-def' on demo/foo below will find the function.
  ;;
  ;; See `demo/foo' for more information.
  nil)

(defun demo/baz (foo)
  ;; `elisp-def' understands that @ is not part of foo here.
  `(blah ,@foo))

When it finds the symbol, elisp-def will also temporarily highlight it for visibility.

Caveats

elisp-def is limited in its ability to analyse quoted symbols.

;; `elisp-def' is able to find these quoted symbols because they're
;; only globally bound in one namespace.
(mapcar 'symbol-name '(foo bar baz))
(add-to-list 'auto-mode-alist '("\\.java\\'" . java-mode))

(require 'cc-mode)
(defun demo/calls-fn (sym)
  (funcall sym))

;; Since `c-version' is both a function and a variable, and we're not
;; using a sharp-quote #'c-version, we have to prompt the user.
(demo/calls-fn 'c-version)

(defun demo/foo (c-version)
  ;; Here we have no idea whether we're using `c-version' as a
  ;; function (e.g. funcall), as a variable (e.g. set) or as a
  ;; parameter (e.g. eval).
  (bar 'c-version nil))

elisp-def cannot find definitions in macros with let* semantics and duplicated variables.

(require 'dash)

(defun demo/foo ()
  (-let ((x 1)
         (x 2))
    ;; `elisp-def' on X below will move to the first X binding, rather
    ;; than the second.
    x))

elisp-def also cannot handle macros that rewrite forms such that the symbol disappears entirely.

(eval-when-compile (require 'cl-lib))

(cl-labels ((foo (x y) (+ x y)))
  ;; `cl-labels' completely rewrites this body to (--cl-foo-- 1 2), so
  ;; `elisp-def' can't find the definition of FOO.
  (foo 1 2))

Thanks/Inspirations

  • elisp-slime-nav-find-elisp-thing-at-point from elisp-slime-nav
  • xref-find-definitions in emacs-lisp-mode (part of Emacs core)
  • semantic-ia-fast-jump from semantic/ia.el (included in Emacs)

The fine folks on #emacs for answering my questions on elisp esoterica, particularly Wasamasa.

The compliment library for Clojure completion has a notion of context which is very similar to how elisp-def extracts and analyses forms.

Hacklang has a similar notion of a placeholder for analysing completions at a point in the code.

License

GPLv3+.

I am providing code in the repository to you under an open source license. Because this is my personal repository, the license you receive to my code is from me and not my employer.

elisp-def's People

Contributors

flatwhatson avatar nbfalcon avatar slamko avatar wilfred avatar wyuenho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

elisp-def's Issues

Find hooks

It would be nice to be able to find ace-window-display-mode-hook, which is defined in ace-window.el using define-minor-mode.

We can't cover all cases (at least I think it would be slow), but this is a common one so it would be nice to handle.

Compare to elisp-slime-nav and xref

What's the difference among elisp-def, elisp-slime-nav and xref, please?
It seems elisp-def is unable to handle the case of use-package.

e.g.

(use-package elisp-refs)

M-. is unable to jump to elisp-refs.el.

Lisp error: (void-function ert--proper-list-p)

This is tested on master

Debugger entered--Lisp error: (void-function ert--proper-list-p)
  ert--proper-list-p((progn (defvar use-package--warning101 #'(lambda (keyword err) (let ((msg ...)) (display-warning 'use-package msg :error)))) (condition-case err (progn (if (fboundp 'js2-mode) nil (autoload #'js2-mode "js2-mode" nil t)) (eval-after-load 'js2-mode #'(lambda nil (condition-case err ... ...))) (add-to-list 'interpreter-mode-alist '("node" . js2-mode))) ((debug error) (funcall use-package--warning101 :catch err)))))
  elisp-def--use-position((progn (defvar use-package--warning101 #'(lambda (keyword err) (let ((msg ...)) (display-warning 'use-package msg :error)))) (condition-case err (progn (if (fboundp 'js2-mode) nil (autoload #'js2-mode "js2-mode" nil t)) (eval-after-load 'js2-mode #'(lambda nil (condition-case err ... ...))) (add-to-list 'interpreter-mode-alist '("node" . js2-mode))) ((debug error) (funcall use-package--warning101 :catch err)))) elisp-def--fresh-placeholder-8)
  elisp-def--namespace-at-point()
  elisp-def()
  funcall-interactively(elisp-def)
  #<subr call-interactively>(elisp-def nil nil)
  apply(#<subr call-interactively> elisp-def (nil nil))
  call-interactively@ido-cr+-record-current-command(#<subr call-interactively> elisp-def nil nil)
  apply(call-interactively@ido-cr+-record-current-command #<subr call-interactively> (elisp-def nil nil))
  call-interactively(elisp-def nil nil)
  command-execute(elisp-def)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.