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