Trace follows a consistent code style based on KiCad’s conventions. This guide covers the key formatting rules for C++ contributions.
Golden rule: When in doubt, follow the existing formatting of the file you’re editing.
Trace uses clang-format for automated code formatting. The repository includes a _clang-format configuration file that defines our style rules.
Setting Up Git Hooks
Enable the formatting hooks to check your code before committing:
git config core.hooksPath .githooks
git config clangFormat.style file
git config kicad.check-format true
# Check formatting (shows warnings without changing files)
git check-format
# Automatically fix formatting errors
git fix-format
You can bypass format checks with git commit --no-verify, but this should be used sparingly.
clang-format doesn’t know about all our nuances — it may suggest changes to code you didn’t modify. When there’s flexibility, match the existing file style rather than rigidly following clang-format.
Indentation & Spacing
Indentation
- Use 4 spaces for indentation (no tabs)
- Continuation lines use 8 spaces
- Constructor initializer lists use 8 spaces
void MyFunction( int aParam )
{
if( aParam > 0 )
{
DoSomething();
}
}
Spaces in Parentheses
Add spaces inside parentheses:
if( condition )
DoSomething( arg1, arg2 );
for( int i = 0; i < count; i++ )
No Space Before Parentheses
if( condition )
while( running )
MyFunction( arg );
Space After Casts
// Good
int* ptr = (int*) voidPtr;
// Bad
int* ptr = (int*)voidPtr;
Braces
Allman Style
Braces go on their own line:
void MyFunction()
{
if( condition )
{
DoSomething();
}
else
{
DoSomethingElse();
}
}
Always Use Braces
Even for single statements:
if( condition )
{
DoSomething();
}
Short Case Labels
Short case labels can be on a single line:
switch( value )
{
case 1: DoOne(); break;
case 2: DoTwo(); break;
default: DoDefault(); break;
}
Line Length
Maximum line length is 120 characters. Break long lines at logical points:
// Break before binary operators (except assignment)
int result = someLongVariable
+ anotherLongVariable
- yetAnotherVariable;
// Break after opening parenthesis for long function calls
SomeLongFunctionName( firstArgument,
secondArgument,
thirdArgument );
Naming Conventions
Variables
| Scope | Prefix | Example |
|---|
| Local | none | camelCase |
| Member | m_ | m_camelCase |
| Static | s_ | s_camelCase |
| Global | g_ | g_camelCase |
| Parameter | a | aCamelCase |
class MyClass
{
public:
void SetValue( int aValue )
{
m_value = aValue;
}
private:
int m_value;
static int s_instanceCount;
};
Functions and Methods
Use PascalCase for function names with verb phrases that describe the action:
void CalculateNetlist();
bool IsModified();
wxString GetFileName();
void SetPosition( const VECTOR2I& aPos );
Classes and Types
Use UPPER_SNAKE_CASE for class names, enums, and enum values:
class PCB_TRACK : public BOARD_ITEM
{
// ...
};
enum class LAYER_TYPE
{
SIGNAL,
POWER,
MIXED
};
Pointers and References
Pointer and reference symbols attach to the type, not the variable:
int* ptr;
const wxString& name;
BOARD* GetBoard();
Single-Line
// This is a single-line comment
int value = 42; // Trailing comment with one space before
Multi-Line
/*
* Multi-line comments use this style
* with asterisks aligned
*/
Doxygen Documentation
Use Doxygen-style comments for public APIs:
/**
* Brief description of the function.
*
* Longer description if needed.
*
* @param aParam description of parameter
* @return description of return value
*/
int MyFunction( int aParam );
Includes
Don’t sort includes automatically — the existing order in files is intentional. Group includes logically:
// 1. Corresponding header (for .cpp files)
#include "my_class.h"
// 2. Project headers
#include <board.h>
#include <pcb_track.h>
// 3. Third-party headers
#include <wx/wx.h>
// 4. Standard library
#include <vector>
#include <string>
Constructors
Constructor initializer lists break after the colon:
MyClass::MyClass( int aValue, const wxString& aName ) :
m_value( aValue ),
m_name( aName ),
m_initialized( true )
{
// Constructor body
}
Lambdas
clang-format doesn’t fully support our lambda style. Follow existing patterns:
auto comparator = []( const ITEM* a, const ITEM* b )
{
return a->GetValue() < b->GetValue();
};
Quick Reference
| Rule | Value |
|---|
| Indentation | 4 spaces |
| Continuation indent | 8 spaces |
| Max line length | 120 characters |
| Brace style | Allman (own line) |
| Tabs | Never (spaces only) |
| Pointer alignment | Left (attach to type) |
| Spaces in parentheses | Yes |
Additional Resources