Fri 23 Apr 2010
One of the things that we think sets SlickEdit apart from other editors is the amount of customization you can do to it. If you aren’t happy with the way something behaves, chances are there’s an option to change it. In addition to the standard settings available in the Options dialog, there’s the fact that much of SlickEdit is written in macro code. This allows for an entirely new level of customization and functionality tailored to the way you work.
Unfortunately, only the most advanced of the advanced users ever consider getting so deep into an application that they learn to write their own macros for it. There’s a few reasons for this. Many people don’t even know that so much functionality is available in macro form. Even if a user did look into making their own macros, finding out what functionality is available in macro code is an enormous challenge. We all have deadlines and important things to do, and learning a new code base like the Slick-C macro language just doesn’t realistically fit into most people’s 24 hour day.
I personally love making little knock-off gizmo utilities for things that fit my workflow. One of the things that I do often is putting debug statements at various points in my code to report the value of some variable. This is very helpful when you want a history of values, not just a one stop breakpoint in the debugger. I decided to make a macro that adds these statements automatically given the word under my cursor (assuming it’s a variable). It’s a simple, first-step macro, and instead of just posting the code, I’m going to walk through the steps to make it.
Starting a macro from scratch
To start, click File > New Item From Template. This will bring up the “Add New Item” dialog. Select Slick-C in the “Categories” tree, select a location where you’d like this file (a scratch development folder is best), and enter insert_debug_value as the name.
Click the Add button. This creates a new file called insert_debug_value.e in the specified directory. This file will be opened in a new buffer with the following code included:
This is the basis for all macros started from scratch. You can load it hitting the escape button to go to the command line, then type “load” and hit enter.
SlickEdit will respond by reporting “Module(s) loaded” in the status area at the bottom of the application. You can now type “insert-debug-value” on the command line and your new command will execute. Of course, it doesn’t do anything yet…
Implementing the macro
A general strategy for this function will be the following:
- Get the current word that the cursor is in.
- Determine which language is being edited.
- Insert a new line beneath that to output it’s value.
That seems simple enough. To start, we’ll use the cur_word() function to determine the full word beneath the cursor. This function has a byref parameter, which returns the beginning column of the current word, so we have to pass a temp variable for that. We can also use the say() function to report the value of curWord to the stdout window. The code currently looks like this:
Again, you can reload this by hitting the escape button to go to the command line, then type “load” and hit enter. If you run it from the command line, it will show the stdout window titled vsapi.dll, and the value of curWord will be shown.
Now we can start to build the text that we’ll insert. Since we want this inserted line to be indented to match the current line, we’ll get the current indentation using the first_non_blank() function. This puts the cursor on the first non-blank column on the line. Next, we’ll get the column number using the p_col property. We can build an indentation string using the indent_string() function, passing the starting column value. The code now looks like this:
For this example, we’ll support three languages; Slick-C, C/C++ and Java. To tell which language we’re in, we can use the p_LangId property, which returns the language ID of the current editor. We can switch on that value and append the code to the variable containing the text to insert. Finally we can call insert_line() to insert the text we’ve built.
Go to the command line and reload the file by typing “load” and hitting enter. Now put the cursor on a variable in the editor, go back to the command line and type “insert-debug-value” and hit enter. A say() statement will be inserted into the file on the line after the cursor that reports the value of the variable your cursor was on. Now you have a way to quickly add a debug statement to your code to report the value of the variable without having to write anything. A final improvement is to store the original line number and column so they can be restored after the new line is inserted.
The macro file can be downloaded by clicking the this link.
Binding a key combination to your macro
A macro like the one we just made works best when bound to a key, since we don’t want to have to go to the command line every time we want to invoke it. To bind a key combination to this macro, bring up the options by clicking Tools > Options, then go to Keyboard and Mouse > Key Bindings in the options tree. Type the name of the macro in the “Search by command:” text box to find it. Double click its entry to bring up the “Bind Key” dialog. We’ll bind it to “Ctrl+Shift+/”. Press that key combination and it will appear in the “Key Sequence:” dialog. Click the “Bind” button to bind it. The key bindings entry should look like this:
Click OK on the options dialog. Now, whenever you press “Ctrl+Shift+/” your macro will execute.
Is it perfect?
Absolutely not! There are many potential problems here. The cursor may not be on a variable. The buffer may be read only. There are also many other languages that this macro could support. The list is potentially huge. However, this macro is a starting point from which you can start to tinker around with writing your own macros. Soon, you’ll be amazed at how much can be done with Slick-C that you’ll start writing lots of little tools and utilities that fit your own unique workflow. Check back for more blog posts in this series, which will build on what we’ve started here.