Browse Source

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
master
Julian Noble 3 days ago
parent
commit
bb9ff66f51
  1. 4
      CHANGELOG.md
  2. 2
      GOALS.md
  3. 33
      goals/G-045-punkargs-authoring-ergonomics.md
  4. 2
      punkproject.toml
  5. 8
      src/modules/punk/args-999999.0a1.0.tm
  6. 3
      src/modules/punk/args-buildversion.txt
  7. 21
      src/tests/modules/punk/args/testsuites/args/rendering.test

4
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` Entries are newest-first; one bullet per notable change. See the root `AGENTS.md`
"Project Versioning" section for the bump policy. "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 ## [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). - 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).

2
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) 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 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) 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 Detail: goals/G-045-punkargs-authoring-ergonomics.md

33
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 # 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) 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. 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. 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 experimental define_docs hack (uncommitted punk.tm working-tree diff at the time of
drafting - superseded by this goal when implemented). 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). - 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

2
punkproject.toml

@ -1,4 +1,4 @@
[project] [project]
name = "punkshell" name = "punkshell"
version = "0.12.3" version = "0.12.4"
license = "BSD-2-Clause" license = "BSD-2-Clause"

8
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 should have their value strings placed with reference to the
left margin in the source code. ie all whitespace in the source left margin in the source code. ie all whitespace in the source
is preserved. is preserved.
Valid on argument lines (e.g -help, -choicelabels) and on the
@cmd directive (-help).
-minsize (type dependant) -minsize (type dependant)
-maxsize (type dependant) -maxsize (type dependant)
-mincap {only valid for regex type - min number of captures} -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 cmdsummary [Dict_getdef $spec_dict cmd_info -summary ""]
set cmdhelp [Dict_getdef $spec_dict cmd_info -help ""] set cmdhelp [Dict_getdef $spec_dict cmd_info -help ""]
#=========== #===========
#unindentedfields ? #@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 maxundent 4
set cmdhelp [punk::lib::undent " $cmdhelp" $maxundent] set cmdhelp [punk::lib::undent " $cmdhelp" $maxundent]
}
#=========== #===========
set docname [Dict_getdef $spec_dict doc_info -name "Manual:"] set docname [Dict_getdef $spec_dict doc_info -name "Manual:"]

3
src/modules/punk/args-buildversion.txt

@ -1,6 +1,7 @@
0.6.0 0.6.1
#First line must be a semantic version number #First line must be a semantic version number
#all other lines are ignored. #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/<type> 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.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/<type> 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.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 #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

21
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 # P2 relative-indent preservation: the documenter's continuation-line indentation
# conventions (e.g. lines 2+ indented by 2) survive to display, measured relative # 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 # to the first line - punk::args preserves but does not enforce them
# P3 -unindentedfields: left-margin authoring works for argument -help (and is # P3 -unindentedfields: left-margin authoring works for argument -help and for
# currently accepted but IGNORED for @cmd -help - pinned as a GAP) # @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 # P4 constructed (string-built) definitions receive no whole-block indent
# normalization ('constructed' - not to be confused with the @dynamic directive): # normalization ('constructed' - not to be confused with the @dynamic directive):
# embedded continuation indentation is interpreted via the display-time # embedded continuation indentation is interpreted via the display-time
@ -251,12 +251,13 @@ namespace eval ::testspace {
}\ }\
-result [list 2] -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 { -setup $common -body {
#the display transform undent(" "+help, max 4) still applies: with #-unindentedfields {-help} on the @cmd line gates the display transform
#continuations at the left margin the common prefix is 0, nothing is #undent(" "+help, max 4), so left-margin authored cmd-help keeps its
#removed, and the first line keeps its injected 4-space prefix. #first line flush with continuations.
#(see punk::args arg_error cmd_info handling: '#unindentedfields ?' todo) #(was rendering_unindentedfields_cmd_help_GAP pinning the ignored-option
#behaviour - first line +4; flipped by G-045 2026-07-12)
punk::args::define { punk::args::define {
@id -id ::testspace::rcmdunind @id -id ::testspace::rcmdunind
@cmd -name testspace::rcmdunind -summary\ @cmd -name testspace::rcmdunind -summary\
@ -268,13 +269,15 @@ GFLUSH line"
@values -min 0 -max 0 @values -min 0 -max 0
} }
set r [render_table ::testspace::rcmdunind] 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]}] 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 { -cleanup {
punk::args::undefine ::testspace::rcmdunind 1 punk::args::undefine ::testspace::rcmdunind 1
}\ }\
-result [list 4] -result [list 0 0]
#--- P4 constructed (string-built) definitions ----------------------------------------- #--- P4 constructed (string-built) definitions -----------------------------------------

Loading…
Cancel
Save