├── .gitignore
├── README.md
└── elisp-slime-nav.el
/.gitignore:
--------------------------------------------------------------------------------
1 | *.elc
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](http://melpa.org/#/elisp-slime-nav)
2 | [](http://stable.melpa.org/#/elisp-slime-nav)
3 |
4 |
5 | # Slime-style navigation for Emacs Lisp
6 |
7 | Slime allows very convenient navigation to the symbol at point (using
8 | M-.), and the ability to pop back to previous marks (using M-,).
9 |
10 | This plugin provides similar navigation for Emacs Lisp, supporting
11 | navigation to the definitions of variables, functions, libraries and
12 | faces.
13 |
14 | Additionally, `elisp-slime-nav` provides a way to describe the symbol
15 | at point, whatever its type. As with `slime-describe-symbol`, this
16 | functionality is bound both to C-c C-d d and C-c C-d
17 | C-d by default.
18 |
19 | ## Installation
20 |
21 | ### Manual
22 |
23 | Ensure `elisp-slime-nav.el` is in a directory on your load-path, and
24 | add the following to your `~/.emacs` or `~/.emacs.d/init.el`:
25 |
26 | ```elisp
27 | (require 'elisp-slime-nav)
28 | (dolist (hook '(emacs-lisp-mode-hook ielm-mode-hook))
29 | (add-hook hook 'elisp-slime-nav-mode))
30 | ```
31 |
32 | ### MELPA
33 |
34 | If you're an Emacs 24 user or you have a recent version of
35 | `package.el` you can install `elisp-slime-nav` from the
36 | [MELPA](http://melpa.org) repository. The version of
37 | `elisp-slime-nav` there will always be up-to-date.
38 |
39 | Enable `elisp-slime-nav` in `emacs-lisp-mode` and `ielm` by adding
40 | code such as the following to your emacs startup file:
41 |
42 | ```elisp
43 | (dolist (hook '(emacs-lisp-mode-hook ielm-mode-hook))
44 | (add-hook hook 'turn-on-elisp-slime-nav-mode))
45 | ```
46 |
47 |
48 | ## About
49 |
50 | Author: Steve Purcell
51 |
52 | Homepage: https://github.com/purcell/elisp-slime-nav
53 |
54 | This little library was extracted from the author's
55 | [full Emacs configuration](https://github.com/purcell/emacs.d), which
56 | readers might find of interest.
57 |
58 |
59 |
60 | [💝 Support this project and my other Open Source work via Patreon](https://www.patreon.com/sanityinc)
61 |
62 | [💼 LinkedIn profile](https://uk.linkedin.com/in/stevepurcell)
63 |
64 | [✍ sanityinc.com](http://www.sanityinc.com/)
65 |
66 |
--------------------------------------------------------------------------------
/elisp-slime-nav.el:
--------------------------------------------------------------------------------
1 | ;;; elisp-slime-nav.el --- Make M-. and M-, work in elisp like they do in slime -*- lexical-binding: t -*-
2 |
3 | ;; Copyright (C) 2016-2020 Steve Purcell
4 |
5 | ;; Author: Steve Purcell
6 | ;; Keywords: languages navigation slime elisp emacs-lisp
7 | ;; URL: https://github.com/purcell/elisp-slime-nav
8 | ;; Package-Version: 0
9 | ;; Package-Requires: ((emacs "24.1") (cl-lib "0.2"))
10 |
11 | ;; This program is free software; you can redistribute it and/or modify
12 | ;; it under the terms of the GNU General Public License as published by
13 | ;; the Free Software Foundation, either version 3 of the License, or
14 | ;; (at your option) any later version.
15 |
16 | ;; This program is distributed in the hope that it will be useful,
17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | ;; GNU General Public License for more details.
20 |
21 | ;; You should have received a copy of the GNU General Public License
22 | ;; along with this program. If not, see .
23 |
24 | ;;; Commentary:
25 | ;;
26 | ;; This package provides Slime's convenient "M-." and "M-," navigation
27 | ;; in `emacs-lisp-mode', together with an elisp equivalent of
28 | ;; `slime-describe-symbol', bound by default to `C-c C-d d`.
29 | ;;
30 | ;; When the main functions are given a prefix argument, they will
31 | ;; prompt for the symbol upon which to operate.
32 | ;;
33 | ;; Usage:
34 | ;;
35 | ;; Enable the package in elisp and ielm modes as follows:
36 | ;;
37 | ;; (require 'elisp-slime-nav) ;; optional if installed via package.el
38 | ;; (dolist (hook '(emacs-lisp-mode-hook ielm-mode-hook))
39 | ;; (add-hook hook 'turn-on-elisp-slime-nav-mode))
40 | ;;
41 | ;; Known issues:
42 | ;;
43 | ;; When navigating into Emacs' C source, "M-," will not be bound to
44 | ;; the same command, but "M-*" will typically do the trick.
45 | ;;
46 | ;;; Code:
47 |
48 | (require 'etags)
49 | (require 'help-mode)
50 |
51 | (defvar elisp-slime-nav-mode-map
52 | (let ((map (make-sparse-keymap)))
53 | (define-key map (kbd "M-.") 'elisp-slime-nav-find-elisp-thing-at-point)
54 | (define-key map (kbd "M-,") 'pop-tag-mark)
55 | (define-key map (kbd "C-c C-d d") 'elisp-slime-nav-describe-elisp-thing-at-point)
56 | (define-key map (kbd "C-c C-d C-d") 'elisp-slime-nav-describe-elisp-thing-at-point)
57 | map))
58 |
59 | ;;;###autoload
60 | (define-minor-mode elisp-slime-nav-mode
61 | "Enable Slime-style navigation of elisp symbols using M-. and M-,"
62 | :lighter " SliNav" :keymap elisp-slime-nav-mode-map)
63 |
64 | ;;;###autoload
65 | (define-obsolete-function-alias 'turn-on-elisp-slime-nav-mode 'elisp-slime-nav-mode
66 | "2020-01-30")
67 |
68 | (defun elisp-slime-nav--all-navigable-symbol-names ()
69 | "Return a list of strings for the symbols to which navigation is possible."
70 | (let ((result '()))
71 | (mapatoms
72 | (lambda (x)
73 | (when (or (fboundp x) (boundp x) (symbol-plist x) (facep x))
74 | (push (symbol-name x) result))))
75 | result))
76 |
77 | (defun elisp-slime-nav--read-symbol-at-point ()
78 | "Return the symbol at point as a string.
79 | If `current-prefix-arg' is not nil, the user is prompted for the symbol."
80 | (let* ((sym-at-point (symbol-at-point))
81 | (at-point (and sym-at-point (symbol-name sym-at-point))))
82 | (if (or current-prefix-arg (null at-point))
83 | (completing-read "Symbol: "
84 | (elisp-slime-nav--all-navigable-symbol-names)
85 | nil t nil nil at-point)
86 | at-point)))
87 |
88 | ;;;###autoload
89 | (defun elisp-slime-nav-find-elisp-thing-at-point (sym-name)
90 | "Find the elisp thing at point, be it a function, variable, library or face.
91 |
92 | With a prefix arg, or if there is no thing at point, prompt for
93 | the symbol to jump to.
94 |
95 | Argument SYM-NAME is the thing to find."
96 | (interactive (list (elisp-slime-nav--read-symbol-at-point)))
97 | (when sym-name
98 | (let ((sym (intern sym-name)))
99 | (message "Searching for %s..." sym-name)
100 | (if (fboundp 'xref-push-marker-stack)
101 | (xref-push-marker-stack)
102 | (with-no-warnings
103 | (ring-insert find-tag-marker-ring (point-marker))))
104 | (cond
105 | ((fboundp sym)
106 | (find-function sym))
107 | ((boundp sym)
108 | (find-variable sym))
109 | ((or (featurep sym) (locate-library sym-name))
110 | (find-library sym-name))
111 | ((facep sym)
112 | (find-face-definition sym))
113 | (t
114 | (pop-tag-mark)
115 | (error "Don't know how to find '%s'" sym))))))
116 |
117 | ;;;###autoload
118 | (defun elisp-slime-nav-describe-elisp-thing-at-point (sym-name)
119 | "Display the full documentation of the elisp thing at point.
120 |
121 | The named subject may be a function, variable, library or face.
122 |
123 | With a prefix arg, or if there is not \"thing\" at point, prompt
124 | for the symbol to jump to.
125 |
126 | Argument SYM-NAME is the thing to find."
127 | (interactive (list (elisp-slime-nav--read-symbol-at-point)))
128 | (if (fboundp 'describe-symbol)
129 | (describe-symbol (intern sym-name))
130 | (with-no-warnings
131 | (help-xref-interned (intern sym-name)))))
132 |
133 |
134 | (provide 'elisp-slime-nav)
135 | ;; Local Variables:
136 | ;; indent-tabs-mode: nil
137 | ;; End:
138 | ;;; elisp-slime-nav.el ends here
139 |
--------------------------------------------------------------------------------