Contents
Making code highlighters for vim
Friday, 18/07/2025
Vim makes it absolutely easy to build code highlighters for your domain specific languages. Regular expressions are at the core of vim syntax configuration files.
Target grammar
Let’s consider a toy scripting language (called smsh script) I wrote a while back, that resembles yaml.
utils.smsh (library)
@python3 -c Click: import pyautogui pyautogui.mouseDown(%args%, 'left') @python3 -c Press: import pyautogui pyautogui.hotkey(%args%) #echo Button %args% was pressed @python3 -c Type: import pyautogui pyautogui.write('%args%') #echo Sequence of characters %args% was simulated on keyboard Open async: xfce4-terminal -e %args% Screenshot: Open async xfce4-screenshooter Press 'Up' Press 'Up' Press 'Up' Press 'Enter' sleep 2 Press 'Up' Press 'Up' Press 'Up' Press 'Down' Press 'Enter' Exit screenshot window: Press 'Alt', 'F4' Wait: sleep %args%
example.smsh (Main code)
using utils Open browser: Open async firefox #Open async google-chrome Goto URL: #Press 'F6' echo 'Going to url %args%' Type %args% Press 'Enter' New tab: Press 'Ctrl', 'T' Close browser: Press 'Alt', 'F4' Open browser New tab Goto URL "www.google.com" Close browser
As you can see the constructs of this language are pretty simple, and so will be the syntax configuration.
Tokenizing the text
A tool like regex101 is quite handy for testing out regular expressions
Below are the regular expressions that single out the language constructs for this example:
Element Type |
Regex Pattern |
String on its own line ending with colon |
/:$/ |
Indented strings |
/^\s\s*.*$/ |
Non-indented strings without colon |
/^\S.*[^:]$/ |
import keyword |
/^import\s/ |
using keyword |
/^using\s/ |
Decorator |
/^@[^" "\t]*/ |
Comment |
/^\s*#[^if].*$/ |
#if Statement |
/^\s*#if.*$/ |
Picking out the colors
Execute ‘:highlight’ in the vim console
This shows you a list of various styles as rendered by the active color theme. Keeping this as a reference, we can specify in our language file how each token is rendered.
Note: these colors vary depending on the active color theme.
The syntax file
This is what the final syntax file looks like:
smsh.vim 📥
" smsh.vim " Define the language name and the file extensions it applies to " Put this syntax file in the 'syntax' directory in Vim runtime " e.g., ~/.vim/syntax/smsh.vim " Use 'au BufRead,BufNewFile *.your_file_extension' for custom file extensions if exists("b:current_syntax") finish endif syntax clear " Define the color for different language elements " String on its own line ending with colon (yellow) syntax match customString /:$/ contains=customStringText highlight link customString BlueSign " Indented strings (blue) syntax match customStringText /^\s\s*.*$/ highlight link customStringText AquaSign " Non-indented strings without colon (yellow) syntax match customNonIndentedString /^\S.*[^:]$/ contains=customNonIndentedStringText highlight link customNonIndentedString AquaSign " Import keyword (pink) syntax match customImport /^import\s/ syntax match customImport /^using\s/ highlight link customImport AquaSign " Decorator syntax match decorator /^@[^" "\t]*/ highlight link decorator BlueSign " Comment (grayed out) syntax match customComment /^\s*#[^if].*$/ highlight link customComment Comment syntax match ifStmt /^\s*#if.*$/ highlight link ifStmt BlueSign
As shown, putting this file in ~/.vim/syntax/ directory will register your language syntax in vim every time vim loads.
Thats it !!
From here, it is straight forward. You could either:
•Open a .smsh script file in vim or
•use the command [:set filetype=smsh] to activate syntax highlighting in an already opened file.