usr_44.txt ForVim version 9.2. Last change: 2026 Feb 14 VIM USER MANUALbyBramMoolenaar Your ownsyntax highlightedVim comes with highlighting fora couple of hundred different file types. Ifthe file you are editing isn't included, read this chapter to find out how toget this type of file highlighted. Also see:syn-define in thereferencemanual.44.1 Basicsyntax commands44.2 Keywords44.3 Matches44.4 Regions44.5 Nested items44.6 Following groups44.7 Other arguments44.8 Clusters44.9 Including anothersyntax file44.10 Synchronizing44.11 Installingasyntax file44.12 Portablesyntax file layout Next chapter:usr_45.txtSelect your language Previous chapter:usr_43.txt UsingfiletypesTable of contents:usr_toc.txt==============================================================================44.1 Basicsyntax commandsUsing an existingsyntax file to start with will save youa lot of time. Tryfindingasyntax file in $VIMRUNTIME/syntax fora language thatis similar.These files will also show you the normal layout ofasyntax file. Tounderstand it, you need to read the following.Let's start with the basic arguments. Before we start defining any newsyntax, we need to clear out any old definitions::syntax clearThis isn't required in the finalsyntax file, but very useful whenexperimenting.There are more simplifications in this chapter. If you arewritingasyntaxfile to be used by others, read all the way through theend to find out thedetails.LISTING DEFINED ITEMSTo check whichsyntax items are currently defined, use this command::syntaxYou can use this to check which items have actually been defined. Quiteuseful when you are experimenting witha newsyntax file. It also shows thecolors used for each item, which helps to find out whatis what. Tolist the items ina specificsyntax group use::syntax list {group-name}This also can be used tolist clusters (explained in44.8). Just includethe@ in the name.MATCHING CASESome languages are notcase sensitive, suchas Pascal. Others, suchas C, arecase sensitive. You need to tell which type you have with the followingcommands::syntax case match:syntax case ignoreThe "match" argument means that Vim will match thecase ofsyntax elements.Therefore, "int" differs from "Int" and "INT". If the "ignore" argumentisused, the following are equivalent: "Procedure", "PROCEDURE" and "procedure". The ":syntaxcase" commands can appear anywhere inasyntax file and affectthesyntaxdefinitions that follow. In most cases, you have only one ":syntaxcase" command in yoursyntax file; if you work with an unusual language thatcontains both case-sensitive and non-case-sensitive elements, however, you canscatter the ":syntaxcase" command throughout the file.==============================================================================44.2 KeywordsThe most basicsyntax elements are keywords. To definea keyword, use thefollowing form::syntax keyword {group} {keyword} ...The{group}is the name ofasyntax group. With the ":highlight" command youcan assign colors toa{group}. The{keyword} argumentis an actual keyword.Here area few examples::syntax keyword xType int long char:syntax keyword xStatement if then else endifThis example uses the group names "xType" and "xStatement". By convention,each group nameis prefixed by thefiletype for the language being defined.This example definessyntax for thex language (eXample language without aninteresting name). Inasyntax file for "csh" scripts the name "cshType"would be used. Thus the prefixis equal to the value of'filetype'. These commands cause the words "int", "long" and "char" to be highlightedone way and the words "if", "then", "else" and "endif" to be highlightedanother way. Now you need to connect thex group names to standard Vimnames. Youdo this with the following commands::highlight link xType Type:highlight link xStatement StatementThis tells Vim to highlight "xType" like "Type" and "xStatement" like"Statement". Seegroup-name for the standard names.UNUSUAL KEYWORDSThe characters used ina keywordmust be in the'iskeyword' option. If youuse another character, theword will never match. Vim doesn't givea warningmessage for this. Thex language uses the '-' character in keywords. Thisis how it's done::setlocal iskeyword+=-:syntax keyword xStatement when-notThe ":setlocal" commandis used to change'iskeyword' only for the currentbuffer. Stillit does change the behavior of commands like "w" and "*". Ifthatis not wanted, don't definea keyword but usea match (explained in thenext section).Thex language allows for abbreviations. For example, "next" can beabbreviated to "n", "ne" or "nex". You can define them by using this command::syntax keyword xStatement n[ext]This doesn't match "nextone", keywords always match whole words only.==============================================================================44.3 MatchesConsider defining somethinga bit more complex. You want to match ordinaryidentifiers. Todo this, you definea matchsyntax item. This one matchesanyword consisting of onlylowercase letters::syntax match xIdentifier /\<\l\+\>/Note:Keywords overrule any othersyntax item. Thus the keywords "if","then", etc., will be keywords,as defined with the ":syntax keyword"commands above, even though they also match thepattern forxIdentifier.The partat theendisa pattern, like it's used for searching. The//isused to surround thepattern (like how it's done ina ":substitute" command).You can use any other character, likea plus oraquote.Now definea match fora comment. In thex languageitis anything from# totheend ofa line::syntax match xComment /#.*/Since you can use any search pattern, you can highlight very complex thingswitha match item. Seepattern forhelp on search patterns.==============================================================================44.4 RegionsIn the examplex language, strings are enclosed in double quotation marks(").To highlight strings you definea region. You needa region start (doublequote) anda regionend (double quote). The definitionisas follows::syntax region xString start=/"/ end=/"/The "start" and "end" directives define the patterns used to find the startandend of the region. But what about strings that look like this?"A string with a double quote (\") in it"This createsa problem: The double quotation marks in the middle of thestringwillend the region. You need to tell Vim to skip over any escaped doublequotes in the string. Do this with the skip keyword::syntax region xString start=/"/ skip=/\\"/ end=/"/The doublebackslash matchesa single backslash, since thebackslashisaspecial character in search patterns.When to usea region instead ofa match? The main differenceis thata matchitemisa single pattern, whichmust matchasa whole.A region startsassoonas the "start"pattern matches. Whether the "end"patternis found ornot doesn't matter. Thus when the item depends on the "end"pattern to match,you cannot usea region. Otherwise, regions are often simpler to define. Anditis easier to use nested items,asis explained in the next section.==============================================================================44.5 Nested itemsTakea lookat this comment:%Get input TODO: Skip white spaceYou want to highlight TODO in big yellow letters, even thoughitis inacomment thatis highlighted blue. To let Vim know about this, you define thefollowingsyntax groups::syntax keyword xTodo TODO contained:syntax match xComment /%.*/ contains=xTodoIn the first line, the "contained" argument tells Vim that this keyword canexist only inside anothersyntax item. The next line has "contains=xTodo".This indicates that the xTodosyntax elementis inside it. The resultis thatthe comment lineasa wholeis matched with "xComment" and made blue. Theword TODO insideitis matched by xTodo and highlighted yellow (highlightingfor xTodo was setup for this).RECURSIVE NESTINGThex language defines code blocks in curly braces. Anda code block maycontain other code blocks. This can be defined this way::syntax region xBlock start=/{/ end=/}/ contains=xBlockSuppose you have this text:while i < b {if a {b = c;}}Firsta xBlock startsat the{ in the first line. In the second line another{is found. Since we are insidea xBlock item, andit contains itself,anested xBlock item will start here. Thus the "b=c" lineis inside thesecond level xBlock region. Thena}is found in the next line, which matcheswith theendpattern of the region. This ends the nested xBlock. Because the}is included in the nested region,itis hidden from the first xBlock region.Thenat the last} the first xBlock region ends.KEEPING THE ENDConsider the following twosyntax items::syntax region xComment start=/%/ end=/$/ contained:syntax region xPreProc start=/#/ end=/$/ contains=xCommentYou definea commentas anything from% to theend of the line.Apreprocessor directiveis anything from# to theend of the line. Because youcan havea comment ona preprocessor line, the preprocessor definitionincludesa "contains=xComment" argument. Now look what happens with thistext:#define X = Y % Comment textint foo = 1;What you seeis that the second lineis also highlightedas xPreProc. Thepreprocessor directive shouldendat theend of the line. Thatis whyyou have used "end=/$/". So whatis going wrong? The problemis the contained comment. The comment starts with% and endsat theend of the line. After the comment ends, the preprocessorsyntaxcontinues. Thisis after theend of the line has been seen, so the nextlineis includedas well. To avoid this problem and to avoida containedsyntax item eatinga neededend of line, use the "keepend" argument. This takes care ofthe double end-of-line matching::syntax region xComment start=/%/ end=/$/ contained:syntax region xPreProc start=/#/ end=/$/ contains=xComment keependCONTAINING MANY ITEMSYou can use the contains argument to specify that everything can be contained.For example::syntax region xList start=/\[/ end=/\]/ contains=ALLAllsyntax items will be contained in this one. It also contains itself, butnotat the same position (that would cause an endless loop). You can specify that some groups are not contained. Thus contain allgroups but the ones that are listed::syntax region xList start=/\[/ end=/\]/ contains=ALLBUT,xStringWith the "TOP" item you can include all items that don't havea "contained"argument. "CONTAINED"is used to only include items witha "contained"argument. See:syn-contains for the details.==============================================================================44.6 Following groupsThex language has statements in this form:if (condition) thenYou want to highlight the three items differently. But "(condition)" and"then" might also appear in other places, where they get differenthighlighting. Thisis how you cando this::syntax match xIf /if/ nextgroup=xIfCondition skipwhite:syntax match xIfCondition /([^)]*)/ contained nextgroup=xThen skipwhite:syntax match xThen /then/ containedThe "nextgroup" argumentspecifies which item can come next. Thisis notrequired. If none of the items that are specified are found, nothing happens.For example, in this text:if not (condition) thenThe "if"is matched by xIf. "not" doesn't match the specified nextgroupxIfCondition, thus only the "if"is highlighted.The "skipwhite" argument tells Vim that whitespace (spaces and tabs) mayappear in between the items. Similar arguments are "skipnl", which allowsaline break in between the items, and "skipempty", which allows empty lines.Notice that "skipnl" doesn't skip an empty line, somethingmust match afterthe line break.==============================================================================44.7 Other argumentsMATCHGROUPWhen you definea region, the entire regionis highlighted according to thegroup name specified. To highlight the text enclosed in parentheses () withthe group xInside, for example, use the following command::syntax region xInside start=/(/ end=/)/Suppose, that you want to highlight the parentheses differently. You candothis witha lot of convoluted region statements, or you can use the"matchgroup" argument. This tells Vim to highlight the start andend ofaregion witha different highlight group (in this case, the xParen group)::syntax region xInside matchgroup=xParen start=/(/ end=/)/The "matchgroup" argument applies to the start orend match that comes afterit. In the previous example both start andend are highlighted with xParen.To highlight theend with xParenEnd::syntax region xInside matchgroup=xParen start=/(/\ matchgroup=xParenEnd end=/)/A side effect of using "matchgroup"is that contained items will not match inthe start orend of the region. The example for "transparent" uses this.TRANSPARENTInaC language file you would like to highlight the () text aftera "while"differently from the () text aftera "for". In both of these there can benested () items, which should be highlighted in the same way. Youmust makesure the () highlighting stopsat the matching ). Thisis one way todo this::syntax region cWhile matchgroup=cWhile start=/while\s*(/ end=/)/\ contains=cCondNest:syntax region cFor matchgroup=cFor start=/for\s*(/ end=/)/\ contains=cCondNest:syntax region cCondNest start=/(/ end=/)/ contained transparentNow you can give cWhile and cFor different highlighting. The cCondNest itemcan appear in either of them, but take over the highlighting of the itemitiscontained in. The "transparent" argument causes this. Notice that the "matchgroup" argument has the same groupas the itemitself. Why defineit then? Well, the side effect of usinga matchgroupisthat contained items are not found in the match with the start item then.This avoids that the cCondNest group matches the( just after the "while" or"for". If this would happen,it would span the whole text until the matching) and the region would continue after it. Now cCondNest only matches afterthe match with the start pattern, thus after the first (.OFFSETSSuppose you want to definea region for the text between( and) after an"if". But you don't want to include the "if" or the( and ). You cando thisby specifying offsets for the patterns. Example::syntax region xCond start=/if\s*(/ms=e+1 end=/)/me=s-1The offset for the startpatternis "ms=e+1". "ms" stands for Match Start.This defines an offset for the start of the match. Normally the match startswhere thepattern matches. "e+1" means that the match now startsat theendof thepattern match, and then one character further. The offset for theendpatternis "me=s-1". "me" stands for Match End."s-1" means the start of thepattern match and then one character back. Theresultis that in this text:if (foo == bar)Only the text "foo==bar" will be highlightedas xCond.More about offsets here::syn-pattern-offset.ONELINEThe "oneline" argument indicates that the region does not crossa lineboundary. For example::syntax region xIfThen start=/if/ end=/then/ onelineThis definesa region that startsat "if" and endsat "then". But if thereisno "then" after the "if", the region doesn't match.Note:When using "oneline" the region doesn't start if theendpatterndoesn't match in the same line. Without "oneline" Vim does _not_check if thereisa match for theend pattern. The region starts evenwhen theendpattern doesn't match in the rest of the file.CONTINUATION LINES AND AVOIDING THEMThings now becomea little more complex. Let's definea preprocessor line.This starts witha# in the first column and continues until theend of theline.A line that ends with \ makes the next linea continuation line. Theway you handle thisis to allow thesyntax item to containa continuationpattern::syntax region xPreProc start=/^#/ end=/$/ contains=xLineContinue:syntax match xLineContinue "\\$" containedIn this case, although xPreProc normally matchesa single line, the groupcontained init (namely xLineContinue) letsitgo on for more than one line.For example,it would match both of these lines:#define SPAM spam spam spam \bacon and spamIn this case, thisis what you want. Ifitis not what you want, you can callfor the region to be ona single line by adding "excludenl" to the containedpattern. For example, you want to highlight "end" in xPreProc, but onlyattheend of the line. To avoid making the xPreProc continue on the next line,like xLineContinue does, use "excludenl" like this::syntax region xPreProc start=/^#/ end=/$/\ contains=xLineContinue,xPreProcEnd:syntax match xPreProcEnd excludenl /end$/ contained:syntax match xLineContinue "\\$" contained"excludenl"must be placed before the pattern. Since "xLineContinue" doesn'thave "excludenl",a match withit will extend xPreProc to the next lineasbefore.==============================================================================44.8 ClustersOne of the things you will noticeas you start to writeasyntax fileis thatyou wind up generatinga lot ofsyntax groups. Vim enables you to defineacollection ofsyntax groups calleda cluster. Suppose you havea language that contains for loops, if statements, whileloops, and functions. Each of them contains the samesyntax elements: numbersand identifiers. You define them like this::syntax match xFor /^for.*/ contains=xNumber,xIdent:syntax match xIf /^if.*/ contains=xNumber,xIdent:syntax match xWhile /^while.*/ contains=xNumber,xIdentYou have to repeat the same "contains=" every time. If you want to addanother contained item, you have to addit three times.Syntax clusterssimplify thesedefinitions by enabling you to have one cluster stand forseveralsyntax groups. To definea cluster for the two items that the three groups contain, usethe following command::syntax cluster xState contains=xNumber,xIdentClusters are used inside othersyntax items just like anysyntax group.Their names start with @. Thus, you can define the three groups like this::syntax match xFor /^for.*/ contains=@xState:syntax match xIf /^if.*/ contains=@xState:syntax match xWhile /^while.*/ contains=@xStateYou can add new group names to this cluster with the "add" argument::syntax cluster xState add=xStringYou can removesyntax groups from thislistas well::syntax cluster xState remove=xNumber==============================================================================44.9 Including anothersyntax fileThe C++ languagesyntaxisa superset of theC language. Because youdo notwant to write twosyntax files, you can have the C++syntax file read in theone forC by using the following command::runtime! syntax/c.vimThe ":runtime!" command searches'runtimepath' for all "syntax/c.vim" files.This makes theC parts of the C++syntax be defined like forC files. If youhave replaced thec.vimsyntax file, or added items with an extra file, thesewill be loadedas well. After loading theCsyntax items the specific C++ items can be defined.For example, add keywords that are not used in C::syntax keyword cppStatementnew delete this friend usingThis works just like in any othersyntax file.Now consider thePerl language.APerlscript consists of two distinct parts:a documentationsection in POD format, anda program written inPerl itself.The PODsection starts with "=head" and ends with "=cut". You want to define the PODsyntax in one file, and useit from thePerlsyntax file. The ":syntax include" command reads inasyntax file and storesthe elementsit defined inasyntax cluster. For Perl, the statements areasfollows::syntax include @Pod <sfile>:p:h/pod.vim:syntax region perlPOD start=/^=head/ end=/^=cut/ contains=@PodWhen "=head"is found inaPerl file, the perlPOD region starts. In thisregion the @Pod clusteris contained. All the items definedas top-levelitems in the pod.vimsyntax files will match here. When "=cut"is found, theregion ends and wego back to the items defined in thePerl file. The ":syntax include" commandis clever enough to ignorea ":syntax clear"command in the included file. And an argument suchas "contains=ALL" willonly contain items defined in the included file, not in the file that includesit. The "<sfile>:p:h/" part uses the name of the current file (<sfile>),expandsit toa full path (:p) and then takes the head (:h). This results inthe directory name of the file. This causes the pod.vim file in the samedirectory to be included.==============================================================================44.10 SynchronizingCompilers haveit easy. They startat the beginning ofa file and parseitstraight through. Vim does not haveit so easy. Itmust start in the middle,where the editingis being done. So how doesit tell whereit is? The secretis the ":syntax sync" command. This tells Vim how to figure outwhereit is. For example, the following command tells Vim to scan backwardfor the beginning orend ofa C-style comment and beginsyntaxcoloring fromthere::syntax sync ccommentYou can tune this processing with some arguments. The "minlines" argumenttells Vim the minimum number of lines to look backward, and "maxlines" tellsthe editor the maximum number of lines to scan. For example, the following command tells Vim to lookat least 10 linesbefore the top of the screen::syntax sync ccomment minlines=10 maxlines=500Ifit cannot figure out whereitis in that space,it starts looking fartherand farther back untilit figures out what to do. Butit looks no fartherback than 500 lines. (A large "maxlines" slows down processing.A small onemight cause synchronization to fail.) To make synchronizinggoa bit faster, tell Vim whichsyntax items can beskipped. Every match and region that only needs to be used when actuallydisplaying text can be given the "display" argument. By default, the comment to be found will be coloredas part of the Commentsyntax group. If you want to color things another way, you can specifyadifferentsyntax group::syntax sync ccomment xAltCommentIf your programming language does not have C-style comments in it, you can tryanothermethod of synchronization. The simplest wayis to tell Vim tospacebacka number of lines and try to figure out things from there. The followingcommand tells Vim togo back 150 lines and start parsing from there::syntax sync minlines=150A large "minlines" value can make Vim slower, especially whenscrollingbackwards in the file. Finally, you can specifyasyntax group to look for by using this command::syntax sync match {sync-group-name}\ grouphere {group-name} {pattern}This tells Vim that whenit sees{pattern} thesyntax group named{group-name}begins just after thepattern given. The{sync-group-name}is used to giveaname to this synchronization specification. For example, the sh scriptinglanguage begins an if statement with "if" and endsit with "fi":if [ --f file.txt ] ; thenecho "File exists"fiTo definea "grouphere" directive for this syntax, you use the followingcommand::syntax sync match shIfSync grouphere shIf "\<if\>"The "groupthere" argument tells Vim that thepattern endsa group. Forexample, theend of the if/fi groupisas follows::syntax sync match shIfSync groupthere NONE "\<fi\>"In this example, the NONE tells Vim that you are not in any specialsyntaxregion. In particular, you are not inside an if block.You also can define matches and regions that are with no "grouphere" or"groupthere" arguments. These groups are forsyntax groups skipped duringsynchronization. For example, the following skips over anything inside {},even ifit would normally match another synchronization method::syntax sync match xSpecial /{.*}/More about synchronizing in thereference manual::syn-sync.==============================================================================44.11 Installingasyntax fileWhen your newsyntax fileis ready to be used, dropit ina "syntax" directoryin'runtimepath'. ForUnix that would be "~/.vim/syntax". The name of thesyntax filemust be equal to the file type, with ".vim"added. Thus for thex language, the full path of the file would be:~/.vim/syntax/x.vimYoumust also make the file type be recognized. See43.2.If your file works well, you might want to makeit available to other Vimusers. First read the nextsection to make sure your file works well forothers. Then e-mailit to the Vim maintainer: <maintainer@vim.org>. Alsoexplain how thefiletype can be detected. Witha bit of luck your file willbe included in the next Vim version!ADDING TO AN EXISTING SYNTAX FILEWe were assuming you were addinga completely newsyntax file. When anexistingsyntax file works, butis missing some items, you can add items inaseparate file. That avoidschanging the distributedsyntax file, which willbe lost when installinga new version of Vim. Writesyntax commands in your file, possibly using group names from theexisting syntax. For example, to add new variable types to theCsyntax file::syntax keyword cType off_t uintWrite the file with the same nameas the originalsyntax file. In thiscase"c.vim". Placeit ina directory near theend of'runtimepath'. This makesit loaded after the originalsyntax file. ForUnix this would be:~/.vim/after/syntax/c.vim==============================================================================44.12 Portablesyntax file layoutWouldn'tit be nice if all Vim users exchangesyntax files? To make thispossible, thesyntax filemust followa few guidelines.Start witha header that explains what thesyntax fileis for, who maintainsit and whenit was last updated. Don't include too much information aboutchanges history, not many people will read it. Example:" Vim syntax file" Language:C" Maintainer:Bram Moolenaar <Bram@vim.org>" Last Change:2001 Jun 18" Remark:Included by the C++ syntax.Use the same layoutas the othersyntax files. Using an existingsyntax fileas an example will save youa lot of time.Choosea good, descriptive name for yoursyntax file. Uselowercase lettersand digits. Don't makeit too long,itis used in many places: The name ofthesyntax file "name.vim",'filetype', b:current_syntax and the start of eachsyntax group (nameType, nameStatement, nameString, etc).Start witha check for "b:current_syntax". Ifitis defined, some othersyntax file, earlier in'runtimepath' was already loaded:if exists("b:current_syntax") finishendifSet "b:current_syntax" to the name of thesyntaxat the end. Don't forgetthat included filesdo this too, you might have to reset "b:current_syntax" ifyou include two files.Do not include anything thatisa user preference. Don't set'tabstop','expandtab', etc. These belong inafiletype plugin.Do not include mappings or abbreviations. Only include setting'iskeyword' ifitis really necessary for recognizing keywords.To allow users select their own preferred colors, makea different group namefor every kind of highlighted item. Then link each of them to one of thestandard highlight groups. That will makeit work with every color scheme.If you select specific colorsit will look bad with some color schemes. Anddon't forget that some people usea different background color, or have onlyeight colors available.For the linking use "hi def link", so that the user can select differenthighlighting before yoursyntax fileis loaded. Example: hi def link nameStringString hi def link nameNumberNumber hi def link nameCommandStatement ... etc ...Add the "display" argument to items that are not used when syncing, to speedupscrolling backwards andCTRL-L.==============================================================================Next chapter:usr_45.txtSelect your languageCopyright: seemanual-copyright vim:tw=78:ts=8:noet:ft=help:norl: