Browse Source

G-083 increment 1: punk::args argument-relations define-time vocabulary (0.19.0)

Spec compiler (resolve) accepts and stores the new relation keys:
- per-argument -conflicts <list>: parsekeys or flag names that must not be
  RECEIVED together with this argument; checked against received args only at
  parse time (defaults never conflict) - parse-time optionconflict enforcement
  lands in a later G-083 increment.
- @opts-level -parsekeymode override|error: per named OPT_GROUPS group; error
  = distinct-member co-occurrence within a shared-parsekey group raises
  optionconflict at parse; override = legacy last-wins, the default.

Both keys are cross-validated at resolve: -conflicts targets must name a defined
argname or declared -parsekey; -parsekeymode requires -group and a value of
override|error. Define-time integrity hole closed: a -parsekey colliding with a
distinct defined argument's name (one not sharing that -parsekey) is now a
resolve error instead of silently forming an implicit shared-key group
(parsekey_collides_with_defined_optname_GAP flipped in parsekey.test to a
define-time error pin, plus redundant-self-name and deliberate-shared-group
guards).

Design settled (recorded in the goal detail): -parsekeymode is per named group
(OPT_GROUPS entry, keyed by the @opts line's -group), not form-wide. Rationale:
lsearch uses per-arg -conflicts only (partial conflicts, groups stay default
override); clock clicks uses -parsekeymode error on its single named group
(full pairwise exclusivity). Unnamed shared-parsekey groups default override.

Legacy untouched by default: -parsekeymode override is the default and absent
-conflicts means no check runs; the pinned parsekey_repeat_ordering last-wins /
prepend-defaults idiom and the full existing suite pass unchanged.

New testsuite relations.test pins the define-time vocabulary (7 tests, matching
the longopts.test/mashopts.test error-pin style). buildversion 0.18.0 -> 0.19.0.

Verification: full punk/args suite via canonical tclsh90s - 356 total / 353
passed / 3 skipped (punkargsKnownBug) / 0 failed. goals_lint clean. No
punkproject.toml bump (define-time only; no shell-level user-visible behaviour
yet - the module change, not the shell product).

Assisted-by: harness=pi; primary-model=huggingface/zai-org/GLM-5.2; api-location=huggingface.co
master
Julian Noble 2 days ago
parent
commit
055f4bbf2f
  1. 28
      goals/G-083-punkargs-argument-relations.md
  2. 84
      src/modules/punk/args-999999.0a1.0.tm
  3. 3
      src/modules/punk/args-buildversion.txt
  4. 2
      src/tests/modules/AGENTS.md
  5. 30
      src/tests/modules/punk/args/testsuites/args/parsekey.test
  6. 116
      src/tests/modules/punk/args/testsuites/args/relations.test

28
goals/G-083-punkargs-argument-relations.md

@ -84,3 +84,31 @@ Design leans (settle and record here during the work):
- Related: G-053 (occurrence arity), G-072 (compound clause types - orthogonal),
G-084 (parsekey completeness fixes; its cross-member -multiple design
decision should be made with this goal's vocabulary in mind).
## Progress
- 2026-08-07 increment 1 (define-time vocabulary, punk::args 0.19.0): spec compiler
accepts and stores the new keys - per-arg `-conflicts <list>` (ARG_INFO) and
@opts-level `-parsekeymode override|error` (per named OPT_GROUPS entry, default
override). Resolve cross-validates: `-conflicts` targets must name a defined
argname or declared `-parsekey`; `-parsekeymode` requires `-group` and a value of
override|error. Define-time integrity hole closed: a `-parsekey` colliding with a
distinct defined argument's name (one not sharing that `-parsekey`) is now a
resolve error instead of silently forming an implicit shared-key group
(parsekey_collides_with_defined_optname_GAP flipped in parsekey.test to a
define-time error pin). No parse-time enforcement yet - the optionconflict raise
and parse_status_classify entry are increment 2. New testsuite relations.test pins
the define-time vocabulary (7 tests). Legacy untouched by default confirmed: full
punk/args suite 356 total / 353 passed / 3 skipped (punkargsKnownBug) / 0 failed
via tclsh90s.
- Design decision settled: `-parsekeymode` is per named group (OPT_GROUPS entry,
keyed by the @opts line's `-group`), not form-wide. Rationale: lsearch has
three shared-parsekey groups and uses per-arg `-conflicts` only (partial
conflicts within/across groups, all groups stay default override); clock
clicks uses `-parsekeymode error` on its single named group (full pairwise
exclusivity). Both adoption cases use named groups. Unnamed shared-parsekey
groups default to override (a user wanting strict adds `-group`).
- Remains for acceptance: increment 2 (parse-time optionconflict raise in the
shared post-resolution block, mash+ordinary parity, parse_status_classify);
increment 3 (synopsis/usage hints for conflicts/parsekeymode; lsearch + clock
clicks moduledoc adoption and dropping the caveat).

84
src/modules/punk/args-999999.0a1.0.tm

@ -2659,7 +2659,7 @@ tcl::namespace::eval punk::args {
-group {
tcl::dict::set tmp_optspec_defaults -group $v
if {$v ne "" && ![tcl::dict::exists $FDICT OPT_GROUPS $v]} {
tcl::dict::set FDICT OPT_GROUPS $v {-parsekey {} -help {}}
tcl::dict::set FDICT OPT_GROUPS $v {-parsekey {} -help {} -parsekeymode override}
}
if {$v ne ""} {
if {[tcl::dict::exists $at_specs -parsekey]} {
@ -2678,15 +2678,37 @@ tcl::namespace::eval punk::args {
set groupdict [tcl::dict::get $FDICT OPT_GROUPS]
#set helprecords [tcl::dict::get $F $fid OPT_GROUPS_HELP]
if {![tcl::dict::exists $groupdict $g]} {
tcl::dict::set FDICT OPT_GROUPS $g [dict create -parsekey {} -help $v]
tcl::dict::set FDICT OPT_GROUPS $g [dict create -parsekey {} -help $v -parsekeymode override]
} else {
tcl::dict::set FDICT OPT_GROUPS $g -help $v
}
}
-parsekeymode {
#G-083: @opts-level strict mode for a shared-parsekey group.
#override (default) = legacy last-wins among distinct members sharing the parsekey.
#error = distinct-member co-occurrence within the group raises optionconflict at parse.
#Applies to the group named by this @opts line's -group (and its -parsekey);
#-group is required when -parsekeymode is given so the target group is named.
if {$v ne "override" && $v ne "error"} {
error "punk::args::resolve Bad @opt line. -parsekeymode must be 'override' or 'error'. got '$v' @id:$DEF_definition_id"
}
if {![tcl::dict::exists $at_specs -group]} {
error "punk::args::resolve Bad @opt line. -parsekeymode requires -group to name the shared-parsekey group it applies to. @id:$DEF_definition_id"
}
set g [tcl::dict::get $at_specs -group]
if {$g eq ""} {
error "punk::args::resolve Bad @opt line. -parsekeymode requires a non-empty -group to name the shared-parsekey group it applies to. @id:$DEF_definition_id"
}
if {![tcl::dict::exists [tcl::dict::get $FDICT OPT_GROUPS] $g]} {
tcl::dict::set FDICT OPT_GROUPS $g [dict create -parsekey {} -help {} -parsekeymode $v]
} else {
tcl::dict::set FDICT OPT_GROUPS $g -parsekeymode $v
}
}
-range {
if {[dict exists $at_specs -type]} {
set tp [dict get $at_specs -type]
} else {
} else {
set tp [dict get $tmp_optspec_defaults -type]
}
if {[llength $tp] == 1} {
@ -2728,7 +2750,7 @@ tcl::namespace::eval punk::args {
tcl::dict::set tmp_optspec_defaults $k $v
}
default {
set known { -parsekey -group -grouphelp
set known { -parsekey -group -grouphelp -parsekeymode
-any -anyopts -mash -arbitrary -form -minsize -maxsize -choices -choicegroups -choicemultiple -choicecolumns -choicelabels -choiceinfo
-type -range -typeranges -default -defaultdisplaytype -typedefaults
-choiceprefix -choiceprefixdenylist -choiceprefixreservelist -choicerestricted -nocase
@ -3376,6 +3398,17 @@ tcl::namespace::eval punk::args {
-parsekey - -group {
tcl::dict::set spec_merged $spec $specval
}
-conflicts {
#G-083: per-argument relation. A list of parsekeys or flag names that
#must not be RECEIVED together with this argument. Checked against
#received arguments only (defaults never conflict); resolved through
#the alias/prefix machinery at check time. Cross-validated against
#the defined argument set after all specs merge.
if {[catch {llength $specval}]} {
error "punk::args::resolve - invalid value for key '$spec' in specifications for argument '$argname' - value must be a list of parsekeys or flag names @id:$DEF_definition_id"
}
tcl::dict::set spec_merged -conflicts $specval
}
-mash {
#allow when any alt in argname is a single letter flag such s -a or -Z
#single letter flags do not have to be -type none to allow -mash to be set true.
@ -3533,7 +3566,7 @@ tcl::namespace::eval punk::args {
} else {
set known_argopts [list {*}{
-form -type
-parsekey -group
-parsekey -group -conflicts
-range -typeranges
-default -defaultdisplaytype -typedefaults
-minsize -maxsize -choices -choicegroups
@ -3740,6 +3773,47 @@ tcl::namespace::eval punk::args {
}
}
#G-083: define-time integrity for -parsekey and the new relations vocabulary.
#Cross-arg checks run here because all ARG_INFO entries for the form exist by now.
set _g83_argnames [dict get $FDICT OPT_NAMES]
lappend _g83_argnames {*}[dict get $FDICT VAL_NAMES]
lappend _g83_argnames {*}[dict get $FDICT LEADER_NAMES]
#(a) -parsekey colliding with a distinct defined arg's name silently forms an
#implicit shared-key group (parsekey_collides_with_defined_optname_GAP). Reject
#unless that other arg also declares the same -parsekey (a deliberate group).
foreach _g83_an $_g83_argnames {
set _g83_pk [punk::args::system::Dict_getdef [dict get $FDICT ARG_INFO $_g83_an] -parsekey ""]
if {$_g83_pk eq ""} continue
foreach _g83_other $_g83_argnames {
if {$_g83_other eq $_g83_an} continue
if {$_g83_other ne $_g83_pk} continue
set _g83_other_pk [punk::args::system::Dict_getdef [dict get $FDICT ARG_INFO $_g83_other] -parsekey ""]
if {$_g83_other_pk ne $_g83_pk} {
error "punk::args::resolve - -parsekey '$_g83_pk' for argument '$_g83_an' collides with the name of defined argument '$_g83_other' (which does not share that -parsekey). Use a distinct -parsekey, or give '$_g83_other' the same -parsekey to form an explicit shared-key group. @id:$DEF_definition_id"
}
}
}
#(b) -conflicts targets must name a defined argname or a declared -parsekey.
#(the alias/prefix resolution of received args happens at parse time.)
set _g83_resolve_targets [dict create]
foreach _g83_t $_g83_argnames {
dict set _g83_resolve_targets $_g83_t 1
set _g83_tpk [punk::args::system::Dict_getdef [dict get $FDICT ARG_INFO $_g83_t] -parsekey ""]
if {$_g83_tpk ne ""} {dict set _g83_resolve_targets $_g83_tpk 1}
}
foreach _g83_an $_g83_argnames {
set _g83_conflicts [punk::args::system::Dict_getdef [dict get $FDICT ARG_INFO $_g83_an] -conflicts {}]
if {![llength $_g83_conflicts]} continue
foreach _g83_target $_g83_conflicts {
if {![dict exists $_g83_resolve_targets $_g83_target]} {
error "punk::args::resolve - -conflicts for argument '$_g83_an' names '$_g83_target' which is neither a defined argument name nor a declared -parsekey in this form. @id:$DEF_definition_id"
}
}
}
unset -nocomplain _g83_argnames _g83_resolve_targets _g83_an _g83_pk _g83_other _g83_other_pk _g83_t _g83_tpk _g83_conflicts _g83_target
#set mashargs [dict get $F $fid OPT_MASHES]
set mashargs [dict get $FDICT OPT_MASHES]
if {[llength $mashargs]} {

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

@ -1,6 +1,7 @@
0.18.0
0.19.0
#First line must be a semantic version number
#all other lines are ignored.
#0.19.0 - G-083 increment 1 (argument-relations define-time vocabulary): new per-argument key -conflicts <list> (parsekeys or flag names that must not be RECEIVED together with this argument; checked against received args only at parse time, defaults never conflict - parse-time optionconflict enforcement lands in a later G-083 increment) and new @opts-level -parsekeymode override|error (per named OPT_GROUPS group; error = distinct-member co-occurrence within a shared-parsekey group raises optionconflict at parse; override = legacy last-wins, the default). Both keys are cross-validated at resolve: -conflicts targets must name a defined argname or declared -parsekey; -parsekeymode requires -group and a value of override|error. Define-time integrity hole closed: a -parsekey value colliding with a distinct defined argument's name (one that does not share that -parsekey) is now a resolve error instead of silently forming an implicit shared-key group (parsekey_collides_with_defined_optname_GAP flipped to a define-time error pin in parsekey.test). Legacy behaviour untouched by default (no -conflicts, default -parsekeymode override, no colliding parsekey). New testsuite relations.test pins the define-time vocabulary; full punk/args suite green.
#0.18.0 - G-151 annotated success render: new punk::args::parse_report - landing report for a SUCCESSFUL parse, one row per value-holding argument (received, or filled from -default) in declaration-section order (leaders, opts, values) with columns Argument | Source | Value - the success-side sibling of the arg_error usage table (a flag-like word consumed as a VALUE by position shows attributed to its consuming argument - the make.tcl dry-run 'kitname = punk91 -confirm 0' class). Input: a punk::args::parse result dict (its id key must resolve to a registered definition), or words + 'withid <id>' (the parse is performed first; a rejected line raises the same validation error parse would - only successful parses have a landing report). Source column: received / received xN (-multiple aggregation count) / default - the plain-mode-safe twin of the colour marking (received CLR(check), default CLR(parsekey_hint)); absent optionals with no default-in-effect get no row. Returns: table (arg_error-styled bordered block via textblock; the default), tableobject, string (plain lines 'name (source) = value'; also the degraded no-textblock path), dict (machine form: id/form/rows with class/source/received/positions/multiple/hasvalue/value - never elided). Display elision is type-aware, deterministic and always marked (display-hint honesty): strings single-line-ized (ansistring VIEW -lf 1 -vt 1 -sp 0 - embedded controls/ANSI render visibly so a value cannot disturb the table; real spaces stay spaces) then grapheme-capped via the new ansistring TRUNCATE (punk::ansi 0.2.0) with trailing '...' plus ' (len N)' citing the raw value's string length; -multiple aggregations and -type list values element-capped with '(+N more)' (whole list-quoted elements kept while they fit, first element char-capped if it alone overflows); -type dict values pair-capped with '(+N pairs)'; markers stay intact so cells can exceed very small caps by the marker width; plain-string fallbacks when punk::ansi is unavailable. Width cascade per the G-149 plumbing precedent: caller -valuewidth > new @cmd directive key -reportvaluewidth > built-in 48; 0 means no cap; deliberately never console-derived (deterministic and pipe-safe - the G-007 emit-then-query lesson). Value-in-effect lookup bridges storage-key folds at display level (-parsekey renames, aliased optionsets' last-|-member finalopts fold) so received aliased/parsekey'd arguments keep their row - G-084 owns the storage-key model itself. Failure-side rendering (arg_error/usage) unchanged. make.tcl retiring its interim one-line 'dry-run: line accepted ...' report in favour of this render is consumer follow-through after a bootsupport promotion (not part of this change). New testsuite parsereport.test; define -help documents @cmd -reportvaluewidth beside the other directive-options.
#0.17.0 - G-149 configurable multi-form synopsis hint labels: the per-form hint labels rendered beside a multi-form definition's synopsis lines in the usage/arg_error table (hard-coded ' i -form N ...' previously) are now a template substituted per form - %formindex% replaced with the form's 0-based ordinal, %formname% with its name; an empty template suppresses the labels entirely (the cell keeps just the Synopsis: label, as single-form renders do). Precedence: caller option > definition > built-in default. New arg_error/usage option -formhint <template> (supplied-empty means suppress; usage pulls it from arg_error's definition via resolved_def); new @cmd directive key -formhint <template> for definition-supplied hints (rides the existing arbitrary-key cmd_info merge, so resolved_def round-trips it; not display-deferred). Unconfigured definitions render byte-identical to 0.16.0 (default template reproduces the exact prior bytes, verified by capture diff). Motivation (G-143 origin): script-level (script) ids - e.g make.tcl's - are unreachable from any repl, so the repl-oriented ' i -form N ...' default is not actionable there; consumers can now name their own per-form navigation. The string (non-table) renderer never carried hint labels and is unchanged. make.tcl adoption is consumer follow-through after a bootsupport promotion (not part of this change). New testsuite formhint.test; define -help documents the @cmd key beside the other directive-options.
#0.16.0 - G-073 unavailable choices: new per-argument key -choiceunavailable <list> - names that are recognised but not available in the current runtime/context. Display: entries render among the choices under a dedicated 'Unavailable (recognised, not selectable here)' group heading (table title / string-renderer Group heading - the distinguishing mechanism) with their ordinary -choicelabels notes, and join the prefix-calculation pool (display shortest-prefix marking reflects their reserving effect); synopsis choice-literal display and value-in-effect/goodarg marking never include them (structural: they are not in -choices/-choicegroups, and -default may not name one). Parse: choiceword_match gains an optional 8th argument unavailablelist and an 'unavailable' result key - a word landing on an unavailable name (exact, or unique prefix; case per -nocase) reports unavailable 1 with the name as canonical while matched stays 0, so matched-only consumers treat it as an ordinary non-match; a prefix shared between an available and an unavailable name is a plain ambiguous non-match. Validation rejects such a landing with the tailored PUNKARGS VALIDATION {choiceunavailable <name> choices <list>} error (-badarg/-badval; message names the entry, its -choicelabels note - e.g a version boundary - and the available values; private::unavailable_choice_msg shared by all raise surfaces). The G-071 allocation screen honours the list (optional-arg landings recorded as G-082 rejection kind 'unavailable' and preferred at the overflow raise sites); required args are unscreened as before, so their landing reports via final validation identically. Ambiguous-prefix messages annotate unavailable longer matches '(recognised but unavailable)'. -choicerestricted 0 keeps full passthrough (no tailored rejection). Resolve-time validation: requires -choices/-choicegroups; entries must not collide with choices, -choicealiases alias names, or -choiceprefixreservelist entries; -default may not be an unavailable name. form_literal_affinity/formcheck screens pass the list through (uniform pool semantics). In-tree adopter: punk::args::moduledoc::tclcore 'string is' forward classes (dict on 8.6). New testsuite choiceunavailable.test; tclcoreparity.test gains forward-class pins + the user-sanctioned 'di' strictness exemption; define -help documents the key.

2
src/tests/modules/AGENTS.md

File diff suppressed because one or more lines are too long

30
src/tests/modules/punk/args/testsuites/args/parsekey.test

@ -358,24 +358,29 @@ namespace eval ::testspace {
]
#added 2026-07-14 (agent) - parsekey coverage review.
#GAP: no define-time validation when a -parsekey value collides with another defined
#option's name. The two options silently conflate into an implicit shared-key group
#(last received wins under the common key).
test parsekey_collides_with_defined_optname_GAP {GAP: -parsekey matching another option's name silently forms an implicit group}\
#added 2026-07-14 (agent) - parsekey coverage review; flipped 2026-08-07 (G-083).
#A -parsekey value colliding with a distinct defined option's name used to silently
#form an implicit shared-key group (last received wins). It is now a define-time error:
#resolve rejects it unless the named option also declares the same -parsekey.
test parsekey_collides_with_defined_optname {-parsekey matching another option's name is a define-time error unless that option shares the parsekey}\
-setup $common -body {
set docids [list]
set argd [punk::args::parse {-a 1 -b 2} withdef @opts {-a -parsekey -b -type string} {-b -type string}]
lappend docids [dict get $argd id]
lappend result [dict get $argd opts]
lappend result [dict get $argd received]
#colliding parsekey - resolve rejects at parse (definitions are lazy)
try {
punk::args::parse {-a 1 -b 2} withdef @opts {-a -parsekey -b -type string} {-b -type string}
lappend result "UNEXPECTED-accepted-collision"
} on error {emsg eopts} {
lappend result [string match "*collides with the name of defined argument*" $emsg]
}
set argd [punk::args::parse {-a 1} withdef @opts {-a -parsekey -b -type string} {-b -type string}]
#an option naming its OWN parsekey is not a collision - -b -parsekey -b is redundant but legal
set argd [punk::args::parse {-b 2} withdef @opts {-b -parsekey -b -type string}]
lappend docids [dict get $argd id]
lappend result [dict get $argd opts]
set argd [punk::args::parse {-b 2} withdef @opts {-a -parsekey -b -type string} {-b -type string}]
#a deliberate shared-key group where one member's name matches the parsekey is legal
set argd [punk::args::parse {-a 1} withdef @opts {-a -parsekey -b -type string} {-b -parsekey -b -type string}]
lappend docids [dict get $argd id]
lappend result [dict get $argd opts]
}\
@ -385,10 +390,9 @@ namespace eval ::testspace {
}
}\
-result [list\
1\
{-b 2}\
{-b 0 -b 1}\
{-b 1}\
{-b 2}
]

116
src/tests/modules/punk/args/testsuites/args/relations.test

@ -0,0 +1,116 @@
package require tcltest
package require punk::args
#G-083 argument relations: -conflicts (per-arg) and -parsekeymode (per @opts group).
#This file pins the DEFINE-TIME vocabulary (spec-compiler storage and validation);
#the parse-time optionconflict enforcement is pinned in validation.test and
#parsekey.test. Error-shape pins use the first three -errorcode elements where the
#failure surfaces through parse, and distinctive message substrings for resolve-time
#definition errors (plain text, no ANSI) - the longopts.test/mashopts.test convention.
#Definitions are lazy: resolve errors surface at first parse, so the parse path is
#used to trigger them and the message substring is pinned.
namespace eval ::testspace {
namespace import ::tcltest::*
variable common {
set result ""
}
#added 2026-08-07 (agent) - G-083 define-time vocabulary characterisation
test parsekeymode_requires_group {@opts -parsekeymode without -group is a resolve error}\
-setup $common -body {
try {
punk::args::parse {} withdef {@opts -parsekeymode error} {-x -type none}
lappend result "UNEXPECTED-accepted"
} on error {emsg eopts} {
lappend result [string match "*-parsekeymode requires -group*" $emsg]
}
set result
}\
-result [list 1]
test parsekeymode_bad_value {@opts -parsekeymode with a value other than override|error is a resolve error}\
-setup $common -body {
try {
punk::args::parse {} withdef {@opts -group G -parsekeymode strict} {-x -type none}
lappend result "UNEXPECTED-accepted"
} on error {emsg eopts} {
lappend result [string match "*-parsekeymode must be 'override' or 'error'*" $emsg]
}
set result
}\
-result [list 1]
test parsekeymode_stored {@opts -parsekeymode error with -group is accepted and stored on the OPT_GROUPS entry}\
-setup $common -body {
set argd [punk::args::parse {} withdef {@opts -group G -parsekeymode error} {-x -type none}]
lappend docids [dict get $argd id]
set spec [punk::args::get_spec [dict get $argd id]]
dict for {fid fd} [dict get $spec FORMS] {
if {[dict exists $fd OPT_GROUPS G -parsekeymode]} {
lappend result [dict get $fd OPT_GROUPS G -parsekeymode]
}
}
set result
}\
-cleanup {
foreach id $docids {punk::args::undefine $id 1}
}\
-result [list error]
test parsekeymode_default_override {an @opts group without -parsekeymode stores the default override}\
-setup $common -body {
set argd [punk::args::parse {} withdef {@opts -group G} {-x -type none}]
lappend docids [dict get $argd id]
set spec [punk::args::get_spec [dict get $argd id]]
dict for {fid fd} [dict get $spec FORMS] {
if {[dict exists $fd OPT_GROUPS G -parsekeymode]} {
lappend result [dict get $fd OPT_GROUPS G -parsekeymode]
}
}
set result
}\
-cleanup {
foreach id $docids {punk::args::undefine $id 1}
}\
-result [list override]
test conflicts_unknown_target {per-arg -conflicts naming an unknown flag/parsekey is a resolve error}\
-setup $common -body {
try {
punk::args::parse {} withdef @opts {-x -type none -conflicts -nope}
lappend result "UNEXPECTED-accepted"
} on error {emsg eopts} {
lappend result [string match "*-conflicts for argument '-x' names '-nope' which is neither a defined argument name nor a declared -parsekey*" $emsg]
}
set result
}\
-result [list 1]
test conflicts_valid_flagname_target {per-arg -conflicts naming a defined flag is accepted at define time}\
-setup $common -body {
#accepted at define time (parse-time enforcement lands in a later G-083 increment)
set argd [punk::args::parse {-x -y} withdef @opts {-x -type none -conflicts -y} {-y -type none}]
lappend docids [dict get $argd id]
lappend result ok
set result
}\
-cleanup {
foreach id $docids {punk::args::undefine $id 1}
}\
-result [list ok]
test conflicts_valid_parsekey_target {per-arg -conflicts naming a declared -parsekey is accepted at define time}\
-setup $common -body {
set argd [punk::args::parse {-x -y} withdef @opts {-x -type none -parsekey -pk -conflicts -y} {-y -type none -parsekey -pk}]
lappend docids [dict get $argd id]
lappend result ok
set result
}\
-cleanup {
foreach id $docids {punk::args::undefine $id 1}
}\
-result [list ok]
}
tcltest::cleanupTests ;#needed to produce test summary line.
Loading…
Cancel
Save