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

Configuration Reference

Every [format] field Drut currently understands, in one place. All of them are set the same way, in a drut.toml file at (or above) the file you’re formatting:

[format]
casing_control_words = "lower"
indent_width = 2

Drut discovers the nearest drut.toml by walking up from the file being processed, stopping at the first drut.toml found, a .git boundary, or the filesystem root — whichever comes first. A project with no drut.toml anywhere behaves exactly like a project with an empty one: every field uses its built-in default. Every field is optional; omitting a key is identical to writing its default value explicitly.

Starter drut.toml

Every field, commented out at its built-in default. Copy this into a drut.toml at your project root and uncomment (then change) only the fields you want to override — a commented-out line changes nothing, so you never need to remember the full field list or its defaults from scratch:

[format]
# casing_control_words = "preserve"    # preserve | upper | lower
# casing_pair_keywords = "preserve"    # preserve | upper | lower
# casing_data_references = "preserve"  # preserve | upper | lower
# casing_function_calls = "preserve"   # preserve | upper | lower
# indent_top_level = "preserve"        # preserve | auto
# indent_width = 4                     # 1-16
# operator_spacing = "preserve"        # preserve | fixed | auto
# blank_lines = "preserve"             # preserve | auto
# blank_lines_top_cap = 2              # 1-50, only used when blank_lines = "auto"
# blank_lines_nested_cap = 1           # 1-50, only used when blank_lines = "auto"
# line_wrap = "preserve"               # preserve | auto
# line_wrap_width = 120                # 20-500, only used when line_wrap = "auto"
# line_wrap_style = "fill"             # fill | one_per_line, only used when line_wrap = "auto"

See Fields below for what each one actually does, and Precedence for how a set value interacts with CLI flags, MCP parameters, and editor settings.

A malformed value never blocks formatting. An unrecognized key or an out-of-range value only affects that one field — it warns (CLI stderr, an LSP Hint diagnostic, or the MCP format tool’s config_warnings field) and falls back to that field’s built-in default. Every other valid setting in the same file still applies.

Precedence

Every field below resolves the same four-tier way, checked in this order — the first tier that sets a value wins:

  1. An explicit CLI flag or MCP tool parameter, passed for one specific invocation — always wins when given.
  2. drut.toml — the nearest one found by the discovery walk above.
  3. An editor client setting — for VS Code, one of the drut.format.* settings under Settings; delivered to drut-lsp via the standard LSP workspace/configuration mechanism. A personal editor preference never overrides a project’s own committed drut.toml — it only fills in a field drut.toml leaves unset.
  4. The built-in default — used only if none of the above set the field.

Each tier only fills in a field the tier(s) before it left unset; a field is never assembled from pieces at different tiers. Every field below resolves this same plain four-tier chain — no field has any extra fallback wrinkle.

A flat casing field once existed, covering control_words+pair_keywords together — removed once the three granular fields below fully superseded it. A drut.toml/CLI/MCP/editor-setting still using casing no longer does anything; it degrades exactly like any other unrecognized key (a warning, falling back to each field’s own built-in default), never a hard failure.

Fields

casing_control_words

Casing convention for the control_words category (things like IF, ENDIF, LOOP, ENDLOOP).

Values: preserve ← default, upper, lower.

Default: preserve.

Also known as: CLI flag --casing-control-words; MCP format tool parameter casing_control_words.

Example:

[format]
casing_control_words = "upper"

Precedence: follows the four-tier chain above.

casing_pair_keywords

Casing convention for the pair_keywords category (keyword names inside a Control statement’s keyword=value pairs, e.g. PATHLOAD, MATI), same shape as casing_control_words above.

Values: preserve ← default, upper, lower.

Default: preserve.

Also known as: CLI flag --casing-pair-keywords; MCP format tool parameter casing_pair_keywords.

Example:

[format]
casing_pair_keywords = "lower"

Precedence: follows the four-tier chain above.

casing_data_references

