(lisp-complete-symbol): Repeating the command
[bpt/emacs.git] / lisp / emacs-lisp / lisp.el
CommitLineData
6594deb0
ER
1;;; lisp.el --- Lisp editing commands for Emacs
2
c6eeec65 3;; Copyright (C) 1985, 1986, 1994, 2000 Free Software Foundation, Inc.
9750e079 4
e5167999 5;; Maintainer: FSF
e9571d2a 6;; Keywords: lisp, languages
e5167999 7
b73b9811 8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
e5167999 12;; the Free Software Foundation; either version 2, or (at your option)
b73b9811 13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
b578f267
EN
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
b73b9811 24
e41b2db1
ER
25;;; Commentary:
26
e50c4203
DL
27;; Lisp editing commands to go with Lisp major mode. More-or-less
28;; applicable in other modes too.
e41b2db1 29
e5167999 30;;; Code:
b73b9811 31
7fe78b07 32;; Note that this variable is used by non-lisp modes too.
30e19aee 33(defcustom defun-prompt-regexp nil
e50c4203 34 "*If non-nil, a regexp to ignore before the character that starts a defun.
7fe78b07 35This is only necessary if the opening paren or brace is not in column 0.
c7f18fba
GM
36See function `beginning-of-defun'.
37
38Setting this variable automatically makes it local to the current buffer."
ba6b3a2a
RS
39 :type '(choice (const nil)
40 regexp)
30e19aee 41 :group 'lisp)
24ff5498 42(make-variable-buffer-local 'defun-prompt-regexp)
b73b9811 43
30e19aee 44(defcustom parens-require-spaces t
e50c4203 45 "Non-nil means `insert-parentheses' should insert whitespace as needed."
30e19aee
RS
46 :type 'boolean
47 :group 'lisp)
44a53673 48
11ae6c5d
SM
49(defvar forward-sexp-function nil
50 "If non-nil, `forward-sexp' delegates to this function.
51Should take the same arguments and behave similarly to `forward-sexp'.")
52
b73b9811 53(defun forward-sexp (&optional arg)
54 "Move forward across one balanced expression (sexp).
c6eeec65 55With ARG, do it that many times. Negative arg -N means
e3f99b91 56move backward across N balanced expressions."
b73b9811 57 (interactive "p")
58 (or arg (setq arg 1))
11ae6c5d
SM
59 (if forward-sexp-function
60 (funcall forward-sexp-function arg)
61 (goto-char (or (scan-sexps (point) arg) (buffer-end arg)))
62 (if (< arg 0) (backward-prefix-chars))))
b73b9811 63
64(defun backward-sexp (&optional arg)
65 "Move backward across one balanced expression (sexp).
c6eeec65 66With ARG, do it that many times. Negative arg -N means
e3f99b91 67move forward across N balanced expressions."
b73b9811 68 (interactive "p")
69 (or arg (setq arg 1))
70 (forward-sexp (- arg)))
71
e50c4203 72(defun mark-sexp (&optional arg)
b73b9811 73 "Set mark ARG sexps from point.
e3f99b91 74The place mark goes is the same place \\[forward-sexp] would
f07493e7
SM
75move to with the same argument.
76If this command is repeated, it marks the next ARG sexps after the ones
77already marked."
b73b9811 78 (interactive "p")
79 (push-mark
80 (save-excursion
f07493e7
SM
81 (if (and (eq last-command this-command) (mark t))
82 (goto-char (mark)))
e50c4203 83 (forward-sexp (or arg 1))
0ba91115
RS
84 (point))
85 nil t))
b73b9811 86
87(defun forward-list (&optional arg)
88 "Move forward across one balanced group of parentheses.
c6eeec65 89With ARG, do it that many times.
b73b9811 90Negative arg -N means move backward across N groups of parentheses."
91 (interactive "p")
92 (or arg (setq arg 1))
93 (goto-char (or (scan-lists (point) arg 0) (buffer-end arg))))
94
95(defun backward-list (&optional arg)
96 "Move backward across one balanced group of parentheses.
c6eeec65 97With ARG, do it that many times.
b73b9811 98Negative arg -N means move forward across N groups of parentheses."
99 (interactive "p")
100 (or arg (setq arg 1))
101 (forward-list (- arg)))
102
e50c4203 103(defun down-list (&optional arg)
b73b9811 104 "Move forward down one level of parentheses.
c6eeec65 105With ARG, do this that many times.
b41c9501 106A negative argument means move backward but still go down a level."
b73b9811 107 (interactive "p")
e50c4203 108 (or arg (setq arg 1))
b73b9811 109 (let ((inc (if (> arg 0) 1 -1)))
110 (while (/= arg 0)
111 (goto-char (or (scan-lists (point) inc -1) (buffer-end arg)))
112 (setq arg (- arg inc)))))
113
e50c4203 114(defun backward-up-list (&optional arg)
b73b9811 115 "Move backward out of one level of parentheses.
c6eeec65 116With ARG, do this that many times.
b41c9501 117A negative argument means move forward but still to a less deep spot."
b73b9811 118 (interactive "p")
e50c4203 119 (up-list (- (or arg 1))))
b73b9811 120
e50c4203 121(defun up-list (&optional arg)
b73b9811 122 "Move forward out of one level of parentheses.
c6eeec65 123With ARG, do this that many times.
b41c9501 124A negative argument means move backward but still to a less deep spot."
b73b9811 125 (interactive "p")
e50c4203 126 (or arg (setq arg 1))
b73b9811 127 (let ((inc (if (> arg 0) 1 -1)))
128 (while (/= arg 0)
129 (goto-char (or (scan-lists (point) inc 1) (buffer-end arg)))
130 (setq arg (- arg inc)))))
131
e50c4203 132(defun kill-sexp (&optional arg)
b73b9811 133 "Kill the sexp (balanced expression) following the cursor.
c6eeec65 134With ARG, kill that many sexps after the cursor.
b73b9811 135Negative arg -N means kill N sexps before the cursor."
136 (interactive "p")
137 (let ((opoint (point)))
e50c4203 138 (forward-sexp (or arg 1))
b73b9811 139 (kill-region opoint (point))))
140
e50c4203 141(defun backward-kill-sexp (&optional arg)
b73b9811 142 "Kill the sexp (balanced expression) preceding the cursor.
c6eeec65 143With ARG, kill that many sexps before the cursor.
b73b9811 144Negative arg -N means kill N sexps after the cursor."
145 (interactive "p")
e50c4203 146 (kill-sexp (- (or arg 1))))
b73b9811 147\f
ab22ee53 148(defvar beginning-of-defun-function nil
c6eeec65
DL
149 "If non-nil, function for `beginning-of-defun-raw' to call.
150This is used to find the beginning of the defun instead of using the
ab22ee53
RS
151normal recipe (see `beginning-of-defun'). Major modes can define this
152if defining `defun-prompt-regexp' is not sufficient to handle the mode's
153needs.
c6eeec65 154
ab22ee53
RS
155The function should go to the line on which the current defun starts,
156and return non-nil, or should return nil if it can't find the beginning.")
c6eeec65 157
b73b9811 158(defun beginning-of-defun (&optional arg)
159 "Move backward to the beginning of a defun.
c6eeec65 160With ARG, do it that many times. Negative arg -N
b73b9811 161means move forward to Nth following beginning of defun.
162Returns t unless search stops due to beginning or end of buffer.
163
164Normally a defun starts when there is an char with open-parenthesis
165syntax at the beginning of a line. If `defun-prompt-regexp' is
166non-nil, then a string which matches that regexp may precede the
c6eeec65
DL
167open-parenthesis, and point ends up at the beginning of the line.
168
ab22ee53
RS
169If variable `beginning-of-defun-function' is non-nil, its value
170is called as a function to find the defun's beginning."
afa995e1
KH
171 (interactive "p")
172 (and (beginning-of-defun-raw arg)
173 (progn (beginning-of-line) t)))
174
175(defun beginning-of-defun-raw (&optional arg)
176 "Move point to the character that starts a defun.
c6eeec65
DL
177This is identical to function `beginning-of-defun', except that point
178does not move to the beginning of the line when `defun-prompt-regexp'
179is non-nil.
180
ab22ee53
RS
181If variable `beginning-of-defun-function' is non-nil, its value
182is called as a function to find the defun's beginning."
b73b9811 183 (interactive "p")
ab22ee53
RS
184 (if beginning-of-defun-function
185 (funcall beginning-of-defun-function)
c6eeec65
DL
186 (and arg (< arg 0) (not (eobp)) (forward-char 1))
187 (and (re-search-backward (if defun-prompt-regexp
418d645c
GM
188 (concat (if open-paren-in-column-0-is-defun-start
189 "^\\s(\\|" "")
c6eeec65
DL
190 "\\(" defun-prompt-regexp "\\)\\s(")
191 "^\\s(")
192 nil 'move (or arg 1))
193 (progn (goto-char (1- (match-end 0)))) t)))
194
ab22ee53 195(defvar end-of-defun-function nil
c6eeec65
DL
196 "If non-nil, function for function `end-of-defun' to call.
197This is used to find the end of the defun instead of using the normal
ab22ee53
RS
198recipe (see `end-of-defun'). Major modes can define this if the
199normal method is not appropriate.")
b73b9811 200
201(defun buffer-end (arg)
202 (if (> arg 0) (point-max) (point-min)))
203
204(defun end-of-defun (&optional arg)
205 "Move forward to next end of defun. With argument, do it that many times.
206Negative argument -N means move back to Nth preceding end of defun.
207
c6eeec65
DL
208An end of a defun occurs right after the close-parenthesis that
209matches the open-parenthesis that starts a defun; see function
ab22ee53
RS
210`beginning-of-defun'.
211
212If variable `end-of-defun-function' is non-nil, its value
213is called as a function to find the defun's end."
b73b9811 214 (interactive "p")
ab22ee53
RS
215 (if end-of-defun-function
216 (funcall end-of-defun-function)
c6eeec65
DL
217 (if (or (null arg) (= arg 0)) (setq arg 1))
218 (let ((first t))
219 (while (and (> arg 0) (< (point) (point-max)))
220 (let ((pos (point)) npos)
221 (while (progn
222 (if (and first
223 (progn
224 (end-of-line 1)
225 (beginning-of-defun-raw 1)))
226 nil
227 (or (bobp) (forward-char -1))
228 (beginning-of-defun-raw -1))
229 (setq first nil)
230 (forward-list 1)
231 (skip-chars-forward " \t")
232 (if (looking-at "\\s<\\|\n")
233 (forward-line 1))
234 (<= (point) pos))))
235 (setq arg (1- arg)))
236 (while (< arg 0)
237 (let ((pos (point)))
238 (beginning-of-defun-raw 1)
239 (forward-sexp 1)
240 (forward-line 1)
241 (if (>= (point) pos)
242 (if (beginning-of-defun-raw 2)
243 (progn
244 (forward-list 1)
245 (skip-chars-forward " \t")
246 (if (looking-at "\\s<\\|\n")
247 (forward-line 1)))
248 (goto-char (point-min)))))
249 (setq arg (1+ arg))))))
b73b9811 250
251(defun mark-defun ()
252 "Put mark at end of this defun, point at beginning.
253The defun marked is the one that contains point or follows point."
254 (interactive)
255 (push-mark (point))
256 (end-of-defun)
0ba91115 257 (push-mark (point) nil t)
b73b9811 258 (beginning-of-defun)
259 (re-search-backward "^\n" (- (point) 1) t))
260
3f7e952d
RS
261(defun narrow-to-defun (&optional arg)
262 "Make text outside current defun invisible.
c6eeec65
DL
263The defun visible is the one that contains point or follows point.
264Optional ARG is ignored."
3f7e952d
RS
265 (interactive)
266 (save-excursion
267 (widen)
e3ac26cb
EN
268 (end-of-defun)
269 (let ((end (point)))
270 (beginning-of-defun)
271 (narrow-to-region (point) end))))
3f7e952d 272
b73b9811 273(defun insert-parentheses (arg)
e3ac26cb
EN
274 "Enclose following ARG sexps in parentheses. Leave point after open-paren.
275A negative ARG encloses the preceding ARG sexps instead.
44a53673 276No argument is equivalent to zero: just insert `()' and leave point between.
d5bfe076
KH
277If `parens-require-spaces' is non-nil, this command also inserts a space
278before and after, depending on the surrounding characters."
b73b9811 279 (interactive "P")
a17f9e55
RS
280 (if arg (setq arg (prefix-numeric-value arg))
281 (setq arg 0))
e3ac26cb
EN
282 (cond ((> arg 0) (skip-chars-forward " \t"))
283 ((< arg 0) (forward-sexp arg) (setq arg (- arg))))
78e367e9 284 (and parens-require-spaces
6696af65 285 (not (bobp))
44a53673 286 (memq (char-syntax (preceding-char)) '(?w ?_ ?\) ))
b73b9811 287 (insert " "))
b73b9811 288 (insert ?\()
289 (save-excursion
a17f9e55 290 (or (eq arg 0) (forward-sexp arg))
b73b9811 291 (insert ?\))
78e367e9 292 (and parens-require-spaces
6696af65 293 (not (eobp))
44a53673 294 (memq (char-syntax (following-char)) '(?w ?_ ?\( ))
a17f9e55 295 (insert " "))))
b73b9811 296
297(defun move-past-close-and-reindent ()
298 "Move past next `)', delete indentation before it, then indent after it."
299 (interactive)
300 (up-list 1)
301 (forward-char -1)
302 (while (save-excursion ; this is my contribution
303 (let ((before-paren (point)))
304 (back-to-indentation)
adce3b5f
RS
305 (and (= (point) before-paren)
306 (progn
307 ;; Move to end of previous line.
308 (beginning-of-line)
309 (forward-char -1)
310 ;; Verify it doesn't end within a string or comment.
311 (let ((end (point))
312 state)
313 (beginning-of-line)
314 ;; Get state at start of line.
c6eeec65 315 (setq state (list 0 nil nil
adce3b5f
RS
316 (null (calculate-lisp-indent))
317 nil nil nil nil
318 nil))
319 ;; Parse state across the line to get state at end.
320 (setq state (parse-partial-sexp (point) end nil nil
321 state))
322 ;; Check not in string or comment.
323 (and (not (elt state 3)) (not (elt state 4))))))))
b73b9811 324 (delete-indentation))
325 (forward-char 1)
326 (newline-and-indent))
c6eeec65
DL
327
328(defun check-parens () ; lame name?
329 "Check for unbalanced parentheses in the current buffer.
330More accurately, check the narrowed part of the buffer for unbalanced
331expressions (\"sexps\") in general. This is done according to the
332current syntax table and will find unbalanced brackets or quotes as
333appropriate. (See Info node `(emacs)Lists and Sexps'.) If imbalance
334is found, an error is signalled and point is left at the first
335unbalanced character."
336 (interactive)
337 (condition-case data
338 ;; Buffer can't have more than (point-max) sexps.
339 (scan-sexps (point-min) (point-max))
340 (scan-error (goto-char (nth 2 data))
341 ;; Could print (nth 1 data), which is either
342 ;; "Containing expression ends prematurely" or
343 ;; "Unbalanced parentheses", but those may not be so
344 ;; accurate/helpful, e.g. quotes may actually be
345 ;; mismatched.
346 (error "Unmatched bracket or quote"))
347 (error (cond ((eq 'scan-error (car data))
348 (goto-char (nth 2 data))
349 (error "Unmatched bracket or quote"))
350 (t (signal (car data) (cdr data)))))))
b73b9811 351\f
e50c4203 352(defun lisp-complete-symbol (&optional predicate)
2eb9adab
RS
353 "Perform completion on Lisp symbol preceding point.
354Compare that symbol against the known Lisp symbols.
1fa1cb1b
RS
355If no characters can be completed, display a list of possible completions.
356Repeating the command at that point scrolls the list.
2eb9adab 357
e50c4203
DL
358When called from a program, optional arg PREDICATE is a predicate
359determining which symbols are considered, e.g. `commandp'.
360If PREDICATE is nil, the context determines which symbols are
361considered. If the symbol starts just after an open-parenthesis, only
362symbols with function definitions are considered. Otherwise, all
363symbols with function definitions, values or properties are
364considered."
b73b9811 365 (interactive)
1fa1cb1b
RS
366
367 (let ((window (get-buffer-window "*Completions*")))
368 (if (and (eq last-command this-command)
369 window (window-live-p window) (window-buffer window)
370 (buffer-name (window-buffer window)))
371 ;; If this command was repeated, and
372 ;; there's a fresh completion window with a live buffer,
373 ;; and this command is repeated, scroll that window.
374 (with-current-buffer (window-buffer window)
375 (if (pos-visible-in-window-p (point-max) window)
376 (set-window-start window (point-min))
377 (save-selected-window
378 (select-window window)
379 (scroll-up))))
380
381 ;; Do completion.
382 (let* ((end (point))
383 (beg (with-syntax-table emacs-lisp-mode-syntax-table
384 (save-excursion
385 (backward-sexp 1)
386 (while (= (char-syntax (following-char)) ?\')
387 (forward-char 1))
388 (point))))
389 (pattern (buffer-substring-no-properties beg end))
390 (predicate
391 (or predicate
392 (save-excursion
393 (goto-char beg)
394 (if (not (eq (char-before) ?\())
395 (lambda (sym) ;why not just nil ? -sm
396 (or (boundp sym) (fboundp sym)
397 (symbol-plist sym)))
398 ;; Looks like a funcall position. Let's double check.
399 (if (condition-case nil
400 (progn (up-list -2) (forward-char 1)
401 (eq (char-after) ?\())
402 (error nil))
403 ;; If the first element of the parent list is an open
404 ;; parenthesis we are probably not in a funcall position.
405 ;; Maybe a `let' varlist or something.
406 nil
407 ;; Else, we assume that a function name is expected.
408 'fboundp)))))
409 (completion (try-completion pattern obarray predicate)))
410 (cond ((eq completion t))
411 ((null completion)
412 (message "Can't find completion for \"%s\"" pattern)
413 (ding))
414 ((not (string= pattern completion))
415 (delete-region beg end)
416 (insert completion))
417 (t
418 (message "Making completion list...")
419 (let ((list (all-completions pattern obarray predicate)))
420 (setq list (sort list 'string<))
421 (or (eq predicate 'fboundp)
422 (let (new)
423 (while list
424 (setq new (cons (if (fboundp (intern (car list)))
425 (list (car list) " <f>")
426 (car list))
427 new))
428 (setq list (cdr list)))
429 (setq list (nreverse new))))
430 (with-output-to-temp-buffer "*Completions*"
431 (display-completion-list list)))
432 (message "Making completion list...%s" "done")))))))
6594deb0
ER
433
434;;; lisp.el ends here