usr_30.txt ForVim version 9.2. Last change: 2026 Feb 14 VIM USER MANUALbyBramMoolenaar Editing programsVim hasvarious commands that aid inwriting computer programs. Compileaprogram and directly jump to reported errors. Automatically set the indentfor many languages and format comments.30.1 Compiling30.2 IndentingC files30.3 Automatic indenting30.4 Other indenting30.5 Tabs and spaces30.6 Formatting comments Next chapter:usr_31.txt Exploiting theGUI Previous chapter:usr_29.txt Moving through programsTable of contents:usr_toc.txt==============================================================================30.1 CompilingVim hasa set of so called "quickfix" commands. They enable you to compileaprogram from within Vim and thengo through theerrors generated and fix them(hopefully). You can then recompile and fix any newerrors that are founduntil finally your program compiles without any error.The following command runs the program "make" (supplyingit with any argumentyou give) and captures the results::make {arguments}Iferrors were generated, they are captured and the editor positions you wherethe first error occurred. Takea lookat an example ":make" session. (Typical:make sessionsgenerate far moreerrors and fewer stupid ones.) After typing ":make" thescreen looks like this::!make | &tee /tmp/vim215953.errgcc -g -Wall -o prog main.c sub.cmain.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 12 returned"main.c" 11L, 111C(3 of 6): too many arguments to function 'do_sub'Press ENTER or type command to continueFrom this you can see that you haveerrors in the file "main.c". When youpress<Enter>, Vim displays the file "main.c", with the cursor positioned online 6, the first line with an error. You did not need to specify the file orthe line number, Vim knew where togo 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::cnextVim jumps to line 10, the last line in the file, where thereis an extra '}'. When thereis not enough room, Vim will shorten the error message. To seethe whole message use::ccYou can get an overview of all the errormessages with the ":clist" command.The output looks like this::clist3 main.c: 6:too many arguments to function 'do_sub'5 main.c: 10:parse error before '}'Only the lines where Vim recognizeda file name and line number are listedhere. It assumes those are the interesting lines and the restis just boringmessages. However, sometimes unrecognized linesdo contain something you wantto see. Output from the linker, for example, about an undefined function.To see all themessages adda "!" to the command::clist!1 gcc -g -Wall -o prog main.c sub.c2 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 1Vim will highlight the current error. Togo back to the previous error, use::cpreviousOther commands to move around in the error list::cfirstto first error:clastto last error:cc 3to error nr 3USING ANOTHER COMPILERThe name of the program to run when the ":make" commandis executedis definedby the'makeprg' option. Usually thisis set to "make", butVisual C++ usersshould set this to "nmake" by executing the following command::set makeprg=nmakeYou can also include arguments in this option.Special characters need tobe escaped witha backslash. Example::set makeprg=nmake\ -f\ project.makYou can include special Vim keywords in the command specification. The%character expands to the name of the current file. So if you execute thecommand::set makeprg=make\ %:SWhen you are editing main.c, then ":make" executes the following command:make main.cThisis not too useful, so you will refine the commanda little and use the:r(root) modifier::set makeprg=make\ %:r:S.oNow the command executedisas follows:make main.oMore about these modifiers here:filename-modifiers.OLD ERROR LISTSSuppose you ":make"a program. Thereisa warning message in one file and anerror message in another. You fix the error and use ":make" again to check ifit was really fixed. Now you want to lookat the warning message. It doesn'tshow up in the last error list, since the file with the warning wasn'tcompiled again. You cango back to the previous errorlist with::colderThen use ":clist" and ":cc{nr}" to jump to the place with the warning. Togo forward to the next error list::cnewerVim remembers ten error lists.SWITCHING COMPILERSYou have to tell Vim what format the errormessages are that your compilerproduces. Thisis done with the'errorformat' option. Thesyntax of thisoptionis quite complicated andit can be made to fit almost any compiler.You can find the explanation here:errorformat.You might be usingvarious different compilers. Setting the'makeprg' option,and especially the'errorformat' each timeis not easy. Vim offersa simplemethod for this. For example, to switch to using the MicrosoftVisual C++compiler::compiler msvcThis will find the Vimscript for the "msvc" compiler and set the appropriateoptions. You can write your own compiler files. Seewrite-compiler-plugin.OUTPUT REDIRECTIONThe ":make" command redirects the output of the executed program to an errorfile. How this works depends onvarious things, suchas the'shell'. If your":make" command doesn't capture the output, check the'makeef' and'shellpipe' options. The'shellquote' and'shellxquote'options might alsomatter.Incase you can't get ":make" to redirect the file for you, an alternativeisto compile the program in anotherwindow and redirect the output intoa file.Then have Vim read this file with::cfile {filename}Jumping toerrors will work like with the ":make" command.==============================================================================30.2 IndentingC style textA programis much easier to understand when the lines have been properlyindented. Vim offersvarious ways to make thisless work. ForC orC styleprograms like Java or C++, set the'cindent' option. Vim knowsa lot aboutCprograms and will try very hard to automatically set the indent for you. Setthe'shiftwidth' option to the amount of spaces you want fora deeper level.Four spaces will work fine. One ":set" command willdo it::set cindent shiftwidth=4With this option enabled, when you type something suchas "if (x)", the nextline will automatically be indented an additional level. if (flag)Automatic indent --->do_the_work();Automatic unindent <-- if (other_flag){Automatic indent --->do_file();keep indentdo_some_more();Automatic unindent <--}When you type something in curly braces ({}), the text will be indentedat thestart and unindentedat 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 indentationis thatit helps you catcherrors inyour code early. When you typea} to finisha function, only to find thatthe automatic indentation givesit more indent than what you expected, thereis probablya} missing. Use the "%" command to find out which{ matches the} you typed.A missing) and; also cause extra indent. Thus if you get more whitespace than you would expect, check the preceding lines.When you have code thatis badly formatted, or you inserted and deleted lines,you need to re-indent the lines. The "="operator does this. The simplestform is:==This indents the current line. Like with all operators, there are three waysto use it. InVisual mode "=" indents the selected lines.A useful textobjectis "a{". This selects the current{} block. Thus, to re-indent thecode block the cursoris in:=a{If you have really badly indented code, you can re-indent the whole file with:gg=GHowever, don'tdo this in files that have been carefully indented manually.The automatic indenting doesa good job, but in some situations you might wantto overrule it.SETTING INDENT STYLEDifferent people have different styles of indentation. By default Vim doesapretty goodjob of indenting ina way that 90% of programmers do. There aredifferent styles, however; so if you want to, you can customize theindentation style with the'cinoptions' option. By default'cinoptions'is empty and Vim uses the default style. You canaddvarious items where you want something different. For example, to makecurly braces be placed like this:if (flag) { i = 8; j = 0; }Use this command::set cinoptions+={2There are many of these items. Seecinoptions-values.==============================================================================30.3 Automatic indentingYou don't want to switch on the'cindent' option manually every time you editaC file. Thisis how you makeit work automatically::filetype indent onActually, this doesa lot more than switching on'cindent' forC files. Firstof all,it enables detecting the type ofa file. That's the sameas whatisused forsyntax highlighting. When thefiletypeis known, Vim will search for an indent file for thistype of file. The Vimdistribution includesa number of these forvariousprogramming languages. This indent file will then prepare for automaticindenting specifically for this file.If you don't like the automatic indenting, you can switchit off again::filetype indent offIf you don't like the indenting for one specific type of file, thisis how youavoid it. Createa file with just this one line::let b:did_indent = 1Now you need to write this ina file witha specific name:{directory}/indent/{filetype}.vimThe{filetype}is the name of the file type, suchas "cpp" or "java". You cansee the exact name that Vim detected with this command::set filetypeIn this file the output is:filetype=helpThus you would use "help" for{filetype}. For the{directory} part you need to use your runtime directory. Lookatthe output of this command:set runtimepathNow use the first item, the name before the first comma. Thus if the outputlooks like this:runtimepath=~/.vim,/usr/local/share/vim/vim60/runtime,~/.vim/afterYou use "~/.vim" for{directory}. Then the resulting file name is:~/.vim/indent/help.vimInstead of switching the indenting off, you could write your own indent file.How todo thatis explained here:indent-expression.==============================================================================30.4 Other indentingThe simplest form of automatic indentingis with the'autoindent' option.It uses the indent from the previous line.A bit smarteris the'smartindent'option. Thisis useful for languages where no indent fileis available.'smartindent'is notas smartas'cindent', but smarter than'autoindent'. With'smartindent' set, an extra level of indentationis added for each{and removed for each }. An extra level of indentation will also be added forany of the words in the'cinwords' option. Lines that begin with# aretreated specially: all indentationis removed. Thisis done so thatpreprocessor directives will all start in column 1. The indentationisrestored for the next line.CORRECTING INDENTSWhen you are using'autoindent' or'smartindent' to get the indent of theprevious line, there will be many times when you need to add or remove one'shiftwidth' worth of indent.A quick way todo thisis using theCTRL-D andCTRL-T commands inInsert mode. For example, you are typinga shellscript thatis supposed to look likethis:if test -n a; then echo a echo "-------"fiStart off by setting these options::set autoindent shiftwidth=3You start by typing the first line,<Enter> and the start of the second line:if test -n a; thenechoNow you see that you need an extra indent. TypeCTRL-T. The result:if test -n a; then echoTheCTRL-T command, inInsert mode, adds one'shiftwidth' to the indent, nomatter where in the line you are. You continue typing the second line,<Enter> and the third line. This timethe indentis OK. Then<Enter> and the last line. Now you have this:if test -n a; then echo a echo "-------" fiTo remove the superfluous indent in the last line pressCTRL-D. This deletesone'shiftwidth' worth of indent, no matter where you are in the line. When you are inNormal mode, you can use the ">>" and "<<" commands toshift lines. ">" and "<" are operators, thus you have the usual three ways tospecify 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 examplethe cursoris on "printf":original textafter ">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 spacesA QUICK HISTORY OF THE RATIONALE BEHIND TABSvi (the ancestor of Vim) was created by Bill Joy. At the time, he was usinga PDP-11 with limited memory and I/O operation capabilities. Back then,itwas common to optimize the size of source code with the following trick. The ASCII table was first designed to remotelycontrol teleprinters. Whencontrol character 9 (the Horizontal Tab, caret notation: ^I) was sent toateleprinter,it would move the carriage to the nexttab stop. Assumingtabstops were separated by 8 columns (a typical standard), this means thatasinglecontrol character could produce the same visual effectas up to 8spacecharacters. For example, the following two lines will display identically1234^I91234 9Using the<Tab> key was also faster than typing<Space> several times; thesame wastrue for<BS>.THE ISSUE WITH TABS AND INDENTATIONIn Vim, the number of columns between two (virtual) horizontaltab stopsis controlled by'tabstop' andis set to eight by default. Although you canchange it, you quickly run into trouble later. Other programs won't know whattabstop value you used. They probably use the default value of eight, andyour text suddenly looks very different. Also, most printers usea fixedtabstop value of eight. Thus it's best to keep'tabstop' alone; if you editafile which was written witha different tabstop setting, see25.3 for howto fix that. For indenting lines ina program, usinga multiple of eight columns makesyou quickly run into the right border of the window. Usinga singlespacedoesn't provide enough visual difference. Many people prefer to use fourspaces,a good compromise. Sinceatab characterat the beginning ofa lineis visually representedas eight spaces and you want to use an indent of four spaces, you can't useatab character to make your indent. To remedy this,vi had the'shiftwidth' option. When set to 4, ona newline, pressing<C-t> inInsert 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 replacethem withtab characters. The following shows what happens pressing<C-t>a few times.A "." stands foraspace character and "------->" foratab character.typeresult<C-t>....<C-t><C-t>-------><C-t><C-t><C-t>------->.... Similarly pressing<C-d> inInsert mode would decrease the indent. Hencewith `set tabstop=8 shiftwidth=2` one hastyperesult<C-t><Tab><C-t>..----->..<C-t><Tab><C-t><C-d>------->A third option that one could set invi was'autoindent'. It copies theindent level of the previous lines,typeresult<Space><Tab>hello.------>hello<Space><Tab>hello<Enter>.------>hello------->but the new lineis produced by optimizing the number of characters used.JUST SPACESBut separatingtab stops with 8 columns was not universal: IBM hada standardat 10 columns, and today some Go developers write code withtabstop=4. Everytime textis displayed witha different'tabstop' value,it risks misaligningthe text, especially once the fileis shared and opened on another machine. In the meantime, computers got much better and the few octets saved by usingtabs were no longer making any real difference. It became possible to useonly spaces and thus guarantee the same resulting text everywhere. But usingonly spaces was impossible invi without sacrificing features. Remember that'autoindent' would systematically try to inputatab character whenit could. Vim 4.0 made working with only spacesas convenientas working only withtabs (ora mix of tabs and spaces), by introducing the'expandtab' option.When set, Vim will replace any horizontaltab characterit would normallyinsert with an equivalent number of spaces, toend up with the same visualeffect.<BS> would continue to remove only one characterata time.typeresult<Tab>........<Tab><BS>.......CHANGING TABS IN SPACES (AND BACK)Setting'expandtab' does not immediately affect existingtab characters. Inorder to purgea file from all its horizontaltab characters, Vim 5.3introduced the:retab command. Use these commands::set expandtab:retabThisisa little bit dangerous, becauseit can also change tabs insideastring. To check if these exist, you could use this:/"[^"\t]*\t[^"]*"It's recommended not to use actualtab characters insidea string.Replacethem with "\t" to avoid trouble. The other way around works justas well::set noexpandtab:retab!SOFT TAB STOPSWhen using only spaces, ora mix of spaces and horizontal tabs, one gets theunpleasant feeling that the two keys<Tab> and<BS>do not act in mirror,astheydo when using onlytab characters. Vim 5.4 introduced the'softtabstop' option. On top of the (hard)tab stopsused to display the horizontaltab characters in the text, Vim adds extrasofttab stops dedicated only to the cursor. When'softtabstop'is set toapositive value, and the<Tab> key will push the cursor to the next softtabstop. Vim willinsert the correct combination oftab characters and spaces tomake the effect visually. Likewise pressing<BS> will have the cursor try toreach the nearest softtab stop. The following example uses`:set softtabstop=4`typeresult<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 thatthe value of'shiftwidth'is used for the number of columns between two softtab stops. If you prefer to have different values for'shiftwidth' and'softtabstop',you can stilldo so and use<C-t> to indent with'shiftwidth'. Or you canuse the'smarttab' option, allowing fora unified<Tab> key that knows what todo in the different situations.VARIABLE TAB STOPSAs we said before, the ASCII table was designed to remotelycontrolteleprinters.A given teleprinter could be configured to have their physicaltab stops have variable spacing. After all, the ^Icontrol character wasonly stipulating:go to the nexttab stop whereverit is. Vim 7.3 introduced'vartabstop' to emulate the same functionality. Forexample if Vim was compiled with+vartabs and `:set vartabstop=2,4` one getsactual characterresult^I->^I^I->--->^I^I^I->--->---> Similarly,'varsofttabstop' was also introduced, to have variably spacedsofttab stops. With `:set varsofttabstop=2,4` one getstype result<Tab> ..<Tab><Tab> ......<Tab><Tab><Tab> ------->....EXAMPLES OF CONFIGURATIONBy default, Vimis configured to use only tabs::set tabstop=8:set shiftwidth=8:set noexpandtab:set softtabstop=0:set nosmarttab If you want to writeC codeas ifit werePython (only spaces, with indentsof 4 spaces), hereis what you can use::set shiftwidth=4:set softtabstop=-1:set expandtab If you want the same behavior but with bettercontrol 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 writeC code likeBramMoolenaar would have(usinga mix of tabs and spaces), you can use:set shiftwidth=4:set softtabstop=-1==============================================================================30.6 Formatting commentsOne of the great things about Vimis thatit understands comments. You canask Vim to formata comment andit willdo 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 formatit by positioning the cursorat the start of thecomment and type:gq]/"gq"is theoperator to format text. "]/"is the motion that takes you to theend ofa comment. The result is:/* * This is a test of the text formatting. */Notice that Vim properly handled the beginning of each line. An alternativeis to select the text thatis to be formatted inVisual modeand type "gq".To adda new line to the comment, position the cursor on the middle line andpress "o". The result looks like this:/* * This is a test of the text formatting. * */Vim has automatically insertedastar andaspace for you. Now you can typethe comment text. Whenit gets longer than'textwidth', Vim will break theline. Again, thestaris 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 flagsmust be present in'formatoptions':rinsert thestar when typing<Enter> inInsert modeoinsert thestar when using "o" or "O" inNormal modecbreak comment text according to'textwidth'Seefo-table for more flags.DEFINING A COMMENTThe'comments' option defines whata comment looks like. Vim distinguishesbetweena single-line comment anda comment that hasa different start,endand middle part. Many single-line comments start witha specific character. In C++//isused, in Makefiles #, in Vim scripts ". For example, to make Vim understandC++ comments::set comments=://The colon separates the flags of an item from the text by which the commentisrecognized. 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. Thisallows recognizing different types of commentsat the same time. For example,let's edit an e-mail message. When replying, the text that others wroteispreceded with ">" and "!" characters. This command would work::set comments=n:>,n:!There are two items, one for commentsstarting with ">" and one for commentsthat start with "!". Both use the flag "n". This means that these commentsnest. Thusa linestarting with ">" may have another comment after the ">".This allowsformattinga 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 thatsite?Try setting'textwidth' toa different value, e.g., 80, and format the text byVisually selectingit 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 toanother. The "I" in the second line would have fitat theend of the firstline, but since that line starts with ">!" and the second line with ">", Vimknows that thisisa different kind of comment.A THREE PART COMMENTAC comment starts with "/*", has "*" in the middle and "*/"at the end. Theentry in'comments' for this looks like this::set comments=s1:/*,mb:*,ex:*/The startis defined with "s1:/*". The "s" indicates the start ofathree-piece comment. The colon separates the flags from the text by which thecommentis recognized: "/*". Thereis one flag: "1". This tells Vim that themiddle part has an offset of one space. The middle part "mb:*" starts with "m", which indicatesitisa middlepart. The "b" flag means thata blankmust follow the text. Otherwise Vimwould consider text like "*pointer" also to be the middle ofa comment. Theend part "ex:*/" has the "e" for identification. The "x" flag hasaspecial meaning. It means that after Vim automatically inserteda star,typing/ will remove the extra space.For more details seeformat-comments.==============================================================================Next chapter:usr_31.txt Exploiting theGUICopyright: seemanual-copyright vim:tw=78:ts=8:noet:ft=help:norl: