]> code.delx.au - gnu-emacs/blob - lisp/progmodes/elisp-mode.el
Merge branch 'map'
[gnu-emacs] / lisp / progmodes / elisp-mode.el
1 ;;; elisp-mode.el --- Emacs Lisp mode -*- lexical-binding:t -*-
2
3 ;; Copyright (C) 1985-1986, 1999-2015 Free Software Foundation, Inc.
4
5 ;; Maintainer: emacs-devel@gnu.org
6 ;; Keywords: lisp, languages
7 ;; Package: emacs
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs 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 ;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23
24 ;;; Commentary:
25
26 ;; The major mode for editing Emacs Lisp code.
27 ;; This mode is documented in the Emacs manual.
28
29 ;;; Code:
30
31 (require 'lisp-mode)
32
33 (define-abbrev-table 'emacs-lisp-mode-abbrev-table ()
34 "Abbrev table for Emacs Lisp mode.
35 It has `lisp-mode-abbrev-table' as its parent."
36 :parents (list lisp-mode-abbrev-table))
37
38 (defvar emacs-lisp-mode-syntax-table
39 (let ((table (make-syntax-table lisp--mode-syntax-table)))
40 (modify-syntax-entry ?\[ "(] " table)
41 (modify-syntax-entry ?\] ")[ " table)
42 table)
43 "Syntax table used in `emacs-lisp-mode'.")
44
45 (defvar emacs-lisp-mode-map
46 (let ((map (make-sparse-keymap "Emacs-Lisp"))
47 (menu-map (make-sparse-keymap "Emacs-Lisp"))
48 (lint-map (make-sparse-keymap))
49 (prof-map (make-sparse-keymap))
50 (tracing-map (make-sparse-keymap)))
51 (set-keymap-parent map lisp-mode-shared-map)
52 (define-key map "\e\t" 'completion-at-point)
53 (define-key map "\e\C-x" 'eval-defun)
54 (define-key map "\e\C-q" 'indent-pp-sexp)
55 (bindings--define-key map [menu-bar emacs-lisp]
56 (cons "Emacs-Lisp" menu-map))
57 (bindings--define-key menu-map [eldoc]
58 '(menu-item "Auto-Display Documentation Strings" eldoc-mode
59 :button (:toggle . (bound-and-true-p eldoc-mode))
60 :help "Display the documentation string for the item under cursor"))
61 (bindings--define-key menu-map [checkdoc]
62 '(menu-item "Check Documentation Strings" checkdoc
63 :help "Check documentation strings for style requirements"))
64 (bindings--define-key menu-map [re-builder]
65 '(menu-item "Construct Regexp" re-builder
66 :help "Construct a regexp interactively"))
67 (bindings--define-key menu-map [tracing] (cons "Tracing" tracing-map))
68 (bindings--define-key tracing-map [tr-a]
69 '(menu-item "Untrace All" untrace-all
70 :help "Untrace all currently traced functions"))
71 (bindings--define-key tracing-map [tr-uf]
72 '(menu-item "Untrace Function..." untrace-function
73 :help "Untrace function, and possibly activate all remaining advice"))
74 (bindings--define-key tracing-map [tr-sep] menu-bar-separator)
75 (bindings--define-key tracing-map [tr-q]
76 '(menu-item "Trace Function Quietly..." trace-function-background
77 :help "Trace the function with trace output going quietly to a buffer"))
78 (bindings--define-key tracing-map [tr-f]
79 '(menu-item "Trace Function..." trace-function
80 :help "Trace the function given as an argument"))
81 (bindings--define-key menu-map [profiling] (cons "Profiling" prof-map))
82 (bindings--define-key prof-map [prof-restall]
83 '(menu-item "Remove Instrumentation for All Functions" elp-restore-all
84 :help "Restore the original definitions of all functions being profiled"))
85 (bindings--define-key prof-map [prof-restfunc]
86 '(menu-item "Remove Instrumentation for Function..." elp-restore-function
87 :help "Restore an instrumented function to its original definition"))
88
89 (bindings--define-key prof-map [sep-rem] menu-bar-separator)
90 (bindings--define-key prof-map [prof-resall]
91 '(menu-item "Reset Counters for All Functions" elp-reset-all
92 :help "Reset the profiling information for all functions being profiled"))
93 (bindings--define-key prof-map [prof-resfunc]
94 '(menu-item "Reset Counters for Function..." elp-reset-function
95 :help "Reset the profiling information for a function"))
96 (bindings--define-key prof-map [prof-res]
97 '(menu-item "Show Profiling Results" elp-results
98 :help "Display current profiling results"))
99 (bindings--define-key prof-map [prof-pack]
100 '(menu-item "Instrument Package..." elp-instrument-package
101 :help "Instrument for profiling all function that start with a prefix"))
102 (bindings--define-key prof-map [prof-func]
103 '(menu-item "Instrument Function..." elp-instrument-function
104 :help "Instrument a function for profiling"))
105 ;; Maybe this should be in a separate submenu from the ELP stuff?
106 (bindings--define-key prof-map [sep-natprof] menu-bar-separator)
107 (bindings--define-key prof-map [prof-natprof-stop]
108 '(menu-item "Stop Native Profiler" profiler-stop
109 :help "Stop recording profiling information"
110 :enable (and (featurep 'profiler)
111 (profiler-running-p))))
112 (bindings--define-key prof-map [prof-natprof-report]
113 '(menu-item "Show Profiler Report" profiler-report
114 :help "Show the current profiler report"
115 :enable (and (featurep 'profiler)
116 (profiler-running-p))))
117 (bindings--define-key prof-map [prof-natprof-start]
118 '(menu-item "Start Native Profiler..." profiler-start
119 :help "Start recording profiling information"))
120
121 (bindings--define-key menu-map [lint] (cons "Linting" lint-map))
122 (bindings--define-key lint-map [lint-di]
123 '(menu-item "Lint Directory..." elint-directory
124 :help "Lint a directory"))
125 (bindings--define-key lint-map [lint-f]
126 '(menu-item "Lint File..." elint-file
127 :help "Lint a file"))
128 (bindings--define-key lint-map [lint-b]
129 '(menu-item "Lint Buffer" elint-current-buffer
130 :help "Lint the current buffer"))
131 (bindings--define-key lint-map [lint-d]
132 '(menu-item "Lint Defun" elint-defun
133 :help "Lint the function at point"))
134 (bindings--define-key menu-map [edebug-defun]
135 '(menu-item "Instrument Function for Debugging" edebug-defun
136 :help "Evaluate the top level form point is in, stepping through with Edebug"
137 :keys "C-u C-M-x"))
138 (bindings--define-key menu-map [separator-byte] menu-bar-separator)
139 (bindings--define-key menu-map [disas]
140 '(menu-item "Disassemble Byte Compiled Object..." disassemble
141 :help "Print disassembled code for OBJECT in a buffer"))
142 (bindings--define-key menu-map [byte-recompile]
143 '(menu-item "Byte-recompile Directory..." byte-recompile-directory
144 :help "Recompile every `.el' file in DIRECTORY that needs recompilation"))
145 (bindings--define-key menu-map [emacs-byte-compile-and-load]
146 '(menu-item "Byte-compile and Load" emacs-lisp-byte-compile-and-load
147 :help "Byte-compile the current file (if it has changed), then load compiled code"))
148 (bindings--define-key menu-map [byte-compile]
149 '(menu-item "Byte-compile This File" emacs-lisp-byte-compile
150 :help "Byte compile the file containing the current buffer"))
151 (bindings--define-key menu-map [separator-eval] menu-bar-separator)
152 (bindings--define-key menu-map [ielm]
153 '(menu-item "Interactive Expression Evaluation" ielm
154 :help "Interactively evaluate Emacs Lisp expressions"))
155 (bindings--define-key menu-map [eval-buffer]
156 '(menu-item "Evaluate Buffer" eval-buffer
157 :help "Execute the current buffer as Lisp code"))
158 (bindings--define-key menu-map [eval-region]
159 '(menu-item "Evaluate Region" eval-region
160 :help "Execute the region as Lisp code"
161 :enable mark-active))
162 (bindings--define-key menu-map [eval-sexp]
163 '(menu-item "Evaluate Last S-expression" eval-last-sexp
164 :help "Evaluate sexp before point; print value in echo area"))
165 (bindings--define-key menu-map [separator-format] menu-bar-separator)
166 (bindings--define-key menu-map [comment-region]
167 '(menu-item "Comment Out Region" comment-region
168 :help "Comment or uncomment each line in the region"
169 :enable mark-active))
170 (bindings--define-key menu-map [indent-region]
171 '(menu-item "Indent Region" indent-region
172 :help "Indent each nonblank line in the region"
173 :enable mark-active))
174 (bindings--define-key menu-map [indent-line]
175 '(menu-item "Indent Line" lisp-indent-line))
176 map)
177 "Keymap for Emacs Lisp mode.
178 All commands in `lisp-mode-shared-map' are inherited by this map.")
179
180 (defun emacs-lisp-byte-compile ()
181 "Byte compile the file containing the current buffer."
182 (interactive)
183 (if buffer-file-name
184 (byte-compile-file buffer-file-name)
185 (error "The buffer must be saved in a file first")))
186
187 (defun emacs-lisp-byte-compile-and-load ()
188 "Byte-compile the current file (if it has changed), then load compiled code."
189 (interactive)
190 (or buffer-file-name
191 (error "The buffer must be saved in a file first"))
192 (require 'bytecomp)
193 ;; Recompile if file or buffer has changed since last compilation.
194 (if (and (buffer-modified-p)
195 (y-or-n-p (format "Save buffer %s first? " (buffer-name))))
196 (save-buffer))
197 (byte-recompile-file buffer-file-name nil 0 t))
198
199 (defun emacs-lisp-macroexpand ()
200 "Macroexpand the form after point.
201 Comments in the form will be lost."
202 (interactive)
203 (let* ((start (point))
204 (exp (read (current-buffer)))
205 ;; Compute it before, since it may signal errors.
206 (new (macroexpand-1 exp)))
207 (if (equal exp new)
208 (message "Not a macro call, nothing to expand")
209 (delete-region start (point))
210 (pp new (current-buffer))
211 (if (bolp) (delete-char -1))
212 (indent-region start (point)))))
213
214 (defcustom emacs-lisp-mode-hook nil
215 "Hook run when entering Emacs Lisp mode."
216 :options '(eldoc-mode imenu-add-menubar-index checkdoc-minor-mode)
217 :type 'hook
218 :group 'lisp)
219
220 ;;;###autoload
221 (define-derived-mode emacs-lisp-mode prog-mode "Emacs-Lisp"
222 "Major mode for editing Lisp code to run in Emacs.
223 Commands:
224 Delete converts tabs to spaces as it moves back.
225 Blank lines separate paragraphs. Semicolons start comments.
226
227 \\{emacs-lisp-mode-map}"
228 :group 'lisp
229 (defvar xref-find-function)
230 (defvar xref-identifier-completion-table-function)
231 (lisp-mode-variables nil nil 'elisp)
232 (add-hook 'after-load-functions #'elisp--font-lock-flush-elisp-buffers)
233 (setq-local electric-pair-text-pairs
234 (append '((?\` . ?\') (?‘ . ?’)) electric-pair-text-pairs))
235 (setq-local electric-quote-string t)
236 (setq imenu-case-fold-search nil)
237 (add-function :before-until (local 'eldoc-documentation-function)
238 #'elisp-eldoc-documentation-function)
239 (setq-local xref-find-function #'elisp-xref-find)
240 (setq-local xref-identifier-completion-table-function
241 #'elisp--xref-identifier-completion-table)
242 (add-hook 'completion-at-point-functions
243 #'elisp-completion-at-point nil 'local))
244
245 ;; Font-locking support.
246
247 (defun elisp--font-lock-flush-elisp-buffers (&optional file)
248 ;; FIXME: Aren't we only ever called from after-load-functions?
249 ;; Don't flush during load unless called from after-load-functions.
250 ;; In that case, FILE is non-nil. It's somehow strange that
251 ;; load-in-progress is t when an after-load-function is called since
252 ;; that should run *after* the load...
253 (when (or (not load-in-progress) file)
254 ;; FIXME: If the loaded file did not define any macros, there shouldn't
255 ;; be any need to font-lock-flush all the Elisp buffers.
256 (dolist (buf (buffer-list))
257 (with-current-buffer buf
258 (when (derived-mode-p 'emacs-lisp-mode)
259 ;; So as to take into account new macros that may have been defined
260 ;; by the just-loaded file.
261 (font-lock-flush))))))
262
263 ;;; Completion at point for Elisp
264
265 (defun elisp--local-variables-1 (vars sexp)
266 "Return the vars locally bound around the witness, or nil if not found."
267 (let (res)
268 (while
269 (unless
270 (setq res
271 (pcase sexp
272 (`(,(or `let `let*) ,bindings)
273 (let ((vars vars))
274 (when (eq 'let* (car sexp))
275 (dolist (binding (cdr (reverse bindings)))
276 (push (or (car-safe binding) binding) vars)))
277 (elisp--local-variables-1
278 vars (car (cdr-safe (car (last bindings)))))))
279 (`(,(or `let `let*) ,bindings . ,body)
280 (let ((vars vars))
281 (dolist (binding bindings)
282 (push (or (car-safe binding) binding) vars))
283 (elisp--local-variables-1 vars (car (last body)))))
284 (`(lambda ,_args)
285 ;; FIXME: Look for the witness inside `args'.
286 (setq sexp nil))
287 (`(lambda ,args . ,body)
288 (elisp--local-variables-1
289 (append (remq '&optional (remq '&rest args)) vars)
290 (car (last body))))
291 (`(condition-case ,_ ,e) (elisp--local-variables-1 vars e))
292 (`(condition-case ,v ,_ . ,catches)
293 (elisp--local-variables-1
294 (cons v vars) (cdr (car (last catches)))))
295 (`(quote . ,_)
296 ;; FIXME: Look for the witness inside sexp.
297 (setq sexp nil))
298 ;; FIXME: Handle `cond'.
299 (`(,_ . ,_)
300 (elisp--local-variables-1 vars (car (last sexp))))
301 (`elisp--witness--lisp (or vars '(nil)))
302 (_ nil)))
303 ;; We didn't find the witness in the last element so we try to
304 ;; backtrack to the last-but-one.
305 (setq sexp (ignore-errors (butlast sexp)))))
306 res))
307
308 (defun elisp--local-variables ()
309 "Return a list of locally let-bound variables at point."
310 (save-excursion
311 (skip-syntax-backward "w_")
312 (let* ((ppss (syntax-ppss))
313 (txt (buffer-substring-no-properties (or (car (nth 9 ppss)) (point))
314 (or (nth 8 ppss) (point))))
315 (closer ()))
316 (dolist (p (nth 9 ppss))
317 (push (cdr (syntax-after p)) closer))
318 (setq closer (apply #'string closer))
319 (let* ((sexp (condition-case nil
320 (car (read-from-string
321 (concat txt "elisp--witness--lisp" closer)))
322 ((invalid-read-syntax end-of-file) nil)))
323 (macroexpand-advice (lambda (expander form &rest args)
324 (condition-case nil
325 (apply expander form args)
326 (error form))))
327 (sexp
328 (unwind-protect
329 (progn
330 (advice-add 'macroexpand :around macroexpand-advice)
331 (macroexpand-all sexp))
332 (advice-remove 'macroexpand macroexpand-advice)))
333 (vars (elisp--local-variables-1 nil sexp)))
334 (delq nil
335 (mapcar (lambda (var)
336 (and (symbolp var)
337 (not (string-match (symbol-name var) "\\`[&_]"))
338 ;; Eliminate uninterned vars.
339 (intern-soft var)
340 var))
341 vars))))))
342
343 (defvar elisp--local-variables-completion-table
344 ;; Use `defvar' rather than `defconst' since defconst would purecopy this
345 ;; value, which would doubly fail: it would fail because purecopy can't
346 ;; handle the recursive bytecode object, and it would fail because it would
347 ;; move `lastpos' and `lastvars' to pure space where they'd be immutable!
348 (let ((lastpos nil) (lastvars nil))
349 (letrec ((hookfun (lambda ()
350 (setq lastpos nil)
351 (remove-hook 'post-command-hook hookfun))))
352 (completion-table-dynamic
353 (lambda (_string)
354 (save-excursion
355 (skip-syntax-backward "_w")
356 (let ((newpos (cons (point) (current-buffer))))
357 (unless (equal lastpos newpos)
358 (add-hook 'post-command-hook hookfun)
359 (setq lastpos newpos)
360 (setq lastvars
361 (mapcar #'symbol-name (elisp--local-variables))))))
362 lastvars)))))
363
364 (defun elisp--expect-function-p (pos)
365 "Return non-nil if the symbol at point is expected to be a function."
366 (or
367 (and (eq (char-before pos) ?')
368 (eq (char-before (1- pos)) ?#))
369 (save-excursion
370 (let ((parent (nth 1 (syntax-ppss pos))))
371 (when parent
372 (goto-char parent)
373 (and
374 (looking-at (concat "(\\(cl-\\)?"
375 (regexp-opt '("declare-function"
376 "function" "defadvice"
377 "callf" "callf2"
378 "defsetf"))
379 "[ \t\r\n]+"))
380 (eq (match-end 0) pos)))))))
381
382 (defun elisp--form-quoted-p (pos)
383 "Return non-nil if the form at POS is not evaluated.
384 It can be quoted, or be inside a quoted form."
385 ;; FIXME: Do some macro expansion maybe.
386 (save-excursion
387 (let ((state (syntax-ppss pos)))
388 (or (nth 8 state) ; Code inside strings usually isn't evaluated.
389 ;; FIXME: The 9th element is undocumented.
390 (let ((nesting (cons (point) (reverse (nth 9 state))))
391 res)
392 (while (and nesting (not res))
393 (goto-char (pop nesting))
394 (cond
395 ((or (eq (char-after) ?\[)
396 (progn
397 (skip-chars-backward " ")
398 (memq (char-before) '(?' ?` ?‘))))
399 (setq res t))
400 ((eq (char-before) ?,)
401 (setq nesting nil))))
402 res)))))
403
404 ;; FIXME: Support for Company brings in features which straddle eldoc.
405 ;; We should consolidate this, so that major modes can provide all that
406 ;; data all at once:
407 ;; - a function to extract "the reference at point" (may be more complex
408 ;; than a mere string, to distinguish various namespaces).
409 ;; - a function to jump to such a reference.
410 ;; - a function to show the signature/interface of such a reference.
411 ;; - a function to build a help-buffer about that reference.
412 ;; FIXME: Those functions should also be used by the normal completion code in
413 ;; the *Completions* buffer.
414
415 (defun elisp--company-doc-buffer (str)
416 (let ((symbol (intern-soft str)))
417 ;; FIXME: we really don't want to "display-buffer and then undo it".
418 (save-window-excursion
419 ;; Make sure we don't display it in another frame, otherwise
420 ;; save-window-excursion won't be able to undo it.
421 (let ((display-buffer-overriding-action
422 '(nil . ((inhibit-switch-frame . t)))))
423 (ignore-errors
424 (cond
425 ((fboundp symbol) (describe-function symbol))
426 ((boundp symbol) (describe-variable symbol))
427 ((featurep symbol) (describe-package symbol))
428 ((facep symbol) (describe-face symbol))
429 (t (signal 'user-error nil)))
430 (help-buffer))))))
431
432 (defun elisp--company-doc-string (str)
433 (let* ((symbol (intern-soft str))
434 (doc (if (fboundp symbol)
435 (documentation symbol t)
436 (documentation-property symbol 'variable-documentation t))))
437 (and (stringp doc)
438 (string-match ".*$" doc)
439 (match-string 0 doc))))
440
441 (declare-function find-library-name "find-func" (library))
442 (declare-function find-function-library "find-func" (function &optional l-o v))
443
444 (defun elisp--company-location (str)
445 (let ((sym (intern-soft str)))
446 (cond
447 ((fboundp sym) (find-definition-noselect sym nil))
448 ((boundp sym) (find-definition-noselect sym 'defvar))
449 ((featurep sym)
450 (require 'find-func)
451 (cons (find-file-noselect (find-library-name
452 (symbol-name sym)))
453 0))
454 ((facep sym) (find-definition-noselect sym 'defface)))))
455
456 (defun elisp-completion-at-point ()
457 "Function used for `completion-at-point-functions' in `emacs-lisp-mode'."
458 (with-syntax-table emacs-lisp-mode-syntax-table
459 (let* ((pos (point))
460 (beg (condition-case nil
461 (save-excursion
462 (backward-sexp 1)
463 (skip-chars-forward "`',‘")
464 (point))
465 (scan-error pos)))
466 (end
467 (unless (or (eq beg (point-max))
468 (member (char-syntax (char-after beg))
469 '(?\s ?\" ?\( ?\))))
470 (condition-case nil
471 (save-excursion
472 (goto-char beg)
473 (forward-sexp 1)
474 (skip-chars-backward "'’")
475 (when (>= (point) pos)
476 (point)))
477 (scan-error pos))))
478 ;; t if in function position.
479 (funpos (eq (char-before beg) ?\())
480 (quoted (elisp--form-quoted-p beg)))
481 (when (and end (or (not (nth 8 (syntax-ppss)))
482 (memq (char-before beg) '(?` ?‘))))
483 (let ((table-etc
484 (if (or (not funpos) quoted)
485 ;; FIXME: We could look at the first element of the list and
486 ;; use it to provide a more specific completion table in some
487 ;; cases. E.g. filter out keywords that are not understood by
488 ;; the macro/function being called.
489 (cond
490 ((elisp--expect-function-p beg)
491 (list nil obarray
492 :predicate #'fboundp
493 :company-doc-buffer #'elisp--company-doc-buffer
494 :company-docsig #'elisp--company-doc-string
495 :company-location #'elisp--company-location))
496 (quoted
497 (list nil obarray
498 ;; Don't include all symbols (bug#16646).
499 :predicate (lambda (sym)
500 (or (boundp sym)
501 (fboundp sym)
502 (featurep sym)
503 (symbol-plist sym)))
504 :annotation-function
505 (lambda (str) (if (fboundp (intern-soft str)) " <f>"))
506 :company-doc-buffer #'elisp--company-doc-buffer
507 :company-docsig #'elisp--company-doc-string
508 :company-location #'elisp--company-location))
509 (t
510 (list nil (completion-table-merge
511 elisp--local-variables-completion-table
512 (apply-partially #'completion-table-with-predicate
513 obarray
514 #'boundp
515 'strict))
516 :company-doc-buffer #'elisp--company-doc-buffer
517 :company-docsig #'elisp--company-doc-string
518 :company-location #'elisp--company-location)))
519 ;; Looks like a funcall position. Let's double check.
520 (save-excursion
521 (goto-char (1- beg))
522 (let ((parent
523 (condition-case nil
524 (progn (up-list -1) (forward-char 1)
525 (let ((c (char-after)))
526 (if (eq c ?\() ?\(
527 (if (memq (char-syntax c) '(?w ?_))
528 (read (current-buffer))))))
529 (error nil))))
530 (pcase parent
531 ;; FIXME: Rather than hardcode special cases here,
532 ;; we should use something like a symbol-property.
533 (`declare
534 (list t (mapcar (lambda (x) (symbol-name (car x)))
535 (delete-dups
536 ;; FIXME: We should include some
537 ;; docstring with each entry.
538 (append
539 macro-declarations-alist
540 defun-declarations-alist)))))
541 ((and (or `condition-case `condition-case-unless-debug)
542 (guard (save-excursion
543 (ignore-errors
544 (forward-sexp 2)
545 (< (point) beg)))))
546 (list t obarray
547 :predicate (lambda (sym) (get sym 'error-conditions))))
548 ((and (or ?\( `let `let*)
549 (guard (save-excursion
550 (goto-char (1- beg))
551 (when (eq parent ?\()
552 (up-list -1))
553 (forward-symbol -1)
554 (looking-at "\\_<let\\*?\\_>"))))
555 (list t obarray
556 :predicate #'boundp
557 :company-doc-buffer #'elisp--company-doc-buffer
558 :company-docsig #'elisp--company-doc-string
559 :company-location #'elisp--company-location))
560 (_ (list nil obarray
561 :predicate #'fboundp
562 :company-doc-buffer #'elisp--company-doc-buffer
563 :company-docsig #'elisp--company-doc-string
564 :company-location #'elisp--company-location
565 ))))))))
566 (nconc (list beg end)
567 (if (null (car table-etc))
568 (cdr table-etc)
569 (cons
570 (if (memq (char-syntax (or (char-after end) ?\s))
571 '(?\s ?>))
572 (cadr table-etc)
573 (apply-partially 'completion-table-with-terminator
574 " " (cadr table-etc)))
575 (cddr table-etc)))))))))
576
577 (define-obsolete-function-alias
578 'lisp-completion-at-point 'elisp-completion-at-point "25.1")
579
580 ;;; Xref backend
581
582 (declare-function xref-make-bogus-location "xref" (message))
583 (declare-function xref-make "xref" (description location))
584 (declare-function xref-collect-matches "xref" (input dir &optional kind))
585
586 (defun elisp-xref-find (action id)
587 (require 'find-func)
588 (pcase action
589 (`definitions
590 (let ((sym (intern-soft id)))
591 (when sym
592 (elisp--xref-find-definitions sym))))
593 (`references
594 (elisp--xref-find-matches id #'xref-collect-references))
595 (`matches
596 (elisp--xref-find-matches id #'xref-collect-matches))
597 (`apropos
598 (elisp--xref-find-apropos id))))
599
600 (defun elisp--xref-identifier-location (type sym)
601 (let ((file
602 (pcase type
603 (`defun (when (fboundp sym)
604 (let ((fun-lib
605 (find-function-library sym)))
606 (setq sym (car fun-lib))
607 (cdr fun-lib))))
608 (`defvar (and (boundp sym)
609 (let ((el-file (symbol-file sym 'defvar)))
610 (if el-file
611 (and
612 ;; Don't show minor modes twice.
613 ;; TODO: If TYPE ever becomes dependent on the
614 ;; context, move this check outside.
615 (not (and (fboundp sym)
616 (memq sym minor-mode-list)))
617 el-file)
618 (help-C-file-name sym 'var)))))
619 (`feature (and (featurep sym)
620 ;; Skip when a function with the same name
621 ;; is defined, because it's probably in the
622 ;; same file.
623 (not (fboundp sym))
624 (ignore-errors
625 (find-library-name (symbol-name sym)))))
626 (`defface (when (facep sym)
627 (symbol-file sym 'defface))))))
628 (when file
629 (when (string-match-p "\\.elc\\'" file)
630 (setq file (substring file 0 -1)))
631 (xref-make-elisp-location sym type file))))
632
633 (defvar elisp--xref-format
634 (let ((str "(%s %s)"))
635 (put-text-property 1 3 'face 'font-lock-keyword-face str)
636 (put-text-property 4 6 'face 'font-lock-function-name-face str)
637 str))
638
639 (defun elisp--xref-find-definitions (symbol)
640 (save-excursion
641 (let (lst)
642 (dolist (type '(feature defface defvar defun))
643 (let ((loc
644 (condition-case err
645 (elisp--xref-identifier-location type symbol)
646 (error
647 (xref-make-bogus-location (error-message-string err))))))
648 (when loc
649 (push
650 (xref-make (format elisp--xref-format type symbol)
651 loc)
652 lst))))
653 lst)))
654
655 (defvar package-user-dir)
656
657 (defun elisp--xref-find-matches (symbol fun)
658 (let* ((dirs (sort
659 (mapcar
660 (lambda (dir)
661 (file-name-as-directory (expand-file-name dir)))
662 ;; It's one level above a number of `load-path'
663 ;; elements (one for each installed package).
664 ;; Save us some process calls.
665 (cons package-user-dir load-path))
666 #'string<))
667 (ref dirs))
668 ;; Delete subdirectories from the list.
669 (while (cdr ref)
670 (if (string-prefix-p (car ref) (cadr ref))
671 (setcdr ref (cddr ref))
672 (setq ref (cdr ref))))
673 (cl-mapcan
674 (lambda (dir)
675 (and (file-exists-p dir)
676 (funcall fun symbol dir)))
677 dirs)))
678
679 (defun elisp--xref-find-apropos (regexp)
680 (apply #'nconc
681 (let (lst)
682 (dolist (sym (apropos-internal regexp))
683 (push (elisp--xref-find-definitions sym) lst))
684 (nreverse lst))))
685
686 (defvar elisp--xref-identifier-completion-table
687 (apply-partially #'completion-table-with-predicate
688 obarray
689 (lambda (sym)
690 (or (boundp sym)
691 (fboundp sym)
692 (featurep sym)
693 (facep sym)))
694 'strict))
695
696 (defun elisp--xref-identifier-completion-table ()
697 elisp--xref-identifier-completion-table)
698
699 (cl-defstruct (xref-elisp-location
700 (:constructor xref-make-elisp-location (symbol type file)))
701 "Location of an Emacs Lisp symbol definition."
702 symbol type file)
703
704 (cl-defmethod xref-location-marker ((l xref-elisp-location))
705 (pcase-let (((cl-struct xref-elisp-location symbol type file) l))
706 (let ((buffer-point
707 (pcase type
708 (`defun (find-function-search-for-symbol symbol nil file))
709 ((or `defvar `defface)
710 (find-function-search-for-symbol symbol type file))
711 (`feature
712 (cons (find-file-noselect file) 1)))))
713 (with-current-buffer (car buffer-point)
714 (goto-char (or (cdr buffer-point) (point-min)))
715 (point-marker)))))
716
717 ;;; Elisp Interaction mode
718
719 (defvar lisp-interaction-mode-map
720 (let ((map (make-sparse-keymap))
721 (menu-map (make-sparse-keymap "Lisp-Interaction")))
722 (set-keymap-parent map lisp-mode-shared-map)
723 (define-key map "\e\C-x" 'eval-defun)
724 (define-key map "\e\C-q" 'indent-pp-sexp)
725 (define-key map "\e\t" 'completion-at-point)
726 (define-key map "\n" 'eval-print-last-sexp)
727 (bindings--define-key map [menu-bar lisp-interaction]
728 (cons "Lisp-Interaction" menu-map))
729 (bindings--define-key menu-map [eval-defun]
730 '(menu-item "Evaluate Defun" eval-defun
731 :help "Evaluate the top-level form containing point, or after point"))
732 (bindings--define-key menu-map [eval-print-last-sexp]
733 '(menu-item "Evaluate and Print" eval-print-last-sexp
734 :help "Evaluate sexp before point; print value into current buffer"))
735 (bindings--define-key menu-map [edebug-defun-lisp-interaction]
736 '(menu-item "Instrument Function for Debugging" edebug-defun
737 :help "Evaluate the top level form point is in, stepping through with Edebug"
738 :keys "C-u C-M-x"))
739 (bindings--define-key menu-map [indent-pp-sexp]
740 '(menu-item "Indent or Pretty-Print" indent-pp-sexp
741 :help "Indent each line of the list starting just after point, or prettyprint it"))
742 (bindings--define-key menu-map [complete-symbol]
743 '(menu-item "Complete Lisp Symbol" completion-at-point
744 :help "Perform completion on Lisp symbol preceding point"))
745 map)
746 "Keymap for Lisp Interaction mode.
747 All commands in `lisp-mode-shared-map' are inherited by this map.")
748
749 (define-derived-mode lisp-interaction-mode emacs-lisp-mode "Lisp Interaction"
750 "Major mode for typing and evaluating Lisp forms.
751 Like Lisp mode except that \\[eval-print-last-sexp] evals the Lisp expression
752 before point, and prints its value into the buffer, advancing point.
753 Note that printing is controlled by `eval-expression-print-length'
754 and `eval-expression-print-level'.
755
756 Commands:
757 Delete converts tabs to spaces as it moves back.
758 Paragraphs are separated only by blank lines.
759 Semicolons start comments.
760
761 \\{lisp-interaction-mode-map}"
762 :abbrev-table nil)
763
764 ;;; Emacs Lisp Byte-Code mode
765
766 (eval-and-compile
767 (defconst emacs-list-byte-code-comment-re
768 (concat "\\(#\\)@\\([0-9]+\\) "
769 ;; Make sure it's a docstring and not a lazy-loaded byte-code.
770 "\\(?:[^(]\\|([^\"]\\)")))
771
772 (defun elisp--byte-code-comment (end &optional _point)
773 "Try to syntactically mark the #@NNN ....^_ docstrings in byte-code files."
774 (let ((ppss (syntax-ppss)))
775 (when (and (nth 4 ppss)
776 (eq (char-after (nth 8 ppss)) ?#))
777 (let* ((n (save-excursion
778 (goto-char (nth 8 ppss))
779 (when (looking-at emacs-list-byte-code-comment-re)
780 (string-to-number (match-string 2)))))
781 ;; `maxdiff' tries to make sure the loop below terminates.
782 (maxdiff n))
783 (when n
784 (let* ((bchar (match-end 2))
785 (b (position-bytes bchar)))
786 (goto-char (+ b n))
787 (while (let ((diff (- (position-bytes (point)) b n)))
788 (unless (zerop diff)
789 (when (> diff maxdiff) (setq diff maxdiff))
790 (forward-char (- diff))
791 (setq maxdiff (if (> diff 0) diff
792 (max (1- maxdiff) 1)))
793 t))))
794 (if (<= (point) end)
795 (put-text-property (1- (point)) (point)
796 'syntax-table
797 (string-to-syntax "> b"))
798 (goto-char end)))))))
799
800 (defun elisp-byte-code-syntax-propertize (start end)
801 (elisp--byte-code-comment end (point))
802 (funcall
803 (syntax-propertize-rules
804 (emacs-list-byte-code-comment-re
805 (1 (prog1 "< b" (elisp--byte-code-comment end (point))))))
806 start end))
807
808 ;;;###autoload
809 (add-to-list 'auto-mode-alist '("\\.elc\\'" . elisp-byte-code-mode))
810 ;;;###autoload
811 (define-derived-mode elisp-byte-code-mode emacs-lisp-mode
812 "Elisp-Byte-Code"
813 "Major mode for *.elc files."
814 ;; TODO: Add way to disassemble byte-code under point.
815 (setq-local open-paren-in-column-0-is-defun-start nil)
816 (setq-local syntax-propertize-function
817 #'elisp-byte-code-syntax-propertize))
818
819
820 ;;; Globally accessible functionality
821
822 (defun eval-print-last-sexp (&optional eval-last-sexp-arg-internal)
823 "Evaluate sexp before point; print value into current buffer.
824
825 Normally, this function truncates long output according to the value
826 of the variables `eval-expression-print-length' and
827 `eval-expression-print-level'. With a prefix argument of zero,
828 however, there is no such truncation. Such a prefix argument
829 also causes integers to be printed in several additional formats
830 \(octal, hexadecimal, and character).
831
832 If `eval-expression-debug-on-error' is non-nil, which is the default,
833 this command arranges for all errors to enter the debugger."
834 (interactive "P")
835 (let ((standard-output (current-buffer)))
836 (terpri)
837 (eval-last-sexp (or eval-last-sexp-arg-internal t))
838 (terpri)))
839
840
841 (defun last-sexp-setup-props (beg end value alt1 alt2)
842 "Set up text properties for the output of `elisp--eval-last-sexp'.
843 BEG and END are the start and end of the output in current-buffer.
844 VALUE is the Lisp value printed, ALT1 and ALT2 are strings for the
845 alternative printed representations that can be displayed."
846 (let ((map (make-sparse-keymap)))
847 (define-key map "\C-m" 'elisp-last-sexp-toggle-display)
848 (define-key map [down-mouse-2] 'mouse-set-point)
849 (define-key map [mouse-2] 'elisp-last-sexp-toggle-display)
850 (add-text-properties
851 beg end
852 `(printed-value (,value ,alt1 ,alt2)
853 mouse-face highlight
854 keymap ,map
855 help-echo "RET, mouse-2: toggle abbreviated display"
856 rear-nonsticky (mouse-face keymap help-echo
857 printed-value)))))
858
859
860 (defun elisp-last-sexp-toggle-display (&optional _arg)
861 "Toggle between abbreviated and unabbreviated printed representations."
862 (interactive "P")
863 (save-restriction
864 (widen)
865 (let ((value (get-text-property (point) 'printed-value)))
866 (when value
867 (let ((beg (or (previous-single-property-change (min (point-max) (1+ (point)))
868 'printed-value)
869 (point)))
870 (end (or (next-single-char-property-change (point) 'printed-value) (point)))
871 (standard-output (current-buffer))
872 (point (point)))
873 (delete-region beg end)
874 (insert (nth 1 value))
875 (or (= beg point)
876 (setq point (1- (point))))
877 (last-sexp-setup-props beg (point)
878 (nth 0 value)
879 (nth 2 value)
880 (nth 1 value))
881 (goto-char (min (point-max) point)))))))
882
883 (defun prin1-char (char) ;FIXME: Move it, e.g. to simple.el.
884 "Return a string representing CHAR as a character rather than as an integer.
885 If CHAR is not a character, return nil."
886 (and (integerp char)
887 (eventp char)
888 (let ((c (event-basic-type char))
889 (mods (event-modifiers char))
890 string)
891 ;; Prevent ?A from turning into ?\S-a.
892 (if (and (memq 'shift mods)
893 (zerop (logand char ?\S-\^@))
894 (not (let ((case-fold-search nil))
895 (char-equal c (upcase c)))))
896 (setq c (upcase c) mods nil))
897 ;; What string are we considering using?
898 (condition-case nil
899 (setq string
900 (concat
901 "?"
902 (mapconcat
903 (lambda (modif)
904 (cond ((eq modif 'super) "\\s-")
905 (t (string ?\\ (upcase (aref (symbol-name modif) 0)) ?-))))
906 mods "")
907 (cond
908 ((memq c '(?\; ?\( ?\) ?\{ ?\} ?\[ ?\] ?\" ?\' ?\\)) (string ?\\ c))
909 ((eq c 127) "\\C-?")
910 (t
911 (string c)))))
912 (error nil))
913 ;; Verify the string reads a CHAR, not to some other character.
914 ;; If it doesn't, return nil instead.
915 (and string
916 (= (car (read-from-string string)) char)
917 string))))
918
919 (defun elisp--preceding-sexp ()
920 "Return sexp before the point."
921 (let ((opoint (point))
922 (left-quote ?‘)
923 expr)
924 (save-excursion
925 (with-syntax-table emacs-lisp-mode-syntax-table
926 ;; If this sexp appears to be enclosed in `...' or ‘...’
927 ;; then ignore the surrounding quotes.
928 (cond ((eq (preceding-char) ?’)
929 (progn (forward-char -1) (setq opoint (point))))
930 ((or (eq (following-char) ?\')
931 (eq (preceding-char) ?\'))
932 (setq left-quote ?\`)))
933 (forward-sexp -1)
934 ;; If we were after `?\e' (or similar case),
935 ;; use the whole thing, not just the `e'.
936 (when (eq (preceding-char) ?\\)
937 (forward-char -1)
938 (when (eq (preceding-char) ??)
939 (forward-char -1)))
940
941 ;; Skip over hash table read syntax.
942 (and (> (point) (1+ (point-min)))
943 (looking-back "#s" (- (point) 2))
944 (forward-char -2))
945
946 ;; Skip over `#N='s.
947 (when (eq (preceding-char) ?=)
948 (let (labeled-p)
949 (save-excursion
950 (skip-chars-backward "0-9#=")
951 (setq labeled-p (looking-at "\\(#[0-9]+=\\)+")))
952 (when labeled-p
953 (forward-sexp -1))))
954
955 (save-restriction
956 (if (eq (following-char) left-quote)
957 ;; vladimir@cs.ualberta.ca 30-Jul-1997: Skip ` in `variable' so
958 ;; that the value is returned, not the name.
959 (forward-char))
960 (when (looking-at ",@?") (goto-char (match-end 0)))
961 (narrow-to-region (point-min) opoint)
962 (setq expr (read (current-buffer)))
963 ;; If it's an (interactive ...) form, it's more useful to show how an
964 ;; interactive call would use it.
965 ;; FIXME: Is it really the right place for this?
966 (when (eq (car-safe expr) 'interactive)
967 (setq expr
968 `(call-interactively
969 (lambda (&rest args) ,expr args))))
970 expr)))))
971 (define-obsolete-function-alias 'preceding-sexp 'elisp--preceding-sexp "25.1")
972
973 (defun elisp--eval-last-sexp (eval-last-sexp-arg-internal)
974 "Evaluate sexp before point; print value in the echo area.
975 If EVAL-LAST-SEXP-ARG-INTERNAL is non-nil, print output into
976 current buffer. If EVAL-LAST-SEXP-ARG-INTERNAL is `0', print
977 output with no limit on the length and level of lists, and
978 include additional formats for integers \(octal, hexadecimal, and
979 character)."
980 (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t)))
981 ;; Setup the lexical environment if lexical-binding is enabled.
982 (elisp--eval-last-sexp-print-value
983 (eval (eval-sexp-add-defvars (elisp--preceding-sexp)) lexical-binding)
984 eval-last-sexp-arg-internal)))
985
986
987 (defun elisp--eval-last-sexp-print-value (value &optional eval-last-sexp-arg-internal)
988 (let ((unabbreviated (let ((print-length nil) (print-level nil))
989 (prin1-to-string value)))
990 (print-length (and (not (zerop (prefix-numeric-value
991 eval-last-sexp-arg-internal)))
992 eval-expression-print-length))
993 (print-level (and (not (zerop (prefix-numeric-value
994 eval-last-sexp-arg-internal)))
995 eval-expression-print-level))
996 (beg (point))
997 end)
998 (prog1
999 (prin1 value)
1000 (let ((str (eval-expression-print-format value)))
1001 (if str (princ str)))
1002 (setq end (point))
1003 (when (and (bufferp standard-output)
1004 (or (not (null print-length))
1005 (not (null print-level)))
1006 (not (string= unabbreviated
1007 (buffer-substring-no-properties beg end))))
1008 (last-sexp-setup-props beg end value
1009 unabbreviated
1010 (buffer-substring-no-properties beg end))
1011 ))))
1012
1013
1014 (defvar elisp--eval-last-sexp-fake-value (make-symbol "t"))
1015
1016 (defun eval-sexp-add-defvars (exp &optional pos)
1017 "Prepend EXP with all the `defvar's that precede it in the buffer.
1018 POS specifies the starting position where EXP was found and defaults to point."
1019 (setq exp (macroexpand-all exp)) ;Eager macro-expansion.
1020 (if (not lexical-binding)
1021 exp
1022 (save-excursion
1023 (unless pos (setq pos (point)))
1024 (let ((vars ()))
1025 (goto-char (point-min))
1026 (while (re-search-forward
1027 "(def\\(?:var\\|const\\|custom\\)[ \t\n]+\\([^; '()\n\t]+\\)"
1028 pos t)
1029 (let ((var (intern (match-string 1))))
1030 (and (not (special-variable-p var))
1031 (save-excursion
1032 (zerop (car (syntax-ppss (match-beginning 0)))))
1033 (push var vars))))
1034 `(progn ,@(mapcar (lambda (v) `(defvar ,v)) vars) ,exp)))))
1035
1036 (defun eval-last-sexp (eval-last-sexp-arg-internal)
1037 "Evaluate sexp before point; print value in the echo area.
1038 Interactively, with prefix argument, print output into current buffer.
1039
1040 Normally, this function truncates long output according to the value
1041 of the variables `eval-expression-print-length' and
1042 `eval-expression-print-level'. With a prefix argument of zero,
1043 however, there is no such truncation. Such a prefix argument
1044 also causes integers to be printed in several additional formats
1045 \(octal, hexadecimal, and character).
1046
1047 If `eval-expression-debug-on-error' is non-nil, which is the default,
1048 this command arranges for all errors to enter the debugger."
1049 (interactive "P")
1050 (if (null eval-expression-debug-on-error)
1051 (elisp--eval-last-sexp eval-last-sexp-arg-internal)
1052 (let ((value
1053 (let ((debug-on-error elisp--eval-last-sexp-fake-value))
1054 (cons (elisp--eval-last-sexp eval-last-sexp-arg-internal)
1055 debug-on-error))))
1056 (unless (eq (cdr value) elisp--eval-last-sexp-fake-value)
1057 (setq debug-on-error (cdr value)))
1058 (car value))))
1059
1060 (defun elisp--eval-defun-1 (form)
1061 "Treat some expressions specially.
1062 Reset the `defvar' and `defcustom' variables to the initial value.
1063 \(For `defcustom', use the :set function if there is one.)
1064 Reinitialize the face according to the `defface' specification."
1065 ;; The code in edebug-defun should be consistent with this, but not
1066 ;; the same, since this gets a macroexpanded form.
1067 (cond ((not (listp form))
1068 form)
1069 ((and (eq (car form) 'defvar)
1070 (cdr-safe (cdr-safe form))
1071 (boundp (cadr form)))
1072 ;; Force variable to be re-set.
1073 `(progn (defvar ,(nth 1 form) nil ,@(nthcdr 3 form))
1074 (setq-default ,(nth 1 form) ,(nth 2 form))))
1075 ;; `defcustom' is now macroexpanded to
1076 ;; `custom-declare-variable' with a quoted value arg.
1077 ((and (eq (car form) 'custom-declare-variable)
1078 (default-boundp (eval (nth 1 form) lexical-binding)))
1079 ;; Force variable to be bound, using :set function if specified.
1080 (let ((setfunc (memq :set form)))
1081 (when setfunc
1082 (setq setfunc (car-safe (cdr-safe setfunc)))
1083 (or (functionp setfunc) (setq setfunc nil)))
1084 (funcall (or setfunc 'set-default)
1085 (eval (nth 1 form) lexical-binding)
1086 ;; The second arg is an expression that evaluates to
1087 ;; an expression. The second evaluation is the one
1088 ;; normally performed not by normal execution but by
1089 ;; custom-initialize-set (for example), which does not
1090 ;; use lexical-binding.
1091 (eval (eval (nth 2 form) lexical-binding))))
1092 form)
1093 ;; `defface' is macroexpanded to `custom-declare-face'.
1094 ((eq (car form) 'custom-declare-face)
1095 ;; Reset the face.
1096 (let ((face-symbol (eval (nth 1 form) lexical-binding)))
1097 (setq face-new-frame-defaults
1098 (assq-delete-all face-symbol face-new-frame-defaults))
1099 (put face-symbol 'face-defface-spec nil)
1100 (put face-symbol 'face-override-spec nil))
1101 form)
1102 ((eq (car form) 'progn)
1103 (cons 'progn (mapcar #'elisp--eval-defun-1 (cdr form))))
1104 (t form)))
1105
1106 (defun elisp--eval-defun ()
1107 "Evaluate defun that point is in or before.
1108 The value is displayed in the echo area.
1109 If the current defun is actually a call to `defvar',
1110 then reset the variable using the initial value expression
1111 even if the variable already has some other value.
1112 \(Normally `defvar' does not change the variable's value
1113 if it already has a value.\)
1114
1115 Return the result of evaluation."
1116 ;; FIXME: the print-length/level bindings should only be applied while
1117 ;; printing, not while evaluating.
1118 (let ((debug-on-error eval-expression-debug-on-error)
1119 (print-length eval-expression-print-length)
1120 (print-level eval-expression-print-level))
1121 (save-excursion
1122 ;; Arrange for eval-region to "read" the (possibly) altered form.
1123 ;; eval-region handles recording which file defines a function or
1124 ;; variable.
1125 (let ((standard-output t)
1126 beg end form)
1127 ;; Read the form from the buffer, and record where it ends.
1128 (save-excursion
1129 (end-of-defun)
1130 (beginning-of-defun)
1131 (setq beg (point))
1132 (setq form (read (current-buffer)))
1133 (setq end (point)))
1134 ;; Alter the form if necessary.
1135 (let ((form (eval-sexp-add-defvars
1136 (elisp--eval-defun-1 (macroexpand form)))))
1137 (eval-region beg end standard-output
1138 (lambda (_ignore)
1139 ;; Skipping to the end of the specified region
1140 ;; will make eval-region return.
1141 (goto-char end)
1142 form))))))
1143 (let ((str (eval-expression-print-format (car values))))
1144 (if str (princ str)))
1145 ;; The result of evaluation has been put onto VALUES. So return it.
1146 (car values))
1147
1148 (defun eval-defun (edebug-it)
1149 "Evaluate the top-level form containing point, or after point.
1150
1151 If the current defun is actually a call to `defvar' or `defcustom',
1152 evaluating it this way resets the variable using its initial value
1153 expression (using the defcustom's :set function if there is one), even
1154 if the variable already has some other value. \(Normally `defvar' and
1155 `defcustom' do not alter the value if there already is one.) In an
1156 analogous way, evaluating a `defface' overrides any customizations of
1157 the face, so that it becomes defined exactly as the `defface' expression
1158 says.
1159
1160 If `eval-expression-debug-on-error' is non-nil, which is the default,
1161 this command arranges for all errors to enter the debugger.
1162
1163 With a prefix argument, instrument the code for Edebug.
1164
1165 If acting on a `defun' for FUNCTION, and the function was
1166 instrumented, `Edebug: FUNCTION' is printed in the echo area. If not
1167 instrumented, just FUNCTION is printed.
1168
1169 If not acting on a `defun', the result of evaluation is displayed in
1170 the echo area. This display is controlled by the variables
1171 `eval-expression-print-length' and `eval-expression-print-level',
1172 which see."
1173 (interactive "P")
1174 (cond (edebug-it
1175 (require 'edebug)
1176 (eval-defun (not edebug-all-defs)))
1177 (t
1178 (if (null eval-expression-debug-on-error)
1179 (elisp--eval-defun)
1180 (let (new-value value)
1181 (let ((debug-on-error elisp--eval-last-sexp-fake-value))
1182 (setq value (elisp--eval-defun))
1183 (setq new-value debug-on-error))
1184 (unless (eq elisp--eval-last-sexp-fake-value new-value)
1185 (setq debug-on-error new-value))
1186 value)))))
1187
1188 ;;; ElDoc Support
1189
1190 (defvar elisp--eldoc-last-data (make-vector 3 nil)
1191 "Bookkeeping; elements are as follows:
1192 0 - contains the last symbol read from the buffer.
1193 1 - contains the string last displayed in the echo area for variables,
1194 or argument string for functions.
1195 2 - 'function if function args, 'variable if variable documentation.")
1196
1197 (defun elisp-eldoc-documentation-function ()
1198 "`eldoc-documentation-function' (which see) for Emacs Lisp."
1199 (let ((current-symbol (elisp--current-symbol))
1200 (current-fnsym (elisp--fnsym-in-current-sexp)))
1201 (cond ((null current-fnsym)
1202 nil)
1203 ((eq current-symbol (car current-fnsym))
1204 (or (apply #'elisp-get-fnsym-args-string current-fnsym)
1205 (elisp-get-var-docstring current-symbol)))
1206 (t
1207 (or (elisp-get-var-docstring current-symbol)
1208 (apply #'elisp-get-fnsym-args-string current-fnsym))))))
1209
1210 (defun elisp-get-fnsym-args-string (sym &optional index prefix)
1211 "Return a string containing the parameter list of the function SYM.
1212 If SYM is a subr and no arglist is obtainable from the docstring
1213 or elsewhere, return a 1-line docstring."
1214 (let ((argstring
1215 (cond
1216 ((not (and sym (symbolp sym) (fboundp sym))) nil)
1217 ((and (eq sym (aref elisp--eldoc-last-data 0))
1218 (eq 'function (aref elisp--eldoc-last-data 2)))
1219 (aref elisp--eldoc-last-data 1))
1220 (t
1221 (let* ((advertised (gethash (indirect-function sym)
1222 advertised-signature-table t))
1223 doc
1224 (args
1225 (cond
1226 ((listp advertised) advertised)
1227 ((setq doc (help-split-fundoc
1228 (condition-case nil (documentation sym t)
1229 (invalid-function nil))
1230 sym))
1231 (car doc))
1232 (t (help-function-arglist sym)))))
1233 ;; Stringify, and store before highlighting, downcasing, etc.
1234 (elisp--last-data-store sym (elisp-function-argstring args)
1235 'function))))))
1236 ;; Highlight, truncate.
1237 (if argstring
1238 (elisp--highlight-function-argument
1239 sym argstring index
1240 (or prefix
1241 (concat (propertize (symbol-name sym) 'face
1242 (if (functionp sym)
1243 'font-lock-function-name-face
1244 'font-lock-keyword-face))
1245 ": "))))))
1246
1247 (defun elisp--highlight-function-argument (sym args index prefix)
1248 "Highlight argument INDEX in ARGS list for function SYM.
1249 In the absence of INDEX, just call `eldoc-docstring-format-sym-doc'."
1250 ;; FIXME: This should probably work on the list representation of `args'
1251 ;; rather than its string representation.
1252 ;; FIXME: This function is much too long, we need to split it up!
1253 (let ((start nil)
1254 (end 0)
1255 (argument-face 'eldoc-highlight-function-argument)
1256 (args-lst (mapcar (lambda (x)
1257 (replace-regexp-in-string
1258 "\\`[(]\\|[)]\\'" "" x))
1259 (split-string args))))
1260 ;; Find the current argument in the argument string. We need to
1261 ;; handle `&rest' and informal `...' properly.
1262 ;;
1263 ;; FIXME: What to do with optional arguments, like in
1264 ;; (defun NAME ARGLIST [DOCSTRING] BODY...) case?
1265 ;; The problem is there is no robust way to determine if
1266 ;; the current argument is indeed a docstring.
1267
1268 ;; When `&key' is used finding position based on `index'
1269 ;; would be wrong, so find the arg at point and determine
1270 ;; position in ARGS based on this current arg.
1271 (when (string-match "&key" args)
1272 (let* (case-fold-search
1273 key-have-value
1274 (sym-name (symbol-name sym))
1275 (cur-w (current-word))
1276 (args-lst-ak (cdr (member "&key" args-lst)))
1277 (limit (save-excursion
1278 (when (re-search-backward sym-name nil t)
1279 (match-end 0))))
1280 (cur-a (if (and cur-w (string-match ":\\([^ ()]*\\)" cur-w))
1281 (substring cur-w 1)
1282 (save-excursion
1283 (let (split)
1284 (when (re-search-backward ":\\([^()\n]*\\)" limit t)
1285 (setq split (split-string (match-string 1) " " t))
1286 (prog1 (car split)
1287 (when (cdr split)
1288 (setq key-have-value t))))))))
1289 ;; If `cur-a' is not one of `args-lst-ak'
1290 ;; assume user is entering an unknown key
1291 ;; referenced in last position in signature.
1292 (other-key-arg (and (stringp cur-a)
1293 args-lst-ak
1294 (not (member (upcase cur-a) args-lst-ak))
1295 (upcase (car (last args-lst-ak))))))
1296 (unless (string= cur-w sym-name)
1297 ;; The last keyword have already a value
1298 ;; i.e :foo a b and cursor is at b.
1299 ;; If signature have also `&rest'
1300 ;; (assume it is after the `&key' section)
1301 ;; go to the arg after `&rest'.
1302 (if (and key-have-value
1303 (save-excursion
1304 (not (re-search-forward ":.*" (point-at-eol) t)))
1305 (string-match "&rest \\([^ ()]*\\)" args))
1306 (setq index nil ; Skip next block based on positional args.
1307 start (match-beginning 1)
1308 end (match-end 1))
1309 ;; If `cur-a' is nil probably cursor is on a positional arg
1310 ;; before `&key', in this case, exit this block and determine
1311 ;; position with `index'.
1312 (when (and cur-a ; A keyword arg (dot removed) or nil.
1313 (or (string-match
1314 (concat "\\_<" (upcase cur-a) "\\_>") args)
1315 (string-match
1316 (concat "\\_<" other-key-arg "\\_>") args)))
1317 (setq index nil ; Skip next block based on positional args.
1318 start (match-beginning 0)
1319 end (match-end 0)))))))
1320 ;; Handle now positional arguments.
1321 (while (and index (>= index 1))
1322 (if (string-match "[^ ()]+" args end)
1323 (progn
1324 (setq start (match-beginning 0)
1325 end (match-end 0))
1326 (let ((argument (match-string 0 args)))
1327 (cond ((string= argument "&rest")
1328 ;; All the rest arguments are the same.
1329 (setq index 1))
1330 ((string= argument "&optional")) ; Skip.
1331 ((string= argument "&allow-other-keys")) ; Skip.
1332 ;; Back to index 0 in ARG1 ARG2 ARG2 ARG3 etc...
1333 ;; like in `setq'.
1334 ((or (and (string-match-p "\\.\\.\\.\\'" argument)
1335 (string= argument (car (last args-lst))))
1336 (and (string-match-p "\\.\\.\\.\\'"
1337 (substring args 1 (1- (length args))))
1338 (= (length (remove "..." args-lst)) 2)
1339 (> index 1) (eq (logand index 1) 1)))
1340 (setq index 0))
1341 (t
1342 (setq index (1- index))))))
1343 (setq end (length args)
1344 start (1- end)
1345 argument-face 'font-lock-warning-face
1346 index 0)))
1347 (let ((doc args))
1348 (when start
1349 (setq doc (copy-sequence args))
1350 (add-text-properties start end (list 'face argument-face) doc))
1351 (setq doc (eldoc-docstring-format-sym-doc prefix doc))
1352 doc)))
1353
1354 ;; Return a string containing a brief (one-line) documentation string for
1355 ;; the variable.
1356 (defun elisp-get-var-docstring (sym)
1357 (cond ((not sym) nil)
1358 ((and (eq sym (aref elisp--eldoc-last-data 0))
1359 (eq 'variable (aref elisp--eldoc-last-data 2)))
1360 (aref elisp--eldoc-last-data 1))
1361 (t
1362 (let ((doc (documentation-property sym 'variable-documentation t)))
1363 (when doc
1364 (let ((doc (eldoc-docstring-format-sym-doc
1365 sym (elisp--docstring-first-line doc)
1366 'font-lock-variable-name-face)))
1367 (elisp--last-data-store sym doc 'variable)))))))
1368
1369 (defun elisp--last-data-store (symbol doc type)
1370 (aset elisp--eldoc-last-data 0 symbol)
1371 (aset elisp--eldoc-last-data 1 doc)
1372 (aset elisp--eldoc-last-data 2 type)
1373 doc)
1374
1375 ;; Note that any leading `*' in the docstring (which indicates the variable
1376 ;; is a user option) is removed.
1377 (defun elisp--docstring-first-line (doc)
1378 (and (stringp doc)
1379 (substitute-command-keys
1380 (save-match-data
1381 ;; Don't use "^" in the regexp below since it may match
1382 ;; anywhere in the doc-string.
1383 (let ((start (if (string-match "\\`\\*" doc) (match-end 0) 0)))
1384 (cond ((string-match "\n" doc)
1385 (substring doc start (match-beginning 0)))
1386 ((zerop start) doc)
1387 (t (substring doc start))))))))
1388 \f
1389 ;; Return a list of current function name and argument index.
1390 (defun elisp--fnsym-in-current-sexp ()
1391 (save-excursion
1392 (let ((argument-index (1- (elisp--beginning-of-sexp))))
1393 ;; If we are at the beginning of function name, this will be -1.
1394 (when (< argument-index 0)
1395 (setq argument-index 0))
1396 ;; Don't do anything if current word is inside a string.
1397 (if (= (or (char-after (1- (point))) 0) ?\")
1398 nil
1399 (list (elisp--current-symbol) argument-index)))))
1400
1401 ;; Move to the beginning of current sexp. Return the number of nested
1402 ;; sexp the point was over or after.
1403 (defun elisp--beginning-of-sexp ()
1404 (let ((parse-sexp-ignore-comments t)
1405 (num-skipped-sexps 0))
1406 (condition-case _
1407 (progn
1408 ;; First account for the case the point is directly over a
1409 ;; beginning of a nested sexp.
1410 (condition-case _
1411 (let ((p (point)))
1412 (forward-sexp -1)
1413 (forward-sexp 1)
1414 (when (< (point) p)
1415 (setq num-skipped-sexps 1)))
1416 (error))
1417 (while
1418 (let ((p (point)))
1419 (forward-sexp -1)
1420 (when (< (point) p)
1421 (setq num-skipped-sexps (1+ num-skipped-sexps))))))
1422 (error))
1423 num-skipped-sexps))
1424
1425 ;; returns nil unless current word is an interned symbol.
1426 (defun elisp--current-symbol ()
1427 (let ((c (char-after (point))))
1428 (and c
1429 (memq (char-syntax c) '(?w ?_))
1430 (intern-soft (current-word)))))
1431
1432 (defun elisp-function-argstring (arglist)
1433 "Return ARGLIST as a string enclosed by ().
1434 ARGLIST is either a string, or a list of strings or symbols."
1435 (let ((str (cond ((stringp arglist) arglist)
1436 ((not (listp arglist)) nil)
1437 (t (format "%S" (help-make-usage 'toto arglist))))))
1438 (if (and str (string-match "\\`([^ )]+ ?" str))
1439 (replace-match "(" t t str)
1440 str)))
1441
1442 (provide 'elisp-mode)
1443 ;;; elisp-mode.el ends here