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