]> code.delx.au - gnu-emacs/blobdiff - lisp/indent.el
Do not prompt twice to save a buffer
[gnu-emacs] / lisp / indent.el
index e733ece66d5b62670e7e8c2642e50676147f4a99..0bbb5209e8aaa6b45e992150c637c9a50928e7fd 100644 (file)
@@ -1,8 +1,8 @@
 ;;; indent.el --- indentation commands for Emacs  -*- lexical-binding:t -*-
 
-;; Copyright (C) 1985, 1995, 2001-2013 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1995, 2001-2016 Free Software Foundation, Inc.
 
-;; Maintainer: FSF
+;; Maintainer: emacs-devel@gnu.org
 ;; Package: emacs
 
 ;; This file is part of GNU Emacs.
@@ -76,15 +76,32 @@ that case, indent by aligning to the previous non-blank line."
       ;; indenting.  Replace with something ad-hoc.
       (let ((column (save-excursion
                      (beginning-of-line)
-                     (skip-chars-backward "\n \t")
-                     (beginning-of-line)
-                     (current-indentation))))
+                     (if (bobp) 0
+                        (beginning-of-line 0)
+                        (if (looking-at "[ \t]*$") 0
+                          (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--default-inside-comment ()
+  (unless (or (> (current-column) (current-indentation))
+              (eq this-command last-command))
+    (let ((ppss (syntax-ppss)))
+      (when (nth 4 ppss)
+        (indent-line-to
+         (save-excursion
+           (forward-line -1)
+           (skip-chars-forward " \t")
+           (when (< (1- (point)) (nth 8 ppss) (line-end-position))
+             (goto-char (nth 8 ppss))
+             (when (looking-at comment-start-skip)
+               (goto-char (match-end 0))))
+           (current-column)))
+        t))))
+
 (defun indent-for-tab-command (&optional arg)
   "Indent the current line or region, or insert a tab, as appropriate.
 This function either inserts a tab, or indents the current line,
@@ -123,7 +140,11 @@ prefix argument is ignored."
          (old-indent (current-indentation)))
 
       ;; Indent the line.
-      (funcall indent-line-function)
+      (or (not (eq (funcall indent-line-function) 'noindent))
+          (indent--default-inside-comment)
+          (when (or (<= (current-column) (current-indentation))
+                    (not (eq tab-always-indent 'complete)))
+            (funcall (default-value 'indent-line-function))))
 
       (cond
        ;; If the text was already indented right, try completion.
@@ -169,37 +190,35 @@ Blank lines are ignored."
 
 (defvar indent-rigidly-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [left]
-      (lambda (beg end) (interactive "r") (indent-rigidly beg end -1)))
-
-    (define-key map [right]
-      (lambda (beg end) (interactive "r") (indent-rigidly beg end 1)))
-
-    (define-key map [S-right]
-      (lambda (beg end) (interactive "r")
-        (let* ((current (indent-rigidly--current-indentation beg end))
-               (next (indent--next-tab-stop current)))
-          (indent-rigidly beg end (- next current)))))
-
-    (define-key map [S-left]
-      (lambda (beg end) (interactive "r")
-        (let* ((current (indent-rigidly--current-indentation beg end))
-               (next (indent--next-tab-stop current 'prev)))
-          (indent-rigidly beg end (- next current)))))
-    map))
+    (define-key map [left]  'indent-rigidly-left)
+    (define-key map [right] 'indent-rigidly-right)
+    (define-key map [S-left]  'indent-rigidly-left-to-tab-stop)
+    (define-key map [S-right] 'indent-rigidly-right-to-tab-stop)
+    map)
+  "Transient keymap for adjusting indentation interactively.
+It is activated by calling `indent-rigidly' interactively.")
 
 (defun indent-rigidly (start end arg &optional interactive)
-  "Indent all lines starting in the region sideways by ARG columns.
-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.
-If used interactively and no prefix argument is given, use a transient
-mode that lets you move the text with cursor keys."
+  "Indent all lines starting in the region.
+If called interactively with no prefix argument, activate a
+transient mode in which the indentation can be adjusted interactively
+by typing \\<indent-rigidly-map>\\[indent-rigidly-left], \\[indent-rigidly-right], \\[indent-rigidly-left-to-tab-stop], or \\[indent-rigidly-right-to-tab-stop].
+Typing any other key deactivates the transient mode.
+
+If called from a program, or interactively with prefix ARG,
+indent all lines starting in the region forward by ARG columns.
+If called from a program, START and END specify the beginning and
+end of the text to act on, in place of the region.
+
+Negative values of ARG indent backward, so you can remove all
+indentation by specifying a large negative ARG."
   (interactive "r\nP\np")
   (if (and (not arg) interactive)
       (progn
-        (message "Edit region indentation with <left>, <right>, <S-left> \
-and <S-right>.")
-        (set-temporary-overlay-map indent-rigidly-map t))
+        (message
+        (substitute-command-keys
+         "Indent region with \\<indent-rigidly-map>\\[indent-rigidly-left], \\[indent-rigidly-right], \\[indent-rigidly-left-to-tab-stop], or \\[indent-rigidly-right-to-tab-stop]."))
+        (set-transient-map indent-rigidly-map t))
     (save-excursion
       (goto-char end)
       (setq end (point-marker))
@@ -215,13 +234,58 @@ and <S-right>.")
               (indent-to (max 0 (+ indent (prefix-numeric-value arg))) 0))
           (delete-region (point) (progn (skip-chars-forward " \t") (point))))
         (forward-line 1))
-      (move-marker end nil))))
+      (move-marker end nil)
+      ;; Keep the active region in transient mode.
+      (when (eq (cadr overriding-terminal-local-map) indent-rigidly-map)
+       (setq deactivate-mark nil)))))
+
+(defun indent-rigidly--pop-undo ()
+  (and (memq last-command '(indent-rigidly-left indent-rigidly-right
+                           indent-rigidly-left-to-tab-stop
+                           indent-rigidly-right-to-tab-stop))
+       (consp buffer-undo-list)
+       (eq (car buffer-undo-list) nil)
+       (pop buffer-undo-list)))
+
+(defun indent-rigidly-left (beg end)
+  "Indent all lines between BEG and END leftward by one space."
+  (interactive "r")
+  (indent-rigidly--pop-undo)
+  (indent-rigidly
+   beg end
+   (if (eq (current-bidi-paragraph-direction) 'right-to-left) 1 -1)))
+
+(defun indent-rigidly-right (beg end)
+  "Indent all lines between BEG and END rightward by one space."
+  (interactive "r")
+  (indent-rigidly--pop-undo)
+  (indent-rigidly
+   beg end
+   (if (eq (current-bidi-paragraph-direction) 'right-to-left) -1 1)))
+
+(defun indent-rigidly-left-to-tab-stop (beg end)
+  "Indent all lines between BEG and END leftward to a tab stop."
+  (interactive "r")
+  (indent-rigidly--pop-undo)
+  (let* ((current (indent-rigidly--current-indentation beg end))
+        (rtl (eq (current-bidi-paragraph-direction) 'right-to-left))
+        (next (indent-next-tab-stop current (if rtl nil 'prev))))
+    (indent-rigidly beg end (- next current))))
+
+(defun indent-rigidly-right-to-tab-stop (beg end)
+  "Indent all lines between BEG and END rightward to a tab stop."
+  (interactive "r")
+  (indent-rigidly--pop-undo)
+  (let* ((current (indent-rigidly--current-indentation beg end))
+        (rtl (eq (current-bidi-paragraph-direction) 'right-to-left))
+        (next (indent-next-tab-stop current (if rtl 'prev))))
+    (indent-rigidly beg end (- next current))))
 
 (defun indent-line-to (column)
   "Indent current line to COLUMN.
 This function removes or adds spaces and tabs at beginning of line
 only if necessary.  It leaves point at end of indentation."
-  (back-to-indentation)
+  (backward-to-indentation 0)
   (let ((cur-col (current-column)))
     (cond ((< cur-col column)
           (if (>= (- column (* (/ cur-col tab-width) tab-width)) tab-width)
@@ -230,7 +294,7 @@ only if necessary.  It leaves point at end of indentation."
           (indent-to column))
          ((> cur-col column) ; too far right (after tab?)
           (delete-region (progn (move-to-column column t) (point))
-                         (progn (back-to-indentation) (point)))))))
+                         (progn (backward-to-indentation 0) (point)))))))
 
 (defun current-left-margin ()
   "Return the left margin to use for this line.
@@ -481,18 +545,19 @@ column to indent to; if it is nil, use one of the three methods above."
     (save-excursion
       (setq end (copy-marker end))
       (goto-char start)
-      (let ((pr (make-progress-reporter "Indenting region..." (point) end)))
-      (while (< (point) end)
-       (or (and (bolp) (eolp))
-           (indent-according-to-mode))
+      (let ((pr (unless (minibufferp)
+                 (make-progress-reporter "Indenting region..." (point) end))))
+       (while (< (point) end)
+         (or (and (bolp) (eolp))
+             (indent-according-to-mode))
           (forward-line 1)
-          (progress-reporter-update pr (point)))
-        (progress-reporter-done pr)
+          (and pr (progress-reporter-update pr (point))))
+       (and pr (progress-reporter-done pr))
         (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))
+  (setq deactivate-mark t))
 
 (defun indent-relative-maybe ()
   "Indent a new line like previous nonblank line.
@@ -541,16 +606,17 @@ See also `indent-relative-maybe'."
          (move-marker opoint nil))
       (tab-to-tab-stop))))
 
-(defcustom tab-stop-list
-  nil
+(defcustom tab-stop-list nil
   "List of tab stop positions used by `tab-to-tab-stop'.
-This should be a list of integers, ordered from smallest to largest.
-It implicitly extends to infinity by repeating the last step (e.g. '(1 2 5)
-is equivalent to '(1 2 5 8 11)).
-If the list has less than 2 elements, `tab-width' is used as the \"last step\"."
+This should be nil, or a list of integers, ordered from smallest to largest.
+It implicitly extends to infinity through repetition of the last step.
+For example, (1 2 5) is equivalent to (1 2 5 8 11 ...).  If the list has
+fewer than 2 elements, `tab-width' is used as the \"last step\".
+A value of nil means a tab stop every `tab-width' columns."
   :group 'indent
+  :version "24.4"                       ; from explicit list to nil
+  :safe 'listp
   :type '(repeat integer))
-(put 'tab-stop-list 'safe-local-variable 'listp)
 
 (defvar edit-tab-stops-map
   (let ((map (make-sparse-keymap)))
@@ -608,7 +674,7 @@ You can add or remove colons and then do \\<edit-tab-stops-map>\\[edit-tab-stops
       (setq tab-stop-list tabs))
   (message "Tab stops installed"))
 
-(defun indent--next-tab-stop (column &optional prev)
+(defun indent-next-tab-stop (column &optional prev)
   "Return the next tab stop after COLUMN.
 If PREV is non-nil, return the previous one instead."
   (let ((tabs tab-stop-list))
@@ -631,6 +697,13 @@ If PREV is non-nil, return the previous one instead."
                             (if (<= column last) -1 (/ (- column last 1) step))
                           (1+ (/ (- column last) step)))))))))
 
+(defun indent-accumulate-tab-stops (limit)
+  "Get a list of tab stops before LIMIT (inclusive)."
+  (let ((tab 0) (tab-stops))
+    (while (<= (setq tab (indent-next-tab-stop tab)) limit)
+      (push tab tab-stops))
+    (nreverse tab-stops)))
+
 (defun tab-to-tab-stop ()
   "Insert spaces or tabs to next defined tab-stop column.
 The variable `tab-stop-list' is a list of columns at which there are tab stops.
@@ -638,7 +711,7 @@ Use \\[edit-tab-stops] to edit them interactively."
   (interactive)
   (and abbrev-mode (= (char-syntax (preceding-char)) ?w)
        (expand-abbrev))
-  (let ((nexttab (indent--next-tab-stop (current-column))))
+  (let ((nexttab (indent-next-tab-stop (current-column))))
     (delete-horizontal-space t)
     (indent-to nexttab)))
 
@@ -647,7 +720,7 @@ Use \\[edit-tab-stops] to edit them interactively."
 The variable `tab-stop-list' is a list of columns at which there are tab stops.
 Use \\[edit-tab-stops] to edit them interactively."
   (interactive)
-  (let ((nexttab (indent--next-tab-stop (current-column))))
+  (let ((nexttab (indent-next-tab-stop (current-column))))
     (let ((before (point)))
       (move-to-column nexttab t)
       (save-excursion