├── .gitignore ├── README.md └── elisp-slime-nav.el /.gitignore: -------------------------------------------------------------------------------- 1 | *.elc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Melpa Status](http://melpa.org/packages/elisp-slime-nav-badge.svg)](http://melpa.org/#/elisp-slime-nav) 2 | [![Melpa Stable Status](http://stable.melpa.org/packages/elisp-slime-nav-badge.svg)](http://stable.melpa.org/#/elisp-slime-nav) 3 | Support me 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 | --------------------------------------------------------------------------------