]> code.delx.au - gnu-emacs/blobdiff - lisp/indent.el
* lisp/electric.el (electric-pair-pairs): New var.
[gnu-emacs] / lisp / indent.el
index fb4e2abd0f0927782ca88370114b93e702cb35b7..e57d6068ef568721353f305f02b2ec150055abce 100644 (file)
@@ -1,9 +1,10 @@
 ;;; indent.el --- indentation commands for Emacs
 
-;; Copyright (C) 1985, 1995, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1995, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+;;   2008, 2009, 2010  Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
+;; Package: emacs
 
 ;; This file is part of GNU Emacs.
 
@@ -49,10 +50,17 @@ Don't rebind TAB unless you really need to.")
 If t, hitting TAB always just indents the current line.
 If nil, hitting TAB indents the current line if point is at the left margin
 or in the line's indentation, otherwise it inserts a \"real\" TAB character.
+If `complete', TAB first tries to indent the current line, and if the line
+was already indented, then try to complete the thing at point.
+
 Some programming language modes have their own variable to control this,
 e.g., `c-tab-always-indent', and do not respect this variable."
   :group 'indent
-  :type '(choice (const nil) (const t) (const always)))
+  :type '(choice
+         (const :tag "Always indent" t)
+         (const :tag "Indent if inside indentation, else TAB" nil)
+         (const :tag "Indent, or if already indented complete" complete)))
+
 
 (defun indent-according-to-mode ()
   "Indent line in proper way for current major mode.
@@ -60,6 +68,7 @@ The buffer-local variable `indent-line-function' determines how to do this,
 but the functions `indent-relative' and `indent-relative-maybe' are
 special; we don't actually use them here."
   (interactive)
+  (syntax-propertize (line-end-position))
   (if (memq indent-line-function
            '(indent-relative indent-relative-maybe))
       ;; These functions are used for tabbing, but can't be used for
@@ -78,11 +87,13 @@ special; we don't actually use them here."
 (defun indent-for-tab-command (&optional arg)
   "Indent line or region in proper way for current major mode or insert a tab.
 Depending on `tab-always-indent', either insert a tab or indent.
-If initial point was within line's indentation, position after
-the indentation.  Else stay at same point in text.
+
+In most major modes, if point was in the current line's indentation,
+it is moved to the first non-whitespace character after indenting;
+otherwise it stays at the same position in the text.
 
 If a prefix argument is given, also rigidly indent the entire
-balanced expression which starts at the beginning the current
+balanced expression which starts at the beginning of the current
 line to reflect the current line's change in indentation.
 
 If `transient-mark-mode' is turned on and the region is active,
@@ -103,26 +114,32 @@ The function actually called to indent the line is determined by the value of
                 (eq this-command last-command))))
     (insert-tab arg))
    (t
-    (let ((end-marker
-          (and arg
-               (save-excursion
-                 (forward-line 0) (forward-sexp) (point-marker))))
-         (old-indent
-          (current-indentation)))
+    (let ((old-tick (buffer-chars-modified-tick))
+          (old-point (point))
+         (old-indent (current-indentation)))
 
       ;; Indent the line.
       (funcall indent-line-function)
 
-      ;; If a prefix argument was given, rigidly indent the following
-      ;; sexp to match the change in the current line's indentation.
-      ;;
-      (when arg
-       (let ((indentation-change (- (current-indentation) old-indent)))
-         (unless (zerop indentation-change)
-           (save-excursion
-             (forward-line 1)
-             (when (< (point) end-marker)
-               (indent-rigidly (point) end-marker indentation-change))))))))))
+      (cond
+       ;; If the text was already indented right, try completion.
+       ((and (eq tab-always-indent 'complete)
+             (eq old-point (point))
+             (eq old-tick (buffer-chars-modified-tick)))
+        (completion-at-point))
+
+       ;; If a prefix argument was given, rigidly indent the following
+       ;; sexp to match the change in the current line's indentation.
+       (arg
+        (let ((end-marker
+               (save-excursion
+                 (forward-line 0) (forward-sexp) (point-marker)))
+              (indentation-change (- (current-indentation) old-indent)))
+          (save-excursion
+            (forward-line 1)
+            (when (and (not (zerop indentation-change))
+                       (< (point) end-marker))
+              (indent-rigidly (point) end-marker indentation-change))))))))))
 
 (defun insert-tab (&optional arg)
   (let ((count (prefix-numeric-value arg)))
@@ -402,7 +419,7 @@ column to indent to; if it is nil, use one of the three methods above."
            (goto-char start)
            (while (< (point) end)
              (or (and (bolp) (eolp))
-                 (funcall indent-line-function))
+                 (indent-according-to-mode))
              (forward-line 1))
            (move-marker end nil))))
     (setq column (prefix-numeric-value column))
@@ -416,7 +433,11 @@ column to indent to; if it is nil, use one of the three methods above."
        (or (eolp)
            (indent-to column 0))
        (forward-line 1))
-      (move-marker end nil))))
+      (move-marker end nil)))
+  ;; In most cases, reindenting modifies the buffer, but it may also
+  ;; leave it unmodified, in which case we have to deactivate the mark
+  ;; by hand.
+  (deactivate-mark))
 
 (defun indent-relative-maybe ()
   "Indent a new line like previous nonblank line.