Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Formatter

The Monkey C formatter aims to be a zero-config one-size-fits-all solution to ensure consistent formatting of your Monkey C code. More opinionated suggestions for the code is implemented in the linter.

Note

I’d love any input and testing on the formatter. Both help finding bugs and inconsistencies but also input on the formatting algorithm. Please create an issue for any bug or feature request.

Wrapping long lines

The formatter is using the Wadler-Lindig algorithm to wrap lines at a default width of 111 columns. 111 is chosen because 80 is too little and 222 is too much.

The magic trailing comma

The formatter uses the same magic trailing comma as ruff to determine if multiple items should be wrapped over multiple lines even when they would fit on a single line. The rule applies to arrays, dictionaries, function declaration parameters, and function / method call arguments.

Original Formatted
function SomeFunction(arg1 as String, arg2 as Number,) as Void {
    var arr = [
        1,
        2,
        3
    ];

    var arr2 = [1, 2, 3,];

    var dict = {
        :keyOne => 1,
        :keyNumberTwo => 2
    };

    var dict2 = {:keyOne=>1, :keyNumberTwo=>2,};

    AnotherFunction(arr, arr2, dict, dict2,)
}
function SomeFunction(
    arg1 as String,
    arg2 as Number,
) as Void {
    var arr = [1, 2, 3];

    var arr2 = [
        1,
        2,
        3,
    ];

    var dict = {:keyOne => 1, :keyNumberTwo => 2};

    var dict2 = {
        :keyOne       => 1,
        :keyNumberTwo => 2,
    };

    AnotherFunction(
        arr,
        arr2,
        dict,
        dict2,
    )
}

Column alignment

When alignment is enabled the formatter pads names so that the separator operators (=> in dictionaries, = in enum variants) line up in a vertical column. The intent is purely visual — to make related entries easier to scan.

Alignment only kicks in when an entry is already rendered multi-line. For dictionaries that follows the magic trailing comma rule above. For enums the formatter looks for runs of two or more consecutive variants that all have an explicit value, and pads the names within each run.

Original Formatted
var dict = {
    :keyOne => 1,
    :keyNumberTwo => 2
    :a => 3
};

enum Color {
    COLOR_RED = 1,
    COLOR_GREEN = 2,
    COLOR_BLUE_DARK = 3,
}

enum State {
    STATE_A,
    STATE_B = 5,
    STATE_C = 6,
    STATE_D,
}
var dict = {
    :keyOne       => 1,
    :keyNumberTwo => 2
    :a            => 3
};

enum Color {
    COLOR_RED       = 1,
    COLOR_GREEN     = 2,
    COLOR_BLUE_DARK = 3,
}

enum State {
    STATE_A,
    STATE_B = 5,
    STATE_C = 6,
    STATE_D,
}

In the State example the run [STATE_B = 5, STATE_C = 6] is already aligned with itself and no padding is needed. The bare variants STATE_A and STATE_D break the run and stay as-is.