Skip to main content
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.

Automated Formatting

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

Checking and Fixing Format

# 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

ScopePrefixExample
LocalnonecamelCase
Memberm_m_camelCase
Statics_s_camelCase
Globalg_g_camelCase
ParameteraaCamelCase
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();

Comments

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

RuleValue
Indentation4 spaces
Continuation indent8 spaces
Max line length120 characters
Brace styleAllman (own line)
TabsNever (spaces only)
Pointer alignmentLeft (attach to type)
Spaces in parenthesesYes

Additional Resources