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