The new emerging NLE for GNU/Linux

this page summarises some style and coding guidelines for the Lumiera code base

Style Guide

The Lumiera project uses GNU indentation style with slight adaptations.

  • no tabs please. The typical “semi indent” of GNU style thus becomes 2 spaces.

  • maximum line length is rather around 110 characters.

  • originally, GNU style focused on plain-C code.
    We thus apply some relaxations and clarifications …

    • the braces for a class scope are indented by 2 spaces

    • the access modifiers start at this brace level, while all declarations and definitions within the class are again indented by 2 spaces

    • the line breaking rules are relaxed. Definitions and statements may be written as single line, provided that the length remains below 110 chars and the result remains legible. Otherwise, we’ll fall back to the default and wrap the lines. More specifically

      • function declarations may be written in one line

      • same for definitions with just a single statement in the body

      • same for simple if-statements without else-branch.

    • the space between function name and opening parenthesis of the argument list is not enforced when this doesn’t make sense, esp. for argument-less functions, chained calls or constructor syntax. But in all other cases, we really value this additional space, it improves legibility.

    • template argument declarations are always written on a separate line, above the return type declaration. This rule holds even if the rest of a definition can be written within a single line.

    • the opening brace of namespaces is placed on the same line. Optionally, the namespace body may be indented, as long as this helps underpinning the nesting structure. But there is no need to use 3 indents on a 3 level nested namespace. One level is enough to highlight the presence of a nesting.

Naming conventions

Naming conventions are used to characterise the kind of element at hand and give a visual clue to the reader. We use our own conventions — there is no point in arguing that this and that library or language uses other conventions.

  • type names start with an uppercase letter

  • variable and function names start with lowercase.

  • fields within a class, especially the private ones are decorated with a trailing underscore

  • a leading underscore may be used to emphasise the strictly internal or technical nature of a type, variable or function

  • namespaces are all-lowercase

  • macros and constants are preferably all-caps (at least where this makes sense)

There is a preference for CamelCase — yet underscores are acceptable, especially when the name is more like a sentence than just a compound term.

plain-C names

Since C has no namespaces, we strictly require a lumiera_ prefix on all non-local names and definitions. Generally, names should be formed according to the following pattern:


In case a definition actually denotes an object, there should be

  • a basic struct name: typedef struct namespace_foo_struct namespace_foo;

  • plus an object pointer/handle: typedef namespace_foo* NamespaceFoo;

The object pointer/handle should be passed as 1st argument with the name self


Lumiera uses British spelling. Please set your spell checker accordingly.

General Code Arrangement and Layout

  • Headers and translation units are named *.hpp and *.cpp rsp. *.h and *.c
    Multilingual headers are called *.h

  • Each header should be named according to the primary facility it exposes. For the filesystem name, the CamelCaseWords of this type are translated into camel-case-words.hpp

  • Each file should start with the GNU licence preamble. The headline should give a one-line summary. The primary author(s) and the year of the initial copyright claim should be mentioned.

  • Each header should be focused on a specific purpose. Preferably it starts with a file-level doxygen comment explaining the intention and anything not obvious from reading the code. At lest a @file tag with one line of classification in a doxygen comment at the top of every file is mandatory.
    [this rule stands simply because, without such a file-level doxygen comment, doxygen will ignore all contents of this file (really, might be surprising, yet it is the way it is…)]

  • when arranging headers and compilation units, please take care of the compilation times and the code size. Avoid unnecessary includes. Use forward declarations where applicable. Yet still, all immediately required direct dependencies should be mentioned, even if already included by another dependency. See the extensive discussion of these issues of code organisation

  • The include block starts with our own dependencies, followed by a second block with the library dependencies. After that, optionally some symbols may be brought into scope (through using clauses). Avoid cluttering top-level namespaces. Never import full namespaces.
    [no using namespace gtk; or using namespace boost please! Experience shows, in the end you’ll be using 5 names or so, but pull in all the others just for sake of laziness. Just type the f**g using clause for every import individually, and we’ll all be better off…]

  • the includes for our own dependencies shall be given relative to source-root (or test root). Don’t use relative includes for headers located in the same directory, or — worse still — in the parent directory.

  • sometimes, the actual translation units will combine several facilities for technical reasons.footnote: [this means, there can be “headers”, which are actually only be intended for inclusion on one or two distinct places. This should be mentioned in the file-level comment, but generally is an acceptable practice, and better then lumping everything into a 1000 lines header. As a guideline, if you expect a rather technical concern not to be of much interest for most readers of a header, then better extract it into a separate self-contained header and include it. E.g., you might be sharing an an implementation-level class or even singleton instance and some constant definitions. Just be sure not to include definitions several times.] Anonymous namespaces should be used liberally to avoid unnecessary exports.

  • template code mostly needs to reside in headers. (same for metaprogramming code). We employ the simple inclusion model (“Borland model”) for template instantiation.

  • But in some specific situations it is preferable to drive explicit instantiations from within a *.cpp file. Most notably this is the case when defining some core class hierarchies. Such explicit instantiations should be limited to just a view obvious places. They should be written into a block at the end of some central implementation file. See assetmanager.cpp for an example.

  • deliberately there is no single top-level namespace. The namespace lumiera is the root of our exported interfaces — intended for use by external scripts and libraries. Everything implementation related is arranged in per-subsystem trees of namespaces. The APIs of the subsystems are exported explicitly into the lumiera namespace.

Design Guidelines and Values

Code is written for being read by humans; code shall convey its meaning even to the casual reader. On the long run, this language nature of code is more important than any performance tweaks. Recall, every idiot can figure out how to make a computer perform something. Yet the real challenge is to write legible code. Code that operates exactly the way you’d guess just from reading it. Black magic and all kinds of surprise trickery and cleverness are nothing to be proud off.

→ please have a look at the Clean Code page for a coherent system of design principles