Vim Tips Wiki
(→‎Build a syntax file: Refer to install.)
Tag: sourceedit
(46 intermediate revisions by 15 users not shown)
Line 1: Line 1:
  +
{{TipNew
{{TipProposed
 
|id=0
+
|id=1561
|previous=0
+
|previous=1560
|next=0
+
|next=1562
|created=April 29, 2008
+
|created=2008
|complexity=basic
+
|complexity=intermediate
 
|author=Clearmoments
 
|author=Clearmoments
 
|version=7.0
 
|version=7.0
 
|subpage=/200804
 
|subpage=/200804
|category1=Syntax
+
|category1=Filetype
|category2=
+
|category2=Syntax
 
}}
 
}}
  +
This is a tutorial showing how to create your own syntax files in Vim. This provides syntax highlighting to show the different elements of files that you use. In this tutorial, all file names matching a particular extension will use the highlighting rules defined with the syntax commands shown below.
==Introduction==
 
Since there isn't a lot of material on creating your own syntax files in Vim, I've decided to write a tutorial on the process. Currently, this tutorial only shows how to make Vim interpret the syntax of files by their file extension. Another tutorial may extend this to show how to interpret the syntax of files by their contents.
 
   
 
==Example: Celestia star catalogs==
 
==Example: Celestia star catalogs==
For this tutorial I am creating a syntax file for Celestia star catalogs. [http://www.shatters.net/celestia/ Celestia] is a great program for anyone who likes astronomy and space, but I digress. All we need to know for this tutorial is that a star catalog lists a star name along with its positional information, distance and attributes (color, radius, mass, brightness). An example entry in a star catalog file (.stc) can be:
+
This tutorial creates a syntax file for Celestia star catalogs. [http://www.shatters.net/celestia/ Celestia] is a great program for anyone who likes astronomy and space. All we need to know for this tutorial is that a star catalog lists a star name with its positional information, distance and attributes (color, radius, mass, brightness). Here is an example entry in a star catalog file (<code>.stc</code>):
 
 
<pre>
 
<pre>
 
600000 "My Star"
 
600000 "My Star"
Line 29: Line 27:
 
</pre>
 
</pre>
   
As you can see it consists of a number, a string, and a block (<tt>{...}</tt>), with some keywords within that block ("RA", "Dec" and "Distance"). Comments are marked out by a "#" like in shell scripts or conf files. In fact, the syntax looks a lot like a conf file. There can be multiple entries like this with a number (the HIP number), the string, and the block containing the attributes. Celestia gets more complicated than this because you can have multiple stars going around a barycenter, etc, but we are not going to get fancy. We'll cover only stars.
+
The entry consists of a number, a string, and a <code>{...}</code> block, with some keywords within that block ("RA", "Dec", etc). Comments are prefixed with "#" like in shell scripts or conf files. There can be multiple entries like this with a number (the HIP number), the string, and the block containing the attributes. Celestia gets more complicated than this because you can have multiple stars going around a barycenter, but we will only cover stars.
   
 
==Syntax files==
 
==Syntax files==
 
===Get your directory straight===
 
Syntax files are editor scripts, just like everything else, and are located in your personal <tt>$HOME/.vim/syntax</tt> directory. If that directory does not exist you can create it. There should also be a system-wide syntax file directory. You can see these in Vim with the command:
 
 
<pre>
 
:set rtp?
 
</pre>
 
 
The system wide syntax directories are OS and system dependent.
 
 
====Unix====
 
/usr/share/vim/vimxx/syntax
 
</pre> Where xx is the vim version. You can verify its location using the
 
previous editor command.
 
 
====Windows====
 
<pre>X:\%PROGRAMFILES%\vim\vim71\syntax
 
[cream users] X:\%PROGRAMFILES%\vim\vim71\cream\syntax
 
</pre>
 
 
Under Windows you must create a <tt>%HOME%</tt> environment variable
 
manually. As per the [[Change_the_color_scheme]] tip:
 
 
 
::On Windows, the $HOME environment variable can be set by going to your desktop, right click on "My Computer", click the "Advanced" tab, select "Environment Variables". If HOME is not in the list of variables, create a new variable named HOME and point it to the location of your vimrc.
 
 
====Mac OS====
 
I am going to assume that Mac OS is the same as the Unix. See Unix.
 
 
The system-wide syntax directory is going to be one of the entries separated by commas (and frankly I'm not expert enough to know which one it is). The first value I know is your Vim personal syntax directory. You may want to study those syntax files and see how they are put together before playing around with this one its your choice.
 
 
 
===Build a syntax file===
 
===Build a syntax file===
First, create a new file in Vim, and add the following contents:
+
First, create a new file named <code>cel.vim</code> with the following contents (see [[#Install the syntax file|below]] for its location):
 
 
<pre>
 
<pre>
 
" Vim syntax file
 
" Vim syntax file
Line 77: Line 43:
 
</pre>
 
</pre>
   
Vim comments start with a quote. So I am following the convention of the built-in syntax files, and making a little comment flower box. The test <tt>if exists("b:current_syntax") ...</tt> checks whether an earlier file has defined a syntax already. If so, the script exits with <tt>finish</tt>.
+
Vim comments start with a quote. Following the convention of the built-in syntax files, we start with a comment flower box. The test <code>if&nbsp;exists("b:current_syntax") ...</code> checks whether an earlier file has defined a syntax already. If so, the script exits with <code>finish</code>.
 
===Keyword, match & region elements===
 
There are three major syntax elements, and commands to describe those elements. In order to syntax highlight, we must be able to describe what to highlight. Here is an example of
 
what they look like:
 
   
  +
===Keyword, match and region elements===
  +
There are three major syntax elements, and commands to describe those elements. In order to syntax highlight, we must be able to describe what to highlight. Here is an example of what they look like:
 
<pre>
 
<pre>
 
" Keywords
 
" Keywords
Line 95: Line 59:
   
 
====Keywords====
 
====Keywords====
Keywords are simple. Take for example the programming language BASIC. In BASIC there are several keywords like PRINT, OPEN and IF. Let's say you would like the editor to recognize them. You can define them like so:
+
Keywords are simple. Take for example the programming language BASIC. In BASIC there are several keywords like PRINT, OPEN and IF. To have Vim recognize them, you can use a definition:
 
 
<pre>
 
<pre>
 
syn keyword basicLanguageKeywords PRINT OPEN IF
 
syn keyword basicLanguageKeywords PRINT OPEN IF
 
</pre>
 
</pre>
   
For now we are not going to worry about <tt>nextgroup=</tt>.
+
For now we are not going to worry about <code>nextgroup=</code>.
 
The editor will now recognize the keywords PRINT, OPEN and IF as syntax elements of type <tt>basicLanguageKeywords</tt>. You can add more on the same line, or add another line with the same type (<tt>basicLanguageKeywords</tt>). In other words if I wanted to add the keywords DO, WHILE and WEND to my list, I could add to the previous line like this:
 
   
  +
Vim will now recognize the keywords PRINT, OPEN and IF as syntax elements of type <code>basicLanguageKeywords</code>. You can add more on the same line, or add another line with the same type (<code>basicLanguageKeywords</code>). For example, to add the keywords DO, WHILE and WEND, you could add to the previous line like this:
 
<pre>
 
<pre>
 
syn keyword basicLanguageKeywords PRINT OPEN IF DO WHILE WEND
 
syn keyword basicLanguageKeywords PRINT OPEN IF DO WHILE WEND
 
</pre>
 
</pre>
   
Or, I could add another line, list this:
+
or, add another line, like this:
 
 
<pre>
 
<pre>
 
syn keyword basicLanguageKeywords PRINT OPEN IF
 
syn keyword basicLanguageKeywords PRINT OPEN IF
Line 116: Line 77:
 
</pre>
 
</pre>
   
Let's use a more relevant example. Take our star catalog entry from above
+
We will apply this procedure to our star catalog entry from above:
 
 
<pre>600000 "My Star"
 
<pre>600000 "My Star"
 
{
 
{
Line 129: Line 89:
 
</pre>
 
</pre>
   
We can group the following keywords as part of a syntax element called <tt>celstcStarBlockCmd</tt> by adding the following to our syntax file.
+
We can group the following keywords as part of a syntax element called <code>celBlockCmd</code> by adding the following to our syntax file.
 
 
<pre>
 
<pre>
syn keyword celstcStarBlockCmd RA Dec SpectralType Mass Distance AbsMag
+
syn keyword celBlockCmd RA Dec SpectralType Mass Distance AbsMag
 
</pre>
 
</pre>
   
The editor will now recognize them. Maybe that's enough for your purposes, but I wanted to
+
Vim will now recognize these keywords which may be sufficient for your purpose. However, what if we want to match the text following the keywords, like those numbers and string values?
make things a little more interesting with matches following the keywords, like those numbers
 
and string values. How do we get those to be recognized?
 
   
 
====Matches (and addendum to keywords)====
 
====Matches (and addendum to keywords)====
All this keyword stuff logically leads to matches. Take the above example once again. After the keywords ("RA", "Dec", "AbsMag" etc) there are numbers. Let's say we want Vim to know that following a certain keyword there is going to be some set of characters to follow (defined as a regular expression maybe).
+
All this keyword stuff logically leads to matches. Take the above example once again. After the keywords ("RA", "Dec", "AbsMag" etc) there are numbers. We want Vim to know that following a certain keyword there is going to be some set of characters, perhaps defined as a regular expression.
 
This is where matches come in; along with an additional caveat to using keywords, the <tt>nextgroup</tt> and <tt>skipwhite</tt> arguments as seen above.
 
   
  +
This is where matches come in; along with an additional caveat to using keywords, the <code>nextgroup</code> and <code>skipwhite</code> arguments as seen above.
 
<pre>
 
<pre>
syn match celstcNumber '\d\+'
+
syn match celNumber '\d\+'
syn keyword celstcStarBlockCmd RA Dec Mass Distance AbsMag nextgroup=celstcNumber skipwhite
+
syn keyword celBlockCmd RA Dec Mass Distance AbsMag nextgroup=celNumber skipwhite
 
</pre>
 
</pre>
   
Now as you can see the match was given a regular expression <tt>\d\+</tt> meaning to match one or more (<tt>\+</tt>) digits 0-9 (<tt>\d</tt>). The keyword syntax element <tt>celstcStarBlockCmd</tt> has been modified slightly because following the <tt>SpectralType</tt> keyword is not a number but a string. We will address that
+
Now as you can see the match was given a regular expression <code>\d\+</code> meaning to match one or more (<code>\+</code>) digits 0-9 (<code>\d</code>). The keyword syntax element <code>celBlockCmd</code> has been modified slightly because following the <code>SpectralType</code> keyword is not a number but a string. Hence it has been excluded from the list of keywords for now. Later we will address that problem by creating another regular expression to match strings and apply it to that keyword.
problem shortly by creating another regular expression to match that. For now,
 
notice the <tt>nextgroup</tt> argument. We are telling the editor to expect a <tt>celstcNumber</tt> after the keyword. So that's the first pattern the
 
editor will attempt to match after finding one of those keywords.
 
   
The <tt>skipwhite</tt> argument simply tells the editor to expect some whitespace (tabs, spaces etc) between the keyword and the number.
+
Notice the <code>nextgroup</code> argument. We are telling the editor to expect a <code>celNumber</code> after the keyword. So that is the first pattern the editor will attempt to match after finding one of those keywords.
   
  +
The <code>skipwhite</code> argument simply tells the editor to expect some whitespace (spaces or tabs) between the keyword and the number.
You may have noticed a slight problem with my implementation. It will only match numbers like 19938, 93, and 0. It won't match decimals 3.91881 or negative numbers (-9).
 
 
How do we fix that? With more interesting regular expressions of course! This was taken from one of the existing Vim syntax files and modified slightly to work for our needs.
 
   
  +
One problem is that the above pattern (<code>\d\+</code>) will only match numbers like 1234, 93, and 0. It will not match numbers like 3.1416 or -1. To fix that, we need a more advanced regular expression borrowed from one of the existing Vim syntax files and slightly modified for our needs.
 
<pre>
 
<pre>
" Regular int like number with - + or nothing in front
+
" Integer with - + or nothing in front
syn match celstcNumber '\d\+'
+
syn match celNumber '\d\+'
syn match celstcNumber '[-+]\d\+'
+
syn match celNumber '[-+]\d\+'
   
 
" Floating point number with decimal no E or e (+,-)
 
" Floating point number with decimal no E or e (+,-)
syn match celstcNumber '\d\+\.\d*'
+
syn match celNumber '\d\+\.\d*'
syn match celstcNumber '[-+]\d\+\.\d*'
+
syn match celNumber '[-+]\d\+\.\d*'
   
 
" Floating point like number with E and no decimal point (+,-)
 
" Floating point like number with E and no decimal point (+,-)
syn match celstcNumber '[-+]\=\d[[:digit:]]*[eE][\-+]\=\d\+'
+
syn match celNumber '[-+]\=\d[[:digit:]]*[eE][\-+]\=\d\+'
syn match celstcNumber '\d[[:digit:]]*[eE][\-+]\=\d\+'
+
syn match celNumber '\d[[:digit:]]*[eE][\-+]\=\d\+'
   
 
" Floating point like number with E and decimal point (+,-)
 
" Floating point like number with E and decimal point (+,-)
syn match celstcNumber '[-+]\=\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+'
+
syn match celNumber '[-+]\=\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+'
syn match celstcNumber '\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+'
+
syn match celNumber '\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+'
 
</pre>
 
</pre>
   
  +
We can keep creating more lines like <code>syn match celNumber ''pattern''</code> to match all those patterns as one syntax element type (in this case <code>celNumber</code>).
Notice how we can keep creating more lines of
 
<tt>syn match celstcNumber 'a pattern'</tt> to match all those
 
patterns as one syntax element type (in this case <tt>celstcNumber</tt>.)
 
   
 
====Regions====
 
====Regions====
But we have another challenge that waits us. Let's look at the star catalog entry again.
+
Looking at the star catalog entry again shows another challenge:
 
 
<pre>
 
<pre>
 
600000 "My Star"
 
600000 "My Star"
Line 197: Line 146:
 
</pre>
 
</pre>
   
The first number is outside of the brackets, and that's not really a number, that's an HIP catalog entry (more like an ID number rather than a value with physical meaning like mass or distance). The real numbers are the arguments to the keywords (like "RA" and "Dec".) Since the definition of a <tt>celstcNumber</tt> conflicts with the pattern of an HIP catalog number since they both consist of the digits 0-9. How do we fix that discrepancy?
+
The first number is outside the brackets, and it's not really a number, it's an [http://www.rssd.esa.int/index.php?project=HIPPARCOS HIP catalog entry] (more like a star's ID number rather than a value with physical meaning like mass or distance). The real numbers are the arguments to the keywords (like "RA" and "Dec"). It would be nice if we could have the editor match those differently than regular numbers. But, since <code>celNumber</code>s and HIPs consist of the digits 0-9 they conflict with one another. How can we fix that discrepancy?
 
Note that numbers with values exist only within brackets. Outside of the brackets it is an ID number rather than a value. We have to add another argument to the keyword and match definitions, and introduce another type of syntax element: a region.
 
   
  +
Note that numbers with values exist only within brackets. Outside of the brackets it is an ID number rather than a value. We have to add another argument to the keyword and match definition blocks, and introduce another type of syntax element: a region.
First, we have to let the editor know that the aforementioned keywords only exist within brackets. Second, we specify that <tt>celstcNumber</tt>s only exist within brackets.
 
This is the concept of a region.
 
   
  +
First, we let the editor know that the keywords only exist within brackets. Second, we specify that <code>celNumber</code> syntax elements only exist within brackets. This is the concept of a region.
 
<pre>
 
<pre>
syn region celstcDescBlock start="{" end="}" fold transparent
+
syn region celDescBlock start="{" end="}" fold transparent
 
</pre>
 
</pre>
   
There we go, and we threw in some arguments for kicks. The <tt>fold</tt> argument means that Vim can increase the fold count inside brackets so you can press Ctrl+<F9> to expand and contract the code. The <tt>transparent</tt> is the important keyword here. It tells the editor to continue to apply matches and keywords to what's inside the region. Otherwise the region would not be colorized properly.
+
The <code>fold</code> argument means that Vim can increase the fold count inside brackets so you can press Ctrl-F9 to expand and contract the code. The <code>transparent</code> is the important keyword here. It tells the editor to continue to apply matches and keywords to what is inside the region. Otherwise the region would not be colorized properly.
   
 
We must add another additional argument to finish off everything.
 
We must add another additional argument to finish off everything.
 
 
<pre>
 
<pre>
syn region celstcDescBlock start="{" end="}" fold transparent contains=celstcNumber,celstcStarBlockCmd
+
syn region celDescBlock start="{" end="}" fold transparent contains=celNumber,celBlockCmd
 
</pre>
 
</pre>
   
The <tt>contains</tt> argument tells the editor which syntax elements this region will contain. In this case keywords and numbers. But we have strings too, right? So let's implement the required syntax elements since we know all about keywords, matches and regions now. In addition we pickup another argument along the way, <tt>contained</tt>.
+
The <code>contains</code> argument tells the editor which syntax elements this region will contain. In this case keywords and numbers. But we have strings too, right? So let's implement the required syntax elements since we know all about keywords, matches and regions now. In addition we pickup another argument along the way, <code>contained</code>.
 
Let's define comments as a syntax element and see how <tt>contained</tt> works.
 
   
  +
Let's define comments as a syntax element and see how <code>contained</code> works.
 
<pre>
 
<pre>
syn keyword celstcTodo contained TODO FIXME XXX NOTE
+
syn keyword celTodo contained TODO FIXME XXX NOTE
syn match celstcComment "#.*$" contains=celstcTodo
+
syn match celComment "#.*$" contains=celTodo
 
</pre>
 
</pre>
   
Comments start with a "#" and run until the end of line. So thats a
+
Comments start with a "#" and run until the end of line. So that's a simple regular expression <code>'#.*$'</code>. Starts with a "#" and match all characters until the end of a line.
simple regular expression <tt>'#.*$'</tt>. Starts with a "#" and match all
 
characters until the end of a line.
 
 
<tt>contained</tt> simply tells the editor that the keyword is only valid when contained by another syntax element, in this case a <tt>celstcTodo</tt> is only treated as a separate syntax element when contained by <tt>celstcComment</tt>.
 
   
  +
<code>contained</code> tells the editor that the keyword is only valid when contained by another syntax element, in this case a <code>celTodo</code> is only treated as a separate syntax element when contained by <code>celComment</code>.
So let's redefine everything from before, and implement all the required grammar, and bring this puppy together.
 
   
 
====Bringing it together====
 
====Bringing it together====
 
<pre>
 
<pre>
syn keyword celstcTodo contained TODO FIXME XXX NOTE
+
syn keyword celTodo contained TODO FIXME XXX NOTE
syn match celstcComment "#.*$" contains=celstcTodo
+
syn match celComment "#.*$" contains=celTodo
   
 
"----------------------------------------------------------------
 
"----------------------------------------------------------------
Line 243: Line 184:
   
 
" Regular int like number with - + or nothing in front
 
" Regular int like number with - + or nothing in front
syn match celstcNumber '\d\+' contained display
+
syn match celNumber '\d\+' contained display
syn match celstcNumber '[-+]\d\+' contained display
+
syn match celNumber '[-+]\d\+' contained display
   
 
" Floating point number with decimal no E or e (+,-)
 
" Floating point number with decimal no E or e (+,-)
syn match celstcNumber '\d\+\.\d*' contained display
+
syn match celNumber '\d\+\.\d*' contained display
syn match celstcNumber '[-+]\d\+\.\d*' contained display
+
syn match celNumber '[-+]\d\+\.\d*' contained display
   
 
" Floating point like number with E and no decimal point (+,-)
 
" Floating point like number with E and no decimal point (+,-)
syn match celstcNumber '[-+]\=\d[[:digit:]]*[eE][\-+]\=\d\+' contained display
+
syn match celNumber '[-+]\=\d[[:digit:]]*[eE][\-+]\=\d\+' contained display
syn match celstcNumber '\d[[:digit:]]*[eE][\-+]\=\d\+' contained display
+
syn match celNumber '\d[[:digit:]]*[eE][\-+]\=\d\+' contained display
   
 
" Floating point like number with E and decimal point (+,-)
 
" Floating point like number with E and decimal point (+,-)
syn match celstcNumber '[-+]\=\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+' contained display
+
syn match celNumber '[-+]\=\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+' contained display
syn match celstcNumber '\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+' contained display
+
syn match celNumber '\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+' contained display
   
syn region celstcString start='"' end='"' contained
+
syn region celString start='"' end='"' contained
syn region celstcDescString start='"' end='"'
+
syn region celDesc start='"' end='"'
   
syn match celstcHip '\d\{1,6}' nextgroup=celstcString
+
syn match celHip '\d\{1,6}' nextgroup=celString
syn region celstcDescBlock start="{" end="}" fold transparent contains=ALLBUT,celstcHip,celstcDescString
+
syn region celDescBlock start="{" end="}" fold transparent contains=ALLBUT,celHip,celString
 
syn keyword celstcStarBlockCmd RA Dec Distance AbsMag nextgroup=celstcNumber
 
syn keyword celstcStarBlockCmd SpectralType nextgroup=celstcString
 
   
  +
syn keyword celBlockCmd RA Dec Distance AbsMag nextgroup=celNumber
  +
syn keyword celBlockCmd SpectralType nextgroup=celDesc
 
</pre>
 
</pre>
   
 
==Telling Vim how to highlight + final touches==
 
==Telling Vim how to highlight + final touches==
You've reached the easiest part, just take the syntax element names you've used and use the <tt>hi def link</tt> command to tell Vim how to highlight.
+
We can now take the syntax elements and use the <code>hi def link</code> command to tell Vim how to highlight them.
 
Set the <tt>b:current_syntax</tt> variable to a name. I called it "celstc". You'll need that name to modify the Un/Commentify (<F6>/Shift+<F6>) script in Cream for example to block comment-out lines with your new file types.
 
   
  +
Set the <code>b:current_syntax</code> variable to a name, for example, "cel". That name can be used to modify the Un/Commentify (F6/Shift-F6) script in Cream, for example to block comment-out lines with the new file type.
 
<pre>
 
<pre>
let b:current_syntax = "celstc"
+
let b:current_syntax = "cel"
   
hi def link celstcTodo Todo
+
hi def link celTodo Todo
hi def link celstcComment Comment
+
hi def link celComment Comment
hi def link celstcStarBlockCmd Statement
+
hi def link celBlockCmd Statement
hi def link celstcHip Type
+
hi def link celHip Type
hi def link celstcString Constant
+
hi def link celString Constant
hi def link celstcDescString PreProc
+
hi def link celDesc PreProc
hi def link celstcNumber Constant
+
hi def link celNumber Constant
 
</pre>
 
</pre>
   
The hi def link command has different types of highlighting options
+
The <code>hi def link</code> command has different types of highlighting options that we need not consider. The ones used here are:
  +
*<code>Todo</code>: used for the todo comments (ones that have "TODO: something" in them)
that I wont go into. But the ones I'm using here are
 
  +
*<code>Comment</code>: indicates a code comment
  +
*<code>Statement</code>: a code statement like a for loop
  +
*<code>Type</code>: a user defined type generally
  +
*<code>PreProc</code>: a pre-processor statement like <code>#include <stdio.h></code> in C
  +
*<code>Constant</code>: like a string or number in code
   
  +
These of course are guidelines. In this example, there are no statements or pre-processor commands, however <code>celBlockCmd</code> has been set to use <code>Statement</code> highlighting, and <code>celHip</code> will use <code>Type</code> highlighting.
*<tt>Todo</tt>: used for the todo comments (ones that have "TODO: blah blah" in them)
 
*<tt>Comment</tt>: indicates a code comment
 
*<tt>Statement</tt>: a code statement like a for loop or something
 
*<tt>Type</tt>: a user defined type generally
 
*<tt>PreProc</tt>: a pre-processor (like a C <tt>#include <stdio.h></tt>)
 
*<tt>Constant</tt>: like a string or number in code
 
   
  +
You can view more options in Vim with {{help|syntax}}
These of course are guidelines. For our purposes we really
 
don't have statements or pre-processor commands, since this
 
is really more like a conf file or like HTML. As you can see I set the
 
<tt>celstcStarBlockCmd</tt>s to use the Statement highlighting.
 
As for the celstcHip I set that to a <tt>Type</tt> (seems like a
 
close match to meaning.)
 
   
  +
===Install the syntax file===
You can view more options in the vim help
 
  +
Save the file, then install it by copying the file to <code>~/.vim/syntax/cel.vim</code> on Unix-based systems, or to <code>$HOME/vimfiles/syntax/cel.vim</code> on Windows systems.
   
  +
You may need to create the <code>.vim</code> (or <code>vimfiles</code>) directory, and you may need to create the <code>syntax</code> subdirectory. In Vim, your home directory is specified with <code>~</code> on Unix systems, and <code>$HOME</code> on Windows systems. You can see what directories to use by entering commands like the following in Vim:
 
<pre>
 
<pre>
  +
:echo expand('~')
:help syntax
 
  +
:echo expand('~/.vim/syntax/cel.vim')
  +
:echo $HOME
  +
:echo expand('$HOME/vimfiles/syntax/cel.vim')
 
</pre>
 
</pre>
   
  +
Using the directory specified above means the syntax file will be available to you, but not to other users. If you want the syntax file to be available to all users, do not save the file under your home directory; instead, copy the file under your Vim system directory. The default for both Unix and Windows is that system-wide syntax files are placed in the <code>$VIM/vimfiles/syntax</code> directory (which you may need to create). You can see the full path name of the required file by entering the following in Vim:
And look at the syntax file help
 
 
 
===Save your work===
 
Finally save your file as celstc.vim (that's what I called it), in your Vim syntax directory (preferably your local one <tt>$HOME/.vim/syntax</tt>).
 
 
===Setup your filetype.vim file===
 
Okay, now we have to make sure Vim knows how to interpret your file. First if <tt>$HOME/.vim/filetype.vim</tt> exists then you are going to find the part of the file that looks like this:
 
 
 
<pre>
 
<pre>
  +
:echo expand('$VIM/vimfiles/syntax/cel.vim')
augroup filetypedetect
 
au! BufRead,BufNewFile *.stc setfiletype celstc
 
augroup END
 
 
</pre>
 
</pre>
   
  +
Another procedure to show the base directories which can be used is to enter either of the following commands in Vim (the first displays the value of the <code>'runtimepath'</code> option, and the second inserts that value into the current buffer):
 
==Adding syntax to Cream EnhancedCommentify==
 
----
 
====Locate EnhancedCommentify.vim for your installation====
 
 
Locate the EnhancedCommentify.vim file in your Cream installation.
 
 
=====Windows=====
 
Under windows you can find your EnhancedCommentify.vim file in the
 
<tt>X:\%PROGRAMFILES%\vim\vimxx\cream</tt> directory. Where xx is the Vim
 
version number
 
 
<!--
 
Mac OS has to be updated. I don't know if Mac OS is really the same.
 
-->
 
 
=====Unix & Mac OS=====
 
You will find it generally in /usr/share/vim/cream/ and go
 
EnhancedCommentify.vim. Make a backup copy of this file before
 
continuing!
 
 
====Edit the GetFileTypeSettings function====
 
 
Open the file up in Vim and locate <tt>GetFileTypeSettings</tt> function in the
 
commentify file. You're going to see sections like this:
 
 
=====Code Snippet 1=====
 
 
<pre>
 
<pre>
  +
:set runtimepath?
"
 
  +
:put =&runtimepath
" GetFileTypeSettings(ft)
 
" ft -- filetype
 
"
 
" This functions sets some buffer-variables, which control the comment
 
" strings and 'empty lines'-handling.
 
"
 
function s:GetFileTypeSettings(ft)
 
let fileType = a:ft
 
 
" I learned about the commentstring option. Let's use it.
 
" For now we ignore it, if it is "/*%s*/". This is the
 
" default. We cannot check wether this is default or C or
 
" something other like CSS, etc. We have to wait, until the
 
" filetypes adopt this option.
 
if &commentstring != "/*%s*/" && !b:ECuseSyntax
 
let b:ECcommentOpen =
 
\ substitute(&commentstring, '%s.*', "", "")
 
let b:ECcommentClose =
 
\ substitute(&commentstring, '.*%s', "", "")
 
" Multipart comments:
 
elseif fileType =~ '^\(c\|b\|css\|csc\|cupl\|indent\|jam\|lex\|lifelines\|'.
 
\ 'lite\|nqc\|phtml\|progress\|rexx\|rpl\|sas\|sdl\|sl\|'.
 
\ 'strace\|xpm\|yacc\)$'
 
 
</pre>
 
</pre>
   
  +
By default, the first item in <code>runtimepath</code> is the base directory for your personal Vim files, and the second item is the base directory for system-wide Vim files. Place the <code>syntax</code> subdirectory under either of these directories; doing that means your syntax file will not be overwritten when you next upgrade Vim. Do not use a directory containing the files distributed with Vim because that will be overwritten during an upgrade (in particular, do not use the <code>$VIMRUNTIME</code> directory).
   
  +
===Make Vim recognize the filetype===
You will see sections like this in the file.
 
  +
Now we have to make sure Vim knows how to interpret your file. There are a few methods to add filetype detection for files of this new type. See {{help|new-filetype}} for full details, but the basics are here.
   
  +
====Add a file in the ftdetect directory====
=====Code Snippet 2=====
 
  +
This is probably the simplest method.
<pre>
 
elseif fileType == 'atlas'
 
let b:ECcommentOpen = 'C'
 
let b:ECcommentClose = '$'
 
elseif fileType =~ '^\(catalog\|sgmldecl\)$'
 
let b:ECcommentOpen = '--'
 
let b:ECcommentClose = '--'
 
elseif fileType == 'dtml'
 
let b:ECcommentOpen = '<dtml-comment>'
 
let b:ECcommentClose = '</dtml-comment>'
 
elseif fileType == 'htmlos'
 
let b:ECcommentOpen = '#'
 
let b:ECcommentClose = '/#'
 
</pre>
 
   
  +
Simply create a file in <code>~/.vim/ftdetect</code> with the same name as your syntax file, in this case <code>~/.vim/ftdetect/cel.vim</code>. In this file place a single line to set the filetype on buffer read or creation:
Do you remember the section of your syntax script? The one that looks like
 
this:
 
   
  +
au BufRead,BufNewFile *.stc set filetype=cel
<pre>
 
let b:current_syntax = "celstc"
 
</pre>
 
   
  +
Note that this will override any previously detected filetype with the new filetype.
Note that in the aforementioned code we have a variable <tt>fileType</tt>.
 
We simply have to add our new file type "celstc" to this file. Along with
 
our comment type, which starts with a # and ends at the end of line.
 
   
=====Code Snippet 3=====
+
====Add to [[filetype.vim]]====
  +
Add filetype detection to [[filetype.vim]]: in this case the Vim script is named <code>cel.vim</code> so we use the filetype "cel".
 
<pre>
 
<pre>
  +
au BufRead,BufNewFile *.stc setfiletype cel
elseif fileType == 'atlas'
 
let b:ECcommentOpen = 'C'
 
let b:ECcommentClose = '$'
 
elseif fileType =~ '^\(catalog\|sgmldecl\)$'
 
let b:ECcommentOpen = '--'
 
let b:ECcommentClose = '--'
 
elseif fileType == 'dtml'
 
let b:ECcommentOpen = '<dtml-comment>'
 
let b:ECcommentClose = '</dtml-comment>'
 
elseif fileType == 'htmlos'
 
let b:ECcommentOpen = '#'
 
let b:ECcommentClose = '/#'
 
 
elseif fileType == 'celstc'
 
let b:ECcommentOpen = '#'
 
let b:ECcommentClose = ''
 
 
</pre>
 
</pre>
   
  +
Note the use of {{help|prefix=no|:setfiletype}} instead of <code>set filetype=</code>. This is so that Vim does not override any previously detected filetypes while running this script. Details {{help|:setfiletype}}.
If you noticed I added the following code to "Code Snippet 2".
 
   
  +
====Add to scripts.vim====
<pre>
 
  +
This method does not apply in our example case, but some filetypes can only be detected by examining buffer contents. For example, maybe you have a config file that is actually in XML format but does not have a normal file extension reflecting that, like *.xml. Details at {{help|new-filetype-scripts}}. Basically you just add tests using {{help|prefix=no|getline()}}, {{help|prefix=no|search()}}, etc. and use them to determine whether to set the filetype with {{help|prefix=no|:setfiletype}}.
elseif fileType == 'celstc'
 
let b:ECcommentOpen = '#'
 
let b:ECcommentClose = ''
 
</pre>
 
 
You could also make this code match multiple file types. Lets say I had
 
multiple file types like <tt>celstsc</tt>, <tt>celssc</tt>, and <tt>celdsc</tt>.
 
You could use a regular expression as follows to match all of those
 
types.
 
 
<pre>
 
elseif fileType =~ '^\(celstsc\|celssc\|celdsc\)$'
 
let b:ECcommentOpen = '--'
 
let b:ECcommentClose = '--'
 
</pre>
 
 
Note the change in the operator from <tt>==</tt> to <tt>=~</tt>. I also
 
am placing each filetype encased in pipes (<tt>|</tt>) and parenthesis.
 
 
Now just save that file, and you can use the block commenting on your
 
new celestia (.stc) file type. <F6>, Shift+<F6>.
 
 
[[Link title]]
 
   
 
==See also==
 
==See also==
*[[Syntax folding of Vim scripts]]
+
*[[Syntax folding of Vim scripts]] for an example of adding to an existing syntax instead of creating your own as this tip demonstrates.
  +
*[[User:Clearmoments/celstarcat|celstarcat.vim]] an actual stc syntax file
  +
*[[User:Clearmoments/celssc|celssc.vim]] an actual ssc syntax file
   
 
==Comments==
 
==Comments==
 
{{Todo}}
 
{{Todo}}
  +
*Is Ctrl-F9 something to do with Cream?
*This new tip is not quite complete. [[Clearmoments]] intends to make further changes soon. Others are of course welcome to contribute as well.
 
  +
*The "Setup your filetype.vim file" section needs a bit more explanation since the linked tip is rather waffly and possibly incorrect (it refers to <code>%USERPROFILE%</code> on Windows).
*What is intended for <tt><nowiki>[[Link title]]</nowiki></tt>?
 
  +
** Remove this todo, as the linked tip has been cleaned up, and the reference to <code>%USERPROFILE%</code> was removed in 2011? --[[User:Hwolfe|-- Herb Wolfe]] ([[User talk:Hwolfe|talk]]) 21:28, July 25, 2014 (UTC)
*How about replacing <tt>celstcStarBlockCmd</tt> with a simpler name?
 
  +
* Make this easier to setup in vim itself. Perhaps add the file ces.vim to ~/.vim/syntax and have vim do the work required to make .ces files use the ces.vim syntax highlighting. Or maybe even add a commandline argument to vim such as vim HelloWorld.ces --use-syntax=~/.vim/syntax/ces.vim
 
  +
** I don't see either of these as being very feasible. Using your first suggestion, say for example with source files for C, which could have many possible file extensions, the user would have to make a copy of the syntax file for each one. Any changes, would then have to be duplicated in the other files. --[[User:Hwolfe|-- Herb Wolfe]] ([[User talk:Hwolfe|talk]]) 21:28, July 25, 2014 (UTC)
----
 
  +
*** Please clean up these comments as you think. Perhaps all that is needed here is the comment about Ctrl-F9 because I have no idea where that key press comes from. [[User:JohnBeckett|JohnBeckett]] ([[User talk:JohnBeckett|talk]]) 06:13, July 28, 2014 (UTC)
 
Also mention using the $HOME/vimfiles/syntax (or $HOME/.vim/syntax) directory for syntax files that not everyone on the system will need. Less likely to be "blown away" by accident, and it won't need to be copied every version of Vim that comes out.
 
 
--[[User:Fritzophrenic|Fritzophrenic]] 13:15, 29 April 2008 (UTC)
 
----
 
 
Thanks for the great recommendations. I just edited the page, I am very pleased about the reaction; frankly I thought it wasn't going to be as good. Feel free to make all the
 
changes in the world. This is no longer my work, it belongs to the community, though I intend to make further changes.
 
[[User:Clearmoments|Clearmoments]] 00:29, 30 April 2008 (UTC)
 
----
 
   
  +
===Directories===
I am debating adding the EnhancedCommentify section as a separate article or
 
  +
I have removed the following advice for MacVim on Mac OS (but will keep this for a while as an explanation):
to leave it as part of the article. Please comment.
 
  +
:For MacVim, put the syntax file in directory <code>/Applications/MacVim.app/Contents/Resources/vim/runtime/syntax</code>
  +
:To get there, right click MacVim in the Applications directory and "Show Package Contents".
  +
While I have no knowledge of MacVim, I have found confirmation that the above is the directory containing Vim's syntax files (i.e. those distributed with Vim). It is always a mistake to make changes in a distribution directory because updating Vim may (and one day will) cause your changes to be lost. [[User:JohnBeckett|JohnBeckett]] 08:55, June 6, 2010 (UTC)
   
  +
==TOhtml==
[[User:Clearmoments|Clearmoments]] 02:45, 30 April 2008 (UTC)
 
  +
It would be nice to have a resulting TOhtml dump in this article
----
 

Revision as of 04:54, 22 February 2015

Tip 1561 Printable Monobook Previous Next

created 2008 · complexity intermediate · author Clearmoments · version 7.0


This is a tutorial showing how to create your own syntax files in Vim. This provides syntax highlighting to show the different elements of files that you use. In this tutorial, all file names matching a particular extension will use the highlighting rules defined with the syntax commands shown below.

Example: Celestia star catalogs

This tutorial creates a syntax file for Celestia star catalogs. Celestia is a great program for anyone who likes astronomy and space. All we need to know for this tutorial is that a star catalog lists a star name with its positional information, distance and attributes (color, radius, mass, brightness). Here is an example entry in a star catalog file (.stc):

600000 "My Star"
{
  RA 24.406489
  Dec -9.404052
  SpectralType "Q"
  Mass 1.09
  AbsMag 1.29
  Distance 124.729260
}

The entry consists of a number, a string, and a {...} block, with some keywords within that block ("RA", "Dec", etc). Comments are prefixed with "#" like in shell scripts or conf files. There can be multiple entries like this with a number (the HIP number), the string, and the block containing the attributes. Celestia gets more complicated than this because you can have multiple stars going around a barycenter, but we will only cover stars.

Syntax files

Build a syntax file

First, create a new file named cel.vim with the following contents (see below for its location):

" Vim syntax file
" Language: Celestia Star Catalogs
" Maintainer: Kevin Lauder
" Latest Revision: 26 April 2008

if exists("b:current_syntax")
  finish
endif

Vim comments start with a quote. Following the convention of the built-in syntax files, we start with a comment flower box. The test if exists("b:current_syntax") ... checks whether an earlier file has defined a syntax already. If so, the script exits with finish.

Keyword, match and region elements

There are three major syntax elements, and commands to describe those elements. In order to syntax highlight, we must be able to describe what to highlight. Here is an example of what they look like:

" Keywords
syn keyword syntaxElementKeyword keyword1 keyword2 nextgroup=syntaxElement2

" Matches
syn match syntaxElementMatch 'regexp' contains=syntaxElement1 nextgroup=syntaxElement2 skipwhite

" Regions
syn region syntaxElementRegion start='x' end='y'

Keywords

Keywords are simple. Take for example the programming language BASIC. In BASIC there are several keywords like PRINT, OPEN and IF. To have Vim recognize them, you can use a definition:

syn keyword basicLanguageKeywords PRINT OPEN IF

For now we are not going to worry about nextgroup=.

Vim will now recognize the keywords PRINT, OPEN and IF as syntax elements of type basicLanguageKeywords. You can add more on the same line, or add another line with the same type (basicLanguageKeywords). For example, to add the keywords DO, WHILE and WEND, you could add to the previous line like this:

syn keyword basicLanguageKeywords PRINT OPEN IF DO WHILE WEND

or, add another line, like this:

syn keyword basicLanguageKeywords PRINT OPEN IF
syn keyword basicLanguageKeywords DO WHILE WEND

We will apply this procedure to our star catalog entry from above:

600000 "My Star"
{
  RA 24.406489
  Dec -9.404052
  SpectralType "Q"
  Mass 1.09
  AbsMag 1.29
  Distance 124.729260
}

We can group the following keywords as part of a syntax element called celBlockCmd by adding the following to our syntax file.

syn keyword celBlockCmd RA Dec SpectralType Mass Distance AbsMag

Vim will now recognize these keywords which may be sufficient for your purpose. However, what if we want to match the text following the keywords, like those numbers and string values?

Matches (and addendum to keywords)

All this keyword stuff logically leads to matches. Take the above example once again. After the keywords ("RA", "Dec", "AbsMag" etc) there are numbers. We want Vim to know that following a certain keyword there is going to be some set of characters, perhaps defined as a regular expression.

This is where matches come in; along with an additional caveat to using keywords, the nextgroup and skipwhite arguments as seen above.

syn match celNumber '\d\+'
syn keyword celBlockCmd RA Dec Mass Distance AbsMag nextgroup=celNumber skipwhite

Now as you can see the match was given a regular expression \d\+ meaning to match one or more (\+) digits 0-9 (\d). The keyword syntax element celBlockCmd has been modified slightly because following the SpectralType keyword is not a number but a string. Hence it has been excluded from the list of keywords for now. Later we will address that problem by creating another regular expression to match strings and apply it to that keyword.

Notice the nextgroup argument. We are telling the editor to expect a celNumber after the keyword. So that is the first pattern the editor will attempt to match after finding one of those keywords.

The skipwhite argument simply tells the editor to expect some whitespace (spaces or tabs) between the keyword and the number.

One problem is that the above pattern (\d\+) will only match numbers like 1234, 93, and 0. It will not match numbers like 3.1416 or -1. To fix that, we need a more advanced regular expression borrowed from one of the existing Vim syntax files and slightly modified for our needs.

" Integer with - + or nothing in front
syn match celNumber '\d\+'
syn match celNumber '[-+]\d\+'

" Floating point number with decimal no E or e (+,-)
syn match celNumber '\d\+\.\d*'
syn match celNumber '[-+]\d\+\.\d*'

" Floating point like number with E and no decimal point (+,-)
syn match celNumber '[-+]\=\d[[:digit:]]*[eE][\-+]\=\d\+'
syn match celNumber '\d[[:digit:]]*[eE][\-+]\=\d\+'

" Floating point like number with E and decimal point (+,-)
syn match celNumber '[-+]\=\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+'
syn match celNumber '\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+'

We can keep creating more lines like syn match celNumber pattern to match all those patterns as one syntax element type (in this case celNumber).

Regions

Looking at the star catalog entry again shows another challenge:

600000 "My Star"
{
  RA 24.406489
  Dec -9.404052
  SpectralType "Q"
  Mass 1.09
  AbsMag 1.29
  Distance 124.729260
}

The first number is outside the brackets, and it's not really a number, it's an HIP catalog entry (more like a star's ID number rather than a value with physical meaning like mass or distance). The real numbers are the arguments to the keywords (like "RA" and "Dec"). It would be nice if we could have the editor match those differently than regular numbers. But, since celNumbers and HIPs consist of the digits 0-9 they conflict with one another. How can we fix that discrepancy?

Note that numbers with values exist only within brackets. Outside of the brackets it is an ID number rather than a value. We have to add another argument to the keyword and match definition blocks, and introduce another type of syntax element: a region.

First, we let the editor know that the keywords only exist within brackets. Second, we specify that celNumber syntax elements only exist within brackets. This is the concept of a region.

syn region celDescBlock start="{" end="}" fold transparent

The fold argument means that Vim can increase the fold count inside brackets so you can press Ctrl-F9 to expand and contract the code. The transparent is the important keyword here. It tells the editor to continue to apply matches and keywords to what is inside the region. Otherwise the region would not be colorized properly.

We must add another additional argument to finish off everything.

syn region celDescBlock start="{" end="}" fold transparent contains=celNumber,celBlockCmd

The contains argument tells the editor which syntax elements this region will contain. In this case keywords and numbers. But we have strings too, right? So let's implement the required syntax elements since we know all about keywords, matches and regions now. In addition we pickup another argument along the way, contained.

Let's define comments as a syntax element and see how contained works.

syn keyword celTodo contained TODO FIXME XXX NOTE
syn match celComment "#.*$" contains=celTodo

Comments start with a "#" and run until the end of line. So that's a simple regular expression '#.*$'. Starts with a "#" and match all characters until the end of a line.

contained tells the editor that the keyword is only valid when contained by another syntax element, in this case a celTodo is only treated as a separate syntax element when contained by celComment.

Bringing it together

syn keyword celTodo contained TODO FIXME XXX NOTE
syn match celComment "#.*$" contains=celTodo

"----------------------------------------------------------------
" Celestia Star Catalog Numbers
"----------------------------------------------------------------

" Regular int like number with - + or nothing in front
syn match celNumber '\d\+' contained display
syn match celNumber '[-+]\d\+' contained display

" Floating point number with decimal no E or e (+,-)
syn match celNumber '\d\+\.\d*' contained display
syn match celNumber '[-+]\d\+\.\d*' contained display

" Floating point like number with E and no decimal point (+,-)
syn match celNumber '[-+]\=\d[[:digit:]]*[eE][\-+]\=\d\+' contained display
syn match celNumber '\d[[:digit:]]*[eE][\-+]\=\d\+' contained display

" Floating point like number with E and decimal point (+,-)
syn match celNumber '[-+]\=\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+' contained display
syn match celNumber '\d[[:digit:]]*\.\d*[eE][\-+]\=\d\+' contained display

syn region celString start='"' end='"' contained
syn region celDesc start='"' end='"'

syn match celHip '\d\{1,6}' nextgroup=celString
syn region celDescBlock start="{" end="}" fold transparent contains=ALLBUT,celHip,celString

syn keyword celBlockCmd RA Dec Distance AbsMag nextgroup=celNumber
syn keyword celBlockCmd SpectralType nextgroup=celDesc

Telling Vim how to highlight + final touches

We can now take the syntax elements and use the hi def link command to tell Vim how to highlight them.

Set the b:current_syntax variable to a name, for example, "cel". That name can be used to modify the Un/Commentify (F6/Shift-F6) script in Cream, for example to block comment-out lines with the new file type.

let b:current_syntax = "cel"

hi def link celTodo        Todo
hi def link celComment     Comment
hi def link celBlockCmd    Statement
hi def link celHip         Type
hi def link celString      Constant
hi def link celDesc        PreProc
hi def link celNumber      Constant

The hi def link command has different types of highlighting options that we need not consider. The ones used here are:

  • Todo: used for the todo comments (ones that have "TODO: something" in them)
  • Comment: indicates a code comment
  • Statement: a code statement like a for loop
  • Type: a user defined type generally
  • PreProc: a pre-processor statement like #include <stdio.h> in C
  • Constant: like a string or number in code

These of course are guidelines. In this example, there are no statements or pre-processor commands, however celBlockCmd has been set to use Statement highlighting, and celHip will use Type highlighting.

You can view more options in Vim with :help syntax

Install the syntax file

Save the file, then install it by copying the file to ~/.vim/syntax/cel.vim on Unix-based systems, or to $HOME/vimfiles/syntax/cel.vim on Windows systems.

You may need to create the .vim (or vimfiles) directory, and you may need to create the syntax subdirectory. In Vim, your home directory is specified with ~ on Unix systems, and $HOME on Windows systems. You can see what directories to use by entering commands like the following in Vim:

:echo expand('~')
:echo expand('~/.vim/syntax/cel.vim')
:echo $HOME
:echo expand('$HOME/vimfiles/syntax/cel.vim')

Using the directory specified above means the syntax file will be available to you, but not to other users. If you want the syntax file to be available to all users, do not save the file under your home directory; instead, copy the file under your Vim system directory. The default for both Unix and Windows is that system-wide syntax files are placed in the $VIM/vimfiles/syntax directory (which you may need to create). You can see the full path name of the required file by entering the following in Vim:

:echo expand('$VIM/vimfiles/syntax/cel.vim')

Another procedure to show the base directories which can be used is to enter either of the following commands in Vim (the first displays the value of the 'runtimepath' option, and the second inserts that value into the current buffer):

:set runtimepath?
:put =&runtimepath

By default, the first item in runtimepath is the base directory for your personal Vim files, and the second item is the base directory for system-wide Vim files. Place the syntax subdirectory under either of these directories; doing that means your syntax file will not be overwritten when you next upgrade Vim. Do not use a directory containing the files distributed with Vim because that will be overwritten during an upgrade (in particular, do not use the $VIMRUNTIME directory).

Make Vim recognize the filetype

Now we have to make sure Vim knows how to interpret your file. There are a few methods to add filetype detection for files of this new type. See :help new-filetype for full details, but the basics are here.

Add a file in the ftdetect directory

This is probably the simplest method.

Simply create a file in ~/.vim/ftdetect with the same name as your syntax file, in this case ~/.vim/ftdetect/cel.vim. In this file place a single line to set the filetype on buffer read or creation:

au BufRead,BufNewFile *.stc set filetype=cel

Note that this will override any previously detected filetype with the new filetype.

Add to filetype.vim

Add filetype detection to filetype.vim: in this case the Vim script is named cel.vim so we use the filetype "cel".

au BufRead,BufNewFile *.stc setfiletype cel

Note the use of :setfiletype instead of set filetype=. This is so that Vim does not override any previously detected filetypes while running this script. Details :help :setfiletype.

Add to scripts.vim

This method does not apply in our example case, but some filetypes can only be detected by examining buffer contents. For example, maybe you have a config file that is actually in XML format but does not have a normal file extension reflecting that, like *.xml. Details at :help new-filetype-scripts. Basically you just add tests using getline(), search(), etc. and use them to determine whether to set the filetype with :setfiletype.

See also

Comments

 TO DO 

  • Is Ctrl-F9 something to do with Cream?
  • The "Setup your filetype.vim file" section needs a bit more explanation since the linked tip is rather waffly and possibly incorrect (it refers to %USERPROFILE% on Windows).
    • Remove this todo, as the linked tip has been cleaned up, and the reference to %USERPROFILE% was removed in 2011? ---- Herb Wolfe (talk) 21:28, July 25, 2014 (UTC)
  • Make this easier to setup in vim itself. Perhaps add the file ces.vim to ~/.vim/syntax and have vim do the work required to make .ces files use the ces.vim syntax highlighting. Or maybe even add a commandline argument to vim such as vim HelloWorld.ces --use-syntax=~/.vim/syntax/ces.vim
    • I don't see either of these as being very feasible. Using your first suggestion, say for example with source files for C, which could have many possible file extensions, the user would have to make a copy of the syntax file for each one. Any changes, would then have to be duplicated in the other files. ---- Herb Wolfe (talk) 21:28, July 25, 2014 (UTC)
      • Please clean up these comments as you think. Perhaps all that is needed here is the comment about Ctrl-F9 because I have no idea where that key press comes from. JohnBeckett (talk) 06:13, July 28, 2014 (UTC)

Directories

I have removed the following advice for MacVim on Mac OS (but will keep this for a while as an explanation):

For MacVim, put the syntax file in directory /Applications/MacVim.app/Contents/Resources/vim/runtime/syntax
To get there, right click MacVim in the Applications directory and "Show Package Contents".

While I have no knowledge of MacVim, I have found confirmation that the above is the directory containing Vim's syntax files (i.e. those distributed with Vim). It is always a mistake to make changes in a distribution directory because updating Vim may (and one day will) cause your changes to be lost. JohnBeckett 08:55, June 6, 2010 (UTC)

TOhtml

It would be nice to have a resulting TOhtml dump in this article