]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/lisp.el
(reb-update-overlays): Distinguish between one and several matches in message.
[gnu-emacs] / lisp / emacs-lisp / lisp.el
index 52912146be9e1096c8815ce63f1e91c30ed94229..25fde86cd964cce143058182434a45bb67802f79 100644 (file)
@@ -1,6 +1,6 @@
 ;;; lisp.el --- Lisp editing commands for Emacs
 
-;; Copyright (C) 1985, 1986, 1994, 2000 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 86, 1994, 2000, 2004  Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: lisp, languages
@@ -33,7 +33,9 @@
 (defcustom defun-prompt-regexp nil
   "*If non-nil, a regexp to ignore before the character that starts a defun.
 This is only necessary if the opening paren or brace is not in column 0.
-See function `beginning-of-defun'."
+See function `beginning-of-defun'.
+
+Setting this variable automatically makes it local to the current buffer."
   :type '(choice (const nil)
                 regexp)
   :group 'lisp)
@@ -70,13 +72,22 @@ move forward across N balanced expressions."
 (defun mark-sexp (&optional arg)
   "Set mark ARG sexps from point.
 The place mark goes is the same place \\[forward-sexp] would
-move to with the same argument."
+move to with the same argument.
+If this command is repeated, it marks the next ARG sexps after the ones
+already marked."
   (interactive "p")
-  (push-mark
-    (save-excursion
-      (forward-sexp (or arg 1))
-      (point))
-    nil t))
+  (cond ((and (eq last-command this-command) (mark t))
+        (set-mark
+         (save-excursion
+          (goto-char (mark))
+          (forward-sexp (or arg 1))
+          (point))))
+       (t
+        (push-mark
+         (save-excursion
+           (forward-sexp (or arg 1))
+           (point))
+         nil t))))
 
 (defun forward-list (&optional arg)
   "Move forward across one balanced group of parentheses.
@@ -97,8 +108,7 @@ Negative arg -N means move forward across N groups of parentheses."
 (defun down-list (&optional arg)
   "Move forward down one level of parentheses.
 With ARG, do this that many times.
-A negative argument means move backward but still go down a level.
-In Lisp programs, an argument is required."
+A negative argument means move backward but still go down a level."
   (interactive "p")
   (or arg (setq arg 1))
   (let ((inc (if (> arg 0) 1 -1)))
@@ -109,16 +119,14 @@ In Lisp programs, an argument is required."
 (defun backward-up-list (&optional arg)
   "Move backward out of one level of parentheses.
 With ARG, do this that many times.
-A negative argument means move forward but still to a less deep spot.
-In Lisp programs, an argument is required."
+A negative argument means move forward but still to a less deep spot."
   (interactive "p")
   (up-list (- (or arg 1))))
 
 (defun up-list (&optional arg)
   "Move forward out of one level of parentheses.
 With ARG, do this that many times.
-A negative argument means move backward but still to a less deep spot.
-In Lisp programs, an argument is required."
+A negative argument means move backward but still to a less deep spot."
   (interactive "p")
   (or arg (setq arg 1))
   (let ((inc (if (> arg 0) 1 -1)))
@@ -149,8 +157,9 @@ normal recipe (see `beginning-of-defun').  Major modes can define this
 if defining `defun-prompt-regexp' is not sufficient to handle the mode's
 needs.
 
-The function should go to the line on which the current defun starts,
-and return non-nil, or should return nil if it can't find the beginning.")
+The function (of no args) should go to the line on which the current
+defun starts, and return non-nil, or should return nil if it can't
+find the beginning.")
 
 (defun beginning-of-defun (&optional arg)
   "Move backward to the beginning of a defun.
@@ -158,7 +167,7 @@ With ARG, do it that many times.  Negative arg -N
 means move forward to Nth following beginning of defun.
 Returns t unless search stops due to beginning or end of buffer.
 
-Normally a defun starts when there is an char with open-parenthesis
+Normally a defun starts when there is a char with open-parenthesis
 syntax at the beginning of a line.  If `defun-prompt-regexp' is
 non-nil, then a string which matches that regexp may precede the
 open-parenthesis, and point ends up at the beginning of the line.
@@ -166,6 +175,8 @@ open-parenthesis, and point ends up at the beginning of the line.
 If variable `beginning-of-defun-function' is non-nil, its value
 is called as a function to find the defun's beginning."
   (interactive "p")
+  (and (eq this-command 'beginning-of-defun)
+       (or (eq last-command 'beginning-of-defun) (push-mark)))
   (and (beginning-of-defun-raw arg)
        (progn (beginning-of-line) t)))
 
@@ -179,12 +190,17 @@ If variable `beginning-of-defun-function' is non-nil, its value
 is called as a function to find the defun's beginning."
   (interactive "p")
   (if beginning-of-defun-function
-      (funcall beginning-of-defun-function)
+      (if (> (setq arg (or arg 1)) 0)
+         (dotimes (i arg)
+           (funcall beginning-of-defun-function))
+       ;; Better not call end-of-defun-function directly, in case
+       ;; it's not defined.
+       (end-of-defun (- arg)))
     (and arg (< arg 0) (not (eobp)) (forward-char 1))
     (and (re-search-backward (if defun-prompt-regexp
                                 (concat (if open-paren-in-column-0-is-defun-start
                                             "^\\s(\\|" "")
-                                        "\\(" defun-prompt-regexp "\\)\\s(")
+                                        "\\(?:" defun-prompt-regexp "\\)\\s(")
                               "^\\s(")
                             nil 'move (or arg 1))
         (progn (goto-char (1- (match-end 0)))) t)))
@@ -209,12 +225,19 @@ matches the open-parenthesis that starts a defun; see function
 If variable `end-of-defun-function' is non-nil, its value
 is called as a function to find the defun's end."
   (interactive "p")
+  (and (eq this-command 'end-of-defun)
+       (or (eq last-command 'end-of-defun) (push-mark)))
+  (if (or (null arg) (= arg 0)) (setq arg 1))
   (if end-of-defun-function
-      (funcall end-of-defun-function)
-    (if (or (null arg) (= arg 0)) (setq arg 1))
+      (if (> arg 0)
+         (dotimes (i arg)
+           (funcall end-of-defun-function))
+       ;; Better not call beginning-of-defun-function
+       ;; directly, in case it's not defined.
+       (beginning-of-defun (- arg)))
     (let ((first t))
       (while (and (> arg 0) (< (point) (point-max)))
-       (let ((pos (point)) npos)
+       (let ((pos (point)))
          (while (progn
                   (if (and first
                            (progn
@@ -247,13 +270,42 @@ is called as a function to find the defun's end."
 
 (defun mark-defun ()
   "Put mark at end of this defun, point at beginning.
-The defun marked is the one that contains point or follows point."
+The defun marked is the one that contains point or follows point.
+If this command is repeated, marks more defuns after the ones
+already marked."
   (interactive)
-  (push-mark (point))
-  (end-of-defun)
-  (push-mark (point) nil t)
-  (beginning-of-defun)
-  (re-search-backward "^\n" (- (point) 1) t))
+  (cond ((and (eq last-command this-command) (mark t))
+        (set-mark
+         (save-excursion
+           (goto-char (mark))
+           (end-of-defun)
+           (point))))
+       (t
+        (let ((opoint (point))
+              beg end)
+          (push-mark opoint)
+          ;; Try first in this order for the sake of languages with nested
+          ;; functions where several can end at the same place as with
+          ;; the offside rule, e.g. Python.
+          (beginning-of-defun)
+          (setq beg (point))
+          (end-of-defun)
+          (setq end (point))
+          (while (looking-at "^\n")
+            (forward-line 1))
+          (if (> (point) opoint)
+              (progn
+                ;; We got the right defun.
+                (push-mark beg nil t)
+                (goto-char end)
+                (exchange-point-and-mark))
+            ;; beginning-of-defun moved back one defun
+            ;; so we got the wrong one.
+            (goto-char opoint)
+            (end-of-defun)
+            (push-mark (point) nil t)
+            (beginning-of-defun))
+          (re-search-backward "^\n" (- (point) 1) t)))))
 
 (defun narrow-to-defun (&optional arg)
   "Make text outside current defun invisible.
@@ -262,34 +314,112 @@ Optional ARG is ignored."
   (interactive)
   (save-excursion
     (widen)
-    (end-of-defun)
-    (let ((end (point)))
+    (let ((opoint (point))
+         beg end)
+      ;; Try first in this order for the sake of languages with nested
+      ;; functions where several can end at the same place as with
+      ;; the offside rule, e.g. Python.
       (beginning-of-defun)
-      (narrow-to-region (point) end))))
-
-(defun insert-parentheses (arg)
+      (setq beg (point))
+      (end-of-defun)
+      (setq end (point))
+      (while (looking-at "^\n")
+       (forward-line 1))
+      (unless (> (point) opoint)
+       ;; beginning-of-defun moved back one defun
+       ;; so we got the wrong one.
+       (goto-char opoint)
+       (end-of-defun)
+       (setq end (point))
+       (beginning-of-defun)
+       (setq beg (point)))
+      (goto-char end)
+      (re-search-backward "^\n" (- (point) 1) t)
+      (narrow-to-region beg end))))
+
+(defvar insert-pair-alist
+  '((?\( ?\)) (?\[ ?\]) (?\{ ?\}) (?\< ?\>) (?\" ?\") (?\' ?\') (?\` ?\'))
+  "Alist of paired characters inserted by `insert-pair'.
+Each element looks like (OPEN-CHAR CLOSE-CHAR) or (COMMAND-CHAR
+OPEN-CHAR CLOSE-CHAR).  The characters OPEN-CHAR and CLOSE-CHAR
+of the pair whose key is equal to the last input character with
+or without modifiers, are inserted by `insert-pair'.")
+
+(defun insert-pair (&optional arg open close)
+  "Enclose following ARG sexps in a pair of OPEN and CLOSE characters.
+Leave point after the first character.
+A negative ARG encloses the preceding ARG sexps instead.
+No argument is equivalent to zero: just insert characters
+and leave point between.
+If `parens-require-spaces' is non-nil, this command also inserts a space
+before and after, depending on the surrounding characters.
+If region is active, insert enclosing characters at region boundaries.
+
+If arguments OPEN and CLOSE are nil, the character pair is found
+from the variable `insert-pair-alist' according to the last input
+character with or without modifiers.  If no character pair is
+found in the variable `insert-pair-alist', then the last input
+character is inserted ARG times."
+  (interactive "P")
+  (if (not (and open close))
+      (let ((pair (or (assq last-command-char insert-pair-alist)
+                      (assq (event-basic-type last-command-event)
+                            insert-pair-alist))))
+        (if pair
+            (if (nth 2 pair)
+                (setq open (nth 1 pair) close (nth 2 pair))
+              (setq open (nth 0 pair) close (nth 1 pair))))))
+  (if (and open close)
+      (if (and transient-mark-mode mark-active)
+          (progn
+            (save-excursion (goto-char (region-end))       (insert close))
+            (save-excursion (goto-char (region-beginning)) (insert open)))
+        (if arg (setq arg (prefix-numeric-value arg))
+          (setq arg 0))
+        (cond ((> arg 0) (skip-chars-forward " \t"))
+              ((< arg 0) (forward-sexp arg) (setq arg (- arg))))
+        (and parens-require-spaces
+             (not (bobp))
+             (memq (char-syntax (preceding-char)) (list ?w ?_ (char-syntax close)))
+             (insert " "))
+        (insert open)
+        (save-excursion
+          (or (eq arg 0) (forward-sexp arg))
+          (insert close)
+          (and parens-require-spaces
+               (not (eobp))
+               (memq (char-syntax (following-char)) (list ?w ?_ (char-syntax open)))
+               (insert " "))))
+    (insert-char (event-basic-type last-command-event)
+                 (prefix-numeric-value arg))))
+
+(defun insert-parentheses (&optional arg)
   "Enclose following ARG sexps in parentheses.  Leave point after open-paren.
 A negative ARG encloses the preceding ARG sexps instead.
 No argument is equivalent to zero: just insert `()' and leave point between.
 If `parens-require-spaces' is non-nil, this command also inserts a space
-before and after, depending on the surrounding characters."
+before and after, depending on the surrounding characters.
+If region is active, insert enclosing characters at region boundaries."
   (interactive "P")
-  (if arg (setq arg (prefix-numeric-value arg))
-    (setq arg 0))
-  (cond ((> arg 0) (skip-chars-forward " \t"))
-       ((< arg 0) (forward-sexp arg) (setq arg (- arg))))
-  (and parens-require-spaces
-       (not (bobp))
-       (memq (char-syntax (preceding-char)) '(?w ?_ ?\) ))
-       (insert " "))
-  (insert ?\()
-  (save-excursion
-    (or (eq arg 0) (forward-sexp arg))
-    (insert ?\))
-    (and parens-require-spaces
-        (not (eobp))
-        (memq (char-syntax (following-char)) '(?w ?_ ?\( ))
-        (insert " "))))
+  (insert-pair arg ?\( ?\)))
+
+(defun delete-pair ()
+  "Delete a pair of characters enclosing the sexp that follows point."
+  (interactive)
+  (save-excursion (forward-sexp 1) (delete-char -1))
+  (delete-char 1))
+
+(defun raise-sexp (&optional arg)
+  "Raise ARG sexps higher up the tree."
+  (interactive "p")
+  (let ((s (if (and transient-mark-mode mark-active)
+               (buffer-substring (region-beginning) (region-end))
+             (buffer-substring
+              (point)
+              (save-excursion (forward-sexp arg) (point))))))
+    (backward-up-list 1)
+    (delete-region (point) (save-excursion (forward-sexp 1) (point)))
+    (save-excursion (insert s))))
 
 (defun move-past-close-and-reindent ()
   "Move past next `)', delete indentation before it, then indent after it."
@@ -349,6 +479,8 @@ unbalanced character."
 (defun lisp-complete-symbol (&optional predicate)
   "Perform completion on Lisp symbol preceding point.
 Compare that symbol against the known Lisp symbols.
+If no characters can be completed, display a list of possible completions.
+Repeating the command at that point scrolls the list.
 
 When called from a program, optional arg PREDICATE is a predicate
 determining which symbols are considered, e.g. `commandp'.
@@ -358,57 +490,73 @@ symbols with function definitions are considered.  Otherwise, all
 symbols with function definitions, values or properties are
 considered."
   (interactive)
-  (let* ((end (point))
-        (beg (with-syntax-table emacs-lisp-mode-syntax-table
-               (save-excursion
-                 (backward-sexp 1)
-                 (while (= (char-syntax (following-char)) ?\')
-                   (forward-char 1))
-                 (point))))
-        (pattern (buffer-substring-no-properties beg end))
-        (predicate
-         (or predicate
-             (save-excursion
-               (goto-char beg)
-               (if (not (eq (char-before) ?\())
-                   (lambda (sym)       ;why not just nil ?   -sm
-                     (or (boundp sym) (fboundp sym)
-                         (symbol-plist sym)))
-                 ;; Looks like a funcall position.  Let's double check.
-                 (backward-char 1)     ;skip paren
-                 (if (condition-case nil
-                         (progn (up-list -2) (forward-char 1)
-                                (eq (char-after) ?\())
-                       (error nil))
-                     ;; If the first element of the parent list is an open
-                     ;; parenthesis we are probably not in a funcall position.
-                     ;; Maybe a `let' varlist or something.
-                     nil
-                   ;; Else, we assume that a function name is expected.
-                   'fboundp)))))
-        (completion (try-completion pattern obarray predicate)))
-    (cond ((eq completion t))
-         ((null completion)
-          (message "Can't find completion for \"%s\"" pattern)
-          (ding))
-         ((not (string= pattern completion))
-          (delete-region beg end)
-          (insert completion))
-         (t
-          (message "Making completion list...")
-          (let ((list (all-completions pattern obarray predicate)))
-            (setq list (sort list 'string<))
-            (or (eq predicate 'fboundp)
-                (let (new)
-                  (while list
-                    (setq new (cons (if (fboundp (intern (car list)))
-                                        (list (car list) " <f>")
-                                      (car list))
-                                    new))
-                    (setq list (cdr list)))
-                  (setq list (nreverse new))))
-            (with-output-to-temp-buffer "*Completions*"
-              (display-completion-list list)))
-          (message "Making completion list...%s" "done")))))
 
+  (let ((window (get-buffer-window "*Completions*")))
+    (if (and (eq last-command this-command)
+            window (window-live-p window) (window-buffer window)
+            (buffer-name (window-buffer window)))
+       ;; If this command was repeated, and
+       ;; there's a fresh completion window with a live buffer,
+       ;; and this command is repeated, scroll that window.
+       (with-current-buffer (window-buffer window)
+         (if (pos-visible-in-window-p (point-max) window)
+             (set-window-start window (point-min))
+           (save-selected-window
+             (select-window window)
+             (scroll-up))))
+
+      ;; Do completion.
+      (let* ((end (point))
+            (beg (with-syntax-table emacs-lisp-mode-syntax-table
+                   (save-excursion
+                     (backward-sexp 1)
+                     (while (= (char-syntax (following-char)) ?\')
+                       (forward-char 1))
+                     (point))))
+            (pattern (buffer-substring-no-properties beg end))
+            (predicate
+             (or predicate
+                 (save-excursion
+                   (goto-char beg)
+                   (if (not (eq (char-before) ?\())
+                       (lambda (sym)   ;why not just nil ?   -sm
+                         (or (boundp sym) (fboundp sym)
+                             (symbol-plist sym)))
+                     ;; Looks like a funcall position.  Let's double check.
+                     (if (condition-case nil
+                             (progn (up-list -2) (forward-char 1)
+                                    (eq (char-after) ?\())
+                           (error nil))
+                         ;; If the first element of the parent list is an open
+                         ;; parenthesis we are probably not in a funcall position.
+                         ;; Maybe a `let' varlist or something.
+                         nil
+                       ;; Else, we assume that a function name is expected.
+                       'fboundp)))))
+            (completion (try-completion pattern obarray predicate)))
+       (cond ((eq completion t))
+             ((null completion)
+              (message "Can't find completion for \"%s\"" pattern)
+              (ding))
+             ((not (string= pattern completion))
+              (delete-region beg end)
+              (insert completion))
+             (t
+              (message "Making completion list...")
+              (let ((list (all-completions pattern obarray predicate)))
+                (setq list (sort list 'string<))
+                (or (eq predicate 'fboundp)
+                    (let (new)
+                      (while list
+                        (setq new (cons (if (fboundp (intern (car list)))
+                                            (list (car list) " <f>")
+                                          (car list))
+                                        new))
+                        (setq list (cdr list)))
+                      (setq list (nreverse new))))
+                (with-output-to-temp-buffer "*Completions*"
+                  (display-completion-list list)))
+              (message "Making completion list...%s" "done")))))))
+
+;;; arch-tag: aa7fa8a4-2e6f-4e9b-9cd9-fef06340e67e
 ;;; lisp.el ends here