ApplicationCommandLine

In Terminix I’m making some improvements to how I’m handling the command-line by moving away from D’s getopts to the GTK method of dealing with it. The primary driver for this is to get the command line sent from the local application to the primary one. To do this, I registered my Options via setMainOptions, added a handler to addOnCommandLine and included the flag HANDLES_COMMAND_LINE when creating the application.

It all worked swimmingly except for one issue, while the primary got the command line just fine, the local instance would just hang and never return. After scratching my head for a bit and asking on the GTK IRC channel, a pointer to a C example gave me the nudge I needed. Looking more closely at the documentation for ApplicationCommandLine, I see this line:

For the case of a remote invocation, the remote process will typically exit when the last reference is dropped on @cmdline.

The issue here is that since D is GC’ed, the ApplicationCommandLine doesn’t get collected in a deterministic fashion. The solution was quite easy, simply destroy it at the end via a scope(exit) block. I’m going to file an issue with GtkD to see if this shouldn’t be made a Scoped reference.

GtkD and Localization

On my todo list for awhile has been adding localization support to Terminix. Unfortunately at this time D does not have an official i18n package nor are there any libraries supporting the GNU gettext which has become a De facto standard for localization over the years. While there are some localization libraries available for D, I really wanted to stick with gettext given the huge eco-system it has in terms of support tooling and websites.

While examining my options, I stumbled on the fact that the GTK GLib library supports gettext and that GtkD has already wrapped them in the glib.Internalization class. After refreshing my knowledge of how gettext works I was able to put together a basic working localization system in about an evenings worth of work. The remainder of the post will describe the steps involved with getting it working.

I knew in Terminix that I would need to support localization, so from day one I had a module gx.i18n.l10n that contained a single function following the gnu gettext pattern as follows:

string _(string text) {
    return text;
}

Whenever something in Terminix would eventually need to be localized, I would simply wrap it in a call to this function. Obviously at this early stage the function does nothing beyond returning the original text. An example of its usage is as follows:

string msg = _("This is a localized string");

For those of you familiar with the usage of gettext in C or other languages this will all seem familiar. For anyone else, in gettext any text you want to localize is wrapped in this function and becomes the key for retrieving a localized version. If no localized version is available, i.e. for a language for which a translation does not yet exist, the key is used as the text that is displayed. in my opinion, this system is much superior to localization systems that require programmers to have to embed artificial keys in the code and is one reason why gettext is so popular.

The next step was to simply incorporate the glib.Internationalization class from GtkD, so I updated my _() method as follows:

string _(string text) {
    return Internationalization.dgettext(_textdomain, text);
}

The textdomain parameter above is used by gettext to differentiate this application from others and will be discussed in more detail later. At this point, the application now supports localization but the real work begins as we need to prepare all of the localization materials that gettext requires. In gettext there are three types of files required for localization:

  • Template. This file, with a .pot extension, is used as the template for the localization. For a given application there is typically only one template file.
  • Portable Object (po). These files, with the extension .po, contain the localization for a specific locale, for example en.po or fr.po. These files are in the same format as the template file.
  • Machine Object (mo). These are the binary files that are used at runtime and are created by the msgfmt utility. These files have a 1:1 mapping with a po file in that each mo file is created from a po file.

Here’s an extract showing what a template/po file looks like:

msgid "Match entire word only"
msgstr "Match entire word only"

msgid "IBeam"
msgstr "IBeam"

msgid "Run command as a login shell"
msgstr "Run command as a login shell"

msgid "Exit the terminal"
msgstr "Exit the terminal"

in the extract above, the msgid is the key while the msgstr is the actual localization and as per above in the template file these will be identical. Additionally for most applications there is no need to provide a localization file for the locale the developer is using since that locale is already embedded in the source code by default.

The challenge at this point was creating the template file, while the gettext program has a utility called xgettext that can extract all of the localized strings from source code, unfortunately D is not one of the languages supported. I thought about creating a version of xgettext using the excellent libdparse, however I opted for a quick and dirty method as Terminix doesn’t have a large amount of strings needing localization.

What I ended up doing is adding some code to my l10n module to capture all the localization requests and then write it out a file when the application terminates. This has the advantage of being relatively easy to do but the disadvantage that you have to exercise the app pretty completely to capture all the strings. For Terminix there were only a few areas I couldn’t exercise easily and for those I simply updated the template file after the fact. Below is the code I used to generate the template file, note the use of the Version specification so this code only gets included in a specific build configuration. I’ve removed some of the comments for the sake of conciseness, you can view the original code in github.

module gx.i18n.l10n;
 
import glib.Internationalization;
 
version (Localize) {
 
    import std.experimental.logger;
    import std.file;
    import std.string;
 
    string[string] messages;
 
    void saveFile(string filename) {
        string output;
        foreach(key,value; messages) {
            if (key.indexOf("%") >= 0) {
                output ~= "#, c-format\n";
            }
            if (key.indexOf("\n") >= 0) {
                string lines;
                foreach(s;key.splitLines()) {
                    lines ~= "\"" ~ s ~ "\"\n"; 
                }
                output ~= ("msgid \"\"\n" ~ lines);
                output ~= ("msgstr \"\"\n" ~ lines ~ "\n");
            } else {
                output ~= "msgid \"" ~ key ~ "\"\n";
                output ~= "msgstr \"" ~ key ~ "\"\n\n";
            }
        }
        write(filename, output);
    } 
}
 
void textdomain(string domain) {
    _textdomain = domain;
}
 
string _(string text) {
    version (Localize) {
        trace("Capturing key " ~ text);
        messages[text] = text;
    }
 
    return Internationalization.dgettext(_textdomain, text);
}
 
private:
string _textdomain;

When capturing text, there are a couple of special cases in gettext to be aware of. The first is that the xgettext utility puts a special comment in front of strings that use C style formatting, i.e. %d or %s. I don’t think this comment is used but I wanted to keep it. The second is that the key for multi-line strings is generated with each line separated. That’s why in the code above you see the check for newline and the splitLines call.

Once the template file is completed we are ready to create our first localization. In my case, I created an English localization as Terminix has some programmatic terms (shortcut identifiers) that were intended to be localized to human friendly language rather then shown directly to the user. Creating the en.po file is just a matter of copying the terminix.pot file to en.po. While gettext has a utility for this, msginit, I just opted to copy it for simplicity.

Once the en.po localization was completed it needs to be compiled into a mo file. In Linux, mo files are stored in usr/share/locale/${LOCALE}/LC_MESSAGES where ${LOCALE} is the standard language/country code. The mo files for the application are named after the textdomain for the application and this is how gettext locates the right file for the application. For example, in Terminix’s case the full path to the English mo file would be usr/share/locale/en/LC_MESSAGES/terminix.mo.

To compile the mo file, simply use the gettext msgfmt utility as follows:

sudo msgfmt en.po -o /usr/share/locale/en/LC_MESSAGES/terminix.mo

Obviously you would want to script the above process as part of creating an installation package, you can see how Terminix does this here.

Using the GAction Framework

In GUI development you typically want to centralize event handlers given that it is pretty common to have multiple GUI elements (button, menu item, etc) invoking the same event. In many frameworks these centralized event handlers are typically referred to as actions. In GTK the action framework is part of GIO and is referred to as GAction. An overview of the framework can be found in the Gnome wiki in this How Do I entry.

Having done Delphi development 15 years ago I had some familiarity with the concept but it still took a bit of time to get up to speed on GActions. While the Gnome wiki provided some basic information, I still found it confusing in some spots so I thought I’d write a bit about my experience using GActions in Terminix as it specifically relates to the D language and the GtkD framework.

First some basics, every GAction has two elements that identify it, a prefix and a name. The prefix is a way to categorize actions and within a prefix the name of the action must be unique. The prefix and the name together, with a period between them, make a detailed action name and this is how you reference actions when binding them to UI elements. So if you have a prefix of “terminal” and a name of “copy” the detailed name would be “terminal.copy”.

Actions are stored in containers which typically implement the interfaces gio.ActionMapIF and gio.ActionGroupIF. Out of the box, GTK implements these interfaces in Application and ApplicationWindow. Actions registered against these objects are automatically assigned the prefix of “app” and “win” respectively. Typically actions registered against the Application object are used in the Gnome application menu and actions registered against ApplicationWindow operate against that window.

