Guest|Author:|Diogo Andre de Assumpcao is a network engineer working on network reliability and automation, and has a deep passion for writing code.
If you walk into a room full of developers, there is one thing you'll quickly notice on their screens - multicolored text. Coloring source code is called syntax highlighting, and it exists not just to make our screens look like a text-based candy crush, the main idea is to improve readability and to make it easier to derive context from an otherwise monochromatic block of text.
The commands we use to configure our Cisco devices are not exactly a programming language. Still, they share many similarities, and there are various advantages in treating configuration as code. Syntax highlighting is one of those advantages, and -being also a developer -it was something I missed when dealing with network configurations. So, a while ago I set out to fix that and created thelanguage-cisco package for the Atom editorand placed it in the DevNet Code Exchange.
Here's what a piece of syntax highlighted configuration looks like:
Neat? Allow me to give you some background and walk you through the basics of syntax highlighting.
There are many text editors out there, some have been around for decades (Vim was first released in 1991), others, like Atom, are very recent (open sourced in 2014). Atom was brought to life by GitHub, with the tagline "a hackable text editor for the 21st Century." I started using Atom very early, and also made some small contributions to the main packages. When I started thinking about writing a syntax highlighter, Atom was the obvious choice for me.
I learned early on my quest that the part of a syntax highlighter I needed to write was called a Grammar. A Grammar has no concept of colors, its only job is to assign properties to parts of the text matched against its patterns. The colors are brought in by the Syntax Themes.
A grammar is basically a set of rules that tells the editor what the role of each part of a text is. It does that by assigning properties to the parts that are matched against specific rules; those properties are later interpreted by the editor, including properties that define scopes (for code folding for example). In summary, a grammar is heavily based on matching keywords and deriving scope from them.
Now, here comes the hard part. Most programming languages are very well structured. The keywords are well defined, and the rules on what constitutes a boundary or a scope are clear. Take the following method written in Ruby as an example:
We know that def is a keyword that marks the beginning of a method and that it is followed by a string that forms the name of the method. We also know that end marks the end of a method, closing the function defining a scope. In Ruby specifically, the list of keywords isn't very long at all.
Cisco configuration files, on the other hand, have a list of keywords that is a bit longer (every command is a keyword), not every scope-defining command has a clear closing marker, and the keywords and scopes change a lot between software versions and different platforms. Here's an example of what I mean by different closings of scope:
The two commands above are very similar. The IOS command on the left has an explicit closing marker exit, the ASA command on the right uses a "!" to mark the end of the scope. Writing a grammar for such a diverse 'language' involves mapping many keywords and covering edge cases and ambiguities.
This may sound complicated, but in reality, it is a lot like playing Lego (if you had to build the blocks yourself). Let's see one of those building blocks. The snipped bellow is written in CSON the CoffeeScript counterpart of JSON. The only thing that it does is match IP addresses:
Quick note: If you haven't guessed yet, there is a lot of regex involved in writing a grammar.
The snippet creates a pattern to match IP addresses. It is a basic Lego brick in our analogy; the next step is to attach a bunch of bricks together to make something more functional. Check the next snippet:
The snippet above is a bit more complex. While it adds more regex to the mix, it also include references to other parts of the grammar, this is what I meant by playing Lego. We include here the ip_address, ipv6_address and description blocks. We can then use these blocks anywhere such matches are required, by reusing parts of the code, we also ensure a consistent output, as all IP addresses will be marked with the constant.numeric.cisco property for example.
I mentioned before that the grammar attaches properties to parts of the text. In the IP address snippet above, the grammar will attach to every matching string the property constant.numeric.cisco. Those properties are in fact HTML classes that will be added by the editor when rendering the text to be presented on screen. These classes will then be used by CSS styles provided by syntax themes to finally add color and style to the text.
Now that you know the basics about creating a syntax highlighter, why not create one for your editor of choice? Better yet, find one that you use and improve it! Check out my language-cisco package for the Atom editor on DevNet Code Exchange. You'll find DevNet Code Exchange to be a great place to learn, build, and collaborate on your projects.
Wherever you are in your network programmer journey, you'll find all kind of resources, learning labs, docs, and sandboxes to help you along. Get your free DevNet account for access.
We'd love to hear what you think. Ask a question or leave a comment below.
And stay connected with Cisco DevNet on social!
Twitter @CiscoDevNet | Facebook | LinkedIn
Visit the new Developer Video Channel