Update copyright notices for 2013.
[bpt/emacs.git] / lisp / indent.el
CommitLineData
1a06eabd
ER
1;;; indent.el --- indentation commands for Emacs
2
ab422c4d 3;; Copyright (C) 1985, 1995, 2001-2013 Free Software Foundation, Inc.
483e630e 4
9750e079 5;; Maintainer: FSF
bd78fa1d 6;; Package: emacs
9750e079 7
483e630e
RM
8;; This file is part of GNU Emacs.
9
eb3fa2cf 10;; GNU Emacs is free software: you can redistribute it and/or modify
483e630e 11;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
483e630e
RM
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
eb3fa2cf 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
483e630e 22
e41b2db1
ER
23;;; Commentary:
24
25;; Commands for making and changing indentation in text. These are
26;; described in the Emacs manual.
27
e5167999 28;;; Code:
483e630e 29
ddb3136e 30(defgroup indent nil
21751995 31 "Indentation commands."
ddb3136e 32 :group 'editing)
106b6d0e 33
ddb3136e 34(defcustom standard-indent 4
9201cc28 35 "Default number of columns for margin-changing functions to indent."
ddb3136e
RS
36 :group 'indent
37 :type 'integer)
38
f059f703 39(defvar indent-line-function 'indent-relative
a17b712b
SM
40 "Function to indent the current line.
41This function will be called with no arguments.
42If it is called somewhere where auto-indentation cannot be done
59b5f3a8 43\(e.g. inside a string), the function should simply return `noindent'.
a17b712b
SM
44Setting this function is all you need to make TAB indent appropriately.
45Don't rebind TAB unless you really need to.")
483e630e 46
20b1d079 47(defcustom tab-always-indent t
9201cc28 48 "Controls the operation of the TAB key.
20b1d079
SM
49If t, hitting TAB always just indents the current line.
50If nil, hitting TAB indents the current line if point is at the left margin
9450aaa0 51or in the line's indentation, otherwise it inserts a \"real\" TAB character.
51ef56c4
SM
52If `complete', TAB first tries to indent the current line, and if the line
53was already indented, then try to complete the thing at point.
54
9450aaa0 55Some programming language modes have their own variable to control this,
f321348b 56e.g., `c-tab-always-indent', and do not respect this variable."
20b1d079 57 :group 'indent
e073d74a
GM
58 :type '(choice
59 (const :tag "Always indent" t)
60 (const :tag "Indent if inside indentation, else TAB" nil)
61 (const :tag "Indent, or if already indented complete" complete)))
62
20b1d079 63
483e630e 64(defun indent-according-to-mode ()
1a2f8b73 65 "Indent line in proper way for current major mode.
e70b5064
CY
66Normally, this is done by calling the function specified by the
67variable `indent-line-function'. However, if the value of that
68variable is `indent-relative' or `indent-relative-maybe', handle
69it specially (since those functions are used for tabbing); in
70that case, indent by aligning to the previous non-blank line."
483e630e 71 (interactive)
f5632fb6 72 (syntax-propertize (line-end-position))
a17b712b
SM
73 (if (memq indent-line-function
74 '(indent-relative indent-relative-maybe))
75 ;; These functions are used for tabbing, but can't be used for
76 ;; indenting. Replace with something ad-hoc.
77 (let ((column (save-excursion
78 (beginning-of-line)
79 (skip-chars-backward "\n \t")
80 (beginning-of-line)
81 (current-indentation))))
82 (if (<= (current-column) (current-indentation))
83 (indent-line-to column)
84 (save-excursion (indent-line-to column))))
85 ;; The normal case.
86 (funcall indent-line-function)))
483e630e 87
a17b712b 88(defun indent-for-tab-command (&optional arg)
e70b5064
CY
89 "Indent the current line or region, or insert a tab, as appropriate.
90This function either inserts a tab, or indents the current line,
91or performs symbol completion, depending on `tab-always-indent'.
92The function called to actually indent the line or insert a tab
93is given by the variable `indent-line-function'.
94
95If a prefix argument is given, after this function indents the
96current line or inserts a tab, it also rigidly indents the entire
ae8ba409 97balanced expression which starts at the beginning of the current
e70b5064 98line, to reflect the current line's indentation.
1225a933 99
e70b5064
CY
100In most major modes, if point was in the current line's
101indentation, it is moved to the first non-whitespace character
102after indenting; otherwise it stays at the same position relative
103to the text.
1225a933 104
e70b5064
CY
105If `transient-mark-mode' is turned on and the region is active,
106this function instead calls `indent-region'. In this case, any
107prefix argument is ignored."
1225a933 108 (interactive "P")
a17b712b 109 (cond
17ee4625 110 ;; The region is active, indent it.
361a81d9 111 ((use-region-p)
17ee4625 112 (indent-region (region-beginning) (region-end)))
fe552b4c 113 ((or ;; indent-to-left-margin is only meant for indenting,
a17b712b
SM
114 ;; so we force it to always insert a tab here.
115 (eq indent-line-function 'indent-to-left-margin)
116 (and (not tab-always-indent)
f202a7a2
SM
117 (or (> (current-column) (current-indentation))
118 (eq this-command last-command))))
a17b712b 119 (insert-tab arg))
6dd697d9 120 (t
51ef56c4
SM
121 (let ((old-tick (buffer-chars-modified-tick))
122 (old-point (point))
123 (old-indent (current-indentation)))
1225a933
MB
124
125 ;; Indent the line.
126 (funcall indent-line-function)
127
51ef56c4
SM
128 (cond
129 ;; If the text was already indented right, try completion.
130 ((and (eq tab-always-indent 'complete)
131 (eq old-point (point))
132 (eq old-tick (buffer-chars-modified-tick)))
133 (completion-at-point))
134
135 ;; If a prefix argument was given, rigidly indent the following
136 ;; sexp to match the change in the current line's indentation.
137 (arg
138 (let ((end-marker
139 (save-excursion
140 (forward-line 0) (forward-sexp) (point-marker)))
141 (indentation-change (- (current-indentation) old-indent)))
142 (save-excursion
143 (forward-line 1)
144 (when (and (not (zerop indentation-change))
145 (< (point) end-marker))
146 (indent-rigidly (point) end-marker indentation-change))))))))))
a17b712b
SM
147
148(defun insert-tab (&optional arg)
149 (let ((count (prefix-numeric-value arg)))
5e9f80a8
RS
150 (if (and abbrev-mode
151 (eq (char-syntax (preceding-char)) ?w))
10992b01
RS
152 (expand-abbrev))
153 (if indent-tabs-mode
4424ce6f 154 (insert-char ?\t count)
10992b01 155 (indent-to (* tab-width (+ count (/ (current-column) tab-width)))))))
483e630e
RM
156
157(defun indent-rigidly (start end arg)
158 "Indent all lines starting in the region sideways by ARG columns.
5a0f9388
EZ
159Called from a program, takes three arguments, START, END and ARG.
160You can remove all indentation from a region by giving a large negative ARG."
483e630e
RM
161 (interactive "r\np")
162 (save-excursion
163 (goto-char end)
164 (setq end (point-marker))
165 (goto-char start)
166 (or (bolp) (forward-line 1))
167 (while (< (point) end)
c1194ae8
RS
168 (let ((indent (current-indentation))
169 eol-flag)
170 (save-excursion
171 (skip-chars-forward " \t")
172 (setq eol-flag (eolp)))
173 (or eol-flag
174 (indent-to (max 0 (+ indent arg)) 0))
175 (delete-region (point) (progn (skip-chars-forward " \t") (point))))
483e630e
RM
176 (forward-line 1))
177 (move-marker end nil)))
178
106b6d0e
RS
179(defun indent-line-to (column)
180 "Indent current line to COLUMN.
181This function removes or adds spaces and tabs at beginning of line
182only if necessary. It leaves point at end of indentation."
ca2a3cb7
BG
183 (back-to-indentation)
184 (let ((cur-col (current-column)))
185 (cond ((< cur-col column)
cd6d305e 186 (if (>= (- column (* (/ cur-col tab-width) tab-width)) tab-width)
a80a30b3
RS
187 (delete-region (point)
188 (progn (skip-chars-backward " ") (point))))
ca2a3cb7
BG
189 (indent-to column))
190 ((> cur-col column) ; too far right (after tab?)
34c3f2b8 191 (delete-region (progn (move-to-column column t) (point))
ca2a3cb7 192 (progn (back-to-indentation) (point)))))))
106b6d0e
RS
193
194(defun current-left-margin ()
195 "Return the left margin to use for this line.
196This is the value of the buffer-local variable `left-margin' plus the value
197of the `left-margin' text-property at the start of the line."
198 (save-excursion
199 (back-to-indentation)
200 (max 0
34c3f2b8
BG
201 (+ left-margin (or (get-text-property
202 (if (and (eobp) (not (bobp)))
203 (1- (point)) (point))
204 'left-margin) 0)))))
106b6d0e 205
34c3f2b8 206(defun move-to-left-margin (&optional n force)
106b6d0e
RS
207 "Move to the left margin of the current line.
208With optional argument, move forward N-1 lines first.
34c3f2b8
BG
209The column moved to is the one given by the `current-left-margin' function.
210If the line's indentation appears to be wrong, and this command is called
211interactively or with optional argument FORCE, it will be fixed."
212 (interactive (list (prefix-numeric-value current-prefix-arg) t))
106b6d0e 213 (beginning-of-line n)
54505d72 214 (skip-chars-forward " \t")
1d1c5af9
RS
215 (if (minibufferp (current-buffer))
216 (if (save-excursion (beginning-of-line) (bobp))
217 (goto-char (minibuffer-prompt-end))
218 (beginning-of-line))
219 (let ((lm (current-left-margin))
220 (cc (current-column)))
221 (cond ((> cc lm)
222 (if (> (move-to-column lm force) lm)
223 ;; If lm is in a tab and we are not forcing, move before tab
224 (backward-char 1)))
225 ((and force (< cc lm))
226 (indent-to-left-margin))))))
106b6d0e 227
f202a7a2 228;; This used to be the default indent-line-function,
483e630e
RM
229;; used in Fundamental Mode, Text Mode, etc.
230(defun indent-to-left-margin ()
34c3f2b8 231 "Indent current line to the column given by `current-left-margin'."
caadec43
RS
232 (save-excursion (indent-line-to (current-left-margin)))
233 ;; If we are within the indentation, move past it.
234 (when (save-excursion
235 (skip-chars-backward " \t")
236 (bolp))
237 (skip-chars-forward " \t")))
106b6d0e 238
34c3f2b8
BG
239(defun delete-to-left-margin (&optional from to)
240 "Remove left margin indentation from a region.
241This deletes to the column given by `current-left-margin'.
242In no case will it delete non-whitespace.
243Args FROM and TO are optional; default is the whole buffer."
106b6d0e 244 (save-excursion
34c3f2b8 245 (goto-char (or to (point-max)))
106b6d0e 246 (setq to (point-marker))
34c3f2b8 247 (goto-char (or from (point-min)))
106b6d0e
RS
248 (or (bolp) (forward-line 1))
249 (while (< (point) to)
34c3f2b8 250 (delete-region (point) (progn (move-to-left-margin nil t) (point)))
106b6d0e
RS
251 (forward-line 1))
252 (move-marker to nil)))
253
a5b3d1b8 254(defun set-left-margin (from to width)
106b6d0e 255 "Set the left margin of the region to WIDTH.
a5b3d1b8
LT
256If `auto-fill-mode' is active, re-fill the region to fit the new margin.
257
258Interactively, WIDTH is the prefix argument, if specified.
259Without prefix argument, the command prompts for WIDTH."
106b6d0e 260 (interactive "r\nNSet left margin to column: ")
106b6d0e
RS
261 (save-excursion
262 ;; If inside indentation, start from BOL.
263 (goto-char from)
264 (skip-chars-backward " \t")
265 (if (bolp) (setq from (point)))
34c3f2b8 266 ;; Place end after whitespace
106b6d0e 267 (goto-char to)
34c3f2b8 268 (skip-chars-forward " \t")
106b6d0e 269 (setq to (point-marker)))
34c3f2b8
BG
270 ;; Delete margin indentation first, but keep paragraph indentation.
271 (delete-to-left-margin from to)
a5b3d1b8
LT
272 (put-text-property from to 'left-margin width)
273 (indent-rigidly from to width)
34c3f2b8 274 (if auto-fill-function (save-excursion (fill-region from to nil t t)))
106b6d0e
RS
275 (move-marker to nil))
276
a5b3d1b8 277(defun set-right-margin (from to width)
106b6d0e 278 "Set the right margin of the region to WIDTH.
a5b3d1b8
LT
279If `auto-fill-mode' is active, re-fill the region to fit the new margin.
280
281Interactively, WIDTH is the prefix argument, if specified.
282Without prefix argument, the command prompts for WIDTH."
8cf19007 283 (interactive "r\nNSet right margin to width: ")
106b6d0e
RS
284 (save-excursion
285 (goto-char from)
286 (skip-chars-backward " \t")
287 (if (bolp) (setq from (point))))
a5b3d1b8 288 (put-text-property from to 'right-margin width)
34c3f2b8 289 (if auto-fill-function (save-excursion (fill-region from to nil t t))))
106b6d0e
RS
290
291(defun alter-text-property (from to prop func &optional object)
292 "Programmatically change value of a text-property.
293For each region between FROM and TO that has a single value for PROPERTY,
294apply FUNCTION to that value and sets the property to the function's result.
295Optional fifth argument OBJECT specifies the string or buffer to operate on."
296 (let ((begin from)
297 end val)
298 (while (setq val (get-text-property begin prop object)
299 end (text-property-not-all begin to prop val object))
300 (put-text-property begin end prop (funcall func val) object)
301 (setq begin end))
302 (if (< begin to)
303 (put-text-property begin to prop (funcall func val) object))))
304
305(defun increase-left-margin (from to inc)
306 "Increase or decrease the left-margin of the region.
307With no prefix argument, this adds `standard-indent' of indentation.
308A prefix arg (optional third arg INC noninteractively) specifies the amount
309to change the margin by, in characters.
310If `auto-fill-mode' is active, re-fill the region to fit the new margin."
311 (interactive "*r\nP")
312 (setq inc (if inc (prefix-numeric-value inc) standard-indent))
313 (save-excursion
314 (goto-char from)
315 (skip-chars-backward " \t")
316 (if (bolp) (setq from (point)))
317 (goto-char to)
318 (setq to (point-marker)))
106b6d0e 319 (alter-text-property from to 'left-margin
34c3f2b8
BG
320 (lambda (v) (max (- left-margin) (+ inc (or v 0)))))
321 (indent-rigidly from to inc)
322 (if auto-fill-function (save-excursion (fill-region from to nil t t)))
106b6d0e
RS
323 (move-marker to nil))
324
325(defun decrease-left-margin (from to inc)
326 "Make the left margin of the region smaller.
327With no prefix argument, decrease the indentation by `standard-indent'.
328A prefix arg (optional third arg INC noninteractively) specifies the amount
329to change the margin by, in characters.
330If `auto-fill-mode' is active, re-fill the region to fit the new margin."
331 (interactive "*r\nP")
332 (setq inc (if inc (prefix-numeric-value inc) standard-indent))
333 (increase-left-margin from to (- inc)))
334
335(defun increase-right-margin (from to inc)
336 "Increase the right-margin of the region.
337With no prefix argument, increase the right margin by `standard-indent'.
338A prefix arg (optional third arg INC noninteractively) specifies the amount
339to change the margin by, in characters. A negative argument decreases
340the right margin width.
341If `auto-fill-mode' is active, re-fill the region to fit the new margin."
342 (interactive "r\nP")
6faab05f 343 (setq inc (if inc (prefix-numeric-value inc) standard-indent))
106b6d0e
RS
344 (save-excursion
345 (alter-text-property from to 'right-margin
6faab05f 346 (lambda (v) (+ inc (or v 0))))
106b6d0e
RS
347 (if auto-fill-function
348 (fill-region from to nil t t))))
349
350(defun decrease-right-margin (from to inc)
351 "Make the right margin of the region smaller.
352With no prefix argument, decrease the right margin by `standard-indent'.
353A prefix arg (optional third arg INC noninteractively) specifies the amount
354of width to remove, in characters. A negative argument increases
355the right margin width.
356If `auto-fill-mode' is active, re-fills region to fit in new margin."
357 (interactive "*r\nP")
358 (setq inc (if inc (prefix-numeric-value inc) standard-indent))
359 (increase-right-margin from to (- inc)))
483e630e 360
34c3f2b8
BG
361(defun beginning-of-line-text (&optional n)
362 "Move to the beginning of the text on this line.
363With optional argument, move forward N-1 lines first.
364From the beginning of the line, moves past the left-margin indentation, the
365fill-prefix, and any indentation used for centering or right-justifying the
f1180544 366line, but does not move past any whitespace that was explicitly inserted
34c3f2b8
BG
367\(such as a tab used to indent the first line of a paragraph)."
368 (interactive "p")
369 (beginning-of-line n)
370 (skip-chars-forward " \t")
371 ;; Skip over fill-prefix.
f1180544 372 (if (and fill-prefix
34c3f2b8
BG
373 (not (string-equal fill-prefix "")))
374 (if (equal fill-prefix
f1180544 375 (buffer-substring
34c3f2b8
BG
376 (point) (min (point-max) (+ (length fill-prefix) (point)))))
377 (forward-char (length fill-prefix)))
7d43e2ad 378 (if (and adaptive-fill-mode adaptive-fill-regexp
34c3f2b8
BG
379 (looking-at adaptive-fill-regexp))
380 (goto-char (match-end 0))))
381 ;; Skip centering or flushright indentation
382 (if (memq (current-justification) '(center right))
383 (skip-chars-forward " \t")))
384
483e630e 385(defvar indent-region-function nil
3704e77e
RS
386 "Short cut function to indent region using `indent-according-to-mode'.
387A value of nil means really run `indent-according-to-mode' on each line.")
483e630e 388
1d9cc345 389(defun indent-region (start end &optional column)
483e630e 390 "Indent each nonblank line in the region.
1a2f8b73
RS
391A numeric prefix argument specifies a column: indent each line to that column.
392
393With no prefix argument, the command chooses one of these methods and
394indents all the lines with it:
395
396 1) If `fill-prefix' is non-nil, insert `fill-prefix' at the
397 beginning of each line in the region that does not already begin
398 with it.
399 2) If `indent-region-function' is non-nil, call that function
400 to indent the region.
e70b5064 401 3) Indent each line via `indent-according-to-mode'.
1a2f8b73
RS
402
403Called from a program, START and END specify the region to indent.
404If the third argument COLUMN is an integer, it specifies the
405column to indent to; if it is nil, use one of the three methods above."
483e630e 406 (interactive "r\nP")
e70b5064
CY
407 (cond
408 (column
88a2603a 409 (setq column (prefix-numeric-value column))
483e630e
RM
410 (save-excursion
411 (goto-char end)
412 (setq end (point-marker))
413 (goto-char start)
414 (or (bolp) (forward-line 1))
415 (while (< (point) end)
416 (delete-region (point) (progn (skip-chars-forward " \t") (point)))
417 (or (eolp)
106b6d0e 418 (indent-to column 0))
483e630e 419 (forward-line 1))
2a96c2a7 420 (move-marker end nil)))
e70b5064
CY
421 (fill-prefix
422 (save-excursion
423 (goto-char end)
424 (setq end (point-marker))
425 (goto-char start)
426 (let ((regexp (regexp-quote fill-prefix)))
427 (while (< (point) end)
428 (or (looking-at regexp)
429 (and (bolp) (eolp))
430 (insert fill-prefix))
431 (forward-line 1)))))
432 (indent-region-function
433 (funcall indent-region-function start end))
434 (t
435 (save-excursion
436 (setq end (copy-marker end))
437 (goto-char start)
438 (while (< (point) end)
439 (or (and (bolp) (eolp))
440 (indent-according-to-mode))
441 (forward-line 1))
442 (move-marker end nil))))
2a96c2a7
SM
443 ;; In most cases, reindenting modifies the buffer, but it may also
444 ;; leave it unmodified, in which case we have to deactivate the mark
445 ;; by hand.
446 (deactivate-mark))
483e630e
RM
447
448(defun indent-relative-maybe ()
1fd63d9b
EZ
449 "Indent a new line like previous nonblank line.
450If the previous nonblank line has no indent points beyond the
451column point starts at, this command does nothing.
452
453See also `indent-relative'."
483e630e
RM
454 (interactive)
455 (indent-relative t))
456
457(defun indent-relative (&optional unindented-ok)
458 "Space out to under next indent point in previous nonblank line.
459An indent point is a non-whitespace character following whitespace.
f6f53207
RS
460The following line shows the indentation points in this line.
461 ^ ^ ^ ^ ^ ^ ^ ^ ^
483e630e 462If the previous nonblank line has no indent points beyond the
1fd63d9b
EZ
463column point starts at, `tab-to-tab-stop' is done instead, unless
464this command is invoked with a numeric argument, in which case it
465does nothing.
466
467See also `indent-relative-maybe'."
483e630e 468 (interactive "P")
5e9f80a8
RS
469 (if (and abbrev-mode
470 (eq (char-syntax (preceding-char)) ?w))
471 (expand-abbrev))
483e630e
RM
472 (let ((start-column (current-column))
473 indent)
474 (save-excursion
475 (beginning-of-line)
476 (if (re-search-backward "^[^\n]" nil t)
477 (let ((end (save-excursion (forward-line 1) (point))))
478 (move-to-column start-column)
479 ;; Is start-column inside a tab on this line?
480 (if (> (current-column) start-column)
481 (backward-char 1))
482 (or (looking-at "[ \t]")
483 unindented-ok
484 (skip-chars-forward "^ \t" end))
485 (skip-chars-forward " \t" end)
486 (or (= (point) end) (setq indent (current-column))))))
487 (if indent
488 (let ((opoint (point-marker)))
483e630e
RM
489 (indent-to indent 0)
490 (if (> opoint (point))
491 (goto-char opoint))
492 (move-marker opoint nil))
493 (tab-to-tab-stop))))
494
ddb3136e 495(defcustom tab-stop-list
483e630e 496 '(8 16 24 32 40 48 56 64 72 80 88 96 104 112 120)
9201cc28 497 "List of tab stop positions used by `tab-to-tab-stop'.
ddb3136e
RS
498This should be a list of integers, ordered from smallest to largest."
499 :group 'indent
500 :type '(repeat integer))
44b275c4 501(put 'tab-stop-list 'safe-local-variable 'listp)
483e630e 502
a17b712b
SM
503(defvar edit-tab-stops-map
504 (let ((map (make-sparse-keymap)))
505 (define-key map "\C-x\C-s" 'edit-tab-stops-note-changes)
506 (define-key map "\C-c\C-c" 'edit-tab-stops-note-changes)
507 map)
508 "Keymap used in `edit-tab-stops'.")
483e630e
RM
509
510(defvar edit-tab-stops-buffer nil
bc57b735
LT
511 "Buffer whose tab stops are being edited.
512This matters if the variable `tab-stop-list' is local in that buffer.")
483e630e
RM
513
514(defun edit-tab-stops ()
515 "Edit the tab stops used by `tab-to-tab-stop'.
516Creates a buffer *Tab Stops* containing text describing the tab stops.
517A colon indicates a column where there is a tab stop.
518You can add or remove colons and then do \\<edit-tab-stops-map>\\[edit-tab-stops-note-changes] to make changes take effect."
519 (interactive)
520 (setq edit-tab-stops-buffer (current-buffer))
521 (switch-to-buffer (get-buffer-create "*Tab Stops*"))
522 (use-local-map edit-tab-stops-map)
523 (make-local-variable 'indent-tabs-mode)
524 (setq indent-tabs-mode nil)
525 (overwrite-mode 1)
526 (setq truncate-lines t)
527 (erase-buffer)
528 (let ((tabs tab-stop-list))
529 (while tabs
530 (indent-to (car tabs) 0)
531 (insert ?:)
532 (setq tabs (cdr tabs))))
533 (let ((count 0))
534 (insert ?\n)
535 (while (< count 8)
536 (insert (+ count ?0))
537 (insert " ")
538 (setq count (1+ count)))
539 (insert ?\n)
540 (while (> count 0)
541 (insert "0123456789")
542 (setq count (1- count))))
543 (insert "\nTo install changes, type C-c C-c")
544 (goto-char (point-min)))
545
546(defun edit-tab-stops-note-changes ()
547 "Put edited tab stops into effect."
548 (interactive)
549 (let (tabs)
550 (save-excursion
551 (goto-char 1)
552 (end-of-line)
553 (while (search-backward ":" nil t)
554 (setq tabs (cons (current-column) tabs))))
555 (bury-buffer (prog1 (current-buffer)
556 (switch-to-buffer edit-tab-stops-buffer)))
557 (setq tab-stop-list tabs))
558 (message "Tab stops installed"))
559
560(defun tab-to-tab-stop ()
561 "Insert spaces or tabs to next defined tab-stop column.
562The variable `tab-stop-list' is a list of columns at which there are tab stops.
563Use \\[edit-tab-stops] to edit them interactively."
564 (interactive)
a2964053
RS
565 (and abbrev-mode (= (char-syntax (preceding-char)) ?w)
566 (expand-abbrev))
483e630e
RM
567 (let ((tabs tab-stop-list))
568 (while (and tabs (>= (current-column) (car tabs)))
569 (setq tabs (cdr tabs)))
570 (if tabs
06b60517
JB
571 (progn
572 (delete-horizontal-space t)
9d840bec 573 (indent-to (car tabs)))
b379356a 574 (insert ?\s))))
483e630e
RM
575
576(defun move-to-tab-stop ()
577 "Move point to next defined tab-stop column.
fbf8f564
RS
578The variable `tab-stop-list' is a list of columns at which there are tab stops.
579Use \\[edit-tab-stops] to edit them interactively."
580 (interactive)
581 (let ((tabs tab-stop-list))
582 (while (and tabs (>= (current-column) (car tabs)))
583 (setq tabs (cdr tabs)))
584 (if tabs
585 (let ((before (point)))
586 (move-to-column (car tabs) t)
587 (save-excursion
588 (goto-char before)
589 ;; If we just added a tab, or moved over one,
590 ;; delete any superfluous spaces before the old point.
b379356a 591 (if (and (eq (preceding-char) ?\s)
fbf8f564
RS
592 (eq (following-char) ?\t))
593 (let ((tabend (* (/ (current-column) tab-width) tab-width)))
594 (while (and (> (current-column) tabend)
b379356a 595 (eq (preceding-char) ?\s))
fbf8f564
RS
596 (forward-char -1))
597 (delete-region (point) before))))))))
598
483e630e 599(define-key global-map "\t" 'indent-for-tab-command)
a17b712b 600(define-key esc-map "\C-\\" 'indent-region)
483e630e
RM
601(define-key ctl-x-map "\t" 'indent-rigidly)
602(define-key esc-map "i" 'tab-to-tab-stop)
1a06eabd
ER
603
604;;; indent.el ends here