Commit | Line | Data |
---|---|---|
6594deb0 ER |
1 | ;;; lisp.el --- Lisp editing commands for Emacs |
2 | ||
acaf905b | 3 | ;; Copyright (C) 1985-1986, 1994, 2000-2012 Free Software Foundation, Inc. |
9750e079 | 4 | |
e5167999 | 5 | ;; Maintainer: FSF |
e9571d2a | 6 | ;; Keywords: lisp, languages |
bd78fa1d | 7 | ;; Package: emacs |
e5167999 | 8 | |
b73b9811 | 9 | ;; This file is part of GNU Emacs. |
10 | ||
d6cba7ae | 11 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
b73b9811 | 12 | ;; it under the terms of the GNU General Public License as published by |
d6cba7ae GM |
13 | ;; the Free Software Foundation, either version 3 of the License, or |
14 | ;; (at your option) any later version. | |
b73b9811 | 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 | |
d6cba7ae | 22 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
b73b9811 | 23 | |
e41b2db1 ER |
24 | ;;; Commentary: |
25 | ||
e50c4203 DL |
26 | ;; Lisp editing commands to go with Lisp major mode. More-or-less |
27 | ;; applicable in other modes too. | |
e41b2db1 | 28 | |
e5167999 | 29 | ;;; Code: |
b73b9811 | 30 | |
7fe78b07 | 31 | ;; Note that this variable is used by non-lisp modes too. |
30e19aee | 32 | (defcustom defun-prompt-regexp nil |
cb711556 | 33 | "If non-nil, a regexp to ignore before a defun. |
7fe78b07 | 34 | This is only necessary if the opening paren or brace is not in column 0. |
a64dc1a4 | 35 | See function `beginning-of-defun'." |
ba6b3a2a RS |
36 | :type '(choice (const nil) |
37 | regexp) | |
30e19aee | 38 | :group 'lisp) |
24ff5498 | 39 | (make-variable-buffer-local 'defun-prompt-regexp) |
b73b9811 | 40 | |
30e19aee | 41 | (defcustom parens-require-spaces t |
becc6788 CY |
42 | "If non-nil, add whitespace as needed when inserting parentheses. |
43 | This affects `insert-parentheses' and `insert-pair'." | |
30e19aee RS |
44 | :type 'boolean |
45 | :group 'lisp) | |
44a53673 | 46 | |
11ae6c5d SM |
47 | (defvar forward-sexp-function nil |
48 | "If non-nil, `forward-sexp' delegates to this function. | |
49 | Should take the same arguments and behave similarly to `forward-sexp'.") | |
50 | ||
b73b9811 | 51 | (defun forward-sexp (&optional arg) |
52 | "Move forward across one balanced expression (sexp). | |
c6eeec65 | 53 | With ARG, do it that many times. Negative arg -N means |
8fc2ac41 AM |
54 | move backward across N balanced expressions. |
55 | This command assumes point is not in a string or comment." | |
61eee794 | 56 | (interactive "^p") |
b73b9811 | 57 | (or arg (setq arg 1)) |
11ae6c5d SM |
58 | (if forward-sexp-function |
59 | (funcall forward-sexp-function arg) | |
60 | (goto-char (or (scan-sexps (point) arg) (buffer-end arg))) | |
61 | (if (< arg 0) (backward-prefix-chars)))) | |
b73b9811 | 62 | |
63 | (defun backward-sexp (&optional arg) | |
64 | "Move backward across one balanced expression (sexp). | |
c6eeec65 | 65 | With ARG, do it that many times. Negative arg -N means |
8fc2ac41 AM |
66 | move forward across N balanced expressions. |
67 | This command assumes point is not in a string or comment." | |
61eee794 | 68 | (interactive "^p") |
b73b9811 | 69 | (or arg (setq arg 1)) |
70 | (forward-sexp (- arg))) | |
71 | ||
afb62fdd | 72 | (defun mark-sexp (&optional arg allow-extend) |
b73b9811 | 73 | "Set mark ARG sexps from point. |
e3f99b91 | 74 | The place mark goes is the same place \\[forward-sexp] would |
f07493e7 | 75 | move to with the same argument. |
afb62fdd | 76 | Interactively, if this command is repeated |
a64dc1a4 | 77 | or (in Transient Mark mode) if the mark is active, |
8fc2ac41 AM |
78 | it marks the next ARG sexps after the ones already marked. |
79 | This command assumes point is not in a string or comment." | |
afb62fdd RS |
80 | (interactive "P\np") |
81 | (cond ((and allow-extend | |
82 | (or (and (eq last-command this-command) (mark t)) | |
83 | (and transient-mark-mode mark-active))) | |
3610d3c9 | 84 | (setq arg (if arg (prefix-numeric-value arg) |
967e1a52 | 85 | (if (< (mark) (point)) -1 1))) |
cad113ae KG |
86 | (set-mark |
87 | (save-excursion | |
967e1a52 JL |
88 | (goto-char (mark)) |
89 | (forward-sexp arg) | |
90 | (point)))) | |
cad113ae KG |
91 | (t |
92 | (push-mark | |
93 | (save-excursion | |
3610d3c9 | 94 | (forward-sexp (prefix-numeric-value arg)) |
cad113ae KG |
95 | (point)) |
96 | nil t)))) | |
b73b9811 | 97 | |
98 | (defun forward-list (&optional arg) | |
99 | "Move forward across one balanced group of parentheses. | |
c6eeec65 | 100 | With ARG, do it that many times. |
8fc2ac41 AM |
101 | Negative arg -N means move backward across N groups of parentheses. |
102 | This command assumes point is not in a string or comment." | |
61eee794 | 103 | (interactive "^p") |
b73b9811 | 104 | (or arg (setq arg 1)) |
105 | (goto-char (or (scan-lists (point) arg 0) (buffer-end arg)))) | |
106 | ||
107 | (defun backward-list (&optional arg) | |
108 | "Move backward across one balanced group of parentheses. | |
c6eeec65 | 109 | With ARG, do it that many times. |
8fc2ac41 AM |
110 | Negative arg -N means move forward across N groups of parentheses. |
111 | This command assumes point is not in a string or comment." | |
61eee794 | 112 | (interactive "^p") |
b73b9811 | 113 | (or arg (setq arg 1)) |
114 | (forward-list (- arg))) | |
115 | ||
e50c4203 | 116 | (defun down-list (&optional arg) |
b73b9811 | 117 | "Move forward down one level of parentheses. |
c6eeec65 | 118 | With ARG, do this that many times. |
8fc2ac41 AM |
119 | A negative argument means move backward but still go down a level. |
120 | This command assumes point is not in a string or comment." | |
61eee794 | 121 | (interactive "^p") |
e50c4203 | 122 | (or arg (setq arg 1)) |
b73b9811 | 123 | (let ((inc (if (> arg 0) 1 -1))) |
124 | (while (/= arg 0) | |
125 | (goto-char (or (scan-lists (point) inc -1) (buffer-end arg))) | |
126 | (setq arg (- arg inc))))) | |
127 | ||
e50c4203 | 128 | (defun backward-up-list (&optional arg) |
b73b9811 | 129 | "Move backward out of one level of parentheses. |
c6eeec65 | 130 | With ARG, do this that many times. |
8fc2ac41 AM |
131 | A negative argument means move forward but still to a less deep spot. |
132 | This command assumes point is not in a string or comment." | |
61eee794 | 133 | (interactive "^p") |
e50c4203 | 134 | (up-list (- (or arg 1)))) |
b73b9811 | 135 | |
e50c4203 | 136 | (defun up-list (&optional arg) |
b73b9811 | 137 | "Move forward out of one level of parentheses. |
c6eeec65 | 138 | With ARG, do this that many times. |
8fc2ac41 AM |
139 | A negative argument means move backward but still to a less deep spot. |
140 | This command assumes point is not in a string or comment." | |
61eee794 | 141 | (interactive "^p") |
e50c4203 | 142 | (or arg (setq arg 1)) |
984edd22 SM |
143 | (let ((inc (if (> arg 0) 1 -1)) |
144 | pos) | |
b73b9811 | 145 | (while (/= arg 0) |
984edd22 SM |
146 | (if (null forward-sexp-function) |
147 | (goto-char (or (scan-lists (point) inc 1) (buffer-end arg))) | |
e44e373d SM |
148 | (condition-case err |
149 | (while (progn (setq pos (point)) | |
150 | (forward-sexp inc) | |
151 | (/= (point) pos))) | |
152 | (scan-error (goto-char (nth (if (> arg 0) 3 2) err)))) | |
153 | (if (= (point) pos) | |
984edd22 SM |
154 | (signal 'scan-error |
155 | (list "Unbalanced parentheses" (point) (point))))) | |
b73b9811 | 156 | (setq arg (- arg inc))))) |
157 | ||
e50c4203 | 158 | (defun kill-sexp (&optional arg) |
dd60a465 RS |
159 | "Kill the sexp (balanced expression) following point. |
160 | With ARG, kill that many sexps after point. | |
8fc2ac41 AM |
161 | Negative arg -N means kill N sexps before point. |
162 | This command assumes point is not in a string or comment." | |
b73b9811 | 163 | (interactive "p") |
164 | (let ((opoint (point))) | |
e50c4203 | 165 | (forward-sexp (or arg 1)) |
b73b9811 | 166 | (kill-region opoint (point)))) |
167 | ||
e50c4203 | 168 | (defun backward-kill-sexp (&optional arg) |
dd60a465 RS |
169 | "Kill the sexp (balanced expression) preceding point. |
170 | With ARG, kill that many sexps before point. | |
8fc2ac41 AM |
171 | Negative arg -N means kill N sexps after point. |
172 | This command assumes point is not in a string or comment." | |
b73b9811 | 173 | (interactive "p") |
e50c4203 | 174 | (kill-sexp (- (or arg 1)))) |
de6d64b2 EZ |
175 | |
176 | ;; After Zmacs: | |
177 | (defun kill-backward-up-list (&optional arg) | |
178 | "Kill the form containing the current sexp, leaving the sexp itself. | |
179 | A prefix argument ARG causes the relevant number of surrounding | |
8fc2ac41 AM |
180 | forms to be removed. |
181 | This command assumes point is not in a string or comment." | |
de6d64b2 EZ |
182 | (interactive "*p") |
183 | (let ((current-sexp (thing-at-point 'sexp))) | |
184 | (if current-sexp | |
185 | (save-excursion | |
186 | (backward-up-list arg) | |
187 | (kill-sexp) | |
188 | (insert current-sexp)) | |
189 | (error "Not at a sexp")))) | |
b73b9811 | 190 | \f |
ab22ee53 | 191 | (defvar beginning-of-defun-function nil |
c6eeec65 DL |
192 | "If non-nil, function for `beginning-of-defun-raw' to call. |
193 | This is used to find the beginning of the defun instead of using the | |
ab22ee53 RS |
194 | normal recipe (see `beginning-of-defun'). Major modes can define this |
195 | if defining `defun-prompt-regexp' is not sufficient to handle the mode's | |
196 | needs. | |
c6eeec65 | 197 | |
50bfa18a SM |
198 | The function takes the same argument as `beginning-of-defun' and should |
199 | behave similarly, returning non-nil if it found the beginning of a defun. | |
200 | Ideally it should move to a point right before an open-paren which encloses | |
201 | the body of the defun.") | |
c6eeec65 | 202 | |
b73b9811 | 203 | (defun beginning-of-defun (&optional arg) |
204 | "Move backward to the beginning of a defun. | |
6957495d CY |
205 | With ARG, do it that many times. Negative ARG means move forward |
206 | to the ARGth following beginning of defun. | |
207 | ||
208 | If search is successful, return t; point ends up at the beginning | |
209 | of the line where the search succeeded. Otherwise, return nil. | |
210 | ||
211 | When `open-paren-in-column-0-is-defun-start' is non-nil, a defun | |
212 | is assumed to start where there is a char with open-parenthesis | |
213 | syntax at the beginning of a line. If `defun-prompt-regexp' is | |
214 | non-nil, then a string which matches that regexp may also precede | |
215 | the open-parenthesis. If `defun-prompt-regexp' and | |
216 | `open-paren-in-column-0-is-defun-start' are both nil, this | |
217 | function instead finds an open-paren at the outermost level. | |
218 | ||
219 | If the variable `beginning-of-defun-function' is non-nil, its | |
220 | value is called as a function, with argument ARG, to find the | |
221 | defun's beginning. | |
222 | ||
223 | Regardless of the values of `defun-prompt-regexp' and | |
224 | `beginning-of-defun-function', point always moves to the | |
225 | beginning of the line whenever the search is successful." | |
61eee794 | 226 | (interactive "^p") |
90c08845 | 227 | (or (not (eq this-command 'beginning-of-defun)) |
967e1a52 JL |
228 | (eq last-command 'beginning-of-defun) |
229 | (and transient-mark-mode mark-active) | |
230 | (push-mark)) | |
afa995e1 KH |
231 | (and (beginning-of-defun-raw arg) |
232 | (progn (beginning-of-line) t))) | |
233 | ||
234 | (defun beginning-of-defun-raw (&optional arg) | |
235 | "Move point to the character that starts a defun. | |
c6eeec65 DL |
236 | This is identical to function `beginning-of-defun', except that point |
237 | does not move to the beginning of the line when `defun-prompt-regexp' | |
238 | is non-nil. | |
239 | ||
ab22ee53 RS |
240 | If variable `beginning-of-defun-function' is non-nil, its value |
241 | is called as a function to find the defun's beginning." | |
61eee794 | 242 | (interactive "^p") ; change this to "P", maybe, if we ever come to pass ARG |
4df5698c CY |
243 | ; to beginning-of-defun-function. |
244 | (unless arg (setq arg 1)) | |
6cb54822 AM |
245 | (cond |
246 | (beginning-of-defun-function | |
50bfa18a SM |
247 | (condition-case nil |
248 | (funcall beginning-of-defun-function arg) | |
249 | ;; We used to define beginning-of-defun-function as taking no argument | |
250 | ;; but that makes it impossible to implement correct forward motion: | |
251 | ;; we used to use end-of-defun for that, but it's not supposed to do | |
252 | ;; the same thing (it moves to the end of a defun not to the beginning | |
253 | ;; of the next). | |
254 | ;; In case the beginning-of-defun-function uses the old calling | |
255 | ;; convention, fallback on the old implementation. | |
256 | (wrong-number-of-arguments | |
257 | (if (> arg 0) | |
258 | (dotimes (i arg) | |
259 | (funcall beginning-of-defun-function)) | |
8e911f6f DG |
260 | (dotimes (i (- arg)) |
261 | (funcall end-of-defun-function)))))) | |
6cb54822 AM |
262 | |
263 | ((or defun-prompt-regexp open-paren-in-column-0-is-defun-start) | |
264 | (and (< arg 0) (not (eobp)) (forward-char 1)) | |
c6eeec65 | 265 | (and (re-search-backward (if defun-prompt-regexp |
418d645c GM |
266 | (concat (if open-paren-in-column-0-is-defun-start |
267 | "^\\s(\\|" "") | |
b5ed9def | 268 | "\\(?:" defun-prompt-regexp "\\)\\s(") |
c6eeec65 | 269 | "^\\s(") |
6cb54822 | 270 | nil 'move arg) |
4114bc49 SM |
271 | (progn (goto-char (1- (match-end 0))) |
272 | t))) | |
6cb54822 | 273 | |
4df5698c CY |
274 | ;; If open-paren-in-column-0-is-defun-start and defun-prompt-regexp |
275 | ;; are both nil, column 0 has no significance - so scan forward | |
276 | ;; from BOB to see how nested point is, then carry on from there. | |
277 | ;; | |
278 | ;; It is generally not a good idea to land up here, because the | |
279 | ;; call to scan-lists below can be extremely slow. This is because | |
280 | ;; back_comment in syntax.c may have to scan from bob to find the | |
281 | ;; beginning of each comment. Fixing this is not trivial -- cyd. | |
282 | ||
283 | ((eq arg 0)) | |
6cb54822 | 284 | (t |
4df5698c CY |
285 | (let ((floor (point-min)) |
286 | (ceiling (point-max)) | |
287 | (arg-+ve (> arg 0))) | |
6cb54822 AM |
288 | (save-restriction |
289 | (widen) | |
4df5698c CY |
290 | (let ((ppss (let (syntax-begin-function |
291 | font-lock-beginning-of-syntax-function) | |
292 | (syntax-ppss))) | |
293 | ;; position of least enclosing paren, or nil. | |
294 | encl-pos) | |
295 | ;; Back out of any comment/string, so that encl-pos will always | |
296 | ;; become nil if we're at top-level. | |
297 | (when (nth 8 ppss) | |
298 | (goto-char (nth 8 ppss)) | |
299 | (setq ppss (syntax-ppss))) ; should be fast, due to cache. | |
300 | (setq encl-pos (syntax-ppss-toplevel-pos ppss)) | |
301 | (if encl-pos (goto-char encl-pos)) | |
302 | ||
303 | (and encl-pos arg-+ve (setq arg (1- arg))) | |
304 | (and (not encl-pos) (not arg-+ve) (not (looking-at "\\s(")) | |
305 | (setq arg (1+ arg))) | |
306 | ||
307 | (condition-case nil ; to catch crazy parens. | |
308 | (progn | |
309 | (goto-char (scan-lists (point) (- arg) 0)) | |
310 | (if arg-+ve | |
311 | (if (>= (point) floor) | |
312 | t | |
313 | (goto-char floor) | |
314 | nil) | |
315 | ;; forward to next (, or trigger the c-c | |
316 | (goto-char (1- (scan-lists (point) 1 -1))) | |
317 | (if (<= (point) ceiling) | |
318 | t | |
319 | (goto-char ceiling) | |
320 | nil))) | |
321 | (error | |
322 | (goto-char (if arg-+ve floor ceiling)) | |
323 | nil)))))))) | |
c6eeec65 | 324 | |
7bbab3e0 SM |
325 | (defvar end-of-defun-function |
326 | (lambda () (forward-sexp 1)) | |
61e21607 | 327 | "Function for `end-of-defun' to call. |
6d3e4d22 | 328 | This is used to find the end of the defun at point. |
61e21607 | 329 | It is called with no argument, right after calling `beginning-of-defun-raw'. |
6d3e4d22 SM |
330 | So the function can assume that point is at the beginning of the defun body. |
331 | It should move point to the first position after the defun.") | |
b73b9811 | 332 | |
333 | (defun buffer-end (arg) | |
a64dc1a4 | 334 | "Return the \"far end\" position of the buffer, in direction ARG. |
03deb635 RS |
335 | If ARG is positive, that's the end of the buffer. |
336 | Otherwise, that's the beginning of the buffer." | |
b73b9811 | 337 | (if (> arg 0) (point-max) (point-min))) |
338 | ||
339 | (defun end-of-defun (&optional arg) | |
a64dc1a4 LT |
340 | "Move forward to next end of defun. |
341 | With argument, do it that many times. | |
b73b9811 | 342 | Negative argument -N means move back to Nth preceding end of defun. |
343 | ||
c6eeec65 DL |
344 | An end of a defun occurs right after the close-parenthesis that |
345 | matches the open-parenthesis that starts a defun; see function | |
ab22ee53 RS |
346 | `beginning-of-defun'. |
347 | ||
348 | If variable `end-of-defun-function' is non-nil, its value | |
349 | is called as a function to find the defun's end." | |
61eee794 | 350 | (interactive "^p") |
90c08845 | 351 | (or (not (eq this-command 'end-of-defun)) |
967e1a52 JL |
352 | (eq last-command 'end-of-defun) |
353 | (and transient-mark-mode mark-active) | |
354 | (push-mark)) | |
44b254cc | 355 | (if (or (null arg) (= arg 0)) (setq arg 1)) |
f9f34ece SM |
356 | (let ((pos (point)) |
357 | (beg (progn (end-of-line 1) (beginning-of-defun-raw 1) (point)))) | |
358 | (funcall end-of-defun-function) | |
f2a8252a SM |
359 | ;; When comparing point against pos, we want to consider that if |
360 | ;; point was right after the end of the function, it's still | |
361 | ;; considered as "in that function". | |
362 | ;; E.g. `eval-defun' from right after the last close-paren. | |
363 | (unless (bolp) | |
364 | (skip-chars-forward " \t") | |
365 | (if (looking-at "\\s<\\|\n") | |
366 | (forward-line 1))) | |
f9f34ece SM |
367 | (cond |
368 | ((> arg 0) | |
369 | ;; Moving forward. | |
370 | (if (> (point) pos) | |
371 | ;; We already moved forward by one because we started from | |
372 | ;; within a function. | |
373 | (setq arg (1- arg)) | |
374 | ;; We started from after the end of the previous function. | |
375 | (goto-char pos)) | |
376 | (unless (zerop arg) | |
377 | (beginning-of-defun-raw (- arg)) | |
378 | (funcall end-of-defun-function))) | |
379 | ((< arg 0) | |
380 | ;; Moving backward. | |
381 | (if (< (point) pos) | |
382 | ;; We already moved backward because we started from between | |
383 | ;; two functions. | |
384 | (setq arg (1+ arg)) | |
385 | ;; We started from inside a function. | |
386 | (goto-char beg)) | |
387 | (unless (zerop arg) | |
388 | (beginning-of-defun-raw (- arg)) | |
389 | (funcall end-of-defun-function)))) | |
390 | (unless (bolp) | |
391 | (skip-chars-forward " \t") | |
392 | (if (looking-at "\\s<\\|\n") | |
393 | (forward-line 1))))) | |
b73b9811 | 394 | |
afb62fdd | 395 | (defun mark-defun (&optional allow-extend) |
b73b9811 | 396 | "Put mark at end of this defun, point at beginning. |
cad113ae | 397 | The defun marked is the one that contains point or follows point. |
afb62fdd RS |
398 | |
399 | Interactively, if this command is repeated | |
a64dc1a4 | 400 | or (in Transient Mark mode) if the mark is active, |
afb62fdd RS |
401 | it marks the next defun after the ones already marked." |
402 | (interactive "p") | |
403 | (cond ((and allow-extend | |
404 | (or (and (eq last-command this-command) (mark t)) | |
405 | (and transient-mark-mode mark-active))) | |
be0d25b6 KG |
406 | (set-mark |
407 | (save-excursion | |
408 | (goto-char (mark)) | |
409 | (end-of-defun) | |
410 | (point)))) | |
411 | (t | |
d3d6bc9b RS |
412 | (let ((opoint (point)) |
413 | beg end) | |
414 | (push-mark opoint) | |
415 | ;; Try first in this order for the sake of languages with nested | |
416 | ;; functions where several can end at the same place as with | |
417 | ;; the offside rule, e.g. Python. | |
418 | (beginning-of-defun) | |
419 | (setq beg (point)) | |
420 | (end-of-defun) | |
421 | (setq end (point)) | |
422 | (while (looking-at "^\n") | |
423 | (forward-line 1)) | |
424 | (if (> (point) opoint) | |
425 | (progn | |
426 | ;; We got the right defun. | |
427 | (push-mark beg nil t) | |
428 | (goto-char end) | |
429 | (exchange-point-and-mark)) | |
430 | ;; beginning-of-defun moved back one defun | |
431 | ;; so we got the wrong one. | |
432 | (goto-char opoint) | |
433 | (end-of-defun) | |
434 | (push-mark (point) nil t) | |
435 | (beginning-of-defun)) | |
436 | (re-search-backward "^\n" (- (point) 1) t))))) | |
b73b9811 | 437 | |
3f7e952d RS |
438 | (defun narrow-to-defun (&optional arg) |
439 | "Make text outside current defun invisible. | |
c6eeec65 DL |
440 | The defun visible is the one that contains point or follows point. |
441 | Optional ARG is ignored." | |
3f7e952d RS |
442 | (interactive) |
443 | (save-excursion | |
444 | (widen) | |
d3d6bc9b RS |
445 | (let ((opoint (point)) |
446 | beg end) | |
447 | ;; Try first in this order for the sake of languages with nested | |
448 | ;; functions where several can end at the same place as with | |
449 | ;; the offside rule, e.g. Python. | |
050cc68b LB |
450 | |
451 | ;; Finding the start of the function is a bit problematic since | |
452 | ;; `beginning-of-defun' when we are on the first character of | |
453 | ;; the function might go to the previous function. | |
454 | ;; | |
455 | ;; Therefore we first move one character forward and then call | |
456 | ;; `beginning-of-defun'. However now we must check that we did | |
457 | ;; not move into the next function. | |
458 | (let ((here (point))) | |
459 | (unless (eolp) | |
460 | (forward-char)) | |
461 | (beginning-of-defun) | |
462 | (when (< (point) here) | |
463 | (goto-char here) | |
464 | (beginning-of-defun))) | |
d3d6bc9b | 465 | (setq beg (point)) |
750e563f | 466 | (end-of-defun) |
d3d6bc9b RS |
467 | (setq end (point)) |
468 | (while (looking-at "^\n") | |
469 | (forward-line 1)) | |
470 | (unless (> (point) opoint) | |
471 | ;; beginning-of-defun moved back one defun | |
472 | ;; so we got the wrong one. | |
473 | (goto-char opoint) | |
474 | (end-of-defun) | |
475 | (setq end (point)) | |
476 | (beginning-of-defun) | |
477 | (setq beg (point))) | |
478 | (goto-char end) | |
479 | (re-search-backward "^\n" (- (point) 1) t) | |
480 | (narrow-to-region beg end)))) | |
3f7e952d | 481 | |
d97c8198 JL |
482 | (defvar insert-pair-alist |
483 | '((?\( ?\)) (?\[ ?\]) (?\{ ?\}) (?\< ?\>) (?\" ?\") (?\' ?\') (?\` ?\')) | |
484 | "Alist of paired characters inserted by `insert-pair'. | |
485 | Each element looks like (OPEN-CHAR CLOSE-CHAR) or (COMMAND-CHAR | |
486 | OPEN-CHAR CLOSE-CHAR). The characters OPEN-CHAR and CLOSE-CHAR | |
487 | of the pair whose key is equal to the last input character with | |
488 | or without modifiers, are inserted by `insert-pair'.") | |
489 | ||
490 | (defun insert-pair (&optional arg open close) | |
5891bf24 JL |
491 | "Enclose following ARG sexps in a pair of OPEN and CLOSE characters. |
492 | Leave point after the first character. | |
e3ac26cb | 493 | A negative ARG encloses the preceding ARG sexps instead. |
5891bf24 JL |
494 | No argument is equivalent to zero: just insert characters |
495 | and leave point between. | |
d5bfe076 | 496 | If `parens-require-spaces' is non-nil, this command also inserts a space |
5891bf24 | 497 | before and after, depending on the surrounding characters. |
d97c8198 JL |
498 | If region is active, insert enclosing characters at region boundaries. |
499 | ||
500 | If arguments OPEN and CLOSE are nil, the character pair is found | |
501 | from the variable `insert-pair-alist' according to the last input | |
502 | character with or without modifiers. If no character pair is | |
503 | found in the variable `insert-pair-alist', then the last input | |
8fc2ac41 AM |
504 | character is inserted ARG times. |
505 | ||
506 | This command assumes point is not in a string or comment." | |
b73b9811 | 507 | (interactive "P") |
d97c8198 | 508 | (if (not (and open close)) |
61a846fb | 509 | (let ((pair (or (assq last-command-event insert-pair-alist) |
d97c8198 JL |
510 | (assq (event-basic-type last-command-event) |
511 | insert-pair-alist)))) | |
512 | (if pair | |
513 | (if (nth 2 pair) | |
514 | (setq open (nth 1 pair) close (nth 2 pair)) | |
515 | (setq open (nth 0 pair) close (nth 1 pair)))))) | |
516 | (if (and open close) | |
517 | (if (and transient-mark-mode mark-active) | |
518 | (progn | |
519 | (save-excursion (goto-char (region-end)) (insert close)) | |
520 | (save-excursion (goto-char (region-beginning)) (insert open))) | |
521 | (if arg (setq arg (prefix-numeric-value arg)) | |
522 | (setq arg 0)) | |
523 | (cond ((> arg 0) (skip-chars-forward " \t")) | |
524 | ((< arg 0) (forward-sexp arg) (setq arg (- arg)))) | |
525 | (and parens-require-spaces | |
526 | (not (bobp)) | |
527 | (memq (char-syntax (preceding-char)) (list ?w ?_ (char-syntax close))) | |
528 | (insert " ")) | |
529 | (insert open) | |
530 | (save-excursion | |
531 | (or (eq arg 0) (forward-sexp arg)) | |
532 | (insert close) | |
533 | (and parens-require-spaces | |
534 | (not (eobp)) | |
535 | (memq (char-syntax (following-char)) (list ?w ?_ (char-syntax open))) | |
536 | (insert " ")))) | |
537 | (insert-char (event-basic-type last-command-event) | |
538 | (prefix-numeric-value arg)))) | |
539 | ||
540 | (defun insert-parentheses (&optional arg) | |
a64dc1a4 LT |
541 | "Enclose following ARG sexps in parentheses. |
542 | Leave point after open-paren. | |
5891bf24 JL |
543 | A negative ARG encloses the preceding ARG sexps instead. |
544 | No argument is equivalent to zero: just insert `()' and leave point between. | |
545 | If `parens-require-spaces' is non-nil, this command also inserts a space | |
546 | before and after, depending on the surrounding characters. | |
8fc2ac41 AM |
547 | If region is active, insert enclosing characters at region boundaries. |
548 | ||
549 | This command assumes point is not in a string or comment." | |
5891bf24 JL |
550 | (interactive "P") |
551 | (insert-pair arg ?\( ?\))) | |
b73b9811 | 552 | |
d97c8198 JL |
553 | (defun delete-pair () |
554 | "Delete a pair of characters enclosing the sexp that follows point." | |
555 | (interactive) | |
556 | (save-excursion (forward-sexp 1) (delete-char -1)) | |
557 | (delete-char 1)) | |
558 | ||
559 | (defun raise-sexp (&optional arg) | |
560 | "Raise ARG sexps higher up the tree." | |
561 | (interactive "p") | |
562 | (let ((s (if (and transient-mark-mode mark-active) | |
563 | (buffer-substring (region-beginning) (region-end)) | |
564 | (buffer-substring | |
565 | (point) | |
566 | (save-excursion (forward-sexp arg) (point)))))) | |
567 | (backward-up-list 1) | |
568 | (delete-region (point) (save-excursion (forward-sexp 1) (point))) | |
569 | (save-excursion (insert s)))) | |
570 | ||
b73b9811 | 571 | (defun move-past-close-and-reindent () |
572 | "Move past next `)', delete indentation before it, then indent after it." | |
573 | (interactive) | |
574 | (up-list 1) | |
575 | (forward-char -1) | |
576 | (while (save-excursion ; this is my contribution | |
577 | (let ((before-paren (point))) | |
578 | (back-to-indentation) | |
adce3b5f RS |
579 | (and (= (point) before-paren) |
580 | (progn | |
581 | ;; Move to end of previous line. | |
582 | (beginning-of-line) | |
583 | (forward-char -1) | |
584 | ;; Verify it doesn't end within a string or comment. | |
585 | (let ((end (point)) | |
586 | state) | |
587 | (beginning-of-line) | |
588 | ;; Get state at start of line. | |
c6eeec65 | 589 | (setq state (list 0 nil nil |
adce3b5f RS |
590 | (null (calculate-lisp-indent)) |
591 | nil nil nil nil | |
592 | nil)) | |
593 | ;; Parse state across the line to get state at end. | |
594 | (setq state (parse-partial-sexp (point) end nil nil | |
595 | state)) | |
596 | ;; Check not in string or comment. | |
597 | (and (not (elt state 3)) (not (elt state 4)))))))) | |
b73b9811 | 598 | (delete-indentation)) |
599 | (forward-char 1) | |
600 | (newline-and-indent)) | |
c6eeec65 DL |
601 | |
602 | (defun check-parens () ; lame name? | |
603 | "Check for unbalanced parentheses in the current buffer. | |
604 | More accurately, check the narrowed part of the buffer for unbalanced | |
605 | expressions (\"sexps\") in general. This is done according to the | |
606 | current syntax table and will find unbalanced brackets or quotes as | |
7bc10886 | 607 | appropriate. (See Info node `(emacs)Parentheses'.) If imbalance is |
8ad8cfa5 | 608 | found, an error is signaled and point is left at the first unbalanced |
7bc10886 | 609 | character." |
c6eeec65 DL |
610 | (interactive) |
611 | (condition-case data | |
612 | ;; Buffer can't have more than (point-max) sexps. | |
613 | (scan-sexps (point-min) (point-max)) | |
614 | (scan-error (goto-char (nth 2 data)) | |
615 | ;; Could print (nth 1 data), which is either | |
616 | ;; "Containing expression ends prematurely" or | |
617 | ;; "Unbalanced parentheses", but those may not be so | |
618 | ;; accurate/helpful, e.g. quotes may actually be | |
619 | ;; mismatched. | |
61e21607 | 620 | (error "Unmatched bracket or quote")))) |
b73b9811 | 621 | \f |
61e21607 | 622 | (defun field-complete (table &optional predicate) |
73ebf88f SM |
623 | (let ((minibuffer-completion-table table) |
624 | (minibuffer-completion-predicate predicate) | |
625 | ;; This made sense for lisp-complete-symbol, but for | |
626 | ;; field-complete, this is out of place. --Stef | |
627 | ;; (completion-annotate-function | |
628 | ;; (unless (eq predicate 'fboundp) | |
629 | ;; (lambda (str) | |
630 | ;; (if (fboundp (intern-soft str)) " <f>")))) | |
631 | ) | |
632 | (call-interactively 'minibuffer-complete))) | |
61e21607 | 633 | |
e50c4203 | 634 | (defun lisp-complete-symbol (&optional predicate) |
2eb9adab RS |
635 | "Perform completion on Lisp symbol preceding point. |
636 | Compare that symbol against the known Lisp symbols. | |
1fa1cb1b RS |
637 | If no characters can be completed, display a list of possible completions. |
638 | Repeating the command at that point scrolls the list. | |
2eb9adab | 639 | |
e50c4203 DL |
640 | When called from a program, optional arg PREDICATE is a predicate |
641 | determining which symbols are considered, e.g. `commandp'. | |
642 | If PREDICATE is nil, the context determines which symbols are | |
643 | considered. If the symbol starts just after an open-parenthesis, only | |
644 | symbols with function definitions are considered. Otherwise, all | |
645 | symbols with function definitions, values or properties are | |
646 | considered." | |
b73b9811 | 647 | (interactive) |
51ef56c4 SM |
648 | (let* ((data (lisp-completion-at-point predicate)) |
649 | (plist (nthcdr 3 data))) | |
ccaa4765 SM |
650 | (if (null data) |
651 | (minibuffer-message "Nothing to complete") | |
2403c841 SM |
652 | (let ((completion-extra-properties plist)) |
653 | (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data) | |
ccaa4765 | 654 | (plist-get plist :predicate)))))) |
0ca12598 | 655 | |
51ef56c4 SM |
656 | |
657 | (defun lisp-completion-at-point (&optional predicate) | |
0ca12598 | 658 | "Function used for `completion-at-point-functions' in `emacs-lisp-mode'." |
51ef56c4 | 659 | ;; FIXME: the `end' could be after point? |
4c528197 | 660 | (with-syntax-table emacs-lisp-mode-syntax-table |
4c14013d JB |
661 | (let* ((pos (point)) |
662 | (beg (condition-case nil | |
663 | (save-excursion | |
664 | (backward-sexp 1) | |
665 | (skip-syntax-forward "'") | |
666 | (point)) | |
667 | (scan-error pos))) | |
668 | (predicate | |
669 | (or predicate | |
670 | (save-excursion | |
671 | (goto-char beg) | |
672 | (if (not (eq (char-before) ?\()) | |
673 | (lambda (sym) ;why not just nil ? -sm | |
674 | (or (boundp sym) (fboundp sym) | |
675 | (symbol-plist sym))) | |
676 | ;; Looks like a funcall position. Let's double check. | |
677 | (if (condition-case nil | |
678 | (progn (up-list -2) (forward-char 1) | |
679 | (eq (char-after) ?\()) | |
680 | (error nil)) | |
681 | ;; If the first element of the parent list is an open | |
682 | ;; paren we are probably not in a funcall position. | |
683 | ;; Maybe a `let' varlist or something. | |
684 | nil | |
685 | ;; Else, we assume that a function name is expected. | |
686 | 'fboundp))))) | |
687 | (end | |
688 | (unless (or (eq beg (point-max)) | |
689 | (member (char-syntax (char-after beg)) '(?\" ?\( ?\)))) | |
690 | (condition-case nil | |
691 | (save-excursion | |
692 | (goto-char beg) | |
693 | (forward-sexp 1) | |
694 | (when (>= (point) pos) | |
695 | (point))) | |
696 | (scan-error pos))))) | |
697 | (when end | |
698 | (list beg end obarray | |
699 | :predicate predicate | |
d2fc7e3d | 700 | :annotation-function |
4c14013d JB |
701 | (unless (eq predicate 'fboundp) |
702 | (lambda (str) (if (fboundp (intern-soft str)) " <f>")))))))) | |
6594deb0 ER |
703 | |
704 | ;;; lisp.el ends here |