An important thing to understand though is you are not limited to registering actions against just Application and ApplicationWindow, you can register actions against any widget in your application using custom prefixes. The key is using the gio.SimpleActionGroup to create your own container to register actions against. You can then bind the SimpleActionGroup to a widget via the method insertActionGroup. An example of this is shown below:

SimpleActionGroup sagTerminalActions = new SimpleActionGroup();
//...create actions and register to the group
insertActionGroup(“terminal”, sagTerminalActions);

Understanding how to create your own action groups gives you a lot of flexibility in organizing your actions. Terminix is an application where the UI is heavily nested and generally I wanted to keep each layer isolated from each other. I didn’t want the Terminal to know too much about the containers it is nested within. Being able to create these custom action groups allows the terminal to have it’s own set of actions without needing a mechanism to bind them to the window.

The other benefit to this approach is that the GIO framework will allow you to have multiple instances of the same action and will determine which instance get’s invoked based on the scope. In Terminix I have multiple terminals each with the same set of “terminal” actions registered. The GAction framework automatically invokes the right action instance based on the terminal that has focus presumably by walking up the widget hierarchy until it finds the first widget with the action it is looking for.

To register an action, you simply create an instance of gio.SimpleAction which is a concrete implementation of the ActionIF interface and the add it to the desired ActionMap. A simple example would look like:

action = new SimpleAction(“copy”, null);
action.addOnActivate(delegate(Variant, SimpleAction) {
vte.copyClipboard();
});
sagTerminalActions.add(action)

Once you have your action, the next step is to bind it to a user interface element. One thing to be aware of is that in GTK there are actually two action frameworks, the one in the gio package (SimpleAction, SimpleActionGroup) and one in the gtk package (Action, ActionGroup). The one in GTK is considered deprecated and it is highly recommended to use the GIO action framework where possible. In general, GTK widgets that work with GIO actions use the method setActionName to specify the target action, the method setActionTargetValue is used by the GTK framework.

To bind the action to a UI element, you simply call the setActionName method with the detailed action name, for example:

button.setActionName(“terminal.copy);

Actions can be represented in menus using a variety of UI elements such as check and radio buttons. This involves declaring that an action has state which is represented by a GLib Variant in the Activate signal. I won’t spend any time on this topic, however for those interested I wrote an actions demo showing how to do this with popovers and it is available in the GtkD repository here.

If you want your action to have an accelerator, i.e. a keyboard shortcut, you need to register the key and the detailed action name with the your global GTK Application instance using the method Application.setAccelsForAction. Here is an example of this:

app.setAccelsForAction(“terminal.copy”, [“c”]);

This concludes the article on GActions, hopefully as you can see this provides a powerful framework for centralizing your event handlers within a GTK application. One final note, for the purposes of this article I’ve been using strings directly for prefixes and names for illustration. Obviously, you should declare these as constants in your code to ensure consistency. If you need to change the name of a prefix or action, having the string declared in one spot makes that job much easier.

Iterating over TreeIter

I’m working on a GTK application and found there were a few spots where I needed to iterate over a TreeModel. Doing this in GtkD is a bit of a pain since TreeModelT isn’t implemented as a Range and so you are forced to use the model methods rather then the convenience of foreach.

To make my life easier, I created a small struct that can be used to wrap a TreeModelIF interface and allows it to be used in D’s foreach construct as per this example:

foreach(TreeIter iter; TreeIterRange(lsProfiles)) {
	if (lsProfiles.getValue(iter, COLUMN_UUID).getString() == window.uuid) {
		lsProfiles.setValue(iter, COLUMN_NAME, profile.name); 
	}
}
/**
 * An implementation of a range that allows using foreach over a range
 */
struct TreeIterRange {
 
private:
    TreeModelIF model;
    TreeIter iter;
    bool _empty;
 
public:
    this(TreeModelIF model) {
        this.model = model;
        _empty = model.getIterFirst(iter);
    }
 
    @property bool empty() {
        return _empty;
    }
 
    @property auto front() {
        return iter;
    }
 
    void popFront() {
        _empty = !model.iterNext(iter);
    }
 
    /**
     * Based on the example here https://www.sociomantic.com/blog/2010/06/opapply-recipe/#.Vm8mW7grKEI
     */
    int opApply(int delegate(ref TreeIter iter) dg) {
        int result = 0;
        TreeIter iter;
        bool hasNext = model.getIterFirst(iter);
        while (hasNext) {
            result = dg(iter);
            if (result) break;
            hasNext = model.iterNext(iter);
        }
        return result;
    }
}

