You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

9.2 KiB

G-049 punk::args parse-status data model with machine-parsable cmdhelp returns

Status: achieved 2026-07-10 Scope: src/modules/punk/args-999999.0a1.0.tm (arg_error, parse error dispatch, colour-scheme handling), src/modules/punk/ns-999999.0a1.0.tm (cmdhelp), src/tests/modules/punk/args/testsuites/args/usagemarking.test, src/tests/modules/punk/ns/testsuites/ns/cmdhelp.test Goal: the information behind usage-display argument marking (which supplied arguments validated, which argument failed and why, which scheme applies) exists as a documented parse-status structure produced from a parse attempt and consumed by both arg_error renderers, and punk::ns::cmdhelp can return it machine-parsably via -return dict - replacing the transient goodargs/badarg locals, the badarg gaps in non-choice validation failures, and the stateful shared colour-array scheme handling. Acceptance: cmdhelp -return dict distinguishes an incomplete, a fully-valid and an invalid argument set via per-argument statuses (received/ok/bad + overall scheme/message/form) with the structure documented; the table and string renderers derive their marking from that same structure, with rendered output unchanged except where the pinned GAP tests flip: badarg marking covers type/allocation failures not just choice violations (cmdhelp_GAP_no_badarg_marking_for_failed_typed_value), an explicit -scheme is honoured on the parse-failure path (cmdhelp_GAP_explicit_scheme_ignored_on_failure), the failure message names the queried command instead of cmdhelp's internal parse source line (cmdhelp_GAP_errormsg_leaks_internal_source), and scheme rendering no longer depends on or mutates shared colour state - the documented -scheme choice value 'nocolour' takes effect and repeated renders of the same call are identical regardless of prior scheme renders (usagemarking_GAP_scheme_nocolour_renders_with_leftover_colours, usagemarking_GAP_dash_nocolour_leaks_into_shared_array, usagemarking_GAP_dash_nocolour_leak_affects_later_info_render); all non-GAP characterization tests in usagemarking.test and cmdhelp.test pass unchanged.

Context

The interactive usage display ('i <args...>' via punk::ns::cmdhelp) marks supplied arguments for validity: a fully-valid argument set renders with the info scheme (grey border) and received arguments struck through in green; a failed parse renders with the error scheme (yellow border) and - for some failure classes - the offending argument in red. This behaviour was characterized 2026-07-10 in usagemarking.test (arg_error primitives) and cmdhelp.test (integration), and several defects were pinned as GAP tests:

  • badarg coverage is uneven: only choiceviolation failures populate -badarg in the validation error dispatch, so only choice violations get the red row marking. A value failing its -type check surfaces as missingrequiredvalue (the value is never assigned, so allocation fails first) with NO badarg - 'i cmd v1 x x' with int-typed values names the failing argument in the message but marks nothing. (cmdhelp_GAP_no_badarg_marking_for_failed_typed_value)
  • explicit -scheme is ignored on the failure path: cmdhelp passes -scheme through to arg_error only on the success path and the tableobject failure branch; for -return table/string failures it returns the parse error message rendered with the default error scheme. (cmdhelp_GAP_explicit_scheme_ignored_on_failure)
  • caller attribution leaks internals: at top call depth (the interactive case) the failure message names cmdhelp's own parse call as raw source text (punk::args::parse $args_remaining -cache 0 ...) instead of the queried command; from nested contexts it attributes correctly. (cmdhelp_GAP_errormsg_leaks_internal_source)
  • scheme colour handling is stateful: arg_error's scheme normalization switch matches "", "-nocolor", "-nocolour" (with dash) for the nocolour arm, so the DOCUMENTED choice value nocolour falls through to the "na" scheme - no override merge - and renders with whatever colours the most recent info/error render left in the shared arg_error_CLR array. The dash spelling does merge, and because scheme merges write the shared array in place, its strike-only goodarg/badarg overrides then leak into all subsequent renders until a colour on/off flip forces an array reload. (usagemarking_GAP_scheme_nocolour_renders_with_leftover_colours, usagemarking_GAP_dash_nocolour_leaks_into_shared_array, usagemarking_GAP_dash_nocolour_leak_affects_later_info_render)

