Browse Source

vfs: sync punk::args 0.11.2, punk::ns 0.5.0, punk::lib 0.4.3, punk 0.2.6, punk::repl 0.5.1, tclcore moduledoc 0.3.3 into _vfscommon.vfs

make.tcl modules + vfscommonupdate + project: all four kits rebuilt
(punkbi, punksys, punk91, punk902z). Kit-mode verification: punk902z
loads args=0.11.2 ns=0.5.0 tclcore=0.3.3 lib=0.4.3 punk=0.2.6, 'i join'
emits no bad-@dynamic warning; punksys (8.6) loads args=0.11.2 and the
after cancel-id discrimination resolves 'cancel someid' to the
cancelscript form (harvested id prefix working on 8.6).

A stale tcl_oauth2_library install leftover in the project's root lib/
tree (its src/vendorlib source was removed 2026-07-12; the libs install
step does not prune targets whose source vanished) was swept into the
vfs lib by vfscommonupdate and removed again before the kit build - it
is deliberately not part of the vendored set yet (G-065..G-068
first-test candidate). The root lib/ leftover itself was removed after
this commit was first authored; its rows remain in lib/.punkcheck.

Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
Julian Noble 2 days ago
parent
commit
7c49fc844e
  1. 57
      src/vfs/_vfscommon.vfs/modules/punk-0.2.6.tm
  2. 893
      src/vfs/_vfscommon.vfs/modules/punk/args-0.11.2.tm
  3. 56
      src/vfs/_vfscommon.vfs/modules/punk/args/moduledoc/tclcore-0.3.3.tm
  4. 75
      src/vfs/_vfscommon.vfs/modules/punk/lib-0.4.3.tm
  5. 162
      src/vfs/_vfscommon.vfs/modules/punk/ns-0.5.0.tm
  6. 15
      src/vfs/_vfscommon.vfs/modules/punk/repl-0.5.1.tm

57
src/vfs/_vfscommon.vfs/modules/punk-0.2.3.tm → src/vfs/_vfscommon.vfs/modules/punk-0.2.6.tm

