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