Skip to content

Add AlignObjectKeys and AutoPadSubObjects formatting properties#167

Open
webdevred wants to merge 6 commits intomasterfrom
align-object-keys-autopad-subobjects
Open

Add AlignObjectKeys and AutoPadSubObjects formatting properties#167
webdevred wants to merge 6 commits intomasterfrom
align-object-keys-autopad-subobjects

Conversation

@webdevred
Copy link
Owner

@webdevred webdevred commented Mar 14, 2026

Summary

Two new JBFL formatting properties for aligning object key/value pairs within and across sibling objects.

AlignObjectKeys

Pads object keys with spaces so the : separators align vertically across all entries in the same object.

// Before
{"type": "car", "name": "Frame", "authors": "Someone"}

// After (AlignObjectKeys: true)
{"type"    : "car", "name"    : "Frame", "authors" : "Someone"}

AutoPadSubObjects

Treats sibling ObjectKey entries whose values are inline objects as table rows. Computes the maximum value width per named sub-key across all siblings and pads so matching sub-key columns align.

Designed for glowMap-style structures where multiple top-level keys map to small inline objects sharing the same sub-keys:

// Before
"signal_L"    : {"color" : [1, 0.6, 0], "size" : 0.3},
"signal_R"    : {"color" : [1, 0.6, 0], "size" : 0.3},
"highbeam"    : {"color" : [0.8, 0.8, 1], "size" : 0.5},

// After (AlignObjectKeys + AutoPadSubObjects: true)
"signal_L" : {"color" : [1, 0.6, 0],    "size" : 0.3},
"signal_R" : {"color" : [1, 0.6, 0],    "size" : 0.3},
"highbeam" : {"color" : [0.8, 0.8, 1],  "size" : 0.5},

Implementation

  • Formatting/Rules.hs: Added AlignObjectKeys and AutoPadSubObjects as PropertyKey Bool constructors; registered in boolProperties, eqKey, and propertyName.
  • Parsing/DSL.hs: Added parseValueForKey cases for both new properties.
  • Formatting.hs:
    • Added fsObjectKeyWidth :: Maybe Int and fsSubObjectWidths :: Map Text Int to FormattingState.
    • doFormatNode: computes max key width (maxKeyW) and per-sub-key max value widths (subObjectWidths); passes them into FormattingState when the respective property is enabled.
    • formatWithCursor (ObjectKey): pads the key to fsObjectKeyWidth and forwards fsSubObjectWidths into the value's formatting state.
    • addDelimiters (ObjectKey): applies column padding via T.justifyLeft (kw + 3 + vw + 1) for non-last entries when the key is found in fsSubObjectWidths. Complex (multi-line) sub-object values are excluded from width computation.
    • Fixed transposeAndFormat crash on empty input (V.null vvs guard).
    • Fixed scalarLength to exclude multiline values (changed isPrefixOf "{"|"[" to T.any (== '\n')).

Example JBFL usage

.*.glowMap {
    AlignObjectKeys: true;
    AutoPadSubObjects: true;
}

Files changed

  • src/JbeamEdit/Formatting.hs
  • src/JbeamEdit/Formatting/Rules.hs
  • src/JbeamEdit/Parsing/DSL.hs
  • examples/jbfl/complex.jbfl: added new rules
  • examples/jbfl/minimal.jbfl: updated with new rules
  • examples/jbeam/frame.jbeam: added glowMap section as a realistic test fixture
  • All examples/formatted_jbeam/, examples/transformed_jbeam/, examples/ast/ fixtures regenerated

AlignObjectKeys: aligns the colon separator for keys within an object,
padding each key to the width of the longest key in the same object.

AutoPadSubObjects: treats sibling ObjectKey values that are inline
objects as rows of a table. Computes the max rendered value-width per
sub-key name across all siblings and pads values so each named column
starts at the same position across all rows. Complex sub-values
(multi-item Objects/Arrays) are excluded from width computation and do
not influence column widths.

Also fixes transposeAndFormat crashing on empty input, and updates
scalarLength to exclude multiline text rather than just { and [
prefixes from column width calculation.

Adds a glowMap section to examples/jbeam/frame.jbeam as a test fixture
demonstrating both properties together, matching the formatting style
seen in real-world jbeam files.
- Update minimal.jbfl with AlignObjectKeys and AutoPadSubObjects rules
- Regenerate all affected formatted/transformed jbeam fixtures
- Regenerate minimal.jbfl AST
@webdevred webdevred force-pushed the align-object-keys-autopad-subobjects branch from c7d261b to 4d68115 Compare March 14, 2026 16:07
- Guard maxKeyW computation behind alignObjectKeysEnabled to avoid
  unconditional work when the feature is off
- Remove redundant newKeyWidth/newSubWidths intermediate bindings
- Check isComplexNode before calling formatWithCursor in subObjectWidths
  to short-circuit the expensive recursive format call
In objectParser, comments were parsed with `skipWhiteSpace` which consumed
whitespace without updating `lastSeparatorHadBlankLine`. This meant
`cHadNewlineBefore` was never set on comments inside objects, so blank lines
between consecutive comments were lost during formatting.

Fix: use `separatorParser` instead of `skipWhiteSpace` after comments in
objectParser, so blank-line state is tracked correctly.

Additionally, the formatter was suppressing newlines before comments whenever
`any isObjectKeyNode rest` was true, regardless of `cHadNewlineBefore`. This
caused blank lines between comments that precede object keys to be dropped.

Fix: only suppress the newline when `cHadNewlineBefore` is false, so that
blank lines present in the source are preserved.

Add a blank line and extra comment in the glowMap section of examples/jbeam/frame.jbeam
to cover this case in the test fixtures.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant