This document describes the coding style for the Verovio project.
- General remarks
- Includes and forward declarations
- Null and boolean
- Class, method and member names
- Comments
- LibMEI
Verovio uses a Clang-Format coding style based on the WebKit style, with a few minor modifications. The modifications include:
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
ColumnLimit: 120
ConstructorInitializerAllOnOneLineOrOnePerLine: true
PointerAlignment: Right
The simplest way to fullfil the Verovio coding style is to use a clang-format tool and to apply the style defined in the .clang-format file available in the project root directory.
An easy way to install clang-format on OS X computers is to use Hombrew. Type this command in the terminal to install:
brew install clang-format
To use clang-format to adjust a single file:
clang-format -style=file -i some-directory/some-file.cpp
The -style=file
option instructs clang-format to search for the .clang-format configuration file (recursively in some parent directory). The -i
option is used to alter the file "in-place". If you don't give the -i
option, a fomatted copy of the file will be sent to standard output.
Includes in the header files must list first the system includes followed by the Verovio includes, if any, and then the includes for the libraries included in Verovio. All includes have to be ordered alphabetically:
#include <string>
#include <utility>
#include <vector>
//----------------------------------------------------------------------------
#include "attclasses.h"
#include "atttypes.h"
//----------------------------------------------------------------------------
#include "pugixml.hpp"
#include "utf8.h"
In the header files, always use forward declarations (and not includes) whenever possible. Forward declaration have to be ordered alphabetically:
class DeviceContext;
class Layer;
class StaffAlignment;
class Syl;
class TimeSpanningInterface;
In the implementation files, the first include in always the include of the corresponding header file, followed by the system includes and then the other Verovio includes with libraries at the end too, if any, also ordered alphabetically:
#include "att.h"
//----------------------------------------------------------------------------
#include <sstream>
#include <stdlib.h>
//----------------------------------------------------------------------------
#include "object.h"
#include "vrv.h"
//----------------------------------------------------------------------------
#include "pugixml.hpp"
The null pointer value should be written as NULL
. Boolean values should be written as true
and false
.
All class names must be in upper CamelCase. The internal capitalization follows the MEI one:
class Measure;
class ScoreDef;
class StaffDef;
All method names must also be in upper CamelCase:
void Measure::AddStaff(Staff *staff) {}
All member names must be in lower camelCase. Instance members must be prefixed with m_
and class (static) members with s_
:
class Glyph {
public:
/** An instance member */
int m_unitsPerEm;
/** A static member */
static std::string s_systemPath;
};
In the class declaration, the methods are declared first, and then the member variables. For both, the declaration order is public
, protected
, and private
.
Comments for describing methods can be grouped using ///@{
and ///@}
delimiters together with the @name
indication:
/**
* @name Add children to an editorial element.
*/
///@{
void AddFloatingElement(FloatingElement *child);
void AddLayerElement(LayerElement *child);
void AddTextElement(TextElement *child);
///@}
The code for the attribute classes of Verovio are generated from the MEI schema using a modified version of LibMEI available here. The code generated is included in the Verovio repository in ./libmei and the LibMEI repository does not need to be cloned for building Verovio.
The attribute classes generated from the MEI schema provide all the members for the element classes of Verovio. They are implemented via multiple inheritance in element classes. The element classes corresponding to the MEI elements are not generated by LibMEI but are implemented explicitly in Verovio. They all inherit from the Object
class (of the vrv
namespace) or from a Object
child class. They can inherit from various interfaces used for the rendering. All the MEI member are defined through the inheritance of generated attribute classes, either grouped as interfaces or individually.
For example, the MEI <note> is implemented as a Note
class that inherit from Object
through LayerElement
. It also inherit from the StemmedDrawingInterface that holds data used for the rendering.
Its MEI members are defined through the DurationInterface
and PitchInterface
that regroup common functionnalities for durational and pitched MEI elements respectively plus some additional individual attribute classes.
The inheritance should always list Object
(or the Object
child class) first, followed by the rendering interfaces, followed by the attribute class interfaces, followed by the individual attribute classes, each of them ordered alphabetically:
class Note : public LayerElement,
public StemmedDrawingInterface,
public DurationInterface,
public PitchInterface,
public AttColoration,
public AttGraced,
public AttStems,
public AttTiepresent
In the implementation, the same order must be followed, for the constructor calls and for the registration of the interfaces and individual attribute classes:
Note::Note()
: LayerElement("note-")
, StemmedDrawingInterface()
, DurationInterface()
, PitchInterface()
, AttColoration()
, AttGraced()
, AttStems()
, AttTiepresent()
{
RegisterInterface(DurationInterface::GetAttClasses(), DurationInterface::IsInterface());
RegisterInterface(PitchInterface::GetAttClasses(), PitchInterface::IsInterface());
RegisterAttClass(ATT_COLORATION);
RegisterAttClass(ATT_GRACED);
RegisterAttClass(ATT_STEMS);
RegisterAttClass(ATT_TIEPRESENT);
Reset();
}
Resetting the attributes is required and follows the same order
void Note::Reset()
{
LayerElement::Reset();
StemmedDrawingInterface::Reset();
DurationInterface::Reset();
PitchInterface::Reset();
ResetColoration();
ResetGraced();
ResetStems();
ResetTiepresent();
// ...
}