I think most people know that besides being a very light weight, and simple text editor for GNOME, gedit can also be “transformed” to a more powerful editor using the many plugins is supplies. One of those plugins is the Snippets plugin, and I would like to point out some of its more advanced features that even most of the gedit developers don’t know about.
Snippets is featured by virtually all source code editors in one way or another. It provides an easy way to insert/activate small templates in your document with some variables, or placeholders to quickly suit it to your specific use case. Placeholder can have default values, you can mirror placeholders in multiple locations, and you can specify where the cursor needs to end up when all the placeholders have been visited (you can read more on basic functionality of snippets in the gedit help). I would like to discuss four features that might be less well known.
1. Python placeholders
Python placeholders are placeholders that execute arbitrary python code to provide the text to be placed at the placeholder location. The placeholder syntax is as follows:
$<n:[k]: python code [return string] >
Here n is the optional placeholder tabstop as with other placeholders. If a python placeholder does not have any dependencies (implicit or explicit) on other placeholders, you will be able to tab to it by that tabstop. The tabstop can also be used to refer to this placeholders’ contents in other placeholders. The second optional modifier is [k], where k is one ore more comma separated tabstops referring to other placeholders. These indicate explicit dependencies (I’ll explain them later). In the python code, you simply return the string you want at the placeholders location. In the code you can use gedit environment variables for snippets (like $GEDIT_CURRENT_DOCUMENT_PATH) and references to other placeholders (using $n). This will provide you with a kind of mirror placeholder doing a particular transformation on one ore more other placeholders. Python variables can be shared between multiple python placeholders using global. This is where explicit dependencies come into play. Snippets does not automatically find out that another placeholder might depend on a change in a global variable, and thus should be updated. Defining the dependencies explicitly ensures the placeholder will be updated when any of its dependencies has changed.
For an example of this more advanced functionality, take a look at the gobject snippet provided for C headers and C sources. It makes extensive use of the python placeholders and is quite a nice way to bootstrap gobject classes.
2. Regular expression placeholders
Python placeholders are very powerful, and using the re module, you can do regular expression substitution quite easily. However, regular expression transformations are quite common, and a special placeholder is available which makes it easier and cleaner to use regular expressions. The syntax is the following:
${[n:]input/regular expression/substitution[/modifiers]}
Here n is the usual tabstop, input is the text on which you want to apply the regular expression. This can be either another placeholder (a number) or an environment variable such as GEDIT_SELECTED_TEXT (useful when you activate the snippet on selected text). The regular expression is a regular expression conform the python re module. This will be searched for in the input (note: this means it does not have to exactly match the input). The last part specifies how to substitute the match. Here you can use \n to backreference matched groups in the regular expression. Additionally, a special syntax allows you to apply a small number of transformations on the backreference using \<n,modifiers>. Modifiers can be one or more of the following:
- U: Uppercase the matched group
- L: Lowercase the matched group
- u: Uppercase only the first character of the matched group
- l: Lowercase only the first character of the matched group
- t: Title case the matched group
Combining them can be useful if you want to want to capitalize only the first word, for example: \<0,Lu>. This will first lowercase the match, and then uppercase only the first character.
The last part of the regular expression placeholder specifies a set of optional modifiers for the regular expression matching equal to the modifiers in the python re module. One last feature is the use of conditions in the substitution part of the placeholder. Using the syntax (?n,truepart,falsepart), you can substitute a group depending on whether it matched or not (useful for optional groups). These can also be nested, so you can build more complex conditions.
3. Dynamic snippets
A new feature was recently developed and is currently available in the development releases (2.29.x): dynamic snippets. Snippets now exposes two functions on the gedit internal message bus (which is used to enable inter plugin communication). The message bus is similar to how you would use dbus, but just for internal use. It allows plugins to hook into each others functionality (for example, you can manipulate the file browser plugin in many useful ways using the bus). For snippets, the following two messages are available:
- /plugins/snippets.activate (trigger[, view, iter])
When this message is send, the snippet corresponding to the tab trigger <trigger> is activated. You can optionally specify the view and iter where to activate the snippet, by default the current view and cursor will be used. - /plugins/snippets.parse-and-activate (snippet[, view, iter])
This message enables the dynamic snippets. Basicly, you provide the full snippet and optionally the iter and view where to activate it. This provides a very powerful mechanism to use all of the power of snippets from other plugins. I use this in one plugin (gedit-commander which I will talk about at some point) to dynamically build a snippet for a doxygen documentation of a function declaration.
4. GtkSourceCompletion integration
The last thing I want to show is the recent integration with gtksourcecompletion nacho recently blogged about. Before, snippets implemented its own completion popup for when there are multiple snippets with the same trigger. This popup was really quite horrible and had a lot of usability problems. This has now been resolved in the development version (2.29.x) using gtksourcecompletion. One additional feature is the use of multiple default values for placeholders. Using the syntax ${n:[value1,value2,value3]}, you can provide multiple choices for the default value. When you tab into this placeholder, a completion popup will show you the available choices so that you can quickly pick one. This is particularly useful for example for CSS snippets, where some CSS properties have a specific set of valid options.
I’ll try to occasionally highlight other hidden gems in gedit, until then…