About snippets

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:

  1. /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.
  2. /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.

Defining a placeholder with multiple defaults

Defining a placeholder with multiple defaults

Activating the snippet

Activating the snippet

I’ll try to occasionally highlight other hidden gems in gedit, until then…

Posted in gedit. 9 Comments »

9 Responses to “About snippets”

  1. jessevdk » About snippets Information By About Says:

    [...] posted here:  jessevdk » About snippets By admin | category: about | tags: doxygen-documentation, one-plugin, plugins, power, [...]

  2. Sri Ramkrishna Says:

    How about you write a GNOME Journal article on GEdit with all the cool tricks you’ve collected. You’ll get better distribution than just planet. Mail us!


  3. Janne Says:

    Didn’t know about snippets. Looks promising.

    One thing: the manual says you need to hit ctrl-space to see the currently available snippets – but ctrl-space is also the key for switching between kana and romaji input for Japanese (and, I believe, for most other IBus-activated input methods). Is there any way to change that key combination?

  4. oliver Says:

    “for example, you can manipulate the file browser plugin in many useful ways using the bus”

    This sounds interesting! I’ve already looked for a way to hook into the file browser plugin but didn’t find a straight-forward way.

    Can you elaborate on this feature? Which Gedit version do I need? Is there some example code around?

    Thanks, Oliver

  5. Jesse van den Kieboom Says:

    @Janne: With the current snippets it is unfortunately hard coded (you can edit /usr/lib/gedit-2/plugins/snippets/Document.py if you really want to change it). The new completion stuff in the upcoming stable release will use gtksourcecompletion to show completions, and here you can configure the keybinding using the normal gtk+ methods (gtkrc)

    @oliver: it’s available from 2.26 I think, but some issues with it were resolved in 2.28 (so if you have the possibility, use 2.28). At the moment the messages it exposes are not really documented (I still need to do this). There is one project out there that uses this functionality to integrate git with the plugin, you can have a look to see how it works (http://gitorious.org/giterdone). Note that there are also bugs in 2.26 in the python bindings for the message bus, so if you want to use it, I also advice 2.28, or using the C API.

  6. joe Says:

    I really like snippets and attempted to import them from my linux machine and it doesn’t seem to work. Is this a known bug?

  7. joe Says:

    Also I noticed that doing command+c and friends for stuff like copy/paste make a “bong” noise whereas ctrl+c and the like do not. Is it possible to keep it from making that noise each time I copy/paste? Trivial but it’s annoying.

  8. Jesse van den Kieboom Says:

    @joe: will need a bit more information than that. Guessing from your second post, you’re using it on the mac. What kind of issues do you have with snippets not working? There might be some snippets using linux specific things. Please file a bug report on bugzilla.gnome.org for this.

    The “bong” noise I don’t know. It appears to have been introduced with the upgrade to gtk+2.18, but I haven’t been able to figure out how to fix it. And yes, it’s pretty annoying!

  9. joe Says:

    Bug ticket created. Thanks!