2013-10-08 06:17:49 +00:00
;;; indent.el --- indentation commands for Emacs -*- lexical-binding:t -*-
1992-05-30 23:12:08 +00:00
2014-01-01 07:43:34 +00:00
;; Copyright (C) 1985, 1995, 2001-2014 Free Software Foundation, Inc.
1991-05-11 18:02:10 +00:00
2014-02-10 01:34:22 +00:00
;; Maintainer: emacs-devel@gnu.org
2010-08-29 16:17:13 +00:00
;; Package: emacs
1992-07-22 04:22:30 +00:00
1991-05-11 18:02:10 +00:00
;; This file is part of GNU Emacs.
2008-05-06 08:06:51 +00:00
;; GNU Emacs is free software: you can redistribute it and/or modify
1991-05-11 18:02:10 +00:00
;; it under the terms of the GNU General Public License as published by
2008-05-06 08:06:51 +00:00
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
1991-05-11 18:02:10 +00:00
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
2008-05-06 08:06:51 +00:00
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
1991-05-11 18:02:10 +00:00
1993-03-22 03:27:18 +00:00
;;; Commentary:
;; Commands for making and changing indentation in text. These are
;; described in the Emacs manual.
1992-07-16 21:47:34 +00:00
;;; Code:
1991-05-11 18:02:10 +00:00
1997-08-19 00:03:01 +00:00
( defgroup indent nil
2005-07-04 02:08:37 +00:00
" Indentation commands. "
1997-08-19 00:03:01 +00:00
:group 'editing )
1995-01-19 04:15:32 +00:00
1997-08-19 00:03:01 +00:00
( defcustom standard-indent 4
2008-12-03 05:48:14 +00:00
" Default number of columns for margin-changing functions to indent. "
1997-08-19 00:03:01 +00:00
:group 'indent
:type 'integer )
2001-12-06 16:17:08 +00:00
( defvar indent-line-function 'indent-relative
2001-10-30 05:37:08 +00:00
" Function to indent the current line.
This function will be called with no arguments.
If it is called somewhere where auto-indentation cannot be done
2008-09-12 03:07:25 +00:00
\(e.g. inside a string ) , the function should simply return ` noindent '.
2001-10-30 05:37:08 +00:00
Setting this function is all you need to make TAB indent appropriately.
Don 't rebind TAB unless you really need to. " )
1991-05-11 18:02:10 +00:00
2000-10-07 04:13:09 +00:00
( defcustom tab-always-indent t
2008-12-03 05:48:14 +00:00
" Controls the operation of the TAB key.
2000-10-07 04:13:09 +00:00
If t , hitting TAB always just indents the current line.
If nil , hitting TAB indents the current line if point is at the left margin
2007-06-12 16:33:39 +00:00
or in the line 's indentation, otherwise it inserts a \"real\" TAB character.
2009-12-07 20:06:26 +00:00
If ` complete ', TAB first tries to indent the current line, and if the line
was already indented, then try to complete the thing at point.
2007-06-12 16:33:39 +00:00
Some programming language modes have their own variable to control this,
2006-12-22 22:46:22 +00:00
e.g., ` c-tab-always-indent ', and do not respect this variable. "
2000-10-07 04:13:09 +00:00
:group 'indent
2010-01-20 03:46:23 +00:00
:type ' ( choice
( const :tag " Always indent " t )
( const :tag " Indent if inside indentation, else TAB " nil )
( const :tag " Indent, or if already indented complete " complete ) ) )
2000-10-07 04:13:09 +00:00
1991-05-11 18:02:10 +00:00
( defun indent-according-to-mode ( )
2002-11-29 15:06:59 +00:00
" Indent line in proper way for current major mode.
2011-11-29 15:55:54 +00:00
Normally, this is done by calling the function specified by the
variable ` indent-line-function '. However, if the value of that
variable is ` indent-relative ' or ` indent-relative-maybe ', handle
it specially ( since those functions are used for tabbing ) ; in
that case, indent by aligning to the previous non-blank line. "
1991-05-11 18:02:10 +00:00
( interactive )
2010-09-18 16:21:16 +00:00
( syntax-propertize ( line-end-position ) )
2001-10-30 05:37:08 +00:00
( if ( memq indent-line-function
' ( indent-relative indent-relative-maybe ) )
;; These functions are used for tabbing, but can't be used for
;; indenting. Replace with something ad-hoc.
( let ( ( column ( save-excursion
( beginning-of-line )
2014-01-13 05:03:31 +00:00
( if ( bobp ) 0
( beginning-of-line 0 )
( if ( looking-at " [ \t ]*$ " ) 0
( current-indentation ) ) ) ) ) )
2001-10-30 05:37:08 +00:00
( if ( <= ( current-column ) ( current-indentation ) )
( indent-line-to column )
( save-excursion ( indent-line-to column ) ) ) )
;; The normal case.
( funcall indent-line-function ) ) )
1991-05-11 18:02:10 +00:00
2001-10-30 05:37:08 +00:00
( defun indent-for-tab-command ( &optional arg )
2011-11-29 15:55:54 +00:00
" Indent the current line or region, or insert a tab, as appropriate.
This function either inserts a tab, or indents the current line,
or performs symbol completion, depending on ` tab-always-indent '.
The function called to actually indent the line or insert a tab
is given by the variable ` indent-line-function '.
If a prefix argument is given, after this function indents the
current line or inserts a tab, it also rigidly indents the entire
2009-05-20 02:35:45 +00:00
balanced expression which starts at the beginning of the current
2011-11-29 15:55:54 +00:00
line, to reflect the current line 's indentation.
2007-12-25 21:07:12 +00:00
2011-11-29 15:55:54 +00:00
In most major modes, if point was in the current line 's
indentation, it is moved to the first non-whitespace character
after indenting ; otherwise it stays at the same position relative
to the text.
2007-12-25 21:07:12 +00:00
2011-11-29 15:55:54 +00:00
If ` transient-mark-mode ' is turned on and the region is active,
this function instead calls ` indent-region '. In this case, any
prefix argument is ignored. "
2007-12-25 21:07:12 +00:00
( interactive " P " )
2001-10-30 05:37:08 +00:00
( cond
2007-09-24 17:48:50 +00:00
;; The region is active, indent it.
2008-10-30 23:52:39 +00:00
( ( use-region-p )
2007-09-24 17:48:50 +00:00
( indent-region ( region-beginning ) ( region-end ) ) )
2001-11-02 04:57:54 +00:00
( ( or ;; indent-to-left-margin is only meant for indenting,
2001-10-30 05:37:08 +00:00
;; so we force it to always insert a tab here.
( eq indent-line-function 'indent-to-left-margin )
( and ( not tab-always-indent )
2003-03-14 23:11:20 +00:00
( or ( > ( current-column ) ( current-indentation ) )
( eq this-command last-command ) ) ) )
2001-10-30 05:37:08 +00:00
( insert-tab arg ) )
2007-09-22 00:57:00 +00:00
( t
2009-12-07 20:06:26 +00:00
( let ( ( old-tick ( buffer-chars-modified-tick ) )
( old-point ( point ) )
( old-indent ( current-indentation ) ) )
2007-12-25 21:07:12 +00:00
;; Indent the line.
( funcall indent-line-function )
2009-12-07 20:06:26 +00:00
( cond
;; If the text was already indented right, try completion.
( ( and ( eq tab-always-indent 'complete )
( eq old-point ( point ) )
( eq old-tick ( buffer-chars-modified-tick ) ) )
( completion-at-point ) )
;; If a prefix argument was given, rigidly indent the following
;; sexp to match the change in the current line's indentation.
( arg
( let ( ( end-marker
( save-excursion
( forward-line 0 ) ( forward-sexp ) ( point-marker ) ) )
( indentation-change ( - ( current-indentation ) old-indent ) ) )
( save-excursion
( forward-line 1 )
( when ( and ( not ( zerop indentation-change ) )
( < ( point ) end-marker ) )
( indent-rigidly ( point ) end-marker indentation-change ) ) ) ) ) ) ) ) ) )
2001-10-30 05:37:08 +00:00
( defun insert-tab ( &optional arg )
( let ( ( count ( prefix-numeric-value arg ) ) )
1997-08-24 16:26:31 +00:00
( if ( and abbrev-mode
( eq ( char-syntax ( preceding-char ) ) ?w ) )
1996-04-28 23:41:52 +00:00
( expand-abbrev ) )
( if indent-tabs-mode
1996-04-29 18:12:08 +00:00
( insert-char ?\t count )
1996-04-28 23:41:52 +00:00
( indent-to ( * tab-width ( + count ( / ( current-column ) tab-width ) ) ) ) ) ) )
1991-05-11 18:02:10 +00:00
2013-10-08 06:17:49 +00:00
( defun indent-rigidly--current-indentation ( beg end )
" Return the smallest indentation in range from BEG to END.
Blank lines are ignored. "
( save-excursion
( save-match-data
( let ( ( beg ( progn ( goto-char beg ) ( line-beginning-position ) ) )
indent )
( goto-char beg )
( while ( re-search-forward " ^ \\ s-*[[:print:]] " end t )
( setq indent ( min ( or indent ( current-indentation ) )
( current-indentation ) ) ) )
indent ) ) ) )
( defvar indent-rigidly-map
( let ( ( map ( make-sparse-keymap ) ) )
2013-12-21 08:37:08 +00:00
( define-key map [ left ] 'indent-rigidly-left )
( define-key map [ right ] 'indent-rigidly-right )
( define-key map [ S-left ] 'indent-rigidly-left-to-tab-stop )
( define-key map [ S-right ] 'indent-rigidly-right-to-tab-stop )
map )
" Transient keymap for adjusting indentation interactively.
It is activated by calling ` indent-rigidly ' interactively. " )
2013-10-08 06:17:49 +00:00
2013-12-21 08:37:08 +00:00
( defun indent-rigidly ( start end arg &optional interactive )
" Indent all lines starting in the region.
If called interactively with no prefix argument, activate a
transient mode in which the indentation can be adjusted interactively
by typing \\<indent-rigidly-map>\\ [ indent-rigidly-left ] , \\ [ indent-rigidly-right ] , \\ [ indent-rigidly-left-to-tab-stop ] , or \\ [ indent-rigidly-right-to-tab-stop ] .
Typing any other key deactivates the transient mode.
2013-10-08 06:17:49 +00:00
2013-12-21 08:37:08 +00:00
If called from a program, or interactively with prefix ARG,
indent all lines starting in the region forward by ARG columns.
If called from a program, START and END specify the beginning and
end of the text to act on, in place of the region.
2013-10-08 06:17:49 +00:00
2013-12-21 08:37:08 +00:00
Negative values of ARG indent backward, so you can remove all
indentation by specifying a large negative ARG. "
2013-10-08 06:17:49 +00:00
( interactive " r \n P \n p " )
( if ( and ( not arg ) interactive )
( progn
2013-12-23 04:07:01 +00:00
( message
( substitute-command-keys
" Indent region with \\ <indent-rigidly-map> \\ [indent-rigidly-left], \\ [indent-rigidly-right], \\ [indent-rigidly-left-to-tab-stop], or \\ [indent-rigidly-right-to-tab-stop]. " ) )
2013-12-23 03:59:10 +00:00
( set-transient-map indent-rigidly-map t ) )
2013-10-08 06:17:49 +00:00
( save-excursion
( goto-char end )
( setq end ( point-marker ) )
( goto-char start )
( or ( bolp ) ( forward-line 1 ) )
( while ( < ( point ) end )
( let ( ( indent ( current-indentation ) )
eol-flag )
( save-excursion
( skip-chars-forward " \t " )
( setq eol-flag ( eolp ) ) )
( or eol-flag
2013-10-17 19:31:11 +00:00
( indent-to ( max 0 ( + indent ( prefix-numeric-value arg ) ) ) 0 ) )
2013-10-08 06:17:49 +00:00
( delete-region ( point ) ( progn ( skip-chars-forward " \t " ) ( point ) ) ) )
( forward-line 1 ) )
2014-01-15 08:22:41 +00:00
( move-marker end nil )
;; Keep the active region in transient mode.
( when ( eq ( cadr overriding-terminal-local-map ) indent-rigidly-map )
( setq deactivate-mark nil ) ) ) ) )
1991-05-11 18:02:10 +00:00
2013-12-21 08:37:08 +00:00
( defun indent-rigidly--pop-undo ( )
( and ( memq last-command ' ( indent-rigidly-left indent-rigidly-right
indent-rigidly-left-to-tab-stop
indent-rigidly-right-to-tab-stop ) )
( consp buffer-undo-list )
( eq ( car buffer-undo-list ) nil )
( pop buffer-undo-list ) ) )
( defun indent-rigidly-left ( beg end )
" Indent all lines between BEG and END leftward by one space. "
( interactive " r " )
( indent-rigidly--pop-undo )
( indent-rigidly
beg end
( if ( eq ( current-bidi-paragraph-direction ) 'right-to-left ) 1 -1 ) ) )
( defun indent-rigidly-right ( beg end )
" Indent all lines between BEG and END rightward by one space. "
( interactive " r " )
( indent-rigidly--pop-undo )
( indent-rigidly
beg end
( if ( eq ( current-bidi-paragraph-direction ) 'right-to-left ) -1 1 ) ) )
( defun indent-rigidly-left-to-tab-stop ( beg end )
" Indent all lines between BEG and END leftward to a tab stop. "
( interactive " r " )
( indent-rigidly--pop-undo )
( let* ( ( current ( indent-rigidly--current-indentation beg end ) )
( rtl ( eq ( current-bidi-paragraph-direction ) 'right-to-left ) )
( next ( indent--next-tab-stop current ( if rtl nil 'prev ) ) ) )
( indent-rigidly beg end ( - next current ) ) ) )
( defun indent-rigidly-right-to-tab-stop ( beg end )
" Indent all lines between BEG and END rightward to a tab stop. "
( interactive " r " )
( indent-rigidly--pop-undo )
( let* ( ( current ( indent-rigidly--current-indentation beg end ) )
( rtl ( eq ( current-bidi-paragraph-direction ) 'right-to-left ) )
( next ( indent--next-tab-stop current ( if rtl 'prev ) ) ) )
( indent-rigidly beg end ( - next current ) ) ) )
1995-01-19 04:15:32 +00:00
( defun indent-line-to ( column )
" Indent current line to COLUMN.
This function removes or adds spaces and tabs at beginning of line
only if necessary. It leaves point at end of indentation. "
2014-01-20 08:45:56 +00:00
( backward-to-indentation 0 )
1995-03-16 22:36:26 +00:00
( let ( ( cur-col ( current-column ) ) )
( cond ( ( < cur-col column )
1997-03-14 16:35:03 +00:00
( if ( >= ( - column ( * ( / cur-col tab-width ) tab-width ) ) tab-width )
1995-11-14 21:05:54 +00:00
( delete-region ( point )
( progn ( skip-chars-backward " " ) ( point ) ) ) )
1995-03-16 22:36:26 +00:00
( indent-to column ) )
( ( > cur-col column ) ; too far right (after tab?)
1995-02-23 18:34:22 +00:00
( delete-region ( progn ( move-to-column column t ) ( point ) )
2014-01-20 08:45:56 +00:00
( progn ( backward-to-indentation 0 ) ( point ) ) ) ) ) ) )
1995-01-19 04:15:32 +00:00
( defun current-left-margin ( )
" Return the left margin to use for this line.
This is the value of the buffer-local variable ` left-margin ' plus the value
of the ` left-margin ' text-property at the start of the line. "
( save-excursion
( back-to-indentation )
( max 0
1995-02-23 18:34:22 +00:00
( + left-margin ( or ( get-text-property
( if ( and ( eobp ) ( not ( bobp ) ) )
( 1- ( point ) ) ( point ) )
'left-margin ) 0 ) ) ) ) )
1995-01-19 04:15:32 +00:00
1995-02-23 18:34:22 +00:00
( defun move-to-left-margin ( &optional n force )
1995-01-19 04:15:32 +00:00
" Move to the left margin of the current line.
With optional argument, move forward N-1 lines first.
1995-02-23 18:34:22 +00:00
The column moved to is the one given by the ` current-left-margin ' function.
If the line 's indentation appears to be wrong, and this command is called
interactively or with optional argument FORCE, it will be fixed. "
( interactive ( list ( prefix-numeric-value current-prefix-arg ) t ) )
1995-01-19 04:15:32 +00:00
( beginning-of-line n )
1995-11-17 22:43:35 +00:00
( skip-chars-forward " \t " )
2004-09-20 16:09:32 +00:00
( if ( minibufferp ( current-buffer ) )
( if ( save-excursion ( beginning-of-line ) ( bobp ) )
( goto-char ( minibuffer-prompt-end ) )
( beginning-of-line ) )
( let ( ( lm ( current-left-margin ) )
( cc ( current-column ) ) )
( cond ( ( > cc lm )
( if ( > ( move-to-column lm force ) lm )
;; If lm is in a tab and we are not forcing, move before tab
( backward-char 1 ) ) )
( ( and force ( < cc lm ) )
( indent-to-left-margin ) ) ) ) ) )
1995-01-19 04:15:32 +00:00
2003-03-14 23:11:20 +00:00
;; This used to be the default indent-line-function,
1991-05-11 18:02:10 +00:00
;; used in Fundamental Mode, Text Mode, etc.
( defun indent-to-left-margin ( )
1995-02-23 18:34:22 +00:00
" Indent current line to the column given by `current-left-margin' . "
2007-10-24 08:10:57 +00:00
( save-excursion ( indent-line-to ( current-left-margin ) ) )
;; If we are within the indentation, move past it.
( when ( save-excursion
( skip-chars-backward " \t " )
( bolp ) )
( skip-chars-forward " \t " ) ) )
1995-01-19 04:15:32 +00:00
1995-02-23 18:34:22 +00:00
( defun delete-to-left-margin ( &optional from to )
" Remove left margin indentation from a region.
This deletes to the column given by ` current-left-margin '.
In no case will it delete non-whitespace.
Args FROM and TO are optional ; default is the whole buffer."
1995-01-19 04:15:32 +00:00
( save-excursion
1995-02-23 18:34:22 +00:00
( goto-char ( or to ( point-max ) ) )
1995-01-19 04:15:32 +00:00
( setq to ( point-marker ) )
1995-02-23 18:34:22 +00:00
( goto-char ( or from ( point-min ) ) )
1995-01-19 04:15:32 +00:00
( or ( bolp ) ( forward-line 1 ) )
( while ( < ( point ) to )
1995-02-23 18:34:22 +00:00
( delete-region ( point ) ( progn ( move-to-left-margin nil t ) ( point ) ) )
1995-01-19 04:15:32 +00:00
( forward-line 1 ) )
( move-marker to nil ) ) )
2004-10-02 00:18:38 +00:00
( defun set-left-margin ( from to width )
1995-01-19 04:15:32 +00:00
" Set the left margin of the region to WIDTH.
2004-10-02 00:18:38 +00:00
If ` auto-fill-mode ' is active, re-fill the region to fit the new margin.
Interactively, WIDTH is the prefix argument, if specified.
Without prefix argument, the command prompts for WIDTH. "
1995-01-19 04:15:32 +00:00
( interactive " r \n NSet left margin to column: " )
( save-excursion
;; If inside indentation, start from BOL.
( goto-char from )
( skip-chars-backward " \t " )
( if ( bolp ) ( setq from ( point ) ) )
1995-02-23 18:34:22 +00:00
;; Place end after whitespace
1995-01-19 04:15:32 +00:00
( goto-char to )
1995-02-23 18:34:22 +00:00
( skip-chars-forward " \t " )
1995-01-19 04:15:32 +00:00
( setq to ( point-marker ) ) )
1995-02-23 18:34:22 +00:00
;; Delete margin indentation first, but keep paragraph indentation.
( delete-to-left-margin from to )
2004-10-02 00:18:38 +00:00
( put-text-property from to 'left-margin width )
( indent-rigidly from to width )
1995-02-23 18:34:22 +00:00
( if auto-fill-function ( save-excursion ( fill-region from to nil t t ) ) )
1995-01-19 04:15:32 +00:00
( move-marker to nil ) )
2004-10-02 00:18:38 +00:00
( defun set-right-margin ( from to width )
1995-01-19 04:15:32 +00:00
" Set the right margin of the region to WIDTH.
2004-10-02 00:18:38 +00:00
If ` auto-fill-mode ' is active, re-fill the region to fit the new margin.
Interactively, WIDTH is the prefix argument, if specified.
Without prefix argument, the command prompts for WIDTH. "
1995-04-07 23:44:31 +00:00
( interactive " r \n NSet right margin to width: " )
1995-01-19 04:15:32 +00:00
( save-excursion
( goto-char from )
( skip-chars-backward " \t " )
( if ( bolp ) ( setq from ( point ) ) ) )
2004-10-02 00:18:38 +00:00
( put-text-property from to 'right-margin width )
1995-02-23 18:34:22 +00:00
( if auto-fill-function ( save-excursion ( fill-region from to nil t t ) ) ) )
1995-01-19 04:15:32 +00:00
( defun alter-text-property ( from to prop func &optional object )
" Programmatically change value of a text-property.
For each region between FROM and TO that has a single value for PROPERTY,
apply FUNCTION to that value and sets the property to the function 's result.
Optional fifth argument OBJECT specifies the string or buffer to operate on. "
( let ( ( begin from )
end val )
( while ( setq val ( get-text-property begin prop object )
end ( text-property-not-all begin to prop val object ) )
( put-text-property begin end prop ( funcall func val ) object )
( setq begin end ) )
( if ( < begin to )
( put-text-property begin to prop ( funcall func val ) object ) ) ) )
( defun increase-left-margin ( from to inc )
" Increase or decrease the left-margin of the region.
With no prefix argument, this adds ` standard-indent ' of indentation.
A prefix arg ( optional third arg INC noninteractively ) specifies the amount
to change the margin by, in characters.
If ` auto-fill-mode ' is active, re-fill the region to fit the new margin. "
( interactive " *r \n P " )
( setq inc ( if inc ( prefix-numeric-value inc ) standard-indent ) )
( save-excursion
( goto-char from )
( skip-chars-backward " \t " )
( if ( bolp ) ( setq from ( point ) ) )
( goto-char to )
( setq to ( point-marker ) ) )
( alter-text-property from to 'left-margin
1995-02-23 18:34:22 +00:00
( lambda ( v ) ( max ( - left-margin ) ( + inc ( or v 0 ) ) ) ) )
( indent-rigidly from to inc )
( if auto-fill-function ( save-excursion ( fill-region from to nil t t ) ) )
1995-01-19 04:15:32 +00:00
( move-marker to nil ) )
( defun decrease-left-margin ( from to inc )
" Make the left margin of the region smaller.
With no prefix argument, decrease the indentation by ` standard-indent '.
A prefix arg ( optional third arg INC noninteractively ) specifies the amount
to change the margin by, in characters.
If ` auto-fill-mode ' is active, re-fill the region to fit the new margin. "
( interactive " *r \n P " )
( setq inc ( if inc ( prefix-numeric-value inc ) standard-indent ) )
( increase-left-margin from to ( - inc ) ) )
( defun increase-right-margin ( from to inc )
" Increase the right-margin of the region.
With no prefix argument, increase the right margin by ` standard-indent '.
A prefix arg ( optional third arg INC noninteractively ) specifies the amount
to change the margin by, in characters. A negative argument decreases
the right margin width.
If ` auto-fill-mode ' is active, re-fill the region to fit the new margin. "
( interactive " r \n P " )
2004-10-24 21:01:20 +00:00
( setq inc ( if inc ( prefix-numeric-value inc ) standard-indent ) )
1995-01-19 04:15:32 +00:00
( save-excursion
( alter-text-property from to 'right-margin
2004-10-24 21:01:20 +00:00
( lambda ( v ) ( + inc ( or v 0 ) ) ) )
1995-01-19 04:15:32 +00:00
( if auto-fill-function
( fill-region from to nil t t ) ) ) )
( defun decrease-right-margin ( from to inc )
" Make the right margin of the region smaller.
With no prefix argument, decrease the right margin by ` standard-indent '.
A prefix arg ( optional third arg INC noninteractively ) specifies the amount
of width to remove, in characters. A negative argument increases
the right margin width.
If ` auto-fill-mode ' is active, re-fills region to fit in new margin. "
( interactive " *r \n P " )
( setq inc ( if inc ( prefix-numeric-value inc ) standard-indent ) )
( increase-right-margin from to ( - inc ) ) )
1991-05-11 18:02:10 +00:00
1995-02-23 18:34:22 +00:00
( defun beginning-of-line-text ( &optional n )
" Move to the beginning of the text on this line.
With optional argument, move forward N-1 lines first.
From the beginning of the line, moves past the left-margin indentation, the
fill-prefix, and any indentation used for centering or right-justifying the
2003-02-04 12:29:42 +00:00
line, but does not move past any whitespace that was explicitly inserted
1995-02-23 18:34:22 +00:00
\(such as a tab used to indent the first line of a paragraph ) . "
( interactive " p " )
( beginning-of-line n )
( skip-chars-forward " \t " )
;; Skip over fill-prefix.
2003-02-04 12:29:42 +00:00
( if ( and fill-prefix
1995-02-23 18:34:22 +00:00
( not ( string-equal fill-prefix " " ) ) )
( if ( equal fill-prefix
2003-02-04 12:29:42 +00:00
( buffer-substring
1995-02-23 18:34:22 +00:00
( point ) ( min ( point-max ) ( + ( length fill-prefix ) ( point ) ) ) ) )
( forward-char ( length fill-prefix ) ) )
1996-03-06 19:12:58 +00:00
( if ( and adaptive-fill-mode adaptive-fill-regexp
1995-02-23 18:34:22 +00:00
( looking-at adaptive-fill-regexp ) )
( goto-char ( match-end 0 ) ) ) )
;; Skip centering or flushright indentation
( if ( memq ( current-justification ) ' ( center right ) )
( skip-chars-forward " \t " ) ) )
1991-05-11 18:02:10 +00:00
( defvar indent-region-function nil
1995-07-26 22:23:11 +00:00
" Short cut function to indent region using `indent-according-to-mode' .
A value of nil means really run ` indent-according-to-mode ' on each line. " )
1991-05-11 18:02:10 +00:00
2002-05-19 16:09:28 +00:00
( defun indent-region ( start end &optional column )
1991-05-11 18:02:10 +00:00
" Indent each nonblank line in the region.
2002-11-29 15:06:59 +00:00
A numeric prefix argument specifies a column: indent each line to that column.
With no prefix argument, the command chooses one of these methods and
indents all the lines with it:
1 ) If ` fill-prefix ' is non-nil, insert ` fill-prefix ' at the
beginning of each line in the region that does not already begin
with it.
2 ) If ` indent-region-function ' is non-nil, call that function
to indent the region.
2011-11-29 15:55:54 +00:00
3 ) Indent each line via ` indent-according-to-mode '.
2002-11-29 15:06:59 +00:00
Called from a program, START and END specify the region to indent.
If the third argument COLUMN is an integer, it specifies the
column to indent to ; if it is nil, use one of the three methods above."
1991-05-11 18:02:10 +00:00
( interactive " r \n P " )
2011-11-29 15:55:54 +00:00
( cond
2013-10-08 06:17:49 +00:00
;; If a numeric prefix is given, indent to that column.
2011-11-29 15:55:54 +00:00
( column
1993-08-06 01:56:26 +00:00
( setq column ( prefix-numeric-value column ) )
1991-05-11 18:02:10 +00:00
( save-excursion
( goto-char end )
( setq end ( point-marker ) )
( goto-char start )
( or ( bolp ) ( forward-line 1 ) )
( while ( < ( point ) end )
( delete-region ( point ) ( progn ( skip-chars-forward " \t " ) ( point ) ) )
( or ( eolp )
1995-01-19 04:15:32 +00:00
( indent-to column 0 ) )
2013-10-08 06:17:49 +00:00
( forward-line 1 ) )
2010-05-19 03:06:48 +00:00
( move-marker end nil ) ) )
2013-10-08 06:17:49 +00:00
;; If a fill-prefix is specified, use it.
2011-11-29 15:55:54 +00:00
( fill-prefix
( save-excursion
( goto-char end )
( setq end ( point-marker ) )
( goto-char start )
( let ( ( regexp ( regexp-quote fill-prefix ) ) )
( while ( < ( point ) end )
( or ( looking-at regexp )
( and ( bolp ) ( eolp ) )
( insert fill-prefix ) )
( forward-line 1 ) ) ) ) )
2013-10-08 06:17:49 +00:00
;; Use indent-region-function is available.
2011-11-29 15:55:54 +00:00
( indent-region-function
( funcall indent-region-function start end ) )
2013-10-08 06:17:49 +00:00
;; Else, use a default implementation that calls indent-line-function on
;; each line.
2011-11-29 15:55:54 +00:00
( t
( save-excursion
( setq end ( copy-marker end ) )
( goto-char start )
2013-12-13 01:54:09 +00:00
( let ( ( pr ( unless ( minibufferp )
( make-progress-reporter " Indenting region... " ( point ) end ) ) ) )
( while ( < ( point ) end )
( or ( and ( bolp ) ( eolp ) )
( indent-according-to-mode ) )
2013-10-08 06:17:49 +00:00
( forward-line 1 )
2013-12-13 01:54:09 +00:00
( and pr ( progress-reporter-update pr ( point ) ) ) )
( and pr ( progress-reporter-done pr ) )
2013-10-08 06:17:49 +00:00
( move-marker end nil ) ) ) ) )
2010-05-19 03:06:48 +00:00
;; In most cases, reindenting modifies the buffer, but it may also
;; leave it unmodified, in which case we have to deactivate the mark
;; by hand.
( deactivate-mark ) )
1991-05-11 18:02:10 +00:00
( defun indent-relative-maybe ( )
2001-06-22 11:49:18 +00:00
" Indent a new line like previous nonblank line.
If the previous nonblank line has no indent points beyond the
column point starts at, this command does nothing.
See also ` indent-relative '. "
1991-05-11 18:02:10 +00:00
( interactive )
( indent-relative t ) )
( defun indent-relative ( &optional unindented-ok )
" Space out to under next indent point in previous nonblank line.
An indent point is a non-whitespace character following whitespace.
1999-09-03 01:00:15 +00:00
The following line shows the indentation points in this line.
^ ^ ^ ^ ^ ^ ^ ^ ^
1991-05-11 18:02:10 +00:00
If the previous nonblank line has no indent points beyond the
2001-06-22 11:49:18 +00:00
column point starts at, ` tab-to-tab-stop ' is done instead, unless
this command is invoked with a numeric argument, in which case it
does nothing.
See also ` indent-relative-maybe '. "
1991-05-11 18:02:10 +00:00
( interactive " P " )
1997-08-24 16:26:31 +00:00
( if ( and abbrev-mode
( eq ( char-syntax ( preceding-char ) ) ?w ) )
( expand-abbrev ) )
1991-05-11 18:02:10 +00:00
( let ( ( start-column ( current-column ) )
indent )
( save-excursion
( beginning-of-line )
( if ( re-search-backward " ^[^ \n ] " nil t )
( let ( ( end ( save-excursion ( forward-line 1 ) ( point ) ) ) )
( move-to-column start-column )
;; Is start-column inside a tab on this line?
( if ( > ( current-column ) start-column )
( backward-char 1 ) )
( or ( looking-at " [ \t ] " )
unindented-ok
( skip-chars-forward " ^ \t " end ) )
( skip-chars-forward " \t " end )
( or ( = ( point ) end ) ( setq indent ( current-column ) ) ) ) ) )
( if indent
( let ( ( opoint ( point-marker ) ) )
( indent-to indent 0 )
( if ( > opoint ( point ) )
( goto-char opoint ) )
( move-marker opoint nil ) )
( tab-to-tab-stop ) ) ) )
2014-01-28 01:49:02 +00:00
( defcustom tab-stop-list nil
2008-12-03 05:48:14 +00:00
" List of tab stop positions used by `tab-to-tab-stop' .
2014-01-28 01:49:02 +00:00
This should be nil , or a list of integers, ordered from smallest to largest.
It implicitly extends to infinity through repetition of the last step.
For example, ' ( 1 2 5 ) is equivalent to ' ( 1 2 5 8 11 . . . ) . If the list has
fewer than 2 elements, ` tab-width ' is used as the \"last step\".
A value of nil means a tab stop every ` tab-width ' columns. "
1997-08-19 00:03:01 +00:00
:group 'indent
2014-01-28 01:49:02 +00:00
:version " 24.4 " ; from explicit list to nil
:safe 'listp
1997-08-19 00:03:01 +00:00
:type ' ( repeat integer ) )
1991-05-11 18:02:10 +00:00
2001-10-30 05:37:08 +00:00
( defvar edit-tab-stops-map
( let ( ( map ( make-sparse-keymap ) ) )
( define-key map " \C -x \C -s " 'edit-tab-stops-note-changes )
( define-key map " \C -c \C -c " 'edit-tab-stops-note-changes )
map )
" Keymap used in `edit-tab-stops' . " )
1991-05-11 18:02:10 +00:00
( defvar edit-tab-stops-buffer nil
2004-08-28 16:13:32 +00:00
" Buffer whose tab stops are being edited.
This matters if the variable ` tab-stop-list ' is local in that buffer. " )
1991-05-11 18:02:10 +00:00
( defun edit-tab-stops ( )
" Edit the tab stops used by `tab-to-tab-stop' .
Creates a buffer *Tab Stops* containing text describing the tab stops.
A colon indicates a column where there is a tab stop.
You can add or remove colons and then do \\<edit-tab-stops-map>\\ [ edit-tab-stops-note-changes ] to make changes take effect. "
( interactive )
( setq edit-tab-stops-buffer ( current-buffer ) )
( switch-to-buffer ( get-buffer-create " *Tab Stops* " ) )
( use-local-map edit-tab-stops-map )
2013-10-08 06:17:49 +00:00
( setq-local indent-tabs-mode nil )
1991-05-11 18:02:10 +00:00
( overwrite-mode 1 )
( setq truncate-lines t )
( erase-buffer )
( let ( ( tabs tab-stop-list ) )
( while tabs
( indent-to ( car tabs ) 0 )
( insert ?: )
( setq tabs ( cdr tabs ) ) ) )
( let ( ( count 0 ) )
( insert ?\n )
( while ( < count 8 )
( insert ( + count ?0 ) )
( insert " " )
( setq count ( 1+ count ) ) )
( insert ?\n )
( while ( > count 0 )
( insert " 0123456789 " )
( setq count ( 1- count ) ) ) )
( insert " \n To install changes, type C-c C-c " )
( goto-char ( point-min ) ) )
( defun edit-tab-stops-note-changes ( )
" Put edited tab stops into effect. "
( interactive )
( let ( tabs )
( save-excursion
( goto-char 1 )
( end-of-line )
( while ( search-backward " : " nil t )
( setq tabs ( cons ( current-column ) tabs ) ) ) )
( bury-buffer ( prog1 ( current-buffer )
( switch-to-buffer edit-tab-stops-buffer ) ) )
( setq tab-stop-list tabs ) )
( message " Tab stops installed " ) )
2013-10-08 06:17:49 +00:00
( defun indent--next-tab-stop ( column &optional prev )
" Return the next tab stop after COLUMN.
If PREV is non-nil, return the previous one instead. "
( let ( ( tabs tab-stop-list ) )
( while ( and tabs ( >= column ( car tabs ) ) )
( setq tabs ( cdr tabs ) ) )
( if tabs
( if ( not prev )
( car tabs )
( let ( ( prevtabs ( cdr ( memq ( car tabs ) ( reverse tab-stop-list ) ) ) ) )
( if ( null prevtabs ) 0
( if ( = column ( car prevtabs ) )
( or ( nth 1 prevtabs ) 0 )
( car prevtabs ) ) ) ) )
;; We passed the end of tab-stop-list: guess a continuation.
( let* ( ( last2 ( last tab-stop-list 2 ) )
( step ( if ( cdr last2 ) ( - ( cadr last2 ) ( car last2 ) ) tab-width ) )
( last ( or ( cadr last2 ) ( car last2 ) 0 ) ) )
;; Repeat the last tab's length.
( + last ( * step ( if prev
( if ( <= column last ) -1 ( / ( - column last 1 ) step ) )
( 1+ ( / ( - column last ) step ) ) ) ) ) ) ) ) )
1991-05-11 18:02:10 +00:00
( defun tab-to-tab-stop ( )
" Insert spaces or tabs to next defined tab-stop column.
The variable ` tab-stop-list ' is a list of columns at which there are tab stops.
Use \\ [ edit-tab-stops ] to edit them interactively. "
( interactive )
1995-08-05 20:21:06 +00:00
( and abbrev-mode ( = ( char-syntax ( preceding-char ) ) ?w )
( expand-abbrev ) )
2013-10-08 06:17:49 +00:00
( let ( ( nexttab ( indent--next-tab-stop ( current-column ) ) ) )
( delete-horizontal-space t )
( indent-to nexttab ) ) )
1991-05-11 18:02:10 +00:00
( defun move-to-tab-stop ( )
" Move point to next defined tab-stop column.
1994-06-23 23:57:33 +00:00
The variable ` tab-stop-list ' is a list of columns at which there are tab stops.
Use \\ [ edit-tab-stops ] to edit them interactively. "
( interactive )
2013-10-08 06:17:49 +00:00
( let ( ( nexttab ( indent--next-tab-stop ( current-column ) ) ) )
( let ( ( before ( point ) ) )
( move-to-column nexttab t )
( save-excursion
( goto-char before )
;; If we just added a tab, or moved over one,
;; delete any superfluous spaces before the old point.
( if ( and ( eq ( preceding-char ) ?\s )
( eq ( following-char ) ?\t ) )
( let ( ( tabend ( * ( / ( current-column ) tab-width ) tab-width ) ) )
( while ( and ( > ( current-column ) tabend )
( eq ( preceding-char ) ?\s ) )
( forward-char -1 ) )
( delete-region ( point ) before ) ) ) ) ) ) )
1994-06-23 23:57:33 +00:00
1991-05-11 18:02:10 +00:00
( define-key global-map " \t " 'indent-for-tab-command )
2001-10-30 05:37:08 +00:00
( define-key esc-map " \C - \\ " 'indent-region )
1991-05-11 18:02:10 +00:00
( define-key ctl-x-map " \t " 'indent-rigidly )
( define-key esc-map " i " 'tab-to-tab-stop )
1992-05-30 23:12:08 +00:00
;;; indent.el ends here