Creating Complex Popovers in D and GtkD

I’m working on a new terminal emulator in my spare time and one UI element I definitely wanted to make use of was Popovers. While creating a simple Popover is quite easy, I was struggling a bit with how to handle the more complex layouts like horizontal buttons as the documentation does not make it very clear. Fortunately, Christian Hergert of Builder fame was on IRC one night and was able to point me in the right direction.

The Popover I created is shown in the image below, in the terminal emulator I’m working on it allows you to split the terminal into multiple views or tiles so the user can see multiple views at the same time in an easily managed container. The Popover allows the user to split the terminal horizontally or vertically (note the icons are temporary, plan on “borrowing” Builder’s icons for this at some point).

Popover

The issue I was struggling with was where to set the display-hint, the section being a gio.Menu doesn’t have methods to set an attribute. What Christian pointed out to me is that you need to create an empty MenuItem to represent the section, add the section to that and then add it the menu used in the Popover. You can then set the necessary attributes on the empty MenuItem to get the items displayed in the way you want.

Here is the code I ended up with:

Popover createPopover(Widget parent) {
GMenu model = new GMenu();
 
GMenuItem splitH = new GMenuItem(null, "view.splith");
splitH.setAttributeValue("verb-icon", new GVariant("go-next-symbolic"));
splitH.setIcon(new ThemedIcon("go-next-symbolic"));
 
GMenuItem splitV = new GMenuItem(null, "view.splitv");
splitV.setAttributeValue("verb-icon", new GVariant("go-down-symbolic"));
splitV.setIcon(new ThemedIcon("go-down-symbolic"));
 
GMenu section = new GMenu();
section.appendItem(splitH);
section.appendItem(splitV);
 
GMenuItem splits = new GMenuItem(null, null);
splits.setSection(section);
splits.setLabel("Split");
splits.setAttributeValue("display-hint", new GVariant("horizontal-buttons"));
 
model.appendItem(splits);
 
Popover pm = new Popover(parent, model);
return pm;
}

Learning D and GTK

Quite awhile ago I wrote a post about learning Python and GTK, unfortunately while I played around with it a bit I never really took to Python. The dynamic typing and the usage of whitespacing as delimiters were not my style. Additionally, I was doing a lot of travel for work at the time and could never really muster the energy at the time to overcome my initial dislike of Python.

So as work slowed down a bit I figured I’d try something new this time. I decided to pick up D due to a number of factors including:

  • It’s derived from the C family so has some similarities to Java
  • It’s a compiled language so performance is excellent
  • Has a garbage collector so again similar to Java.
  • And most importantly, has full and up to date bindings for GTK

I had also considered trying Go, but the last point put a bullet in that the available GTK bindings appear to have a ways to go.

So to put the conclusion first, I did end up writing a small utility in D and GTK called Visual Grep. It’s a GTK based GUI for grep that follows Gnome Human Interface Guidelines (HIG) as much as possible. A screenshot is below, if you are interested in trying it out you can find it on Github.

Visual Grep

Learning D

I’ve had my eye on D for a number of years as a possible language to use for building GUI applications. The language itself is well designed and as a lot of advantages in the GUI space with safety features such as garbage collection combined with high performance as a compiled language.

Learning the D language itself is relatively straight forward and I didn’t find the learning curve to be that high. Coming from Java, the biggest hurdle was understanding ranges which is core to many features in D. I found it helpful as a starting point to think of ranges as an advanced version of Java’s Iterator class. The other key features in D, such as templates, can be learned over time but Ranges are core to D and need to be understood right up front so I’d recommend dedicating some time to it right at the beginning.

The next aspect of learning D is understanding the standard library called phobos. This library can be thought of as occupying a similar space as the core J2SE libraries. Learning the library and features available is not overly difficult, however the documentation available on dlang can often be overly succint. Additionally, in the Java world if you google on any API you can find a wealth of information, discussion and examples. Since D is much less popular, the amount of resources available is also consequently much less (a theme that will re-occur in subsequent sections).

Having said that, the D community is big enough that questions on forums and the irc channel got answered and I never found myself blocked on any particular issue.

The only issue with D, and reflected in phobos, is the general lack of a library eco-system. In more mainstream environments like Java and Python, there are a plethora of libraries to pretty much cover any use case. Want to create and parse XML, work with PDF files, do localization, interface with USB, etc you have your pick of libraries. In D not so much, while most core functions are available, some key ones are not. For example, there is currently no standard i18n package available for localization, logging is deigned experimental, etc.

This lack of resources is also reflected in phobos itself in terms of implementation and execution. For example, D has an excellent design with respect to multi-threaded communication based on message passing. D also supports the concept of declaring variables as immutable which would seem to be a perfect fit with respect to this message passing. From a design perspective it should work, however due to limitations in the implementation of variants in D you can’t actually use an immutable variable in this scenario. Either you pass a shared variable (D’s way of declaring a variable to be shared among multiple threads) or pass a pointer to the immutable variable and de-reference it on the receive.

Finally the last area of D that I struggled with a bit is pointers. While I have done some work with pointers in the past in Delphi, the usage of pointers in Delphi tended to be very rare. I have to be careful and not exaggerate as by no means is the usage of pointers in D constant need when building GTK apps, it’s just I did find I needed to work with them more then I did in Delphi due to the need to interface with C. Having coded only in Java for the last 12 years, coming back to pointers was a bit of a culture shock.

Learning GTK

My previous experience with GUI frameworks includes Java Swing (hate it) and Delphi VCL (love it).. D has a very complete set of bindings for GTK called GTKD and is highly recommended, Mike Wey does a great job keeping these up to date for each release of GTK. Based on my experiences with Swing and VCL, learning and getting productive with the basics of GTK was very easy with two notable exceptions.

The first is the GTK Treeview which, despite the name, is really an all encompassing listbox/treeview which serves multiple use cases. While it is undeniably powerful, I found it’s API a bit obtuse and difficult to accomplish the basic use cases. The sheer variety of objects related to the TreeView (TreeView, TreeModel, TreePath, TreeIter, CellRenderer, etc) is a bit overwhelming to the newbie.

The other aspect I struggled with a bit was the multi-threading. In GTK, the preferred approach to multi-threading is to setup a callback gdk-threads-add-idle. While not an issue in GTK per se, GTKD does not really give any examples on how best to integrate this with D. Looking at the design though, I went with integrating this with D’s threaded message passing infrastructure and it turned out to work very well but I burned quite a lot of time prototyping and testing to make sure I understood how everything worked.

An invaluable resource for learning GTK and GtkD was the grestful application, an open source D/GtkD application for testing REST requests. I borrowed quite a bit of code from that application including the plumbing for being able to tie in a D delegate to the GTK thread idle callback so a big thanks to that project for this.

Finally, I’d really recommend having some basic proficiency in another language with full bindings in GTK, either C or Python. The reason for this is that there is very little information out there on using D with GTK but GTK examples in other languages are easily ported to D providing you can work through the code of the example. My C and Python knowledge is pretty sparse but I found I knew enough to get by.

Tool Chain

The tool chain for D is somewhat primitive in comparison to Java but is imminently useable. I do all my development on Linux and so ended up using Mono-D and generally had a pretty positive experience. My only complaints are as follows:

  • When trying to run a program, you can an error about failing to create a console. Turns out this is an issue with gnome-terminal as documented here. Unsetting the GNOME_DESKTOP_SESSION_ID variable fixed the problem.
  • Code completion seems a bit hit and miss, most of the time it works great but once in a while you hit the’.’ and nothing happens.

Debugging can be done in Mono-D using the GDB plugin and I found this to work quite as well when I was dealing with segmentation faults with my multi-threading code.

For builds I used DUB which is somewhat similar to Maven in the Java world in that it is based on convention not configuration and manages dependencies. I found DUB worked quite well for me and have been pretty happy with it though admittedly my two projects are pretty simple.

Conclusion

Based on my experience so far, I think D and GtkD are a great combination for creating GTK applications in Linux. The learning curve is far shorter then using C and the language itself is much more productive then I say that as a C neophyte so take that with a pinch of salt. Additionally, the safety features of D (GC, RAII, exceptions, etc) make for more reliable software in comparison to C.

Python would also be a very good choice, but coming from a Java background D just felt much more comfortable to me.