Christian Brabandt | b4ddc6c | 2024-01-02 16:51:11 +0100 | [diff] [blame] | 1 | *usr_44.txt* For Vim version 9.1. Last change: 2017 May 06 |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 2 | |
| 3 | VIM USER MANUAL - by Bram Moolenaar |
| 4 | |
| 5 | Your own syntax highlighted |
| 6 | |
| 7 | |
| 8 | Vim comes with highlighting for a couple of hundred different file types. If |
| 9 | the file you are editing isn't included, read this chapter to find out how to |
| 10 | get this type of file highlighted. Also see |:syn-define| in the reference |
| 11 | manual. |
| 12 | |
| 13 | |44.1| Basic syntax commands |
| 14 | |44.2| Keywords |
| 15 | |44.3| Matches |
| 16 | |44.4| Regions |
| 17 | |44.5| Nested items |
| 18 | |44.6| Following groups |
| 19 | |44.7| Other arguments |
| 20 | |44.8| Clusters |
| 21 | |44.9| Including another syntax file |
| 22 | |44.10| Synchronizing |
| 23 | |44.11| Installing a syntax file |
| 24 | |44.12| Portable syntax file layout |
| 25 | |
| 26 | Next chapter: |usr_45.txt| Select your language |
| 27 | Previous chapter: |usr_43.txt| Using filetypes |
| 28 | Table of contents: |usr_toc.txt| |
| 29 | |
| 30 | ============================================================================== |
| 31 | *44.1* Basic syntax commands |
| 32 | |
| 33 | Using an existing syntax file to start with will save you a lot of time. Try |
| 34 | finding a syntax file in $VIMRUNTIME/syntax for a language that is similar. |
| 35 | These files will also show you the normal layout of a syntax file. To |
| 36 | understand it, you need to read the following. |
| 37 | |
| 38 | Let's start with the basic arguments. Before we start defining any new |
| 39 | syntax, we need to clear out any old definitions: > |
| 40 | |
| 41 | :syntax clear |
| 42 | |
| 43 | This isn't required in the final syntax file, but very useful when |
| 44 | experimenting. |
| 45 | |
| 46 | There are more simplifications in this chapter. If you are writing a syntax |
| 47 | file to be used by others, read all the way through the end to find out the |
| 48 | details. |
| 49 | |
| 50 | |
| 51 | LISTING DEFINED ITEMS |
| 52 | |
| 53 | To check which syntax items are currently defined, use this command: > |
| 54 | |
| 55 | :syntax |
| 56 | |
| 57 | You can use this to check which items have actually been defined. Quite |
| 58 | useful when you are experimenting with a new syntax file. It also shows the |
| 59 | colors used for each item, which helps to find out what is what. |
| 60 | To list the items in a specific syntax group use: > |
| 61 | |
| 62 | :syntax list {group-name} |
| 63 | |
| 64 | This also can be used to list clusters (explained in |44.8|). Just include |
| 65 | the @ in the name. |
| 66 | |
| 67 | |
| 68 | MATCHING CASE |
| 69 | |
| 70 | Some languages are not case sensitive, such as Pascal. Others, such as C, are |
| 71 | case sensitive. You need to tell which type you have with the following |
| 72 | commands: > |
| 73 | :syntax case match |
| 74 | :syntax case ignore |
| 75 | |
| 76 | The "match" argument means that Vim will match the case of syntax elements. |
| 77 | Therefore, "int" differs from "Int" and "INT". If the "ignore" argument is |
| 78 | used, the following are equivalent: "Procedure", "PROCEDURE" and "procedure". |
| 79 | The ":syntax case" commands can appear anywhere in a syntax file and affect |
| 80 | the syntax definitions that follow. In most cases, you have only one ":syntax |
| 81 | case" command in your syntax file; if you work with an unusual language that |
| 82 | contains both case-sensitive and non-case-sensitive elements, however, you can |
| 83 | scatter the ":syntax case" command throughout the file. |
| 84 | |
| 85 | ============================================================================== |
| 86 | *44.2* Keywords |
| 87 | |
| 88 | The most basic syntax elements are keywords. To define a keyword, use the |
| 89 | following form: > |
| 90 | |
| 91 | :syntax keyword {group} {keyword} ... |
| 92 | |
| 93 | The {group} is the name of a syntax group. With the ":highlight" command you |
| 94 | can assign colors to a {group}. The {keyword} argument is an actual keyword. |
| 95 | Here are a few examples: > |
| 96 | |
| 97 | :syntax keyword xType int long char |
| 98 | :syntax keyword xStatement if then else endif |
| 99 | |
| 100 | This example uses the group names "xType" and "xStatement". By convention, |
| 101 | each group name is prefixed by the filetype for the language being defined. |
| 102 | This example defines syntax for the x language (eXample language without an |
| 103 | interesting name). In a syntax file for "csh" scripts the name "cshType" |
| 104 | would be used. Thus the prefix is equal to the value of 'filetype'. |
| 105 | These commands cause the words "int", "long" and "char" to be highlighted |
| 106 | one way and the words "if", "then", "else" and "endif" to be highlighted |
| 107 | another way. Now you need to connect the x group names to standard Vim |
| 108 | names. You do this with the following commands: > |
| 109 | |
| 110 | :highlight link xType Type |
| 111 | :highlight link xStatement Statement |
| 112 | |
| 113 | This tells Vim to highlight "xType" like "Type" and "xStatement" like |
| 114 | "Statement". See |group-name| for the standard names. |
| 115 | |
| 116 | |
| 117 | UNUSUAL KEYWORDS |
| 118 | |
| 119 | The characters used in a keyword must be in the 'iskeyword' option. If you |
| 120 | use another character, the word will never match. Vim doesn't give a warning |
| 121 | message for this. |
| 122 | The x language uses the '-' character in keywords. This is how it's done: |
| 123 | > |
| 124 | :setlocal iskeyword+=- |
| 125 | :syntax keyword xStatement when-not |
| 126 | |
| 127 | The ":setlocal" command is used to change 'iskeyword' only for the current |
| 128 | buffer. Still it does change the behavior of commands like "w" and "*". If |
| 129 | that is not wanted, don't define a keyword but use a match (explained in the |
| 130 | next section). |
| 131 | |
| 132 | The x language allows for abbreviations. For example, "next" can be |
| 133 | abbreviated to "n", "ne" or "nex". You can define them by using this command: |
| 134 | > |
| 135 | :syntax keyword xStatement n[ext] |
| 136 | |
| 137 | This doesn't match "nextone", keywords always match whole words only. |
| 138 | |
| 139 | ============================================================================== |
| 140 | *44.3* Matches |
| 141 | |
| 142 | Consider defining something a bit more complex. You want to match ordinary |
| 143 | identifiers. To do this, you define a match syntax item. This one matches |
| 144 | any word consisting of only lowercase letters: > |
| 145 | |
| 146 | :syntax match xIdentifier /\<\l\+\>/ |
| 147 | < |
| 148 | Note: |
| 149 | Keywords overrule any other syntax item. Thus the keywords "if", |
| 150 | "then", etc., will be keywords, as defined with the ":syntax keyword" |
| 151 | commands above, even though they also match the pattern for |
| 152 | xIdentifier. |
| 153 | |
| 154 | The part at the end is a pattern, like it's used for searching. The // is |
| 155 | used to surround the pattern (like how it's done in a ":substitute" command). |
| 156 | You can use any other character, like a plus or a quote. |
| 157 | |
| 158 | Now define a match for a comment. In the x language it is anything from # to |
| 159 | the end of a line: > |
| 160 | |
| 161 | :syntax match xComment /#.*/ |
| 162 | |
| 163 | Since you can use any search pattern, you can highlight very complex things |
| 164 | with a match item. See |pattern| for help on search patterns. |
| 165 | |
| 166 | ============================================================================== |
| 167 | *44.4* Regions |
| 168 | |
| 169 | In the example x language, strings are enclosed in double quotation marks ("). |
| 170 | To highlight strings you define a region. You need a region start (double |
| 171 | quote) and a region end (double quote). The definition is as follows: > |
| 172 | |
| 173 | :syntax region xString start=/"/ end=/"/ |
| 174 | |
| 175 | The "start" and "end" directives define the patterns used to find the start |
| 176 | and end of the region. But what about strings that look like this? |
| 177 | |
| 178 | "A string with a double quote (\") in it" ~ |
| 179 | |
| 180 | This creates a problem: The double quotation marks in the middle of the string |
| 181 | will end the region. You need to tell Vim to skip over any escaped double |
| 182 | quotes in the string. Do this with the skip keyword: > |
| 183 | |
| 184 | :syntax region xString start=/"/ skip=/\\"/ end=/"/ |
| 185 | |
| 186 | The double backslash matches a single backslash, since the backslash is a |
| 187 | special character in search patterns. |
| 188 | |
| 189 | When to use a region instead of a match? The main difference is that a match |
| 190 | item is a single pattern, which must match as a whole. A region starts as |
| 191 | soon as the "start" pattern matches. Whether the "end" pattern is found or |
| 192 | not doesn't matter. Thus when the item depends on the "end" pattern to match, |
| 193 | you cannot use a region. Otherwise, regions are often simpler to define. And |
| 194 | it is easier to use nested items, as is explained in the next section. |
| 195 | |
| 196 | ============================================================================== |
| 197 | *44.5* Nested items |
| 198 | |
| 199 | Take a look at this comment: |
| 200 | |
| 201 | %Get input TODO: Skip white space ~ |
| 202 | |
| 203 | You want to highlight TODO in big yellow letters, even though it is in a |
| 204 | comment that is highlighted blue. To let Vim know about this, you define the |
| 205 | following syntax groups: > |
| 206 | |
| 207 | :syntax keyword xTodo TODO contained |
| 208 | :syntax match xComment /%.*/ contains=xTodo |
| 209 | |
| 210 | In the first line, the "contained" argument tells Vim that this keyword can |
| 211 | exist only inside another syntax item. The next line has "contains=xTodo". |
| 212 | This indicates that the xTodo syntax element is inside it. The result is that |
| 213 | the comment line as a whole is matched with "xComment" and made blue. The |
| 214 | word TODO inside it is matched by xTodo and highlighted yellow (highlighting |
| 215 | for xTodo was setup for this). |
| 216 | |
| 217 | |
| 218 | RECURSIVE NESTING |
| 219 | |
| 220 | The x language defines code blocks in curly braces. And a code block may |
| 221 | contain other code blocks. This can be defined this way: > |
| 222 | |
| 223 | :syntax region xBlock start=/{/ end=/}/ contains=xBlock |
| 224 | |
| 225 | Suppose you have this text: |
| 226 | |
| 227 | while i < b { ~ |
| 228 | if a { ~ |
| 229 | b = c; ~ |
| 230 | } ~ |
| 231 | } ~ |
| 232 | |
| 233 | First a xBlock starts at the { in the first line. In the second line another |
| 234 | { is found. Since we are inside a xBlock item, and it contains itself, a |
| 235 | nested xBlock item will start here. Thus the "b = c" line is inside the |
| 236 | second level xBlock region. Then a } is found in the next line, which matches |
| 237 | with the end pattern of the region. This ends the nested xBlock. Because the |
| 238 | } is included in the nested region, it is hidden from the first xBlock region. |
| 239 | Then at the last } the first xBlock region ends. |
| 240 | |
| 241 | |
| 242 | KEEPING THE END |
| 243 | |
| 244 | Consider the following two syntax items: > |
| 245 | |
| 246 | :syntax region xComment start=/%/ end=/$/ contained |
| 247 | :syntax region xPreProc start=/#/ end=/$/ contains=xComment |
| 248 | |
| 249 | You define a comment as anything from % to the end of the line. A |
| 250 | preprocessor directive is anything from # to the end of the line. Because you |
| 251 | can have a comment on a preprocessor line, the preprocessor definition |
| 252 | includes a "contains=xComment" argument. Now look what happens with this |
| 253 | text: |
| 254 | |
| 255 | #define X = Y % Comment text ~ |
| 256 | int foo = 1; ~ |
| 257 | |
| 258 | What you see is that the second line is also highlighted as xPreProc. The |
| 259 | preprocessor directive should end at the end of the line. That is why |
| 260 | you have used "end=/$/". So what is going wrong? |
| 261 | The problem is the contained comment. The comment starts with % and ends |
| 262 | at the end of the line. After the comment ends, the preprocessor syntax |
| 263 | continues. This is after the end of the line has been seen, so the next |
| 264 | line is included as well. |
| 265 | To avoid this problem and to avoid a contained syntax item eating a needed |
| 266 | end of line, use the "keepend" argument. This takes care of |
| 267 | the double end-of-line matching: > |
| 268 | |
| 269 | :syntax region xComment start=/%/ end=/$/ contained |
| 270 | :syntax region xPreProc start=/#/ end=/$/ contains=xComment keepend |
| 271 | |
| 272 | |
| 273 | CONTAINING MANY ITEMS |
| 274 | |
| 275 | You can use the contains argument to specify that everything can be contained. |
| 276 | For example: > |
| 277 | |
| 278 | :syntax region xList start=/\[/ end=/\]/ contains=ALL |
| 279 | |
| 280 | All syntax items will be contained in this one. It also contains itself, but |
| 281 | not at the same position (that would cause an endless loop). |
| 282 | You can specify that some groups are not contained. Thus contain all |
| 283 | groups but the ones that are listed: |
| 284 | > |
| 285 | :syntax region xList start=/\[/ end=/\]/ contains=ALLBUT,xString |
| 286 | |
| 287 | With the "TOP" item you can include all items that don't have a "contained" |
| 288 | argument. "CONTAINED" is used to only include items with a "contained" |
| 289 | argument. See |:syn-contains| for the details. |
| 290 | |
| 291 | ============================================================================== |
| 292 | *44.6* Following groups |
| 293 | |
| 294 | The x language has statements in this form: |
| 295 | |
| 296 | if (condition) then ~ |
| 297 | |
| 298 | You want to highlight the three items differently. But "(condition)" and |
| 299 | "then" might also appear in other places, where they get different |
| 300 | highlighting. This is how you can do this: > |
| 301 | |
| 302 | :syntax match xIf /if/ nextgroup=xIfCondition skipwhite |
| 303 | :syntax match xIfCondition /([^)]*)/ contained nextgroup=xThen skipwhite |
| 304 | :syntax match xThen /then/ contained |
| 305 | |
| 306 | The "nextgroup" argument specifies which item can come next. This is not |
| 307 | required. If none of the items that are specified are found, nothing happens. |
| 308 | For example, in this text: |
| 309 | |
| 310 | if not (condition) then ~ |
| 311 | |
| 312 | The "if" is matched by xIf. "not" doesn't match the specified nextgroup |
| 313 | xIfCondition, thus only the "if" is highlighted. |
| 314 | |
| 315 | The "skipwhite" argument tells Vim that white space (spaces and tabs) may |
| 316 | appear in between the items. Similar arguments are "skipnl", which allows a |
| 317 | line break in between the items, and "skipempty", which allows empty lines. |
| 318 | Notice that "skipnl" doesn't skip an empty line, something must match after |
| 319 | the line break. |
| 320 | |
| 321 | ============================================================================== |
| 322 | *44.7* Other arguments |
| 323 | |
| 324 | MATCHGROUP |
| 325 | |
| 326 | When you define a region, the entire region is highlighted according to the |
| 327 | group name specified. To highlight the text enclosed in parentheses () with |
| 328 | the group xInside, for example, use the following command: > |
| 329 | |
| 330 | :syntax region xInside start=/(/ end=/)/ |
| 331 | |
| 332 | Suppose, that you want to highlight the parentheses differently. You can do |
| 333 | this with a lot of convoluted region statements, or you can use the |
| 334 | "matchgroup" argument. This tells Vim to highlight the start and end of a |
| 335 | region with a different highlight group (in this case, the xParen group): > |
| 336 | |
| 337 | :syntax region xInside matchgroup=xParen start=/(/ end=/)/ |
| 338 | |
| 339 | The "matchgroup" argument applies to the start or end match that comes after |
| 340 | it. In the previous example both start and end are highlighted with xParen. |
| 341 | To highlight the end with xParenEnd: > |
| 342 | |
| 343 | :syntax region xInside matchgroup=xParen start=/(/ |
| 344 | \ matchgroup=xParenEnd end=/)/ |
| 345 | |
| 346 | A side effect of using "matchgroup" is that contained items will not match in |
| 347 | the start or end of the region. The example for "transparent" uses this. |
| 348 | |
| 349 | |
| 350 | TRANSPARENT |
| 351 | |
| 352 | In a C language file you would like to highlight the () text after a "while" |
| 353 | differently from the () text after a "for". In both of these there can be |
| 354 | nested () items, which should be highlighted in the same way. You must make |
| 355 | sure the () highlighting stops at the matching ). This is one way to do this: |
| 356 | > |
| 357 | :syntax region cWhile matchgroup=cWhile start=/while\s*(/ end=/)/ |
| 358 | \ contains=cCondNest |
| 359 | :syntax region cFor matchgroup=cFor start=/for\s*(/ end=/)/ |
| 360 | \ contains=cCondNest |
| 361 | :syntax region cCondNest start=/(/ end=/)/ contained transparent |
| 362 | |
| 363 | Now you can give cWhile and cFor different highlighting. The cCondNest item |
| 364 | can appear in either of them, but take over the highlighting of the item it is |
| 365 | contained in. The "transparent" argument causes this. |
| 366 | Notice that the "matchgroup" argument has the same group as the item |
| 367 | itself. Why define it then? Well, the side effect of using a matchgroup is |
| 368 | that contained items are not found in the match with the start item then. |
| 369 | This avoids that the cCondNest group matches the ( just after the "while" or |
| 370 | "for". If this would happen, it would span the whole text until the matching |
| 371 | ) and the region would continue after it. Now cCondNest only matches after |
| 372 | the match with the start pattern, thus after the first (. |
| 373 | |
| 374 | |
| 375 | OFFSETS |
| 376 | |
| 377 | Suppose you want to define a region for the text between ( and ) after an |
| 378 | "if". But you don't want to include the "if" or the ( and ). You can do this |
| 379 | by specifying offsets for the patterns. Example: > |
| 380 | |
| 381 | :syntax region xCond start=/if\s*(/ms=e+1 end=/)/me=s-1 |
| 382 | |
| 383 | The offset for the start pattern is "ms=e+1". "ms" stands for Match Start. |
| 384 | This defines an offset for the start of the match. Normally the match starts |
| 385 | where the pattern matches. "e+1" means that the match now starts at the end |
| 386 | of the pattern match, and then one character further. |
| 387 | The offset for the end pattern is "me=s-1". "me" stands for Match End. |
| 388 | "s-1" means the start of the pattern match and then one character back. The |
| 389 | result is that in this text: |
| 390 | |
| 391 | if (foo == bar) ~ |
| 392 | |
| 393 | Only the text "foo == bar" will be highlighted as xCond. |
| 394 | |
| 395 | More about offsets here: |:syn-pattern-offset|. |
| 396 | |
| 397 | |
| 398 | ONELINE |
| 399 | |
| 400 | The "oneline" argument indicates that the region does not cross a line |
| 401 | boundary. For example: > |
| 402 | |
| 403 | :syntax region xIfThen start=/if/ end=/then/ oneline |
| 404 | |
| 405 | This defines a region that starts at "if" and ends at "then". But if there is |
| 406 | no "then" after the "if", the region doesn't match. |
| 407 | |
| 408 | Note: |
| 409 | When using "oneline" the region doesn't start if the end pattern |
| 410 | doesn't match in the same line. Without "oneline" Vim does _not_ |
| 411 | check if there is a match for the end pattern. The region starts even |
| 412 | when the end pattern doesn't match in the rest of the file. |
| 413 | |
| 414 | |
| 415 | CONTINUATION LINES AND AVOIDING THEM |
| 416 | |
| 417 | Things now become a little more complex. Let's define a preprocessor line. |
| 418 | This starts with a # in the first column and continues until the end of the |
| 419 | line. A line that ends with \ makes the next line a continuation line. The |
| 420 | way you handle this is to allow the syntax item to contain a continuation |
| 421 | pattern: > |
| 422 | |
| 423 | :syntax region xPreProc start=/^#/ end=/$/ contains=xLineContinue |
| 424 | :syntax match xLineContinue "\\$" contained |
| 425 | |
| 426 | In this case, although xPreProc normally matches a single line, the group |
| 427 | contained in it (namely xLineContinue) lets it go on for more than one line. |
| 428 | For example, it would match both of these lines: |
| 429 | |
| 430 | #define SPAM spam spam spam \ ~ |
| 431 | bacon and spam ~ |
| 432 | |
| 433 | In this case, this is what you want. If it is not what you want, you can call |
| 434 | for the region to be on a single line by adding "excludenl" to the contained |
| 435 | pattern. For example, you want to highlight "end" in xPreProc, but only at |
| 436 | the end of the line. To avoid making the xPreProc continue on the next line, |
| 437 | like xLineContinue does, use "excludenl" like this: > |
| 438 | |
| 439 | :syntax region xPreProc start=/^#/ end=/$/ |
| 440 | \ contains=xLineContinue,xPreProcEnd |
| 441 | :syntax match xPreProcEnd excludenl /end$/ contained |
| 442 | :syntax match xLineContinue "\\$" contained |
| 443 | |
| 444 | "excludenl" must be placed before the pattern. Since "xLineContinue" doesn't |
| 445 | have "excludenl", a match with it will extend xPreProc to the next line as |
| 446 | before. |
| 447 | |
| 448 | ============================================================================== |
| 449 | *44.8* Clusters |
| 450 | |
| 451 | One of the things you will notice as you start to write a syntax file is that |
| 452 | you wind up generating a lot of syntax groups. Vim enables you to define a |
| 453 | collection of syntax groups called a cluster. |
| 454 | Suppose you have a language that contains for loops, if statements, while |
| 455 | loops, and functions. Each of them contains the same syntax elements: numbers |
| 456 | and identifiers. You define them like this: > |
| 457 | |
| 458 | :syntax match xFor /^for.*/ contains=xNumber,xIdent |
| 459 | :syntax match xIf /^if.*/ contains=xNumber,xIdent |
| 460 | :syntax match xWhile /^while.*/ contains=xNumber,xIdent |
| 461 | |
| 462 | You have to repeat the same "contains=" every time. If you want to add |
| 463 | another contained item, you have to add it three times. Syntax clusters |
| 464 | simplify these definitions by enabling you to have one cluster stand for |
| 465 | several syntax groups. |
| 466 | To define a cluster for the two items that the three groups contain, use |
| 467 | the following command: > |
| 468 | |
| 469 | :syntax cluster xState contains=xNumber,xIdent |
| 470 | |
| 471 | Clusters are used inside other syntax items just like any syntax group. |
| 472 | Their names start with @. Thus, you can define the three groups like this: > |
| 473 | |
| 474 | :syntax match xFor /^for.*/ contains=@xState |
| 475 | :syntax match xIf /^if.*/ contains=@xState |
| 476 | :syntax match xWhile /^while.*/ contains=@xState |
| 477 | |
| 478 | You can add new group names to this cluster with the "add" argument: > |
| 479 | |
| 480 | :syntax cluster xState add=xString |
| 481 | |
| 482 | You can remove syntax groups from this list as well: > |
| 483 | |
| 484 | :syntax cluster xState remove=xNumber |
| 485 | |
| 486 | ============================================================================== |
| 487 | *44.9* Including another syntax file |
| 488 | |
| 489 | The C++ language syntax is a superset of the C language. Because you do not |
| 490 | want to write two syntax files, you can have the C++ syntax file read in the |
| 491 | one for C by using the following command: > |
| 492 | |
| 493 | :runtime! syntax/c.vim |
| 494 | |
| 495 | The ":runtime!" command searches 'runtimepath' for all "syntax/c.vim" files. |
Bram Moolenaar | 8f3f58f | 2010-01-06 20:52:26 +0100 | [diff] [blame] | 496 | This makes the C parts of the C++ syntax be defined like for C files. If you |
| 497 | have replaced the c.vim syntax file, or added items with an extra file, these |
| 498 | will be loaded as well. |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 499 | After loading the C syntax items the specific C++ items can be defined. |
| 500 | For example, add keywords that are not used in C: > |
| 501 | |
| 502 | :syntax keyword cppStatement new delete this friend using |
| 503 | |
| 504 | This works just like in any other syntax file. |
| 505 | |
Bram Moolenaar | 8f3f58f | 2010-01-06 20:52:26 +0100 | [diff] [blame] | 506 | Now consider the Perl language. A Perl script consists of two distinct parts: |
| 507 | a documentation section in POD format, and a program written in Perl itself. |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 508 | The POD section starts with "=head" and ends with "=cut". |
| 509 | You want to define the POD syntax in one file, and use it from the Perl |
| 510 | syntax file. The ":syntax include" command reads in a syntax file and stores |
| 511 | the elements it defined in a syntax cluster. For Perl, the statements are as |
| 512 | follows: > |
| 513 | |
| 514 | :syntax include @Pod <sfile>:p:h/pod.vim |
| 515 | :syntax region perlPOD start=/^=head/ end=/^=cut/ contains=@Pod |
| 516 | |
| 517 | When "=head" is found in a Perl file, the perlPOD region starts. In this |
| 518 | region the @Pod cluster is contained. All the items defined as top-level |
| 519 | items in the pod.vim syntax files will match here. When "=cut" is found, the |
| 520 | region ends and we go back to the items defined in the Perl file. |
| 521 | The ":syntax include" command is clever enough to ignore a ":syntax clear" |
| 522 | command in the included file. And an argument such as "contains=ALL" will |
| 523 | only contain items defined in the included file, not in the file that includes |
| 524 | it. |
| 525 | The "<sfile>:p:h/" part uses the name of the current file (<sfile>), |
| 526 | expands it to a full path (:p) and then takes the head (:h). This results in |
| 527 | the directory name of the file. This causes the pod.vim file in the same |
| 528 | directory to be included. |
| 529 | |
| 530 | ============================================================================== |
| 531 | *44.10* Synchronizing |
| 532 | |
| 533 | Compilers have it easy. They start at the beginning of a file and parse it |
| 534 | straight through. Vim does not have it so easy. It must start in the middle, |
| 535 | where the editing is being done. So how does it tell where it is? |
| 536 | The secret is the ":syntax sync" command. This tells Vim how to figure out |
| 537 | where it is. For example, the following command tells Vim to scan backward |
| 538 | for the beginning or end of a C-style comment and begin syntax coloring from |
| 539 | there: > |
| 540 | |
| 541 | :syntax sync ccomment |
| 542 | |
| 543 | You can tune this processing with some arguments. The "minlines" argument |
| 544 | tells Vim the minimum number of lines to look backward, and "maxlines" tells |
| 545 | the editor the maximum number of lines to scan. |
| 546 | For example, the following command tells Vim to look at least 10 lines |
| 547 | before the top of the screen: > |
| 548 | |
| 549 | :syntax sync ccomment minlines=10 maxlines=500 |
| 550 | |
| 551 | If it cannot figure out where it is in that space, it starts looking farther |
| 552 | and farther back until it figures out what to do. But it looks no farther |
Bram Moolenaar | 402d2fe | 2005-04-15 21:00:38 +0000 | [diff] [blame] | 553 | back than 500 lines. (A large "maxlines" slows down processing. A small one |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 554 | might cause synchronization to fail.) |
| 555 | To make synchronizing go a bit faster, tell Vim which syntax items can be |
| 556 | skipped. Every match and region that only needs to be used when actually |
| 557 | displaying text can be given the "display" argument. |
| 558 | By default, the comment to be found will be colored as part of the Comment |
| 559 | syntax group. If you want to color things another way, you can specify a |
| 560 | different syntax group: > |
| 561 | |
| 562 | :syntax sync ccomment xAltComment |
| 563 | |
| 564 | If your programming language does not have C-style comments in it, you can try |
| 565 | another method of synchronization. The simplest way is to tell Vim to space |
| 566 | back a number of lines and try to figure out things from there. The following |
| 567 | command tells Vim to go back 150 lines and start parsing from there: > |
| 568 | |
| 569 | :syntax sync minlines=150 |
| 570 | |
| 571 | A large "minlines" value can make Vim slower, especially when scrolling |
| 572 | backwards in the file. |
| 573 | Finally, you can specify a syntax group to look for by using this command: |
| 574 | > |
| 575 | :syntax sync match {sync-group-name} |
| 576 | \ grouphere {group-name} {pattern} |
| 577 | |
| 578 | This tells Vim that when it sees {pattern} the syntax group named {group-name} |
| 579 | begins just after the pattern given. The {sync-group-name} is used to give a |
| 580 | name to this synchronization specification. For example, the sh scripting |
| 581 | language begins an if statement with "if" and ends it with "fi": |
| 582 | |
| 583 | if [ --f file.txt ] ; then ~ |
| 584 | echo "File exists" ~ |
| 585 | fi ~ |
| 586 | |
| 587 | To define a "grouphere" directive for this syntax, you use the following |
| 588 | command: > |
| 589 | |
| 590 | :syntax sync match shIfSync grouphere shIf "\<if\>" |
| 591 | |
| 592 | The "groupthere" argument tells Vim that the pattern ends a group. For |
| 593 | example, the end of the if/fi group is as follows: > |
| 594 | |
| 595 | :syntax sync match shIfSync groupthere NONE "\<fi\>" |
| 596 | |
| 597 | In this example, the NONE tells Vim that you are not in any special syntax |
| 598 | region. In particular, you are not inside an if block. |
| 599 | |
| 600 | You also can define matches and regions that are with no "grouphere" or |
| 601 | "groupthere" arguments. These groups are for syntax groups skipped during |
| 602 | synchronization. For example, the following skips over anything inside {}, |
| 603 | even if it would normally match another synchronization method: > |
| 604 | |
| 605 | :syntax sync match xSpecial /{.*}/ |
| 606 | |
| 607 | More about synchronizing in the reference manual: |:syn-sync|. |
| 608 | |
| 609 | ============================================================================== |
| 610 | *44.11* Installing a syntax file |
| 611 | |
| 612 | When your new syntax file is ready to be used, drop it in a "syntax" directory |
| 613 | in 'runtimepath'. For Unix that would be "~/.vim/syntax". |
| 614 | The name of the syntax file must be equal to the file type, with ".vim" |
| 615 | added. Thus for the x language, the full path of the file would be: |
| 616 | |
| 617 | ~/.vim/syntax/x.vim ~ |
| 618 | |
| 619 | You must also make the file type be recognized. See |43.2|. |
| 620 | |
| 621 | If your file works well, you might want to make it available to other Vim |
| 622 | users. First read the next section to make sure your file works well for |
| 623 | others. Then e-mail it to the Vim maintainer: <maintainer@vim.org>. Also |
| 624 | explain how the filetype can be detected. With a bit of luck your file will |
| 625 | be included in the next Vim version! |
| 626 | |
| 627 | |
| 628 | ADDING TO AN EXISTING SYNTAX FILE |
| 629 | |
| 630 | We were assuming you were adding a completely new syntax file. When an existing |
| 631 | syntax file works, but is missing some items, you can add items in a separate |
| 632 | file. That avoids changing the distributed syntax file, which will be lost |
| 633 | when installing a new version of Vim. |
| 634 | Write syntax commands in your file, possibly using group names from the |
| 635 | existing syntax. For example, to add new variable types to the C syntax file: |
| 636 | > |
| 637 | :syntax keyword cType off_t uint |
| 638 | |
| 639 | Write the file with the same name as the original syntax file. In this case |
| 640 | "c.vim". Place it in a directory near the end of 'runtimepath'. This makes |
| 641 | it loaded after the original syntax file. For Unix this would be: |
| 642 | |
| 643 | ~/.vim/after/syntax/c.vim ~ |
| 644 | |
| 645 | ============================================================================== |
| 646 | *44.12* Portable syntax file layout |
| 647 | |
| 648 | Wouldn't it be nice if all Vim users exchange syntax files? To make this |
| 649 | possible, the syntax file must follow a few guidelines. |
| 650 | |
| 651 | Start with a header that explains what the syntax file is for, who maintains |
| 652 | it and when it was last updated. Don't include too much information about |
| 653 | changes history, not many people will read it. Example: > |
| 654 | |
| 655 | " Vim syntax file |
| 656 | " Language: C |
| 657 | " Maintainer: Bram Moolenaar <Bram@vim.org> |
| 658 | " Last Change: 2001 Jun 18 |
| 659 | " Remark: Included by the C++ syntax. |
| 660 | |
| 661 | Use the same layout as the other syntax files. Using an existing syntax file |
| 662 | as an example will save you a lot of time. |
| 663 | |
| 664 | Choose a good, descriptive name for your syntax file. Use lowercase letters |
| 665 | and digits. Don't make it too long, it is used in many places: The name of |
Bram Moolenaar | 8f3f58f | 2010-01-06 20:52:26 +0100 | [diff] [blame] | 666 | the syntax file "name.vim", 'filetype', b:current_syntax and the start of each |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 667 | syntax group (nameType, nameStatement, nameString, etc). |
| 668 | |
| 669 | Start with a check for "b:current_syntax". If it is defined, some other |
Bram Moolenaar | c1e3790 | 2006-04-18 21:55:01 +0000 | [diff] [blame] | 670 | syntax file, earlier in 'runtimepath' was already loaded: > |
| 671 | |
| 672 | if exists("b:current_syntax") |
| 673 | finish |
| 674 | endif |
| 675 | |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 676 | Set "b:current_syntax" to the name of the syntax at the end. Don't forget |
| 677 | that included files do this too, you might have to reset "b:current_syntax" if |
| 678 | you include two files. |
| 679 | |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 680 | Do not include anything that is a user preference. Don't set 'tabstop', |
| 681 | 'expandtab', etc. These belong in a filetype plugin. |
| 682 | |
| 683 | Do not include mappings or abbreviations. Only include setting 'iskeyword' if |
| 684 | it is really necessary for recognizing keywords. |
| 685 | |
Bram Moolenaar | 2e2a281 | 2006-03-27 20:55:21 +0000 | [diff] [blame] | 686 | To allow users select their own preferred colors, make a different group name |
| 687 | for every kind of highlighted item. Then link each of them to one of the |
| 688 | standard highlight groups. That will make it work with every color scheme. |
| 689 | If you select specific colors it will look bad with some color schemes. And |
| 690 | don't forget that some people use a different background color, or have only |
| 691 | eight colors available. |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 692 | |
Bram Moolenaar | 2e2a281 | 2006-03-27 20:55:21 +0000 | [diff] [blame] | 693 | For the linking use "hi def link", so that the user can select different |
| 694 | highlighting before your syntax file is loaded. Example: > |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 695 | |
Bram Moolenaar | 2e2a281 | 2006-03-27 20:55:21 +0000 | [diff] [blame] | 696 | hi def link nameString String |
| 697 | hi def link nameNumber Number |
| 698 | hi def link nameCommand Statement |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 699 | ... etc ... |
| 700 | |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 701 | Add the "display" argument to items that are not used when syncing, to speed |
| 702 | up scrolling backwards and CTRL-L. |
| 703 | |
| 704 | ============================================================================== |
| 705 | |
| 706 | Next chapter: |usr_45.txt| Select your language |
| 707 | |
Bram Moolenaar | d473c8c | 2018-08-11 18:00:22 +0200 | [diff] [blame] | 708 | Copyright: see |manual-copyright| vim:tw=78:ts=8:noet:ft=help:norl: |