]> code.delx.au - gnu-emacs/blobdiff - lisp/indent.el
(TEMACS_LDFLAGS): Add trailing comment.
[gnu-emacs] / lisp / indent.el
index 6c2f1462de9b9d9f852c8bf0802c07a2f0b78f95..cdf5ac49b9ec3a5cf00047db307b6644338e3274 100644 (file)
@@ -1,6 +1,6 @@
 ;;; indent.el --- indentation commands for Emacs
 
 ;;; indent.el --- indentation commands for Emacs
 
-;; Copyright (C) 1985, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1995, 2001 Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 
 
 ;; Maintainer: FSF
 
 
 ;;; Code:
 
 
 ;;; Code:
 
-(defvar standard-indent 4 "\
-Default number of columns for margin-changing functions to indent.")
-
-(defvar indent-line-function 'indent-to-left-margin "\
-Function to indent current line.")
+(defgroup indent nil
+  "Indentation commands"
+  :group 'editing)
+
+(defcustom standard-indent 4
+  "*Default number of columns for margin-changing functions to indent."
+  :group 'indent
+  :type 'integer)
+
+(defvar indent-line-function 'indent-relative
+  "Function to indent the current line.
+This function will be called with no arguments.
+If it is called somewhere where auto-indentation cannot be done
+\(f.ex. inside a string), the function should simply return `noindent'.
+Setting this function is all you need to make TAB indent appropriately.
+Don't rebind TAB unless you really need to.")
+
+(defcustom tab-always-indent t
+  "*Controls the operation of the TAB key.
+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 insert a `real' tab character."
+  :group 'indent
+  :type '(choice (const nil) (const t) (const always)))
 
 (defun indent-according-to-mode ()
   "Indent line in proper way for current major mode."
   (interactive)
 
 (defun indent-according-to-mode ()
   "Indent line in proper way for current major mode."
   (interactive)
-  (funcall indent-line-function))
-
-(defun indent-for-tab-command (&optional prefix-arg)
-  "Indent line in proper way for current major mode."
+  (if (memq indent-line-function
+           '(indent-relative indent-relative-maybe))
+      ;; These functions are used for tabbing, but can't be used for
+      ;; indenting.  Replace with something ad-hoc.
+      (let ((column (save-excursion
+                     (beginning-of-line)
+                     (skip-chars-backward "\n \t")
+                     (beginning-of-line)
+                     (current-indentation))))
+       (if (<= (current-column) (current-indentation))
+           (indent-line-to column)
+         (save-excursion (indent-line-to column))))
+    ;; The normal case.
+    (funcall indent-line-function)))
+
+(defun indent-for-tab-command (&optional arg)
+  "Indent line 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.
+The function actually called to indent is determined by the value of
+`indent-line-function'."
   (interactive "P")
   (interactive "P")
-  (if (eq indent-line-function 'indent-to-left-margin)
-      (insert-tab prefix-arg)
-    (if prefix-arg
-       (funcall indent-line-function prefix-arg)
-      (funcall indent-line-function))))
-
-(defun insert-tab (&optional prefix-arg)
-  (let ((count (prefix-numeric-value prefix-arg)))
-    (if abbrev-mode
+  (cond
+   ((or ;; indent-to-left-margin is only meant for indenting,
+       ;; so we force it to always insert a tab here.
+       (eq indent-line-function 'indent-to-left-margin)
+       (and (not tab-always-indent)
+            (> (current-column) (current-indentation))))
+    (insert-tab arg))
+   ;; Those functions are meant specifically for tabbing and not for
+   ;; indenting, so we can't pass them to indent-according-to-mode.
+   ((memq indent-line-function '(indent-relative indent-relative-maybe))
+    (funcall indent-line-function))
+   (t ;; The normal case.
+    (indent-according-to-mode))))
+
+(defun insert-tab (&optional arg)
+  (let ((count (prefix-numeric-value arg)))
+    (if (and abbrev-mode
+            (eq (char-syntax (preceding-char)) ?w))
        (expand-abbrev))
     (if indent-tabs-mode
        (expand-abbrev))
     (if indent-tabs-mode
-       (insert ?\t count)
+       (insert-char ?\t count)
       (indent-to (* tab-width (+ count (/ (current-column) tab-width)))))))
 
 (defun indent-rigidly (start end arg)
   "Indent all lines starting in the region sideways by ARG columns.
       (indent-to (* tab-width (+ count (/ (current-column) tab-width)))))))
 
 (defun indent-rigidly (start end arg)
   "Indent all lines starting in the region sideways by ARG columns.
-Called from a program, takes three arguments, START, END and ARG."
+Called from a program, takes three arguments, START, END and ARG.
+You can remove all indentation from a region by giving a large negative ARG."
   (interactive "r\np")
   (save-excursion
     (goto-char end)
   (interactive "r\np")
   (save-excursion
     (goto-char end)
@@ -84,7 +131,7 @@ only if necessary.  It leaves point at end of indentation."
   (back-to-indentation)
   (let ((cur-col (current-column)))
     (cond ((< cur-col column)
   (back-to-indentation)
   (let ((cur-col (current-column)))
     (cond ((< cur-col column)
-          (if (> (- column (* (/ cur-col tab-width) tab-width)) tab-width)
+          (if (>= (- column (* (/ cur-col tab-width) tab-width)) tab-width)
               (delete-region (point)
                              (progn (skip-chars-backward " ") (point))))
           (indent-to column))
               (delete-region (point)
                              (progn (skip-chars-backward " ") (point))))
           (indent-to column))
@@ -276,13 +323,16 @@ line, but does not move past any whitespace that was explicitly inserted
   "Short cut function to indent region using `indent-according-to-mode'.
 A value of nil means really run `indent-according-to-mode' on each line.")
 
   "Short cut function to indent region using `indent-according-to-mode'.
 A value of nil means really run `indent-according-to-mode' on each line.")
 
-(defun indent-region (start end column)
+(defun indent-region (start end &optional column)
   "Indent each nonblank line in the region.
   "Indent each nonblank line in the region.
-With no argument, indent each line using `indent-according-to-mode',
+With no prefix argument, indent each line using `indent-according-to-mode',
 or use `indent-region-function' to do the whole region if that's non-nil.
 If there is a fill prefix, make each line start with the fill prefix.
 With argument COLUMN, indent each line to that column.
 or use `indent-region-function' to do the whole region if that's non-nil.
 If there is a fill prefix, make each line start with the fill prefix.
 With argument COLUMN, indent each line to that column.
-Called from a program, takes three args: START, END and COLUMN."
+
+When you call this from a program, START and END specify
+the region to indent, and COLUMN specifies the indentation column.
+If COLUMN is nil, then indent each line according to the mode."
   (interactive "r\nP")
   (if (null column)
       (if fill-prefix
   (interactive "r\nP")
   (if (null column)
       (if fill-prefix
@@ -299,10 +349,8 @@ Called from a program, takes three args: START, END and COLUMN."
        (if indent-region-function
            (funcall indent-region-function start end)
          (save-excursion
        (if indent-region-function
            (funcall indent-region-function start end)
          (save-excursion
-           (goto-char end)
-           (setq end (point-marker))
+           (setq end (copy-marker end))
            (goto-char start)
            (goto-char start)
-           (or (bolp) (forward-line 1))
            (while (< (point) end)
              (or (and (bolp) (eolp))
                  (funcall indent-line-function))
            (while (< (point) end)
              (or (and (bolp) (eolp))
                  (funcall indent-line-function))
@@ -322,17 +370,29 @@ Called from a program, takes three args: START, END and COLUMN."
       (move-marker end nil))))
 
 (defun indent-relative-maybe ()
       (move-marker end nil))))
 
 (defun indent-relative-maybe ()
-  "Indent a new line like previous nonblank line."
+  "Indent a new line like previous nonblank line.
+If the previous nonblank line has no indent points beyond the
+column point starts at, this command does nothing.
+
+See also `indent-relative'."
   (interactive)
   (indent-relative t))
 
 (defun indent-relative (&optional unindented-ok)
   "Space out to under next indent point in previous nonblank line.
 An indent point is a non-whitespace character following whitespace.
   (interactive)
   (indent-relative t))
 
 (defun indent-relative (&optional unindented-ok)
   "Space out to under next indent point in previous nonblank line.
 An indent point is a non-whitespace character following whitespace.
+The following line shows the indentation points in this line.
+    ^         ^    ^     ^   ^           ^      ^  ^    ^
 If the previous nonblank line has no indent points beyond the
 If the previous nonblank line has no indent points beyond the
-column point starts at, `tab-to-tab-stop' is done instead."
+column point starts at, `tab-to-tab-stop' is done instead, unless
+this command is invoked with a numeric argument, in which case it
+does nothing.
+
+See also `indent-relative-maybe'."
   (interactive "P")
   (interactive "P")
-  (if abbrev-mode (expand-abbrev))
+  (if (and abbrev-mode
+          (eq (char-syntax (preceding-char)) ?w))
+      (expand-abbrev))
   (let ((start-column (current-column))
        indent)
     (save-excursion
   (let ((start-column (current-column))
        indent)
     (save-excursion
@@ -350,24 +410,25 @@ column point starts at, `tab-to-tab-stop' is done instead."
            (or (= (point) end) (setq indent (current-column))))))
     (if indent
        (let ((opoint (point-marker)))
            (or (= (point) end) (setq indent (current-column))))))
     (if indent
        (let ((opoint (point-marker)))
-         (delete-region (point) (progn (skip-chars-backward " \t") (point)))
          (indent-to indent 0)
          (if (> opoint (point))
              (goto-char opoint))
          (move-marker opoint nil))
       (tab-to-tab-stop))))
 
          (indent-to indent 0)
          (if (> opoint (point))
              (goto-char opoint))
          (move-marker opoint nil))
       (tab-to-tab-stop))))
 
-(defvar tab-stop-list
+(defcustom tab-stop-list
   '(8 16 24 32 40 48 56 64 72 80 88 96 104 112 120)
   '(8 16 24 32 40 48 56 64 72 80 88 96 104 112 120)
-  "*List of tab stop positions used by `tab-to-tab-stops'.
-This should be a list of integers, ordered from smallest to largest.")
-
-(defvar edit-tab-stops-map nil "Keymap used in `edit-tab-stops'.")
-(if edit-tab-stops-map
-    nil
-  (setq edit-tab-stops-map (make-sparse-keymap))
-  (define-key edit-tab-stops-map "\C-x\C-s" 'edit-tab-stops-note-changes)
-  (define-key edit-tab-stops-map "\C-c\C-c" 'edit-tab-stops-note-changes))
+  "*List of tab stop positions used by `tab-to-tab-stop'.
+This should be a list of integers, ordered from smallest to largest."
+  :group 'indent
+  :type '(repeat integer))
+
+(defvar edit-tab-stops-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-x\C-s" 'edit-tab-stops-note-changes)
+    (define-key map "\C-c\C-c" 'edit-tab-stops-note-changes)
+    map)
+  "Keymap used in `edit-tab-stops'.")
 
 (defvar edit-tab-stops-buffer nil
   "Buffer whose tab stops are being edited--in case
 
 (defvar edit-tab-stops-buffer nil
   "Buffer whose tab stops are being edited--in case
@@ -431,8 +492,7 @@ Use \\[edit-tab-stops] to edit them interactively."
       (setq tabs (cdr tabs)))
     (if tabs
        (let ((opoint (point)))
       (setq tabs (cdr tabs)))
     (if tabs
        (let ((opoint (point)))
-         (skip-chars-backward " \t")
-         (delete-region (point) opoint)
+         (delete-horizontal-space t)
          (indent-to (car tabs)))
       (insert ?\ ))))
 
          (indent-to (car tabs)))
       (insert ?\ ))))
 
@@ -460,7 +520,7 @@ Use \\[edit-tab-stops] to edit them interactively."
                  (delete-region (point) before))))))))
 
 (define-key global-map "\t" 'indent-for-tab-command)
                  (delete-region (point) before))))))))
 
 (define-key global-map "\t" 'indent-for-tab-command)
-(define-key esc-map "\034" 'indent-region)
+(define-key esc-map "\C-\\" 'indent-region)
 (define-key ctl-x-map "\t" 'indent-rigidly)
 (define-key esc-map "i" 'tab-to-tab-stop)
 
 (define-key ctl-x-map "\t" 'indent-rigidly)
 (define-key esc-map "i" 'tab-to-tab-stop)