From 4c7cdecac20ea95b3cf80618b1ddadbe566566ba Mon Sep 17 00:00:00 2001 From: webdevred <148627186+webdevred@users.noreply.github.com> Date: Tue, 31 Mar 2026 18:52:56 +0200 Subject: [PATCH 1/4] Wire up ObjectPrefixKey for JBFL wildcard pattern matching - Add ObjectPrefixKey constructor to NodeSelector - Add ObjectPrefixKey case to compareSB using T.isPrefixOf so JBFL wildcard patterns (e.g. `.foo*`) actually match during formatting - Parse trailing `*` in object keys as ObjectPrefixKey in DSL.hs --- src/JbeamEdit/Core/NodeCursor.hs | 2 ++ src/JbeamEdit/Core/NodePath.hs | 1 + src/JbeamEdit/Parsing/DSL.hs | 5 +++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/JbeamEdit/Core/NodeCursor.hs b/src/JbeamEdit/Core/NodeCursor.hs index ed4884e5..59580490 100644 --- a/src/JbeamEdit/Core/NodeCursor.hs +++ b/src/JbeamEdit/Core/NodeCursor.hs @@ -10,6 +10,7 @@ module JbeamEdit.Core.NodeCursor ( import Data.Sequence (Seq (..)) import Data.Sequence qualified as Seq (empty, null) import Data.Text (Text) +import Data.Text qualified as T (isPrefixOf) import JbeamEdit.Core.Node (Node (..), maybeObjectKey) import JbeamEdit.Core.NodePath qualified as NP @@ -56,6 +57,7 @@ Validate whether all the selectors match the corresponding breadcrumb, returning -} compareSB :: SelCrumbCompFun compareSB (NP.ObjectKey s) (ObjectIndexAndKey _ k) = s == k +compareSB (NP.ObjectPrefixKey s) (ObjectIndexAndKey _ k) = s `T.isPrefixOf` k compareSB (NP.ObjectIndex s) (ObjectIndexAndKey i _) = s == i compareSB (NP.ArrayIndex s) (ArrayIndex i) = s == i compareSB _ _ = False diff --git a/src/JbeamEdit/Core/NodePath.hs b/src/JbeamEdit/Core/NodePath.hs index a515a871..34193605 100644 --- a/src/JbeamEdit/Core/NodePath.hs +++ b/src/JbeamEdit/Core/NodePath.hs @@ -25,6 +25,7 @@ import JbeamEdit.Core.Node qualified as N ( data NodeSelector = ArrayIndex Int | ObjectKey Text + | ObjectPrefixKey Text | ObjectIndex Int deriving (Eq, Ord, Read, Show) diff --git a/src/JbeamEdit/Parsing/DSL.hs b/src/JbeamEdit/Parsing/DSL.hs index 47f54dcf..69c76470 100644 --- a/src/JbeamEdit/Parsing/DSL.hs +++ b/src/JbeamEdit/Parsing/DSL.hs @@ -21,7 +21,7 @@ import Data.Map qualified as M (fromList, fromListWith, union) import Data.Sequence qualified as Seq (fromList) import Data.Set qualified as S (fromList) import Data.Text (Text) -import Data.Text qualified as T (unpack) +import Data.Text qualified as T (init, isSuffixOf, unpack) import Data.Text.Encoding (decodeUtf8') import Data.Word (Word8) import JbeamEdit.Core.NodePath @@ -41,7 +41,8 @@ type JbflParser a = Parser Identity a objectKeyParser :: JbflParser NodePatternSelector objectKeyParser = byteChar '.' *> key where - key = parseWord8s (Selector . ObjectKey) (MP.some . MP.satisfy $ p) + key = parseWord8s (Selector . t) (MP.some . MP.satisfy $ p) + t k = if T.isSuffixOf "*" k then ObjectPrefixKey (T.init k) else ObjectKey k p = charBoth (not . isSpace) (`notElem` [',', '[', '.']) . toChar objectIndexParser :: JbflParser NodePatternSelector From 9d8d9ecd54d8c6552750033b2abe8e7462d192b8 Mon Sep 17 00:00:00 2001 From: webdevred <148627186+webdevred@users.noreply.github.com> Date: Tue, 31 Mar 2026 19:01:25 +0200 Subject: [PATCH 2/4] Document prefix wildcard pattern syntax in JBFL docs --- JBFL_DOCS.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/JBFL_DOCS.md b/JBFL_DOCS.md index 5d80daf0..fed43d68 100644 --- a/JBFL_DOCS.md +++ b/JBFL_DOCS.md @@ -37,11 +37,12 @@ Typical use cases include: | Pattern | Description | |----------|----------------------------------------------------------------------------------| -| `.*` | Matches **any key** at the current object level, regardless of name. | -| `[*]` | Matches **all elements** in a list (1D array). | -| `[*][*]` | Matches **all elements in the innermost lists** of 2D arrays (arrays of arrays). | -| `.test` | Matches the value with key `test` in an object. | -| `[4]` | Matches the value at index 4 in an array. | +| `.*` | Matches **any key** at the current object level, regardless of name. | +| `[*]` | Matches **all elements** in a list (1D array). | +| `[*][*]` | Matches **all elements in the innermost lists** of 2D arrays (arrays of arrays). | +| `.test` | Matches the value with key `test` in an object. | +| `.test*` | Matches any key that **starts with** `test` (prefix match). | +| `[4]` | Matches the value at index 4 in an array. | ## Properties Overview @@ -59,6 +60,7 @@ Typical use cases include: - Patterns traverse nested objects and arrays. - `.*` matches all keys at the current level. +- `.foo*` matches any key starting with `foo` (e.g. `.deformGroups_oilPan*` matches `deformGroups_oilPanFront`, `deformGroups_oilPanRear`, etc.). - `[*]` matches all elements of an array. - Combinations like `.*.nodes[*][*]` match all elements inside inner lists under `nodes` keys. - Properties apply **to each matched value individually**. From c79a1e833892887cc83d888b814ccb510aaadf32 Mon Sep 17 00:00:00 2001 From: webdevred <148627186+webdevred@users.noreply.github.com> Date: Tue, 31 Mar 2026 19:02:00 +0200 Subject: [PATCH 3/4] Document object index pattern and PreserveNumberFormat property --- JBFL_DOCS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/JBFL_DOCS.md b/JBFL_DOCS.md index fed43d68..708b8ab3 100644 --- a/JBFL_DOCS.md +++ b/JBFL_DOCS.md @@ -42,6 +42,7 @@ Typical use cases include: | `[*][*]` | Matches **all elements in the innermost lists** of 2D arrays (arrays of arrays). | | `.test` | Matches the value with key `test` in an object. | | `.test*` | Matches any key that **starts with** `test` (prefix match). | +| `.0` | Matches the object child at positional index 0 (by order, ignoring key name). | | `[4]` | Matches the value at index 4 in an array. | ## Properties Overview @@ -54,6 +55,7 @@ Typical use cases include: | `AlignObjectKeys` | Pads object keys so that `:` separators align vertically across all entries in the same object. | Objects | | `AutoPadSubObjects` | Aligns values within sibling inline objects by treating matching sub-keys as columns. Useful for `glowMap`-style structures. | Objects with inline sub-objects | | `ComplexNewLine` | Controls multiline formatting for complex structures. `None` disables it (inline output). `Force` always enables it. Replaces the deprecated `NoComplexNewLine` and `ForceComplexNewLine` properties. | Any complex data structure | +| `PreserveNumberFormat` | Outputs numbers exactly as written in the source file instead of normalizing them. Useful for preserving intentional formatting like `+1` or `0.002` vs `2.0e-3`. | Numeric values | | `Indent` | Controls the amount of indentation. Defaults to 4 spaces. | Any complex data structure | ## How Matching Works From 7abc7c7fcd5703231b140e93bb65015fb70f6f2e Mon Sep 17 00:00:00 2001 From: webdevred <148627186+webdevred@users.noreply.github.com> Date: Tue, 31 Mar 2026 19:54:24 +0200 Subject: [PATCH 4/4] Add unit tests for ObjectPrefixKey parsing and matching --- test/Core/NodeCursorSpec.hs | 8 ++++++++ test/Parsing/DSLSpec.hs | 2 ++ 2 files changed, 10 insertions(+) diff --git a/test/Core/NodeCursorSpec.hs b/test/Core/NodeCursorSpec.hs index 559b89d0..137df667 100644 --- a/test/Core/NodeCursorSpec.hs +++ b/test/Core/NodeCursorSpec.hs @@ -23,6 +23,14 @@ spec = do compareSB (NP.ArrayIndex 3) (ArrayIndex 3) `shouldBe` True compareSB (NP.ArrayIndex 4) (ArrayIndex 3) `shouldBe` False + it "matches ObjectPrefixKey correctly" $ do + compareSB (NP.ObjectPrefixKey "deform") (ObjectIndexAndKey 0 "deformGroups") + `shouldBe` True + compareSB (NP.ObjectPrefixKey "deform") (ObjectIndexAndKey 0 "deform") + `shouldBe` True + compareSB (NP.ObjectPrefixKey "deform") (ObjectIndexAndKey 0 "other") + `shouldBe` False + it "does not match mismatched cases" $ compareSB (NP.ArrayIndex 1) (ObjectIndexAndKey 1 "x") `shouldBe` False diff --git a/test/Parsing/DSLSpec.hs b/test/Parsing/DSLSpec.hs index 41ee917b..6ed36d19 100644 --- a/test/Parsing/DSLSpec.hs +++ b/test/Parsing/DSLSpec.hs @@ -23,6 +23,8 @@ patternSelectorSpecs = [ (".*", AnyObjectKey) , ("[*]", AnyArrayIndex) , (".test", Selector (NP.ObjectKey "test")) + , (".test*", Selector (NP.ObjectPrefixKey "test")) + , (".deformGroups_oilPan*", Selector (NP.ObjectPrefixKey "deformGroups_oilPan")) , (".3", Selector (NP.ObjectIndex 3)) , ("[3]", Selector (NP.ArrayIndex 3)) ]