From bb9ff66f518ae4a056c5124a726304043c37cfe9 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Sun, 12 Jul 2026 19:11:58 +1000 Subject: [PATCH] G-045 increment 1: punk::args 0.6.1 - @cmd honours -unindentedfields for -help (project 0.12.4) arg_error's cmd-help display transform (undent " "+help, max 4 - the '#unindentedfields ?' todo site) is now gated by "-help" membership in the @cmd line's -unindentedfields list, mirroring the existing per-argument gate. The single transform site feeds both the table and string renderers, so left-margin-authored @cmd help renders its first line flush with continuations in both. @cmd -summary carries no indent transform in any renderer, so -unindentedfields for -summary is vacuously honoured. No in-tree definitions set -unindentedfields on @cmd - existing rendering is unchanged. define doc for -unindentedfields now states where the option is valid. Tests: rendering_unindentedfields_cmd_help_GAP flipped to rendering_unindentedfields_cmd_help (aligned expectation, both renderers measured). Full punk::args suite 175 pass / 1 pre-existing skip / 0 fail; punk::ns suite 53/53 (arg_error consumer); make.tcl modules builds clean (tclsh 9.0.3). Also: G-045 flipped proposed -> active (user direction 2026-07-12); progress and remaining-work recorded in the detail file. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com --- CHANGELOG.md | 4 +++ GOALS.md | 2 +- goals/G-045-punkargs-authoring-ergonomics.md | 33 ++++++++++++++++++- punkproject.toml | 2 +- src/modules/punk/args-999999.0a1.0.tm | 12 +++++-- src/modules/punk/args-buildversion.txt | 3 +- .../punk/args/testsuites/args/rendering.test | 21 +++++++----- 7 files changed, 61 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2303cb15..1e99cc90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ The latest `## [X.Y.Z]` header must match the `version` field in `punkproject.to Entries are newest-first; one bullet per notable change. See the root `AGENTS.md` "Project Versioning" section for the bump policy. +## [0.12.4] - 2026-07-12 + +- G-045 (increment): punk::args 0.6.1 - the @cmd directive now honours -unindentedfields for -help, so command help authored at the left margin renders its first line flush with continuations in help/usage displays (previously the option was accepted on @cmd but ignored). No shipped definitions used it yet, so existing help rendering is unchanged; the define documentation states where -unindentedfields is valid. + ## [0.12.3] - 2026-07-12 - punk::args 0.6.0 synced into the common vfs payload (_vfscommon.vfs): help/usage synopses render small restricted choice sets as literal alternates (module change committed earlier as c309ed47; this ships it in built kits). diff --git a/GOALS.md b/GOALS.md index b5ca7a7d..7aaea16e 100644 --- a/GOALS.md +++ b/GOALS.md @@ -210,7 +210,7 @@ Detail: goals/G-043-subshell-definition-plugins.md Scope: src/modules/punk/repl-999999.0a1.0.tm (editbuf/reader integration, provider seam), src/modules/punk/args-999999.0a1.0.tm + src/modules/punk/ns-999999.0a1.0.tm (introspection surfaces as consumed), src/modules/punk/console-999999.0a1.0.tm (rendering) Detail: goals/G-044-repl-command-completion.md -### G-045 [proposed] punk::args definition authoring ergonomics: record continuation, @cmd unindented fields, constructed-definition normalization +### G-045 [active] punk::args definition authoring ergonomics: record continuation, @cmd unindented fields, constructed-definition normalization Scope: src/modules/punk/args-999999.0a1.0.tm (record parsing in resolve, tstr interplay, arg_error @cmd rendering), src/tests/modules/punk/args/testsuites/ (rendering.test/defquoting.test as the safety net), src/modules/punk-999999.0a1.0.tm (::punk::helptopic::define_docs de-hacked as the consumer proof) Detail: goals/G-045-punkargs-authoring-ergonomics.md diff --git a/goals/G-045-punkargs-authoring-ergonomics.md b/goals/G-045-punkargs-authoring-ergonomics.md index e3a080c4..2461a3d3 100644 --- a/goals/G-045-punkargs-authoring-ergonomics.md +++ b/goals/G-045-punkargs-authoring-ergonomics.md @@ -1,6 +1,6 @@ # G-045 punk::args definition authoring ergonomics: record continuation, @cmd unindented fields, constructed-definition normalization -Status: proposed +Status: active Scope: src/modules/punk/args-999999.0a1.0.tm (record parsing in resolve, tstr interplay, arg_error @cmd rendering), src/tests/modules/punk/args/testsuites/ (rendering.test/defquoting.test as the safety net), src/modules/punk-999999.0a1.0.tm (::punk::helptopic::define_docs de-hacked as the consumer proof) Goal: authoring punk::args definitions no longer requires backslash line-continuations or ad-hoc workarounds for multi-line records and constructed definitions - a parser-recognised record-continuation mechanism (candidate: an unquoted trailing -& token, with the detail file recording the collision analysis and the element-count disambiguation alternative), -unindentedfields honoured for @cmd fields, and constructed (string-built) definitions able to opt into the same whole-block indent normalization file-style definitions get - with the container quoting rules (braced=literal, quoted=Tcl backslash semantics, \$\{ escape) promoted from defquoting.test into the define documentation. Acceptance: a definition using the chosen record-continuation mechanism parses identically to its backslash-continuation equivalent (existing definitions unchanged - continuation is additive), with the token's collision rules documented and an escape/rejection story for values that legitimately match it; @cmd -help/-summary honour -unindentedfields (the rendering.test GAP rendering_unindentedfields_cmd_help_GAP flips to aligned); a constructed definition can request whole-block normalization so embedded continuation indentation behaves as in file-style definitions (the rendering_constructed_def_indent_characterization expectations updated to the chosen semantics), and ::punk::helptopic::define_docs drops its manual pre-normalization to prove it; the quoting rules from defquoting.test appear in the punk::args::define -help documentation; the full punk::args suite (128 tests incl. the rendering invariants: nesting independence, relative-indent preservation) passes with GAP tests flipped, none weakened. @@ -95,3 +95,34 @@ punk::imap4's {\Deleted}/{$MDNSent} choice values) have them stated, not just te experimental define_docs hack (uncommitted punk.tm working-tree diff at the time of drafting - superseded by this goal when implemented). - Archived-goal references in this file: G-046 achieved 2026-07-10 (goals/archive/G-046-punkargs-deferred-help-and-fixes.md). + +## Progress + +### 2026-07-12 increment 1: @cmd -unindentedfields honoured (punk::args 0.6.1) + +- arg_error's cmd-help display transform (undent " "+help, max 4 - the + '#unindentedfields ?' todo site) is now gated by "-help" membership in the @cmd + line's -unindentedfields list, mirroring the existing per-argument gate. The + single transform site feeds both the table and string renderers. +- rendering_unindentedfields_cmd_help_GAP flipped to + rendering_unindentedfields_cmd_help (expects aligned; both renderers measured). +- @cmd -summary: verified no renderer applies an indent transform to -summary (it + is only used inline in synopsis "# ..." lines), so -unindentedfields membership + for -summary is accepted and vacuously honoured - nothing to gate. This + satisfies the acceptance's "-help/-summary honour" clause for -summary. +- Blast radius checked before the change: no in-tree definition sets + -unindentedfields on a @cmd line, so no existing rendering changed. +- define doc for -unindentedfields now states where the option is valid + (argument lines and the @cmd directive's -help). +- Verified (tclsh 9.0.3): full punk::args suite 175 pass / 1 pre-existing skip / + 0 fail; punk::ns suite 53/53 (arg_error consumer); make.tcl modules builds + clean. + +Remaining for acceptance: +- record-continuation mechanism (the -& candidate): collision rules, escape + story, parses identically to backslash-continuation equivalent, documented +- constructed-definition whole-block normalization opt-in, with + rendering_constructed_def_indent_characterization expectations updated and + ::punk::helptopic::define_docs de-hacked as the consumer proof +- defquoting.test container quoting rules promoted into the punk::args::define + -help documentation diff --git a/punkproject.toml b/punkproject.toml index ca522472..cf4764ba 100644 --- a/punkproject.toml +++ b/punkproject.toml @@ -1,4 +1,4 @@ [project] name = "punkshell" -version = "0.12.3" +version = "0.12.4" license = "BSD-2-Clause" diff --git a/src/modules/punk/args-999999.0a1.0.tm b/src/modules/punk/args-999999.0a1.0.tm index 2179d8c6..b3b2aa48 100644 --- a/src/modules/punk/args-999999.0a1.0.tm +++ b/src/modules/punk/args-999999.0a1.0.tm @@ -1037,6 +1037,8 @@ tcl::namespace::eval punk::args { should have their value strings placed with reference to the left margin in the source code. ie all whitespace in the source is preserved. + Valid on argument lines (e.g -help, -choicelabels) and on the + @cmd directive (-help). -minsize (type dependant) -maxsize (type dependant) -mincap {only valid for regex type - min number of captures} @@ -4965,9 +4967,13 @@ tcl::namespace::eval punk::args { set cmdsummary [Dict_getdef $spec_dict cmd_info -summary ""] set cmdhelp [Dict_getdef $spec_dict cmd_info -help ""] #=========== - #unindentedfields ? - set maxundent 4 - set cmdhelp [punk::lib::undent " $cmdhelp" $maxundent] + #@cmd -unindentedfields {-help} means the help text is authored at the left + #margin: skip the display-time indent transform (goal G-045; same gate as + #argument -help below) + if {"-help" ni [Dict_getdef $spec_dict cmd_info -unindentedfields {}]} { + set maxundent 4 + set cmdhelp [punk::lib::undent " $cmdhelp" $maxundent] + } #=========== set docname [Dict_getdef $spec_dict doc_info -name "Manual:"] diff --git a/src/modules/punk/args-buildversion.txt b/src/modules/punk/args-buildversion.txt index 274dfd65..0705b740 100644 --- a/src/modules/punk/args-buildversion.txt +++ b/src/modules/punk/args-buildversion.txt @@ -1,6 +1,7 @@ -0.6.0 +0.6.1 #First line must be a semantic version number #all other lines are ignored. +#0.6.1 - G-045: @cmd honours -unindentedfields for -help - arg_error's display-time indent transform (undent " "+help, max 4) is now gated by "-help" membership in the @cmd line's -unindentedfields list (same gate argument -help already had), so left-margin-authored cmd help renders its first line flush with continuations in both the table and string renderers. Previously the option was accepted on @cmd but ignored (rendering.test rendering_unindentedfields_cmd_help_GAP - flipped to rendering_unindentedfields_cmd_help). No in-tree definitions set @cmd -unindentedfields, so existing rendering is unchanged. Note: @cmd -summary has no indent transform in any renderer, so -unindentedfields membership for -summary is accepted and vacuously honoured. define doc for -unindentedfields now states where the option is valid. #0.6.0 - synopsis display: small restricted choice sets now render as literal alternates - an argument whose choice pool (-choices plus -choicegroups members, deduplicated) has 1-3 members and -choicerestricted true (the default) displays those words unitalicised joined by | in synopses (e.g 'after cancel' shows literal cancel; a 3-choice option shows (left|centre|right)), matching the display style of literal()/literalprefix() type-alternatives. Larger or unrestricted (-choicerestricted 0) choice sets keep the italicised argname/ display, and an explicit -typesynopsis always takes precedence. New private helper punk::args::private::synopsis_choice_literals shared by both synopsis render paths (leaders/values via synopsis_form_arg_display, options inline in synopsis); applies only to single-element -type lists (multi-element clause display unchanged). define doc for -choices documents the rule. Tests: synopsis.test - new characterization coverage for literal/literalprefix/stringstartswith/stringendswith type-alternates, option alternate parenthesization, multi-element clause display, -typesynopsis (value element lists, option passthrough incl documenter ANSI), plus the new choice-literal rule (small sets in leader/option/value positions, choicegroups counting, >3 and unrestricted fallbacks, -typesynopsis precedence) #0.5.0 - G-049 parse-status data model: new punk::args::parse_status - runs a parse attempt (withid/withdef) and returns a documented status structure instead of raising on validation failure (overall ok/status valid|invalid|incomplete/scheme/message/errorcode-minus-argspecs/failureclass/badarg/id/form/receivednames + per-argument argstatus with class/status ok|bad|unparsed/received/positions/hasvalue/value-in-effect incl -default fill). arg_error: new -parsestatus option - both renderers (table and string) now derive goodarg/badarg row marking and choice value-in-effect highlighting from the structure (built internally from -badarg/-parsedargs when not supplied), replacing the transient goodargs/badarg locals; scheme colours resolve per-render into a local array (scheme renders no longer mutate the shared arg_error_CLR array - the -nocolour leak) and the DOCUMENTED -scheme choice value 'nocolour' (and 'nocolor') now takes effect instead of falling through to leftover colours. parse: new -caller option overriding the %caller% frame-walk substitution in validation failure messages (parse_status defaults it to the definition's @cmd -name). get_dict: missingrequiredvalue/missingrequiredleader allocation failures now carry -badarg (type-failed words get badarg marking, not just choice violations). Tests: parsestatus.test (new), usagemarking.test nocolour/leak GAP pins flipped + -parsestatus render parity #0.4.2 - G-046: display-field deferral - resolve no longer tstr-expands display-only content during argument resolution: ${...} in -help (@cmd/@examples/argument records) and @formdisplay -header/-body is masked with inert tokens (spec key DISPLAY_DEFERRED) and expanded on demand at display time (arg_error/eg/resolved_def/@default-copyfrom hooks; separate argdefcache_display cache for non-dynamic defs; @dynamic display content re-expands per render preserving provider refresh). First parse of heavily documented commands drops accordingly (punk::ansi::mark_columns ~4.3s -> ~12ms; tclcore ::lseq resolve ~184ms -> ~2ms) and -help content that calls punk::args-parsing commands (including against its own id) no longer stalls or loops - plus a display-time reentrancy guard (raw ${...} source substituted on nested expansion of the same id). Record splitter factored to private::split_definition_records. Also: @dynamic second-round multiline substitutions into deferred fields now get the 'line' paramindents alignment (rendering_atdynamic_multiline_help_insertion GAP flipped); prefix/alias choice normalization writeback no longer list-quotes single-element-clause values ({\Deleted} shape bug, choicegroups_imap_prefix_shape GAP flipped); -return string renderer aligns cmd-help continuations under the Description label and its Example line shows the example instead of the doc url. Tests: deferredhelp.test (new), rendering.test/choicegroups.test updated per G-046 acceptance diff --git a/src/tests/modules/punk/args/testsuites/args/rendering.test b/src/tests/modules/punk/args/testsuites/args/rendering.test index 7a7bcec6..49c75d2e 100644 --- a/src/tests/modules/punk/args/testsuites/args/rendering.test +++ b/src/tests/modules/punk/args/testsuites/args/rendering.test @@ -15,8 +15,8 @@ package require punk::ansi # P2 relative-indent preservation: the documenter's continuation-line indentation # conventions (e.g. lines 2+ indented by 2) survive to display, measured relative # to the first line - punk::args preserves but does not enforce them -# P3 -unindentedfields: left-margin authoring works for argument -help (and is -# currently accepted but IGNORED for @cmd -help - pinned as a GAP) +# P3 -unindentedfields: left-margin authoring works for argument -help and for +# @cmd -help (the @cmd gate was a pinned GAP until G-045 honoured it, 2026-07-12) # P4 constructed (string-built) definitions receive no whole-block indent # normalization ('constructed' - not to be confused with the @dynamic directive): # embedded continuation indentation is interpreted via the display-time @@ -251,12 +251,13 @@ namespace eval ::testspace { }\ -result [list 2] - test rendering_unindentedfields_cmd_help_GAP {GAP: @cmd accepts -unindentedfields but ignores it - left-margin authored cmd-help misaligns (first line +4 vs continuations)}\ + test rendering_unindentedfields_cmd_help {@cmd -help with -unindentedfields: left-margin authoring renders aligned}\ -setup $common -body { - #the display transform undent(" "+help, max 4) still applies: with - #continuations at the left margin the common prefix is 0, nothing is - #removed, and the first line keeps its injected 4-space prefix. - #(see punk::args arg_error cmd_info handling: '#unindentedfields ?' todo) + #-unindentedfields {-help} on the @cmd line gates the display transform + #undent(" "+help, max 4), so left-margin authored cmd-help keeps its + #first line flush with continuations. + #(was rendering_unindentedfields_cmd_help_GAP pinning the ignored-option + #behaviour - first line +4; flipped by G-045 2026-07-12) punk::args::define { @id -id ::testspace::rcmdunind @cmd -name testspace::rcmdunind -summary\ @@ -268,13 +269,15 @@ GFLUSH line" @values -min 0 -max 0 } set r [render_table ::testspace::rcmdunind] - #pinned CURRENT behaviour: first line renders 4 right of its continuation lappend result [expr {[markercol $r GFIRST] - [markercol $r GFLUSH]}] + #and the string renderer shares the gated transform + set rs [render_string ::testspace::rcmdunind] + lappend result [expr {[markercol $rs GFIRST] - [markercol $rs GFLUSH]}] }\ -cleanup { punk::args::undefine ::testspace::rcmdunind 1 }\ - -result [list 4] + -result [list 0 0] #--- P4 constructed (string-built) definitions -----------------------------------------