VIM: usr_30

## USR_30

    *usr_30.txt*	For Vim version 9.1.  Last change: 2025 Jun 10

    		     VIM USER MANUAL - by Bram Moolenaar

    			      Editing programs

    Vim has various commands that aid in writing computer programs.  Compile a
    program and directly jump to reported errors.  Automatically set the indent
    for many languages and format comments.

    |30.1|	Compiling
    |30.2|	Indenting C files
    |30.3|	Automatic indenting
    |30.4|	Other indenting
    |30.5|	Tabs and spaces
    |30.6|	Formatting comments

         Next chapter: |usr_31|  Exploiting the GUI
     Previous chapter: |usr_29|  Moving through programs
    Table of contents: |usr_toc|

    *30.1*	Compiling

    Vim has a set of so called "quickfix" commands.  They enable you to compile a
    program from within Vim and then go through the errors generated and fix them
    (hopefully).  You can then recompile and fix any new errors that are found
    until finally your program compiles without any error.

    The following command runs the program "make" (supplying it with any argument
    you give) and captures the results:

    	:make {arguments}

    If errors were generated, they are captured and the editor positions you where
    the first error occurred.
       Take a look at an example ":make" session.  (Typical :make sessions generate
    far more errors and fewer stupid ones.)  After typing ":make" the screen looks
    like this:

    	:!make | &tee /tmp/vim215953.err
    	gcc -g -Wall -o prog main.c sub.c
    	main.c: In function 'main':
    	main.c:6: too many arguments to function 'do_sub'
    	main.c: At top level:
    	main.c:10: parse error before '}'
    	make: *** [prog] Error 1

    	2 returned
    	"main.c" 11L, 111C
    	(3 of 6): too many arguments to function 'do_sub'
    	Press ENTER or type command to continue

    From this you can see that you have errors in the file "main.c".  When you
    press <Enter>, Vim displays the file "main.c", with the cursor positioned on
    line 6, the first line with an error.  You did not need to specify the file or
    the line number, Vim knew where to go by looking in the error messages.

    		+---------------------------------------------------+
    		|int main()					    |
    		|{						    |
    		|	int i=3;				    |
          cursor -> |	do_sub("foo");				    |
    		|	++i;					    |
    		|	return (0);				    |
    		|}						    |
    		|}						    |
    		| ~						    |
    		|(3 of 12): too many arguments to function 'do_sub' |
    		+---------------------------------------------------+

    The following command goes to where the next error occurs:

    	:cnext

    Vim jumps to line 10, the last line in the file, where there is an extra '}'.
       When there is not enough room, Vim will shorten the error message.  To see
    the whole message use:

    	:cc

    You can get an overview of all the error messages with the ":clist" command.
    The output looks like this:

    	:clist
    	3 main.c: 6:too many arguments to function 'do_sub'
    	5 main.c: 10:parse error before '}'

    Only the lines where Vim recognized a file name and line number are listed
    here.  It assumes those are the interesting lines and the rest is just boring
    messages.  However, sometimes unrecognized lines do contain something you want
    to see.  Output from the linker, for example, about an undefined function.
    To see all the messages add a "!" to the command:

    	:clist!
    	1 gcc -g -Wall -o prog main.c sub.c
    	2 main.c: In function 'main':
    	3 main.c:6: too many arguments to function 'do_sub'
    	4 main.c: At top level:
    	5 main.c:10: parse error before '}'
    	6 make: *** [prog] Error 1

    Vim will highlight the current error.  To go back to the previous error, use:

    	:cprevious

    Other commands to move around in the error list:

    	:cfirst		to first error
    	:clast		to last error
    	:cc 3		to error nr 3

    USING ANOTHER COMPILER

    The name of the program to run when the ":make" command is executed is defined
    by the 'makeprg' option.  Usually this is set to "make", but Visual C++ users
    should set this to "nmake" by executing the following command:

    	:set makeprg=nmake

    You can also include arguments in this option.  Special characters need to
    be escaped with a backslash.  Example:

    	:set makeprg=nmake\ -f\ project.mak

    You can include special Vim keywords in the command specification.  The %
    character expands to the name of the current file.  So if you execute the
    command:
    	:set makeprg=make\ %:S

    When you are editing main.c, then ":make" executes the following command:

    	make main.c

    This is not too useful, so you will refine the command a little and use the :r
    (root) modifier:

    	:set makeprg=make\ %:r:S.o

    Now the command executed is as follows:

    	make main.o

    More about these modifiers here: |filename-modifiers|.

    OLD ERROR LISTS

    Suppose you ":make" a program.  There is a warning message in one file and an
    error message in another.  You fix the error and use ":make" again to check if
    it was really fixed.  Now you want to look at the warning message.  It doesn't
    show up in the last error list, since the file with the warning wasn't
    compiled again.  You can go back to the previous error list with:

    	:colder

    Then use ":clist" and ":cc {nr}" to jump to the place with the warning.
       To go forward to the next error list:

    	:cnewer

    Vim remembers ten error lists.

    SWITCHING COMPILERS

    You have to tell Vim what format the error messages are that your compiler
    produces.  This is done with the 'errorformat' option.  The syntax of this
    option is quite complicated and it can be made to fit almost any compiler.
    You can find the explanation here: |errorformat|.

    You might be using various different compilers.  Setting the 'makeprg' option,
    and especially the 'errorformat' each time is not easy.  Vim offers a simple
    method for this.  For example, to switch to using the Microsoft Visual C++
    compiler:

    	:compiler msvc

    This will find the Vim script for the "msvc" compiler and set the appropriate
    options.
       You can write your own compiler files.  See |write-compiler-plugin|.

    OUTPUT REDIRECTION

    The ":make" command redirects the output of the executed program to an error
    file.  How this works depends on various things, such as the 'shell'.  If your
    ":make" command doesn't capture the output, check the 'makeef' and
    'shellpipe' options.  The 'shellquote' and 'shellxquote' options might also
    matter.

    In case you can't get ":make" to redirect the file for you, an alternative is
    to compile the program in another window and redirect the output into a file.
    Then have Vim read this file with:

    	:cfile {filename}

    Jumping to errors will work like with the ":make" command.

    *30.2*	Indenting C style text

    A program is much easier to understand when the lines have been properly
    indented.  Vim offers various ways to make this less work.  For C or C style
    programs like Java or C++, set the 'cindent' option.  Vim knows a lot about C
    programs and will try very hard to automatically set the indent for you.  Set
    the 'shiftwidth' option to the amount of spaces you want for a deeper level.
    Four spaces will work fine.  One ":set" command will do it:

    	:set cindent shiftwidth=4

    With this option enabled, when you type something such as "if (x)", the next
    line will automatically be indented an additional level.

    				    if (flag)
    	Automatic indent   --->		do_the_work();
    	Automatic unindent <--	    if (other_flag) {
    	Automatic indent   --->		do_file();
    	keep indent			do_some_more();
    	Automatic unindent <--	    }

    When you type something in curly braces ({}), the text will be indented at the
    start and unindented at the end.  The unindenting will happen after typing the
    '}', since Vim can't guess what you are going to type.

    One side effect of automatic indentation is that it helps you catch errors in
    your code early.  When you type a } to finish a function, only to find that
    the automatic indentation gives it more indent than what you expected, there
    is probably a } missing.  Use the "%" command to find out which { matches the
    } you typed.
       A missing ) and ; also cause extra indent.  Thus if you get more white
    space than you would expect, check the preceding lines.

    When you have code that is badly formatted, or you inserted and deleted lines,
    you need to re-indent the lines.  The "=" operator does this.  The simplest
    form is:

    This indents the current line.  Like with all operators, there are three ways
    to use it.  In Visual mode "=" indents the selected lines.  A useful text
    object is "a{".  This selects the current {} block.  Thus, to re-indent the
    code block the cursor is in:

    	=a{

    If you have really badly indented code, you can re-indent the whole file with:

    	gg=G

    However, don't do this in files that have been carefully indented manually.
    The automatic indenting does a good job, but in some situations you might want
    to overrule it.

    SETTING INDENT STYLE

    Different people have different styles of indentation.  By default Vim does a
    pretty good job of indenting in a way that 90% of programmers do.  There are
    different styles, however; so if you want to, you can customize the
    indentation style with the 'cinoptions' option.
       By default 'cinoptions' is empty and Vim uses the default style.  You can
    add various items where you want something different.  For example, to make
    curly braces be placed like this:

    	if (flag)
    	  {
    	    i = 8;
    	    j = 0;
    	  }

    Use this command:

    	:set cinoptions+={2

    There are many of these items.  See |cinoptions-values|.

    *30.3*	Automatic indenting

    You don't want to switch on the 'cindent' option manually every time you edit
    a C file.  This is how you make it work automatically:

    	:filetype indent on

    Actually, this does a lot more than switching on 'cindent' for C files.  First
    of all, it enables detecting the type of a file.  That's the same as what is
    used for syntax highlighting.
       When the filetype is known, Vim will search for an indent file for this
    type of file.  The Vim distribution includes a number of these for various
    programming languages.  This indent file will then prepare for automatic
    indenting specifically for this file.

    If you don't like the automatic indenting, you can switch it off again:

    	:filetype indent off

    If you don't like the indenting for one specific type of file, this is how you
    avoid it.  Create a file with just this one line:

    	:let b:did_indent = 1

    Now you need to write this in a file with a specific name:

    	{directory}/indent/{filetype}.vim

    The {filetype} is the name of the file type, such as "cpp" or "java".  You can
    see the exact name that Vim detected with this command:

    	:set filetype

    In this file the output is:

    	filetype=help

    Thus you would use "help" for {filetype}.
       For the {directory} part you need to use your runtime directory.  Look at
    the output of this command:

    	set runtimepath

    Now use the first item, the name before the first comma.  Thus if the output
    looks like this:

    	runtimepath=~/.vim,/usr/local/share/vim/vim60/runtime,~/.vim/after

    You use "~/.vim" for {directory}.  Then the resulting file name is:

    	~/.vim/indent/help.vim

    Instead of switching the indenting off, you could write your own indent file.
    How to do that is explained here: |indent-expression|.

    *30.4*	Other indenting

    The simplest form of automatic indenting is with the 'autoindent' option.
    It uses the indent from the previous line.  A bit smarter is the 'smartindent'
    option.  This is useful for languages where no indent file is available.
    'smartindent' is not as smart as 'cindent', but smarter than 'autoindent'.
       With 'smartindent' set, an extra level of indentation is added for each {
    and removed for each }.  An extra level of indentation will also be added for
    any of the words in the 'cinwords' option.  Lines that begin with # are
    treated specially: all indentation is removed.  This is done so that
    preprocessor directives will all start in column 1.  The indentation is
    restored for the next line.

    CORRECTING INDENTS

    When you are using 'autoindent' or 'smartindent' to get the indent of the
    previous line, there will be many times when you need to add or remove one
    'shiftwidth' worth of indent.  A quick way to do this is using the CTRL-D and
    CTRL-T commands in Insert mode.
       For example, you are typing a shell script that is supposed to look like
    this:

    	if test -n a; then
    	   echo a
    	   echo "-------"
    	fi

    Start off by setting these options:

    	:set autoindent shiftwidth=3

    You start by typing the first line, <Enter> and the start of the second line:

    	if test -n a; then
    	echo

    Now you see that you need an extra indent.  Type CTRL-T.  The result:

    	if test -n a; then
    	   echo

    The CTRL-T command, in Insert mode, adds one 'shiftwidth' to the indent, no
    matter where in the line you are.
       You continue typing the second line, <Enter> and the third line.  This time
    the indent is OK.  Then <Enter> and the last line.  Now you have this:

    	if test -n a; then
    	   echo a
    	   echo "-------"
    	   fi

    To remove the superfluous indent in the last line press CTRL-D.  This deletes
    one 'shiftwidth' worth of indent, no matter where you are in the line.
       When you are in Normal mode, you can use the ">>" and "<<" commands to
    shift lines.  ">" and "<" are operators, thus you have the usual three ways to
    specify the lines you want to indent.  A useful combination is:

    	>i{

    This adds one indent to the current block of lines, inside {}.  The { and }
    lines themselves are left unmodified.  ">a{" includes them.  In this example
    the cursor is on "printf":

    	original text		after ">i{"		after ">a{"

    	if (flag)		if (flag)		if (flag)
    	{			{			    {
    	printf("yes");		    printf("yes");	    printf("yes");
    	flag = 0;		    flag = 0;		    flag = 0;
    	}			}			    }

    *30.5*	Tabs and spaces

    A QUICK HISTORY OF THE RATIONALE BEHIND TABS

    `vi` (the ancestor of Vim) was created by Bill Joy.  At the time, he was using
    a PDP-11 with limited memory and I/O operation capabilities.  Back then, it
    was common to optimize the size of source code with the following trick.
      The ASCII table was first designed to remotely control teleprinters.  When
    control character 9 (the Horizontal Tab, caret notation: ^I) was sent to a
    teleprinter, it would move the carriage to the next tab stop.  Assuming tab
    stops were separated by 8 columns (a typical standard), this means that a
    single control character could produce the same visual effect as up to 8 space
    characters.  For example, the following two lines will display identically

    	1234^I9
    	1234    9

    Using the <Tab> key was also faster than typing <Space> several times; the
    same was true for <BS>.

    THE ISSUE WITH TABS AND INDENTATION

    In Vim, the number of columns between two (virtual) horizontal tab stops
    is controlled by 'tabstop' and is set to eight by default.  Although you can
    change it, you quickly run into trouble later.  Other programs won't know what
    tabstop value you used.  They probably use the default value of eight, and
    your text suddenly looks very different.  Also, most printers use a fixed
    tabstop value of eight.  Thus it's best to keep 'tabstop' alone; if you edit a
    file which was written with a different tabstop setting, see |25.3| for how
    to fix that.
       For indenting lines in a program, using a multiple of eight columns makes
    you quickly run into the right border of the window.  Using a single space
    doesn't provide enough visual difference.  Many people prefer to use four
    spaces, a good compromise.
       Since a tab character at the beginning of a line is visually represented
    as eight spaces and you want to use an indent of four spaces, you can't use a
    tab character to make your indent.
      To remedy this, `vi` had the 'shiftwidth' option.  When set to 4, on a new
    line, pressing <C-t> in Insert mode would indent the line by 4 spaces,
    a result impossible to get with the <Tab> key and 'tabstop' set to 8.
     To optimize space, `vi` would also silently remove packs of spaces and replace
    them with tab characters.  The following shows what happens pressing <C-t>
    a few times.
      A "." stands for a space character and "------->" for a tab character.

    	type				result
    	<C-t>				....
    	<C-t><C-t>			------->
    	<C-t><C-t><C-t>			------->....

      Similarly pressing <C-d> in Insert mode would decrease the indent.  Hence
    with `set tabstop=8 shiftwidth=2` one has

    	type				result
    	<C-t><Tab><C-t>			..----->..
    	<C-t><Tab><C-t><C-d>		------->

      A third option that one could set in `vi` was 'autoindent'.  It copies the
    indent level of the previous lines,

    	type				result
    	<Space><Tab>hello		.------>hello
    	<Space><Tab>hello<Enter>	.------>hello
    					------->

    but the new line is produced by optimizing the number of characters used.

    JUST SPACES

    But separating tab stops with 8 columns was not universal: IBM had a standard
    at 10 columns, and today some Go developers write code with `tabstop=4`.  Every
    time text is displayed with a different 'tabstop' value, it risks misaligning
    the text, especially once the file is shared and opened on another machine.
      In the meantime, computers got much better and the few octets saved by using
    tabs were no longer making any real difference.  It became possible to use
    only spaces and thus guarantee the same resulting text everywhere.  But using
    only spaces was impossible in `vi` without sacrificing features.  Remember that
    'autoindent' would systematically try to input a tab character when it could.
      Vim 4.0 made working with only spaces as convenient as working only with
    tabs (or a mix of tabs and spaces), by introducing the 'expandtab' option.
    When set, Vim will replace any horizontal tab character it would normally
    insert with an equivalent number of spaces, to end up with the same visual
    effect. <BS> would continue to remove only one character at a time.

    	type				result
    	<Tab>				........
    	<Tab><BS>			.......

    CHANGING TABS IN SPACES (AND BACK)

    Setting 'expandtab' does not immediately affect existing tab characters.  In
    order to purge a file from all its horizontal tab characters, Vim 5.3
    introduced the |:retab| command.  Use these commands:

    	:set expandtab
    	:retab

    This is a little bit dangerous, because it can also change tabs inside a
    string.  To check if these exist, you could use this:

    	/"[^"\t]*\t[^"]*"

    It's recommended not to use actual tab characters inside a string.  Replace
    them with "\t" to avoid trouble.

      The other way around works just as well:

    	:set noexpandtab
    	:retab!

    SOFT TAB STOPS

    When using only spaces, or a mix of spaces and horizontal tabs, one gets the
    unpleasant feeling that the two keys <Tab> and <BS> do not act in mirror, as
    they do when using only tab characters.
      Vim 5.4 introduced the 'softtabstop' option.  On top of the (hard) tab stops
    used to display the horizontal tab characters in the text, Vim adds extra
    soft tab stops dedicated only to the cursor.  When 'softtabstop' is set to a
    positive value, and the <Tab> key will push the cursor to the next soft tab
    stop.  Vim will insert the correct combination of tab characters and spaces to
    make the effect visually.  Likewise pressing <BS> will have the cursor try to
    reach the nearest soft tab stop.  The following example uses
    `:set softtabstop=4`

    	type			result
    	<Tab>			....
    	<Tab><Tab>a		------->a
    	<Tab><Tab>a<Tab>	------->a...
    	<Tab><Tab>a<Tab><BS>	------->a

      To maintain global coherence, one can `:set softtabstop=-1` so that
    the value of 'shiftwidth' is use for the number of columns between two soft
    tab stops.

      If you prefer to have different values for 'shiftwidth' and 'softtabstop',
    you can still do so and use <C-t> to indent with 'shiftwidth'.  Or you can
    use the 'smarttab' option, allowing for a unified <Tab> key that knows what to
    do in the different situations.

    VARIABLE TAB STOPS

    As we said before, the ASCII table was designed to remotely control
    teleprinters.  A given teleprinter could be configured to have their physical
    tab stops have variable spacing.  After all, the ^I control character was
    only stipulating: go to the next tab stop wherever it is.
      Vim 7.3 introduced 'vartabstop' to emulate the same functionality.  For
    example if Vim was compiled with `+vartabs` and `:set vartabstop=2,4` one gets

    	actual character	result
    	^I			->
    	^I^I			->--->
    	^I^I^I			->--->--->

      Similarly, 'varsofttabstop' was also introduced, to have variably spaced
    soft tab stops.  With `:set varsofttabstop=2,4` one gets

    	type			  result
    	<Tab>			  ..
    	<Tab><Tab>		  ......
    	<Tab><Tab><Tab>		  ------->....

    EXAMPLES OF CONFIGURATION

    By default, Vim is configured to use only tabs:

    	:set tabstop=8
    	:set shiftwidth=8
    	:set noexpandtab
    	:set softtabstop=0
    	:set nosmarttab

      If you want to write C code as if it were Python (only spaces, with indents
    of 4 spaces), here is what you can use:

    	:set shiftwidth=4
    	:set softtabstop=-1
    	:set expandtab

      If you want the same behavior but with better control over alignment
    (e.g.  lining up parameters or comments in multiples of 2 spaces), use:

    	:set shiftwidth=4
    	:set softtabstop=2
    	:set expandtab
    	:set smarttab

      If instead, you would like to write C code like Bram Moolenaar would have
    (using a mix of tabs and spaces), you can use

    	:set shiftwidth=4
    	:set softtabstop=-1

    *30.6*	Formatting comments

    One of the great things about Vim is that it understands comments.  You can
    ask Vim to format a comment and it will do the right thing.
       Suppose, for example, that you have the following comment:

    	/*
    	 * This is a test
    	 * of the text formatting.
    	 */

    You then ask Vim to format it by positioning the cursor at the start of the
    comment and type:

    	gq]/

    "gq" is the operator to format text.  "]/" is the motion that takes you to the
    end of a comment.  The result is:

    	/*
    	 * This is a test of the text formatting.
    	 */

    Notice that Vim properly handled the beginning of each line.
      An alternative is to select the text that is to be formatted in Visual mode
    and type "gq".

    To add a new line to the comment, position the cursor on the middle line and
    press "o".  The result looks like this:

    	/*
    	 * This is a test of the text formatting.
    	 *
    	 */

    Vim has automatically inserted a star and a space for you.  Now you can type
    the comment text.  When it gets longer than 'textwidth', Vim will break the
    line.  Again, the star is inserted automatically:

    	/*
    	 * This is a test of the text formatting.
    	 * Typing a lot of text here will make Vim
    	 * break
    	 */

    For this to work some flags must be present in 'formatoptions':

    	r	insert the star when typing <Enter> in Insert mode
    	o	insert the star when using "o" or "O" in Normal mode
    	c	break comment text according to 'textwidth'

    See |fo-table| for more flags.

    DEFINING A COMMENT

    The 'comments' option defines what a comment looks like.  Vim distinguishes
    between a single-line comment and a comment that has a different start, end
    and middle part.
       Many single-line comments start with a specific character.  In C++ // is
    used, in Makefiles #, in Vim scripts ".  For example, to make Vim understand
    C++ comments:

    	:set comments=://

    The colon separates the flags of an item from the text by which the comment is
    recognized.  The general form of an item in 'comments' is:

    	{flags}:{text}

    The {flags} part can be empty, as in this case.
       Several of these items can be concatenated, separated by commas.  This
    allows recognizing different types of comments at the same time.  For example,
    let's edit an e-mail message.  When replying, the text that others wrote is
    preceded with ">" and "!" characters.  This command would work:

    	:set comments=n:>,n:!

    There are two items, one for comments starting with ">" and one for comments
    that start with "!".  Both use the flag "n".  This means that these comments
    nest.  Thus a line starting with ">" may have another comment after the ">".
    This allows formatting a message like this:

    	> ! Did you see that site?
    	> ! It looks really great.
    	> I don't like it.  The
    	> colors are terrible.
    	What is the URL of that
    	site?

    Try setting 'textwidth' to a different value, e.g., 80, and format the text by
    Visually selecting it and typing "gq".  The result is:

    	> ! Did you see that site?  It looks really great.
    	> I don't like it.  The colors are terrible.
    	What is the URL of that site?

    You will notice that Vim did not move text from one type of comment to
    another.  The "I" in the second line would have fit at the end of the first
    line, but since that line starts with "> !" and the second line with ">", Vim
    knows that this is a different kind of comment.

    A THREE PART COMMENT

    A C comment starts with "/*", has "*" in the middle and "*/" at the end.  The
    entry in 'comments' for this looks like this:

    	:set comments=s1:/*,mb:*,ex:*/

    The start is defined with "s1:/*".  The "s" indicates the start of a
    three-piece comment.  The colon separates the flags from the text by which the
    comment is recognized: "/*".  There is one flag: "1".  This tells Vim that the
    middle part has an offset of one space.
       The middle part "mb:*" starts with "m", which indicates it is a middle
    part.  The "b" flag means that a blank must follow the text.  Otherwise Vim
    would consider text like "*pointer" also to be the middle of a comment.
       The end part "ex:*/" has the "e" for identification.  The "x" flag has a
    special meaning.  It means that after Vim automatically inserted a star,
    typing / will remove the extra space.

    For more details see |format-comments|.

    Next chapter: |usr_31|  Exploiting the GUI

    Copyright: see |manual-copyright|  vim:tw=78:ts=8:noet:ft=help:norl:

Generated by vim2html on 16.10.2025