diff --git a/src/decktemplates/custom/_project/layout_refs/punk.project-0.1_overrides@custom+_project+punk.project-0.1.ref b/src/decktemplates/custom/_project/layout_refs/punk.project-0.1_overrides#custom+_project+punk.project-0.1.fauxlink similarity index 100% rename from src/decktemplates/custom/_project/layout_refs/punk.project-0.1_overrides@custom+_project+punk.project-0.1.ref rename to src/decktemplates/custom/_project/layout_refs/punk.project-0.1_overrides#custom+_project+punk.project-0.1.fauxlink diff --git a/src/decktemplates/custom/_project/layout_refs/punk.shell-0.1_overrides@custom+_project+punk.shell-0.1.ref b/src/decktemplates/custom/_project/layout_refs/punk.shell-0.1_overrides#custom+_project+punk.shell-0.1.fauxlink similarity index 100% rename from src/decktemplates/custom/_project/layout_refs/punk.shell-0.1_overrides@custom+_project+punk.shell-0.1.ref rename to src/decktemplates/custom/_project/layout_refs/punk.shell-0.1_overrides#custom+_project+punk.shell-0.1.fauxlink diff --git a/src/decktemplates/vendor/punk/layout_refs/@vendor+punk+basic.ref b/src/decktemplates/vendor/punk/layout_refs/basic#vendor+punk+basic.fauxlink similarity index 100% rename from src/decktemplates/vendor/punk/layout_refs/@vendor+punk+basic.ref rename to src/decktemplates/vendor/punk/layout_refs/basic#vendor+punk+basic.fauxlink diff --git a/src/decktemplates/vendor/punk/layout_refs/@vendor+punk+minimal.ref b/src/decktemplates/vendor/punk/layout_refs/minimal#vendor+punk+minimal.fauxlink similarity index 100% rename from src/decktemplates/vendor/punk/layout_refs/@vendor+punk+minimal.ref rename to src/decktemplates/vendor/punk/layout_refs/minimal#vendor+punk+minimal.fauxlink diff --git a/src/decktemplates/vendor/punk/layout_refs/@vendor+punk+sample-0.1.ref b/src/decktemplates/vendor/punk/layout_refs/project#vendor+punk+project-0.1.fauxlink similarity index 100% rename from src/decktemplates/vendor/punk/layout_refs/@vendor+punk+sample-0.1.ref rename to src/decktemplates/vendor/punk/layout_refs/project#vendor+punk+project-0.1.fauxlink diff --git a/src/decktemplates/vendor/punk/layout_refs/project@vendor+punk+project-0.1.ref b/src/decktemplates/vendor/punk/layout_refs/sample-0.1#vendor+punk+sample-0.1.fauxlink similarity index 100% rename from src/decktemplates/vendor/punk/layout_refs/project@vendor+punk+project-0.1.ref rename to src/decktemplates/vendor/punk/layout_refs/sample-0.1#vendor+punk+sample-0.1.fauxlink diff --git a/src/modules/punk/cap/handlers/templates-999999.0a1.0.tm b/src/modules/punk/cap/handlers/templates-999999.0a1.0.tm index 3ac039f2..154efdfa 100644 --- a/src/modules/punk/cap/handlers/templates-999999.0a1.0.tm +++ b/src/modules/punk/cap/handlers/templates-999999.0a1.0.tm @@ -19,6 +19,7 @@ ##e.g package require frobz package require punk::repo +package require fauxlink ;#layout refs are .fauxlink/.fxlnk files (G-087 stage 2 - bespoke .ref grammar retired) # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ @@ -511,14 +512,12 @@ namespace eval punk::cap::handlers::templates { set sourceinfo [dict get $refinfo sourceinfo] set path [dict get $refinfo path] set reftail [file tail $path] - set atparts [split [file rootname $reftail] @] - #may be two @s if referencing a renamed layout override? - # e.g ref may be @vendor+punks+othersample@sample-0.1 or layoutalias-1.1@vendor+punk+othersample@sample-0.1 - #there must always be an @ before vendor or custom . There is either a template-name alias or empty string before this first @ - #trim off first @ part - set tailats [join [lrange $atparts 1 end] @] - # @ parts after the first are part of the path within the project_layouts structure - set subpathlist [split $tailats +] + #layout refs are fauxlink files: #.fauxlink|.fxlnk + #target is relative to /src/project_layouts + # e.g project#vendor+punk+project-0.1.fauxlink + #an @ within a target segment is literal fauxlink content (derived-layout folder names such as othersample@sample-0.1) + #unresolvable refs were already skipped (with a warning) by get_itemdict_projectlayoutrefs + set targetpath [dict get [fauxlink::resolve $reftail] targetpath] if {[dict exists $refinfo sourceinfo base]} { #some template pathtypes refer to the projectroot from the template - not the cwd set ref_projectroot [dict get $refinfo sourceinfo base] @@ -528,7 +527,7 @@ namespace eval punk::cap::handlers::templates { if {$ref_projectroot ne ""} { set layoutroot [file join $ref_projectroot src/project_layouts] - set layoutfolder [file join $layoutroot {*}$subpathlist] + set layoutfolder [file join $layoutroot $targetpath] if {[file isdirectory $layoutfolder]} { #todo - check if layoutname already in layoutdict append .ref path to list of refs that linked to this layout? set layoutinfo [list path $layoutfolder basefolder $layoutroot sourceinfo $sourceinfo] @@ -546,31 +545,37 @@ namespace eval punk::cap::handlers::templates { @values -maxvalues -1 -unnamed 1 }] method get_itemdict_projectlayoutrefs {args} { + #layout refs are fauxlink files: #.fauxlink|.fxlnk (target relative to /src/project_layouts) set config { -templatefolder_subdir "layout_refs"\ -command_get_items_from_base {apply {{base} { - set matched_files [glob -nocomplain -dir $base -type f *@*.ref] + set matched_files [glob -nocomplain -dir $base -type f {*#*.fauxlink} {*#*.fxlnk}] set items [list] foreach rf $matched_files { - #puts stderr "--> $rf" - if {[string match ignore* $rf]} { + set ftail [file tail $rf] + if {[string match ignore* $ftail]} { continue } - #we silently skip .ref files that don't match - todo - more verification - and warn of invalid .refs? - if {[string match *@vendor+* $rf] || [string match *@custom+* $rf]} { - lappend items $rf + if {[string index $ftail 0] eq "#"} { + #alias-less ref: punkcheck-based tooling treats leading-# filenames as hidden/aside, + #so such a ref would silently vanish from punkcheck-driven installs of the containing tree. + puts stderr "punk::cap::handlers::templates get_itemdict_projectlayoutrefs WARNING - skipping layout ref '$rf' - layout refs must carry a non-empty nominal name (leading-# filenames are excluded by punkcheck-based tooling)" + continue + } + #only accept refs whose encoded target is rooted at vendor or custom (within src/project_layouts) + if {!([string match {*#vendor+*} $ftail] || [string match {*#custom+*} $ftail])} { + continue } + if {[catch {fauxlink::resolve $ftail} resolve_result]} { + puts stderr "punk::cap::handlers::templates get_itemdict_projectlayoutrefs WARNING - skipping unresolvable layout ref '$rf' ($resolve_result)" + continue + } + lappend items $rf } return $items }}}\ -command_get_item_name {apply {{vendor basefolder itempath} { - set itemtail [file rootname [file tail $itempath]] - set alias [lindex [split $itemtail @] 0] - if {$alias eq ""} { - set itemname [lindex [split $itemtail +] end] - } else { - set itemname $alias - } + set itemname [dict get [fauxlink::resolve [file tail $itempath]] name] if {$vendor ne "_project"} { set itemname $vendor.$itemname } diff --git a/src/modules/punk/cap/handlers/templates-buildversion.txt b/src/modules/punk/cap/handlers/templates-buildversion.txt index b5fe9372..9050d3e3 100644 --- a/src/modules/punk/cap/handlers/templates-buildversion.txt +++ b/src/modules/punk/cap/handlers/templates-buildversion.txt @@ -1,5 +1,6 @@ -0.1.1 +0.2.0 #First line must be a semantic version number #all other lines are ignored. +#0.2.0 - G-087 stage 2: layout refs are now fauxlink files (#.fauxlink|.fxlnk, resolved via the fauxlink module; target relative to /src/project_layouts). Bespoke @.ref grammar removed - .ref files are no longer recognised. Alias-less (leading-#) refs and unresolvable refs are skipped with a warning (punkcheck excludes leading-# filenames). New dependency: fauxlink. Also fixes the ignore* skip (previously matched against the full glob path, so it never applied). #0.1.1 - fix: pkg_register 'absolute' pathtype branch had a non-braced expr 'if {!file exists $normpath}' which raised an expr syntax error on any absolute-pathtype provider registration; now correctly tests ![file exists $normpath] #0.1.1 - fix: pkg_register duplicate-registration guard did 'dict get $provider_info $pkg' without a dict exists check, erroring for any second provider package registering the same capability diff --git a/src/modules/punk/mix/#modpod-templates-999999.0a1.0/templates/layout_refs/project@vendor+punk+project-0.1.ref b/src/modules/punk/mix/#modpod-templates-999999.0a1.0/templates/layout_refs/project#vendor+punk+project-0.1.fauxlink similarity index 100% rename from src/modules/punk/mix/#modpod-templates-999999.0a1.0/templates/layout_refs/project@vendor+punk+project-0.1.ref rename to src/modules/punk/mix/#modpod-templates-999999.0a1.0/templates/layout_refs/project#vendor+punk+project-0.1.fauxlink diff --git a/src/modules/punk/mix/templates-buildversion.txt b/src/modules/punk/mix/templates-buildversion.txt index d2fae757..ad54d12c 100644 --- a/src/modules/punk/mix/templates-buildversion.txt +++ b/src/modules/punk/mix/templates-buildversion.txt @@ -1,4 +1,5 @@ -0.1.4 +0.1.5 #First line must be a semantic version number #all other lines are ignored. +#0.1.5 - G-087 stage 2: module-shipped layout ref migrated to fauxlink grammar (project#vendor+punk+project-0.1.fauxlink) #0.1.4 - removed dead templates/layouts/project payload subtree (design-generation residue: no reader; layout payloads live in src/project_layouts, located via layout_refs - G-087 hygiene) diff --git a/src/project_layouts/README.md b/src/project_layouts/README.md index ef2c7bcb..d1da9276 100644 --- a/src/project_layouts/README.md +++ b/src/project_layouts/README.md @@ -26,24 +26,33 @@ suffixed #2, #3, ... Layout refs ----------- -A layout ref is a zero-byte file in a layout_refs/ folder under a template -base (e.g. src/decktemplates/vendor/punk/layout_refs/, or a module-shipped -templates/layout_refs/). The entire meaning is in the filename: +A layout ref is a zero-byte fauxlink file in a layout_refs/ folder under a +template base (e.g. src/decktemplates/vendor/punk/layout_refs/, or a +module-shipped templates/layout_refs/). The entire meaning is in the filename, +which follows the standard fauxlink grammar (see the fauxlink package +documentation) resolved by the vendored fauxlink module: - @++... .ref + #++... .fauxlink (or .fxlnk) -- The text before the first @ is the alias - the layout's nominal name. - If the alias is empty the last + separated segment is used as the name. -- The text after the first @ is a + separated path relative to - /src/project_layouts identifying the layout folder. - Segments after the first @ may themselves contain @ (derived-layout folder - names such as othersample@sample-0.1). +- The text before the first # is the alias - the layout's nominal name. + Layout refs MUST carry a non-empty alias: punkcheck-based tooling treats + leading-# filenames as hidden/aside, so an alias-less ref would silently + vanish from punkcheck-driven installs. The handler warns about and skips + such refs. +- The text after the first # is the fauxlink-encoded target: a + separated + path relative to /src/project_layouts identifying the layout + folder. Segments may contain literal @ (derived-layout folder names such + as othersample@sample-0.1); other special characters use fauxlink %XX + encoding. fauxlink::link_as generates conformant names programmatically. - The visible layout name is prefixed with the vendor folder name and a dot unless the vendor is the pseudo-vendor _project - (e.g. project@vendor+punk+project-0.1.ref in a vendor/punk/layout_refs + (e.g. project#vendor+punk+project-0.1.fauxlink in a vendor/punk/layout_refs folder presents as layout name "punk.project"). -- Only filenames matching *@vendor+*.ref or *@custom+*.ref are recognised; - files named ignore* are skipped. +- Only filenames whose encoded target starts at vendor+ or custom+ are + recognised; files named ignore* are skipped; unresolvable fauxlink names + are skipped with a warning. +- The pre-fauxlink @.ref grammar was retired 2026-07-17 + (G-087 stage 2) - .ref files are no longer recognised. The ref indirection exists to break recursion: layout payloads may embed module trees (including the punk::mix::templates module itself), so modules