Lex Trotman Version 0.1 for Geany 0.19 and up
At some point in most software development workflows there comes a time when the editing is over and a command needs to be run. Some of the commands used are:
Simply running the program using an interpreter, eg Python code, or viewing HTML, where the command depends on the language being used.
Compiling a source file and running the result, or building a document, where again the command depends on the language in use.
Compiling and linking several source files and running/viewing the result
Complex processes involving multiple source files, installation etc.
Where multiple files are involved it is usual to use some sort of build tool, make, Cmake, JHbuild, BJam, Ant, Scons, WAF, Fabricate etc. These tools usually have their own configuration and the commands to activate them do not depend on the language the source files use.
It is also rare that a programmer works on only one thing at a time, most of us have several projects (using the word in its normal English meaning) on the go at one time. These may need different tool sets, even for the same source language.
Overall there can be potentially quite complex requirements of the task of turning source text into execution.
Development environments have traditionally addressed this complexity in one of two ways:
Limiting the complexity by restricting the user to one or two tool sets. This tends to result in tight integration and detailed support from the development environment.
Providing a lot of flexibility allowing users to configure the tools that suit them. This tends to result in a slightly more arms length approach to the integration of tools.
The approach of limiting the tool sets is appropriate for development environments which concentrate on limited languages, the original model of IDEs like Eclipse and Netbeans which heavily integrated the Java workflow.
However Geany supports a wide range of platforms and programming and documentation languages so it is more appropriate that it takes the approach of providing flexibility.
This document describes the implementation of that flexibility in Geany, how it is presented to the user and how it is configured using the GUI and by editing the configuration files.
Geany supports a wide range of user experience, from beginners to experts, from occasional users to continuous users. So it is important that its flexibility is presented to the user in a simple, intuitive manner. This is provided by the Build menu.
The menu is broken into sections that roughly follow the usual workflow for software/document development.
The top section generally provides menu items for working with the file you are currently working on, eg to compile it. These commands naturally depend on the language the file uses, and the menu items change as you change files. This section may even disappear entirely if Geany doesn’t know what to do with a particular filetype (specifically filetype None).
The second section generally provides menu items that do not depend on the specific file, usually they are for working on groups of files, eg running a builder program.
The third section helps with navigation to the places that the tools found errors in your source so you can correct them.
The fourth section provides methods of executing the program that results from a successful compile/build, or of viewing resulting documents. These commands may depend on the type of the source file or may not.
The final section opens a dialog to assist in configuration (see Configuring with the GUI below)
This structure has been used by Geany for some time and has proven easy to use and flexible. Many other development environments also use a similar arrangement further supporting its utility.
Commands from the first and second sections are run in such a way that Geany can see their output and can parse it for recognisable messages, usually errors. The results of this parse are used to mark the source file and to allow clicking on the message in the compile window to cause the editor to go to that file and line.
For increased flexibility the second item in the filetype independent section pops up a dialog and any text entered will be appended to the command that the menu item runs. Previous text entered in the current session is available on the combo-box list. This allows the same command to be run with differing parameters without having to configure each option separately.
Implementation, how flexibility is achieved
Behind the simple menu presentation to the user Geany still has to manage the complexity of the range of use-cases described in the introduction and map it to the menu.
This is achieved using a technique that is common in software systems, ordering the sources of information from most general to most specific and having more specific settings override less specific ones. Examples of this approach that you may be familiar with include, object oriented languages where functions redefined on derived (ie more specific) types override the same function of the (more general) base type, or cascading style sheets for HTML where more specific and later settings override a less specific/earlier one.
This overriding occurs independently for each position in the build menu, so some menu items may derive their settings from the user, some from the project and some from the system sources.
For the build system configuration the sources of the settings are fixed and the ordering (from general to specific) is:
default settings coded in Geany
settings in the system, that is the installed filetype file for the type of file selected in the editor
settings from the user preferences file
settings from a user configured filetype file for the type of file selected in the editor
settings independent of filetype from the open project file
settings for a specific filetype for the type of file selected in the editor which come from the open project file
Remember the setting from the source lowest in the list “wins”, ie that is what is used in the particular menu item, and each menu item is determined individually.
Not all the sources will exist, for example the user may have no configured filetype files or may not have a project open. Missing sources are simply ignored.
Notice that in reality there are only three sources, system, user and project settings with project overriding user overriding system. Within each of these, settings that depend on the filetype of the file selected in the editor are considered more specific than, and so override, settings for all filetypes.
This simple paradigm handles most of the use cases outlined in the introduction.
Configuring with the User Interface, the easy way
Geany provides GUI configuration dialogs for some of the build system settings. To keep the GUI simple not all combinations of settings can be handled from the GUI, but the most common can. All configuration combinations can be achieved by hand editing the configuration files as described in the next section. Note that even if you do end up hand editing, you should start off defining as much as you can using the GUI so that you will have a template to use for your changes.
There are two configuration dialogs:
one for editing user preference settings, activated by the “Set Build Commands” menu item, and
one for editing project preferences settings, it is the build tab in the Project→Properties dialog and is only available when a project is open.
Both dialogs are arranged the same:
This dialogs show the three configurable sections of the build menu and the items in them in the same order as they are shown on the finished menu.
The dialog shows only the configurable sections of the build menu, section three (the navigate error items) and section five (the set build commands) cannot be configured and are not shown to avoid the dialog becoming too big.
Like the menu, the dialog shows the commands for menu items in section one that relate to the filetype of the file currently selected in the editor.
Thus the dialog directly relates to the menu that is available as soon as it is closed.
The three columns in the dialog show:
the label to be shown on the menu,
the command to be executed, and
the working directory to run the command in.
The numbers of items in each section of the menu are set at startup by hidden preferences (see the Geany manual), so there can be spare unused items which show in the dialog, but if they do not have a label, they are not shown on the menu (well after all what good is a blank menu item).
To add/edit a label click on the button in the label column and a sub-dialog will open. If you precede a character with an underscore (_) that character will be the mnemonic character for that menu item, make sure that they are all unique within the menu.
To remove an item use the clear button on the right, do not just remove the label.
Note: An entry with a blank label (you deleted all the characters in the label submenu) will not show in the menu, but will still override lower priority entries, this is how you can hide unwanted default menu items, and so projects can ensure that there are no unwanted user configurations or defaults that could cause confusion.
Within the command and working directory entries the following character strings are substituted when the command is run.
%f – replaced by the filename of the file selected in the editor when the menu item is selected.
%e – replaced by the same filename but without the last extension.
%d – replaced by the absolute path of the directory of the file selected in the editor when the menu item is selected.
%p – replaced by the absolute path of the base directory of the currently open project.
More than one substitution can be made so for instance %d%e.exe would be used for the absolute filename of an executable on a windows system.
An empty command will of course do nothing, but an empty working directory will default to the same directory as %d.
The commands run by the first two menu sections have the output parsed for error messages and when found the relevant lines in the file(s) are marked with red wavy underlines and the line in the Compiler output window is shown red to indicate that it has been recognised as an error. Clicking on the red error line will take you to that line in the file in the editing window (opening the file if it isn’t already open).
Each of the first two sections has a regular expression that can customise the parse. This is a Perl-compatible regular expression (PCRE) where the first two match groups provide the filename (either absolute or relative) and the line number. These can occur in any order, a match group containing only digits is taken as the line number and the other is taken as the filename. If no regular expression is specified for a menu section then a hard coded default parser that matches many of the common error message formats will be used for the menu items in that section.
Changes to these dialogs are not saved until you click ok.
Remember that these commands can be set in the project preferences where they will be applicable only when the project is open. These settings will override settings in the user preferences dialog. If this is the case the whole row of the user preferences dialog will be insensitive and will show the values configured by the project preferences. This ensures that the user preference dialog continues to show the menu as it will be when the dialog is closed, and it also prevents possible confusion from editing a user preference setting and finding that it has no effect.
When there is a setting that can be overridden by editing it in this dialog (eg user by project or default by user), it will be shown in a lighter text colour. When you start to edit anything in the row, all the values from the settings being overridden are copied to the dialog and so will become normal coloured text. This copying ensures that all entries are complete.
Configuring by hand, with absolute power comes absolute responsibility
This section assumes that you have the basic skills to find the files to edit and understand the basic layout of Geany configuration files. If not review the manual now.
As the implementation section above explained, there are six sources of build system settings. Five of them are files that can be edited, but you should not edit the system filetype files. These are overwritten each time you upgrade Geany and you will lose your customisations.
Also the project filetype dependent settings and project filetype independent settings are both stored in the project configuration (the .geany) file, so in fact there are only three places to edit:
filetype files in the user configuration directory, filetype.ext where ext is a filetype name.
the user preference file , geany.conf in the user configuration directory, and
the project file project_name.geany which can be stored in the project tree or outside it as you chose.
Within these files only the contents of the [build_menu] section will be discussed, but first a mention of the [build_settings] section.
The [build_settings] section is the section where build settings were stored pre-Geany 0.19.
So that the system filetypes files didn’t have to all be updated at once and to remain backward compatible with older user configurations, the settings in the [build_settings] section are loaded it the menu item they are defining is not already defined by a [build_menu] section entry in the same file. This has worked so well that at the time of writing almost no system filetypes files have been converted.
Geany 0.19 and later will only write changes made in the build GUI to the [build_menu] section and will not touch the [build_settings] section. Because of the restricted changes that can be made in the GUI this should work. But the semantics of the two sections are different, so when you are hand editing you probably should not have both sections in the same file.
As noted before, filetype dependent settings are only considered if the file currently selected in the editor matches the filetype the setting is for. For settings in the filetype file, clearly that is the filetype the settings are in, but for project settings both the filetype and non-filetype dependent settings are stored in the project file. As detailed below, the format of the entries will specify which filetype they apply to.
As described in Using the Build System, the Build menu is divided into sections with filetype dependent items, filetype independent items and execute items.
Unlike editing with the GUI, when configuring by hand, this division is purely convention, despite the names there is no restriction on which section of the Build menu can be configured by which source, filetype files can configure menu items in the filetype independent section of the menu and vice versa.
But why would you want to mix things up like that?
Consider a Ruby programmer, it might be appropriate to configure the Ruby filetype to replace the Make commands in the filetype independent section of the Build menu with Rake commands, while still leaving Make available for other languages.
And although the default execute command uses the name of the file currently selected in the editor, this is incorrect when using builders like make, since they generate the same target program irrespective of the file open in the editor. A solution is to have a project file configured to override the default execute with a command that runs the fixed result of the builder. Putting this in the project file allows it to be kept with the commands used to build the executable and overrides the user and system filetype dependent settings. Putting it in the user filetype independent settings would not work as it would be overridden by any user filetype settings (although you could delete those of course).
Of course this flexibility can be used for evil as well as good, moving menu items around in shared configurations without reason is sure to confuse other users, so don’t do it.
Entries in the [build_menu] section of configuration files all have the same format:
SS – is a two letter mnemonic for the menu section:
FT – for the filetype (first) section
NF – for the non-filetype (second) section
EX – for the execute (fourth) section
NN – is a two digit decimal number of the position within the section, starting at 00
FF – is a two character mnemonic for the field to change:
LB – is the text of the label, remember that an underscore prefixes the mnemonic character
CM – is the command field
WD – is the working directory field
The label field entries can be localised by specifying the language in square brackets after the entry name, there may be several entries with different translations, eg
FT_00_LB = _Beer! FT_00_LB[de] = _Bier! FT_00_LB[fr] = _Bière! FT_00_CM = drink FT_00_WD = bar
To allow entries for multiple filetypes to be stored in the one project file, the entries are prefixed by the filetype name, eg
CFT_01_LB = Compile CFT_01_CM = gcc -c %f CFT_01_WD = C++FT_01_LB = Compile C++FT_01_CM = g++ -g -c %f C++FT_01_WD =
This prefixing only applies to project files.
Multiple Project Files
There is no reason that you cannot have multiple project files for the one source tree, allowing commands for differing uses to be stored, but not mixed. An example would be to have “secret-project-x-linux.geany” that used gcc and friends to compile the project and “secret-project-x-windows.geany” that contained the commands to compile with the windows tools.
Since you can only get one set of commands or the other depending on which project file you opened instead of having two sets of commands side by side in the same menu there is no chance of hitting the wrong one.
When doing this it is best to turn project session files off.
Different Build Types
Often software has the concept of different build types which use differing options such as “debug”, “release” or “testing”.
These differing commands are good candidates for replacing the default Make commands, either in the project or your own user preferences if you haven’t used a project.
When doing this remember that the second filetype independent command pops up a dialog and appends text the user enters to the command.