Casing for the data-reference category: Matrix/Line/Node/Zone/Database abbreviations (MI/MO/MW, LI/LW, NI/NW, ZI/ZONES/Z, DBI/DBA), RO, the link-endpoint fields A/B, and the reserved loop-index identifiers I/J.

Values: preserve ← default, upper, lower.

Default: preserve.

Also known as: CLI flag --casing-data-references; MCP format tool parameter casing_data_references.

Example:

[format]
casing_data_references = "lower"

Precedence: follows the four-tier chain above.

casing_function_calls

Casing for recognized Cube Voyager built-in function names (e.g. REPLACESTR, ROUND, TRIM) — only a name immediately followed by ( with no intervening whitespace counts as a call; the same name elsewhere (a keyword=value pair name, a plain identifier) is untouched by this field. Covers 138 names spanning the general Control Language core (Numeric/Trig/Character-String functions), Highway/Matrix-program functions, Public Transport skim functions, the CONVERGE-phase iteration-statistics family, and CUBE Cluster utility functions — see the Formatter Guide for the full list and how two real names (FORMAT, LOG) that also exist as a pair-keyword/ control word respectively are disambiguated by position.

Values: preserve ← default, upper, lower.

Default: preserve.

Also known as: CLI flag --casing-function-calls; MCP format tool parameter casing_function_calls.

Example:

[format]
casing_function_calls = "upper"

Precedence: follows the four-tier chain above.

indent_top_level

Whether top-level (depth-0, not inside any block) statement indentation is left exactly as written, or normalized to column 0.

Values:

  • preserve ← default — leave top-level indentation exactly as written.
  • auto — force every top-level line to column 0.

Default: preserve.

Also known as: CLI flag --indent-top-level; MCP format tool parameter indent_top_level.

Example:

[format]
indent_top_level = "auto"

Precedence: follows the four-tier chain above.

indent_width

Spaces per nesting level of block indentation, relative to the enclosing block’s own opening-statement column.

Values: any integer from 1 to 16default 4.

Default: 4.

Also known as: CLI flag --indent-width; MCP format tool parameter indent_width.

Example:

[format]
indent_width = 2

Precedence: follows the four-tier chain above. An out-of-range value (0, 500, …) at any tier is treated as unset for that tier — resolution falls through to the next tier exactly as if the field had been omitted there.

operator_spacing

Whitespace normalization around =, comparison operators (==, <>, >=, <=, <, >), binary arithmetic (+, -, *, /), comma spacing between multiple keyword=value pairs, and interior padding inside [...]/(...).

Values:

  • preserve ← default — leave existing spacing exactly as written.
  • fixed — normalize every occurrence to exactly one space on each side (and zero interior padding inside brackets/parens), independent of neighboring lines.
  • auto — everything fixed does, plus vertically aligns the = of consecutive Assignment statements at the same nesting depth to the column of the longest left-hand side in the run. A run resets at a blank line, a comment-only line, a nesting-depth change, or a non-Assignment statement.

Default: preserve.

Also known as: CLI flag --operator-spacing; MCP format tool parameter operator_spacing.

Example:

[format]
operator_spacing = "auto"

See the Formatter Guide for full before/after examples of fixed vs. auto.

Precedence: follows the four-tier chain above.

blank_lines

Whether runs of consecutive blank lines (including whitespace-only lines) are left as written or contracted down to a configured cap.

Values:

  • preserve ← default — leave every blank-line run exactly as written, however long.
  • auto — contract a run down to the applicable cap (blank_lines_top_cap or blank_lines_nested_cap) only when the run exceeds that cap — never pads a shorter run up.

Default: preserve.

Also known as: CLI flag --blank-lines; MCP format tool parameter blank_lines.

Example:

[format]
blank_lines = "auto"

Precedence: follows the four-tier chain above.

blank_lines_top_cap

The maximum number of consecutive blank lines blank_lines = "auto" allows between top-level statements/blocks before contracting the run. Only meaningful when blank_lines is "auto".

Values: any integer from 1 to 50default 2.

Default: 2.

Also known as: CLI flag --blank-lines-top-cap; MCP format tool parameter blank_lines_top_cap.

Example:

[format]
blank_lines = "auto"
blank_lines_top_cap = 1

Precedence: follows the four-tier chain above. An out-of-range value at any tier is treated as unset for that tier, same as indent_width.

blank_lines_nested_cap

The maximum number of consecutive blank lines blank_lines = "auto" allows inside any block’s own body, uniformly regardless of nesting depth, before contracting the run. Only meaningful when blank_lines is "auto".

Values: any integer from 1 to 50default 1.

Default: 1.

Also known as: CLI flag --blank-lines-nested-cap; MCP format tool parameter blank_lines_nested_cap.

Example:

[format]
blank_lines = "auto"
blank_lines_nested_cap = 2

Precedence: follows the four-tier chain above. Same out-of-range handling as blank_lines_top_cap.

line_wrap

Whether an over-width Control statement’s keyword=value pair list is wrapped across multiple physical lines, using Cube Voyager’s own existing line-continuation syntax (a trailing comma already tells the parser the next physical line continues the same statement — no new syntax is introduced). Only Control statements are eligible — an Assignment statement’s arithmetic/string expression is out of scope. A statement that already contains a continuation character anywhere is left completely untouched, however long, regardless of width — never re-flowed, which is also what makes this field idempotent by construction: once wrapped, a statement is “already continued” on the next pass.

Values:

  • preserve ← default — leave every line exactly as written, however long.
  • auto — wrap once a statement’s line length exceeds line_wrap_width, using line_wrap_style to decide how pairs are distributed across the new continuation lines.

Default: preserve.

Also known as: CLI flag --line-wrap; MCP format tool parameter line_wrap.

Example (width lowered to 40 here only to keep the before/after readable on this page — 120 is the real default):

[format]
line_wrap = "auto"
line_wrap_width = 40

Before:

RUN PGM=MATRIX, ZONES=5, PRINT=1, COMBINE=T

After, with line_wrap_style = "fill" (the default) — packs as many pairs as fit per continuation line:

RUN PGM=MATRIX, ZONES=5, PRINT=1,
    COMBINE=T

After, with line_wrap_style = "one_per_line" instead — exactly one pair per continuation line:

RUN PGM=MATRIX,
    ZONES=5,
    PRINT=1,
    COMBINE=T

See the Formatter Guide for this same example plus the already-hand-wrapped case.

Precedence: follows the four-tier chain above.

line_wrap_width

The maximum line width line_wrap = "auto" wraps toward — once a Control statement’s line exceeds this many characters, it becomes a wrap candidate. Only meaningful when line_wrap is "auto".

Values: any integer from 20 to 500default 120.

Default: 120.

Also known as: CLI flag --line-wrap-width; MCP format tool parameter line_wrap_width.

Example:

[format]
line_wrap = "auto"
line_wrap_width = 100

Precedence: follows the four-tier chain above. An out-of-range value at any tier is treated as unset for that tier, same as indent_width.

line_wrap_style

How a wrapped statement’s keyword=value pairs are distributed across the new continuation lines once line_wrap wraps it. Only meaningful when line_wrap is "auto".

Values:

  • fill ← default — greedily packs as many pairs as fit within line_wrap_width onto each continuation line before breaking.
  • one_per_line — places exactly one pair per continuation line, regardless of how much width is left over on any given line.

Default: fill — chosen over one_per_line deliberately: a statement’s wrap style, once applied, is never undone by a later format pass (see line_wrap above), so fill is the cheaper direction to manually diverge from afterward if you don’t like it for one specific statement, versus starting from one_per_line and wanting to hand-compact it back down.

Also known as: CLI flag --line-wrap-style; MCP format tool parameter line_wrap_style.

Example:

[format]
line_wrap = "auto"
line_wrap_style = "one_per_line"

See line_wrap above for the before/after example showing both styles side by side.

Precedence: follows the four-tier chain above.