@ -8494,7 +8494,12 @@ namespace eval punk {
}
#keep help-text lines manually folded (~70 cols) - the usage tables don't yet
#wrap to terminal width, so line lengths here directly set the table width
set basehelp {Help system for the punk shell.
#help text is authored as indented blocks (structural leading newline) and
#the generated definition declares @normalize (G-045): block-form
#multi-line values are re-based to the file-style convention at resolve
#time - no manual undent/trim and no left-margin authoring in this builder
set basehelp {
Help system for the punk shell.
With no arguments - an overview of some key shell
commands is displayed.
When the first argument is a recognised topic - help
@ -8504,12 +8509,19 @@ namespace eval punk {
command info (type and synopsis) is shown for a
resolvable command, or the resolved path for an
external executable.}
set topichelp "Help topic, or command words for basic command info.\nTopics accept their aliases and unique prefixes\n(some short words deliberately fall through to command lookup)."
set topichelp {
Help topic, or command words for basic command info.
Topics accept their aliases and unique prefixes
(some short words deliberately fall through to command lookup).}
set specs [list]
lappend specs ::punk::help help "Punk shell help system." ""
lappend specs ::punk::help_chunks punk::help_chunks "Punk shell help system - content as {channel text} chunks." "\n\nhelp_chunks returns the help content as a list of\n{channel text} chunks rather than emitting it."
lappend specs ::punk::help_chunks punk::help_chunks "Punk shell help system - content as {channel text} chunks." {
help_chunks returns the help content as a list of
{channel text} chunks rather than emitting it.}
foreach {id name summary extra} $specs {
set def ""
append def "@normalize" \n
append def "@id -id $id" \n
append def "@cmd -name $name -summary \"$summary\" -help \"$basehelp$extra\"" \n
append def "@leaders -min 0 -max -1" \n
@ -8604,7 +8616,11 @@ namespace eval punk {
warnings for known Tcl bugs affecting this interpreter
and known bugs in bundled library packages
(as detected by the punk::lib::check::has_tclbug_*
and has_libbug_* checks)."
and has_libbug_* checks).
A warning whose buginfo reports a shipped punkshell
mitigation keeps its severity level but is annotated
'(mitigated)' and rendered subdued (grey), with the
mitigation described."
@values -min 0 -max 0
}
proc tcl {context args} {
@ -8627,17 +8643,36 @@ namespace eval punk {
if {[dict exists $buginfo level]} {
set level [dict get $buginfo level]
}
switch -- $level {
minor {set highlight [punk::ansi::a+ cyan]}
medium {set highlight [punk::ansi::a+ yellow]}
major {set highlight [punk::ansi::a+ red bold]}
default {set highlight ""}
#mitigated is an axis orthogonal to level: the defect keeps its severity
#classification but a shipped punkshell mitigation covers it, so the
#warning renders subdued (grey) with a '(mitigated)' annotation and any
#mitigation text from the buginfo dict.
set mitigated 0
if {[dict exists $buginfo mitigated]} {
set mitigated [dict get $buginfo mitigated]
}
if {$mitigated} {
set highlight [punk::ansi::a+ term-grey]
} else {
switch -- $level {
minor {set highlight [punk::ansi::a+ cyan]}
medium {set highlight [punk::ansi::a+ yellow]}
major {set highlight [punk::ansi::a+ red bold]}
default {set highlight ""}
}
}
set levelshown $level
if {$mitigated} {
append levelshown " (mitigated)"
}
set indent " "
append warningblock \n $highlight "warning level: $level $bp triggered."
append warningblock \n $highlight "warning level: $levelshown $bp triggered."
if {[dict exists $buginfo description]} {
append warningblock \n "[punk::lib::indent [dict get $buginfo description] $indent]"
}
if {[dict exists $buginfo mitigation] && [dict get $buginfo mitigation] ne ""} {
append warningblock \n "[punk::lib::indent "mitigated: [dict get $buginfo mitigation]" $indent]"
}
if {[dict exists $buginfo url] && [dict get $buginfo url] ne ""} {
#full reference url (e.g. non tcl-core trackers such as tcludp)
append warningblock \n "${indent}see [punk::ansi::hyperlink [dict get $buginfo url]]"
@ -9403,7 +9438,7 @@ punkcheck::cli set_alias punkcheck
package provide punk [namespace eval punk {
#FUNCTL
variable version
set version 0.2.3
set version 0.2.6
}]

893
src/vfs/_vfscommon.vfs/modules/punk/args-0.6.0.tm → src/vfs/_vfscommon.vfs/modules/punk/args-0.11.2.tm

File diff suppressed because it is too large Load Diff

56
src/vfs/_vfscommon.vfs/modules/punk/args/moduledoc/tclcore-0.2.0.tm → src/vfs/_vfscommon.vfs/modules/punk/args/moduledoc/tclcore-0.3.3.tm

@ -8,7 +8,7 @@
# (C) 2025
#
# @@ Meta Begin
# Application punk::args::moduledoc::tclcore 0.2.0
# Application punk::args::moduledoc::tclcore 0.3.3
# Meta platform tcl
# Meta license MIT
# @@ Meta End
@ -18,7 +18,7 @@
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin punkshell_module_punk::args::moduledoc::tclcore 0 0.2.0]
#[manpage_begin punkshell_module_punk::args::moduledoc::tclcore 0 0.3.3]
#[copyright "2025"]
#[titledesc {punk::args definitions for tcl core commands}] [comment {-- Name section and table of contents description --}]
#[moddesc {tcl core argument definitions}] [comment {-- Description at end of page heading --}]
@ -257,7 +257,7 @@ tcl::namespace::eval punk::args::moduledoc::tclcore {
-summary\
"first start-of-word index after supplied index ${$I}start${$NI}"\
-help\
"Returns the index of the first start-of-word location that occurs after a starting index start
{Returns the index of the first start-of-word location that occurs after a starting index start
in the string str. A start-of-word location is defined to be the first word character following a
non-word character. Returns -1 if there are no more start-of-word locations after the starting point.
@ -268,7 +268,7 @@ tcl::namespace::eval punk::args::moduledoc::tclcore {
set idx [tcl_startOfNextWord $theString $idx]} {
puts "Word start index: $idx"
}
"
}
@values -min 2 -max 2
str -type string
start -type indexexpression
@ -4527,6 +4527,31 @@ tcl::namespace::eval punk::args::moduledoc::tclcore {
############################################################################################################################################################
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
#the after-id shape is harvested from the RUNNING interpreter (G-054 technique;
#user-directed 2026-07-13, probe record in goals/G-055) rather than hard-coded:
#a scheduled command's id is "after#N" in all known releases (tclTimer.c
#"after#%d"), and the cancelid/info forms use it as their id discriminator so
#accept/reject parity follows the interpreter these docs load into.
#The probe is safe: create + immediately cancel - no event loop entry, no output,
#no lasting state.
#The harvested prefix is consumed via tstr ${$after_id_prefix} placeholders in the
#::after definition below. The variable MUST live in the argdoc namespace: that is
#the DEFSPACE registered PUNKARGS definitions resolve their placeholders in
#whenever an argdoc child exists - even when the PUNKARGS list itself is in the
#parent, as here - and an unresolvable param is left silently literal (see the
#'Interpolation and the defspace' section of the punk::args::define help).
namespace eval argdoc {
set after_id_prefix "after#"
if {![catch {after 999999 {}} _aip_id]} {
catch {after cancel $_aip_id}
if {[regexp {^(.+#)\d+$} $_aip_id -> _aip_prefix]} {
set after_id_prefix $_aip_prefix
}
}
unset -nocomplain _aip_id _aip_prefix
}
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
#test of @form
@id -id ::after
@ -4570,7 +4595,15 @@ tcl::namespace::eval punk::args::moduledoc::tclcore {
@leaders -min 1 -max 1
cancel -choices {cancel}
@values -min 1 -max 1
id
#id typed by the harvested id shape: a word of any other shape belongs to the
#cancelscript form (real 'after cancel <non-id>' is a script-match no-op).
#An id-SHAPED word remains genuinely ambiguous with a script of the same text -
#real Tcl resolves that by id liveness at runtime (tries the id first, falls
#back to script match), which no static type expresses (goals/G-055 record).
id -type stringstartswith(${$after_id_prefix}) -typesynopsis id -help\
"Identifier of the delayed command to cancel.
It must have been the return value from a previous
after command (${$after_id_prefix}N shaped)."
#@form -form {cancelscript} -synopsis "after cancel script ?script...?"
@ -4593,7 +4626,13 @@ tcl::namespace::eval punk::args::moduledoc::tclcore {
@leaders -min 1 -max 1
info -choices {info} -choiceprefixreservelist {idle}
@values -min 0 -max 1
id -optional 1
#real 'after info <non-id-shaped-word>' errors at runtime ("event ... doesn't
#exist") - the model's shape rejection keeps error-vs-ok parity
id -optional 1 -type stringstartswith(${$after_id_prefix}) -typesynopsis id -help\
"Identifier of an existing event handler - the
return value from some previous call to after
(${$after_id_prefix}N shaped). It must not have triggered
yet or been canceled."
} "@doc -name Manpage: -url [manpage_tcl after]"\
{
@ -4848,7 +4887,6 @@ tcl::namespace::eval punk::args::moduledoc::tclcore {
return [punk::args::ensemble_subcommands_definition -groupdict $groups -columns 2 array]
}
lappend PUNKARGS [list {
@dynamic
@id -id ::array
@cmd -name "Built-in: array"\
-summary\
@ -6463,7 +6501,6 @@ tcl::namespace::eval punk::args::moduledoc::tclcore {
# -- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@dynamic
@id -id ::join
@cmd -name "Built-in: join"\
-summary\
@ -9299,7 +9336,6 @@ tcl::namespace::eval punk::args::moduledoc::tclcore {
}]}
}
punk::args::define {
@dynamic
@id -id ::split
@cmd -name "Built-in: split"\
-summary\
@ -12543,7 +12579,7 @@ namespace eval ::punk::args::register {
package provide punk::args::moduledoc::tclcore [tcl::namespace::eval punk::args::moduledoc::tclcore {
variable pkg punk::args::moduledoc::tclcore
variable version
set version 0.2.0
set version 0.3.3
}]
return

75
src/vfs/_vfscommon.vfs/modules/punk/lib-0.4.0.tm → src/vfs/_vfscommon.vfs/modules/punk/lib-0.4.3.tm

@ -8,7 +8,7 @@
# (C) 2024
#
# @@ Meta Begin
# Application punk::lib 0.4.0
# Application punk::lib 0.4.3
# Meta platform tcl
# Meta license BSD
# @@ Meta End
@ -18,7 +18,7 @@
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin punkshell_module_punk::lib 0 0.4.0]
#[manpage_begin punkshell_module_punk::lib 0 0.4.3]
#[copyright "2024"]
#[titledesc {punk general utility functions}] [comment {-- Name section and table of contents description --}]
#[moddesc {punk library}] [comment {-- Description at end of page heading --}]
@ -250,6 +250,63 @@ tcl::namespace::eval punk::lib::check {
return [dict create bug $bug bugref e38dc74e2 description $description level medium]
}
#G-076: version gate for the tcl9 dead-console defect (upstream ticket f10d91c2d3, root-caused
#in G-039). Shared by the 'help tcl' warning and the repl dead-console watchdog arming (both
#consult has_tclbug_console_deadspin). Empty = no released Tcl is known to contain the upstream
#fix, so every Tcl 9 windows runtime classifies as affected. Set this only after the G-039 kill
#procedure, re-run on the fixed released runtime with the watchdog disabled, shows a clean
#script-visible eof exit (see goals/G-076-tcl9-deadconsole-fix-adoption.md).
variable tclbug_console_deadspin_fixed_in ""
#pure classifier, separated for testability - facts in, verdict out
proc tclbug_console_deadspin_applies {platform tclversion fixed_in} {
if {$platform ne "windows"} {
return 0
}
if {![package vsatisfies $tclversion 9]} {
#tcl 8.6 has a different console driver - out of scope per G-039 (user decision 2026-07-12)
return 0
}
if {$fixed_in eq ""} {
#no released fix known - all Tcl 9 windows runtimes affected
return 1
}
return [expr {[package vcompare $tclversion $fixed_in] < 0}]
}
proc has_tclbug_console_deadspin {} {
#Tcl 9 windows console driver defect pair (win/tclWinConsole.c): when the hosting
#console dies (killed conhost/terminal), (a) ConsoleEventProc drops the error/EOF
#notification so a stdin readable fileevent never fires - the script is blind to the
#dead console; (b) ConsoleReaderThread busy-loops on the persistent error, spinning
#~2 cores until the channel is closed. Root-caused 2026-07-12 - see archived goal
#G-039; upstream ticket f10d91c2d3 filed 2026-07-12. punk::repl >= 0.5.0 mitigates
#with a console liveness watchdog (repl::console_watchdog) gated on this same check.
#Version-based detection only - a behavioural probe would require killing a console.
#The buginfo dict carries the mitigated/mitigation axis: level stays major (the core
#defect's severity), mitigated reports whether punk::repl >= 0.5.0 (console liveness
#watchdog) is available to this runtime - 'help tcl' renders mitigated warnings subdued.
variable tclbug_console_deadspin_fixed_in
set bug [tclbug_console_deadspin_applies $::tcl_platform(platform) [info patchlevel] $tclbug_console_deadspin_fixed_in]
set description "Tcl 9 windows console driver: a dead console (killed conhost/terminal) is never\ndelivered to the script as a fileevent, and the core's console reader thread busy-loops\non the persistent error - an orphaned tclsh spins CPU indefinitely. Plain tclsh scripts\nreading a console stdin have no script-level escape (see goal G-076)."
set replversion [package provide punk::repl]
if {$replversion eq ""} {
#not loaded - determine what version would be provided, without loading it:
#an unsatisfiable require triggers the package unknown scan (registering ifneeded
#scripts) then fails before any load (0.4.3 dev modules are alpha - below 999999).
catch {package require punk::repl 999999}
set available [package versions punk::repl]
if {[llength $available]} {
set replversion [lindex [lsort -command {package vcompare} $available] end]
}
}
set mitigated [expr {$bug && $replversion ne "" && [package vsatisfies $replversion 0.5-]}]
set mitigation ""
if {$mitigated} {
set mitigation "punk::repl $replversion is available to this runtime: its console liveness watchdog\n(armed when the repl serves the process-default console) closes the dead channel and\nexits cleanly instead of spinning. Non-repl console reads remain exposed."
}
return [dict create bug $bug bugref f10d91c2d3 description $description level major mitigated $mitigated mitigation $mitigation]
}
#has_libbug_* procs report bugs in bundled/vendored library packages rather than the Tcl core.
#They are surfaced through the same 'help tcl' warning report as the has_tclbug_* checks.
@ -2455,8 +2512,11 @@ namespace eval punk::lib {
#no change in origin - so we are into the arguments of the command, or have an invalid subcommand - stop looking for subcommands
#todo - detect invalid subcommand and count as unknown command?
break
} elseif {[dict get $test_cinfo cmdtype] in {"proc" "native" "notfound"}} {
} elseif {[dict get $test_cinfo cmdtype] in {"proc" "native" "notfound" "doconly"}} {
#we have a subcommand that won't be introspectable at a deeper level.
#(doconly: G-051 - cmdinfo's truthful cmdtype for documentation-only
#levels such as 'string is xdigit', previously reported 'notfound';
#treated identically here to preserve prior analysis behaviour)
set cinfo $test_cinfo
set ctype [dict get $cinfo cmdtype]
break
@ -2714,7 +2774,12 @@ namespace eval punk::lib {
dict lappend resultd commands_native $dispatchwords
}
}
"notfound" {
"notfound" -
"doconly" {
#doconly: G-051 - documentation-only level (e.g 'string is xdigit'),
#previously reported as 'notfound'; bucketed identically to preserve
#prior analysis behaviour (a future refinement may count doconly as a
#valid command word rather than notfound)
if {$dispatchwords ni [dict get $resultd commands_notfound]} {
dict lappend resultd commands_notfound $dispatchwords
}
@ -9173,7 +9238,7 @@ namespace eval ::punk::args::register {
package provide punk::lib [tcl::namespace::eval punk::lib {
variable pkg punk::lib
variable version
set version 0.4.0
set version 0.4.3
}]
return

162
src/vfs/_vfscommon.vfs/modules/punk/ns-0.2.0.tm → src/vfs/_vfscommon.vfs/modules/punk/ns-0.5.0.tm

@ -7,7 +7,7 @@
# (C) 2023
#
# @@ Meta Begin
# Application punk::ns 0.2.0
# Application punk::ns 0.5.0
# Meta platform tcl
# Meta license <unspecified>
# @@ Meta End
@ -4845,6 +4845,15 @@ y" {return quirkykeyscript}
return [cmdinfo {*}$next]
}
}
if {$cmdtype eq "notfound" && $docid ne ""} {
#G-051: resolution landed on a punk::args id with no corresponding real
#command - a documentation-only level below (or beside) a real command,
#e.g the per-class id "::tcl::string::is true" documenting a level below
#the real ::tcl::string::is (the class words are arguments, not
#subcommands). Report it distinctly so consumers can tell it from a
#genuinely unknown command. The docid remains authoritative for display.
set cmdtype doconly
}
return [list origin $origin cmdtype $cmdtype args_resolved [list [lindex $commands 0] {*}$consumed_args] args_remaining $remainingargs docid $docid stack $stack]
}
proc cmd_traverse {ns formid args} {
@ -5023,8 +5032,49 @@ y" {return quirkykeyscript}
#(would not support shor-form prefix of subcommand - even if the proc implementation did)
set docid_exists 0
set eparams [list]
set a_spaceform ""
if {[punk::args::id_exists "$origin [lindex $args $i]"]} {
set a [lindex $args $i]
set a_spaceform [lindex $args $i]
} elseif {$docid ne "" && [punk::args::id_exists $docid]} {
#G-051 space-form docid prefix parity: no space-form id exists for the
#exact word - if the current level's definition has a choices-bearing
#first leader, resolve the word with the same shared resolver argument
#parsing uses (punk::args::choiceword_match - honouring -choiceprefix,
#-nocase, -choicealiases, -choiceprefixdenylist,
#-choiceprefixreservelist) and retry the space-form lookup with the
#canonical word - so 'i string is tr' lands on the documentation for
#what 'string is tr' actually executes. No second matching rule: a word
#parse would reject resolves nothing here either, and a canonical with
#no space-form id falls through to the normal per-level handling.
set pf_spec [punk::args::get_spec $docid]
set pf_fid [lindex [dict get $pf_spec form_names] 0]
set pf_leaders [dict get $pf_spec FORMS $pf_fid LEADER_NAMES]
if {[llength $pf_leaders]} {
set pf_arginfo [dict get $pf_spec FORMS $pf_fid ARG_INFO [lindex $pf_leaders 0]]
set pf_allchoices [punk::args::system::Dict_getdef $pf_arginfo -choices {}]
foreach {_pf_g pf_members} [punk::args::system::Dict_getdef $pf_arginfo -choicegroups {}] {
lappend pf_allchoices {*}$pf_members
}
if {[llength $pf_allchoices]} {
set pf_matchinfo [punk::args::choiceword_match [lindex $args $i]\
[punk::args::system::Dict_getdef $pf_arginfo -nocase 0]\
$pf_allchoices\
[punk::args::system::Dict_getdef $pf_arginfo -choicealiases {}]\
[punk::args::system::Dict_getdef $pf_arginfo -choiceprefix 1]\
[punk::args::system::Dict_getdef $pf_arginfo -choiceprefixdenylist {}]\
[punk::args::system::Dict_getdef $pf_arginfo -choiceprefixreservelist {}]\
]
if {[dict get $pf_matchinfo matched]} {
set pf_canonical [dict get $pf_matchinfo canonical]
if {$pf_canonical ne [lindex $args $i] && [punk::args::id_exists "$origin $pf_canonical"]} {
set a_spaceform $pf_canonical
}
}
}
}
}
if {$a_spaceform ne ""} {
set a $a_spaceform
#review - tests?
#puts stderr "cmd_traverse - skipping to documented subcommand '$origin $a'"
#we can only seek beyond an undocumented subcommand level via a space delimited path, as we can make no assumption about the actual location of a subcommand relative to its parent
@ -5034,7 +5084,7 @@ y" {return quirkykeyscript}
set origin [list $origin $a]
incr i
set queryargs [lrange $args $i end]
set resolvedargs [list $a] ;#
set resolvedargs [list $a] ;#the canonical word (a resolved prefix/alias records its canonical, as parse normalization does)
set queryargs_untested $queryargs
} elseif {[punk::args::id_exists $docid]} {
set docid_exists 1
@ -5374,6 +5424,10 @@ y" {return quirkykeyscript}
on separate lines.
If -form formname|<int> is given, supply only
the synopsis for that form.
For a multiform command, trailing argument words
after the command path underline the form(s) they
match - the best candidate when no form fully
matches (G-041 multi-form candidacy).
"
@opts
-form -type number|name -default * -help\
@ -5422,10 +5476,38 @@ y" {return quirkykeyscript}
return
}
#G-041: for a multiform definition with trailing argument words and no explicit
#-form restriction, determine the form(s) the words match via the advisory parse
#(punk::args::parse_status multi-form candidacy) - the matching/best-candidate
#form's synopsis line is underlined below (e.g 's after cancel someid' marks the
#cancel form). Skipped when alias currying makes the remaining words unreliable.
set markforms [list]
set docid_forms [list]
if {$form eq "*" && !$excess && [llength $unresolved_args] && $doc_id ne ""} {
catch {set docid_forms [punk::args::forms $doc_id]}
if {[llength $docid_forms] > 1} {
if {![catch {punk::args::parse_status $unresolved_args withid $doc_id} pstat]} {
dict for {fname finfo} [dict get $pstat formstatus] {
if {[dict get $finfo status] eq "valid"} {
lappend markforms $fname
}
}
if {![llength $markforms]} {
#no form fully matches - mark the best candidate
set markforms [list [dict get $pstat form]]
}
}
}
}
#when we use list operations on $syn - it can get extra braces due to ANSI - use join to bring back to a string without extraneous bracing
switch -- $opt_return {
full - summary {
set resultstr ""
#ordinal position of each non-comment line maps to the definition's form
#(declaration order - both the full and summary renders emit one synopsis
#line per form in that order)
set formidx 0
foreach synline [split $syn \n] {
if {[string range $synline 0 1] in {"# " "##"}} {
append resultstr $synline \n
@ -5454,8 +5536,14 @@ y" {return quirkykeyscript}
append lineout " " [list $part]
}
}
set lineout [string trim $lineout]
#G-041: underline the form(s) the supplied trailing words match
if {[llength $markforms] && [lindex $docid_forms $formidx] in $markforms} {
set lineout "[punk::ansi::a+ underline]$lineout[punk::ansi::a+ nounderline]"
}
incr formidx
#must be no leading space for tests in test::punk::args synopsis.test
append resultstr [string trim $lineout] \n
append resultstr $lineout \n
}
}
@ -5520,8 +5608,13 @@ y" {return quirkykeyscript}
} {${[punk::args::resolved_def -types opts ::punk::args::arg_error -scheme]}} {
-form -default 0 -help\
"Ordinal index or name of command form"
-form -default * -help\
"Restrict to the listed command forms - each element an
ordinal index or form name (see punk::args::parse -form).
With the default * the usage display presents the form
best matching any supplied argument words (G-041
multi-form candidacy) - e.g 'i after cancel <id>'
presents the cancel form."
-grepstr -default "" -type list -typesynopsis regex -help\
"Case insensitive grep for pattern in the output.
list consisting of regex, optionally followed by ANSI names for highlighting"
@ -5605,15 +5698,24 @@ y" {return quirkykeyscript}
#-caller attributes any failure message to the queried command rather than
#an internal parse call site.
set pstatus [punk::args::parse_status $queryargs -form $opt_form -caller $querycommand withid $rootdoc]
#With NO supplied args a failure only reflects missing required
#leaders/values - nothing to mark and nothing wrong with the user's (absent)
#input, so we show plain usage in the info scheme instead of the
#internal-looking parse error (G-046 item 5).
#A failing advisory parse renders with the error scheme and its
#message even when NO args were supplied - see the matching site in
#the main cmdhelp body for the history (G-046 item 5 suppression
#reversed 2026-07-12 after the G-049 -caller attribution made the
#messages accurate).
#G-041: render the usage for the form the advisory parse selected
#(the matched or best-candidate form within the caller's -form
#selection); for a no-form-match pass every ranked candidate and for
#an ambiguous match every matching form - the first form's argument
#table renders and all passed forms are marked in the synopsis.
if {![dict get $pstatus ok] && [dict get $pstatus failureclass] in {noformmatch multipleformmatches}} {
dict set nextopts -form [dict keys [dict get $pstatus formstatus]]
} else {
dict set nextopts -form [dict get $pstatus form]
}
if {$opt_return eq "dict"} {
if {$scheme_received} {
dict set pstatus scheme [dict get $opts -scheme]
} elseif {![dict get $pstatus ok] && ![llength $queryargs]} {
dict set pstatus scheme info
}
return [dict create origin $rootorigin docid $rootdoc cmdtype $rootorigintype args_remaining $queryargs parsestatus $pstatus]
}
@ -5623,11 +5725,6 @@ y" {return quirkykeyscript}
dict set nextopts -scheme info
}
set result [punk::args::arg_error "" [punk::args::get_spec $rootdoc] {*}$nextopts -aserror 0 -parsestatus $pstatus]
} elseif {![llength $queryargs]} {
if {!$scheme_received} {
dict set nextopts -scheme info
}
set result [punk::args::arg_error "" [punk::args::get_spec $rootdoc] {*}$nextopts -aserror 0]
} else {
set result [punk::args::arg_error [dict get $pstatus message] [punk::args::get_spec $rootdoc] {*}$nextopts -aserror 0 -parsestatus $pstatus]
}
@ -5712,15 +5809,27 @@ y" {return quirkykeyscript}
#-errorstyle minimal so no usage table is built inside a discarded error and
#dynamically updated ensembles are reflected).
set pstatus [punk::args::parse_status $args_remaining -form $opt_form -caller $caller_display withid $origindoc]
#With NO supplied trailing args a failure only reflects missing required
#leaders/values (e.g 'i string is') - nothing to mark and nothing wrong with the
#user's (absent) input, so we show plain usage in the info scheme instead of the
#internal-looking parse error (G-046 item 5).
#A failing advisory parse renders with the error scheme and its message even
#when NO trailing args were supplied: 'i if' indicating "Bad number of
#trailing values for if. Got 0 values. Expected at least 2" is useful signal
#that the command cannot be called bare. (History: G-046 item 5 suppressed
#this path because the pre-G-049 message was internal-looking - "for
#punk::args::parse $args_remaining" - but the G-049 -caller attribution made
#the messages accurate, so the suppression was reversed 2026-07-12 by user
#direction, restoring the pre-G-046 indication with the improved messages.)
#G-041: render the usage for the form the advisory parse selected (the
#matched or best-candidate form within the caller's -form selection); for a
#no-form-match pass every ranked candidate and for an ambiguous match every
#matching form - the first form's argument table renders and all passed
#forms are marked in the synopsis.
if {![dict get $pstatus ok] && [dict get $pstatus failureclass] in {noformmatch multipleformmatches}} {
dict set nextopts -form [dict keys [dict get $pstatus formstatus]]
} else {
dict set nextopts -form [dict get $pstatus form]
}
if {$opt_return eq "dict"} {
if {$scheme_received} {
dict set pstatus scheme [dict get $opts -scheme]
} elseif {![dict get $pstatus ok] && ![llength $args_remaining]} {
dict set pstatus scheme info
}
return [dict create origin $origin docid $origindoc cmdtype $origintype args_remaining $args_remaining parsestatus $pstatus]
}
@ -5730,11 +5839,6 @@ y" {return quirkykeyscript}
dict set nextopts -scheme info
}
set result [punk::args::arg_error "" [punk::args::get_spec $origindoc] {*}$nextopts -aserror 0 -parsestatus $pstatus]
} elseif {![llength $args_remaining]} {
if {!$scheme_received} {
dict set nextopts -scheme info
}
set result [punk::args::arg_error "" [punk::args::get_spec $origindoc] {*}$nextopts -aserror 0]
} else {
set result [punk::args::arg_error [dict get $pstatus message] [punk::args::get_spec $origindoc] {*}$nextopts -aserror 0 -parsestatus $pstatus]
}
@ -7657,6 +7761,6 @@ namespace eval ::punk::args::register {
## Ready
package provide punk::ns [tcl::namespace::eval punk::ns {
variable version
set version 0.2.0
set version 0.5.0
}]
return

15
src/vfs/_vfscommon.vfs/modules/punk/repl-0.5.0.tm → src/vfs/_vfscommon.vfs/modules/punk/repl-0.5.1.tm

@ -634,12 +634,16 @@ proc repl::start {args} {
#thread busy-loops on the persistent error - an orphaned shell would spin CPU forever.
#Poll liveness on the process console so the repl can finish via the normal eof path.
#Armed only for a tcl9 console channel (-inputmode present) on the process-default
#console; piped/foreign/8.6 inputs are unaffected.
#console; piped/foreign/8.6 inputs are unaffected. The version gate (G-076) is
#punk::lib::check::has_tclbug_console_deadspin - shared with the 'help tcl' warning -
#so runtimes at or past a verified fixed Tcl release (check::tclbug_console_deadspin_fixed_in)
#don't arm the probe.
variable console_watchdog_afterids
variable console_watchdog_ms
set watchdog_chan ""
if {"windows" eq $::tcl_platform(platform) && [console_is_default]
&& ![info exists console_watchdog_afterids($inchan)]} {
&& ![info exists console_watchdog_afterids($inchan)]
&& [dict get [punk::lib::check::has_tclbug_console_deadspin] bug]} {
if {![catch {chan configure $inchan} wdconf] && [dict exists $wdconf -inputmode]} {
set watchdog_chan $inchan
set console_watchdog_afterids($inchan) [after $console_watchdog_ms [list [namespace current]::console_watchdog $inchan]]
@ -983,7 +987,10 @@ namespace eval repl::argdoc {
Armed by repl::start only for a tcl9 console channel (-inputmode present
in the chan configure dict) serving the process-default console on
windows. Scheduling state is kept per channel name in
windows, and only while punk::lib::check::has_tclbug_console_deadspin
reports the runtime affected (G-076 shared version gate - a Tcl release
containing the verified upstream fix for ticket f10d91c2d3 arms nothing).
Scheduling state is kept per channel name in
repl::console_watchdog_afterids; a watchdog whose channel has
disappeared disarms itself silently."
@values -min 1 -max 1
@ -4518,7 +4525,7 @@ namespace eval ::punk::args::register {
package provide punk::repl [namespace eval punk::repl {
variable version
set version 0.5.0
set version 0.5.1
}]
#repl::start $program_read_stdin_pipe
Loading…
Cancel
Save