Meanwhile the good/bad/scheme information itself exists only as transient locals inside arg_error (goodargs list derived from -parsedargs 'received', badarg string, scheme name) and as colour in the output. Nothing machine-readable reports "these supplied words validated, this one failed, for this reason". cmdhelp's -return choices are string/table/tableobject only.

Approach

  1. Define a parse-status structure (dict) produced from a parse attempt against a definition: per-argument entries (name, received value/position, status ok|bad|unparsed, failure class when bad) plus overall fields (scheme, message, form). Success and failure of punk::args::parse both map onto it (failure via the PUNKARGS VALIDATION errorcode payload - which should carry -badarg for type/allocation failures, not just choice violations).
  2. Make arg_error's table and string renderers consume the structure (replacing the goodargs/badarg locals), resolving colours per-render from the scheme arrays instead of merging into the shared array - fixing the nocolour choice and the leakage as a side effect.
  3. Add -return dict to punk::ns::cmdhelp returning the structure alongside resolution info (origin/docid/cmdtype from cmdinfo), and pass the explicit -scheme through the failure path.
  4. Fix caller attribution for the usage-display path (the message should name the queried command; related to the G-046 'Bad number of leading values...' rewording acceptance item - coordinate, don't duplicate).

Notes

  • G-050 (synopsis marking) and G-044 (repl completion/hinting) consume this structure; land the structure first.
  • Characterization baseline: usagemarking.test (14 tests) and cmdhelp.test (19 tests), both green on Tcl 9.0.3 and 8.7 as of 2026-07-10. GAP-prefixed tests pin the defects above and flip with this goal.
  • Preserved surface includes the goodchoice highlighting (reverse video on the choice word matching an argument's value-in-effect - supplied choice for received arguments, default choice for arguments the parse filled from -default; only when a parse result is supplied). The status structure should carry value-in-effect per argument so the renderers keep this without reaching back into the raw parse result.
  • The scheme discrimination trick used by the tests (info border SGR params are the only scheme-unique style; error border shares params with info title) is itself a hint that scheme styling deserves a small documented palette rather than ad-hoc per-key overrides.

Outcome (achieved 2026-07-10)

Shipped as punk::args 0.5.0 + punk::ns 0.2.0 (punkshell 0.5.0):

  • Structure producer: punk::args::parse_status (withid/withdef, -form, -caller) - the structure is documented in its PUNKARGS definition. Builder/classifier live in punk::args::private::parse_status_build / parse_status_classify / parse_status_formname. Overall status classifies count/missing failure classes as incomplete (count classes only below the minimum) and everything else invalid; a type-failed word surfacing as missingrequiredvalue therefore reads incomplete with badarg set - the per-argument statuses carry the specifics (documented).
  • arg_error -parsestatus option; both renderers consume the structure ($argstatusd per-arg status/hasvalue/value + receivednames for the group-parsekey check), built internally from -badarg/-parsedargs when not supplied. Colour resolution is per-render into a proc-local CLR array; the shared arrays are never written by scheme merges, and the scheme switch accepts the documented nocolour (plus nocolor; dash spellings retained for compat).
  • get_dict missingrequiredvalue/missingrequiredleader raise sites carry -badarg.
  • punk::args::parse -caller overrides the %caller% Get_caller frame walk (also added to the parse cache key); parse_status defaults it to the definition's @cmd -name.
  • cmdhelp: -return dict {origin docid cmdtype args_remaining parsestatus} on all resolution paths (empty parsestatus for undocumented commands); both advisory-parse branches use parse_status (uncached, minimal errorstyle) with -caller = querycommand + consumed subcommand words; failures render via arg_error -parsestatus with $nextopts so an explicit -scheme reaches the failure render.
  • Verification: all six GAP pins flipped (usagemarking.test 17, cmdhelp.test 25 incl 4 new cmdhelp_return_dict_*, parsestatus.test 12 new) - full punk/args (162+1skip) and punk/ns (53) trees green on Tcl 9.0.3 and 8.7; full source-tree suite green (known exec-14.3 core baseline failure only); make.tcl modules + projectversion OK.
  • The G-046 'Bad number of leading values...' rewording item remains untouched (coordinated, not duplicated): cmdhelp's no-supplied-words suppression is preserved and the dict return reports scheme info for that case.