Browse Source

G-118 item 10: launch subcommand family docs as punk::args definitions (moduledoc punkexe)

New punk::args::moduledoc::punkexe 0.1.0: (script)::punkexe dispatch
definition (package modes, subcommand enumeration, default reclassification)
+ (script)::punkexe::tclsh full contract (stock arg-form parity incl the
deliberate no -e boundary (G-077), lib: refusal, piperepl ::tclsh state
array + env gates, intended divergences recorded per item decisions 2/6/8)
+ summary definitions for script/shell/punk/shellspy. G-032-compatible: the
launcher help/parse wiring renders from these ids later.

punk::args 0.12.7: update_definitions handles tag-prefixed id namespaces
first-class - namespace_docpackages consulted with the tagged key (usage/
real_id on registered-but-unloaded (script)::* ids no longer no-such-id),
generic tag strip for the real-namespace probes, unqualified-ns warning no
longer fires for tag ids. args/ns/repl suites 352 pass 0 fail.

punk::repl 0.5.3: code-interp setup catch-requires the punkexe moduledoc
beside tclcore (both sites) so the docs are queryable in any punk shell.

ARCHITECTURE.md: tclsh subcommand bullet in the boot/launch chain
(architecture_lint clean). punkproject 0.20.1 + CHANGELOG.

Verified: fresh-interp usage-first render (real_id path); rebuilt punk902z
kit self-carries 0.1.0 (5298-char tclsh render); piped punk session renders
(script)::punkexe with no manual require.

Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
Julian Noble 1 week ago
parent
commit
f5deb4d1b8
  1. 1
      ARCHITECTURE.md
  2. 19
      CHANGELOG.md
  3. 23
      goals/G-118-tclsh-subcommand-review.md
  4. 2
      punkproject.toml
  5. 22
      src/modules/punk/args-999999.0a1.0.tm
  6. 3
      src/modules/punk/args-buildversion.txt
  7. 343
      src/modules/punk/args/moduledoc/punkexe-999999.0a1.0.tm
  8. 3
      src/modules/punk/args/moduledoc/punkexe-buildversion.txt
  9. 2
      src/modules/punk/repl-999999.0a1.0.tm
  10. 3
      src/modules/punk/repl-buildversion.txt
  11. 28
      src/vfs/_vfscommon.vfs/modules/punk/args-0.12.7.tm
  12. 343
      src/vfs/_vfscommon.vfs/modules/punk/args/moduledoc/punkexe-0.1.0.tm
  13. BIN
      src/vfs/_vfscommon.vfs/modules/punk/mix/templates-0.2.0.tm
  14. 4
      src/vfs/_vfscommon.vfs/modules/punk/repl-0.5.3.tm

1
ARCHITECTURE.md

@ -46,6 +46,7 @@ app package from src/lib/ (app-punkshell, app-punkscript, app-repl, app-shellsp
- **Package modes pick module provenance.** `internal` uses module snapshots baked into the kit at build time; `dev` loads build outputs from repo-root `modules/` and `lib/`; `src` loads the unbuilt working tree (`src/modules`, `src/lib`, `src/bootsupport`, `src/vendormodules`) with `package prefer latest` so magic-version dev modules (`999999.0a1.0`) beat stamped snapshots. `src` mode is the standard way to verify working-tree changes without a rebuild. Source: `bin/AGENTS.md` "Launch package modes".
- **Static package capture (G-058, achieved).** Boot probe-loads the runtime's statically linked packages in a throwaway interp and records what each provides; every interp the shell fabricates (boot, codethread, shellthread workers) seeds `package ifneeded <name> <ver> {load {} <prefix>}` from that record, and `punk::packagepreference` resolves static-vs-bundled version-aware. Sources: `src/vfs/AGENTS.md`, `goals/archive/G-058-static-runtime-packages.md`.
- **`script` subcommand (G-015, achieved).** The lean non-interactive path: default punk shell module/alias environment, no shellfilter stacks/transforms, honest exit codes, launch plumbing emits nothing on stdout/stderr (exec-style callers see only the script's own output). Supports `lib:<name>` scriptlib resolution. App package: `src/lib/app-punkscript/`.
- **`tclsh` subcommand (G-118).** Plain-tclsh emulation with NO punk modules loaded: stock argument-form parity (`-encoding name file`; any other leading `-` argument means no script, everything stays in `::argv`; no `-e` one-liner - deliberate stock parity, see G-077 for the punk-level one-liner direction), `lib:` refused with a pointer at `script`, missing script file is a clean exit 1. On piperepl-patched runtimes (the punk family runtimes - `src/buildsuites/suite_tcl90/patches/`) the C-level machinery publishes `::tclsh` launch state (`istty`, `dorepl`, `evalinput`, `inputbuffer`, `reopened`) allowing piped input to hand over to a live console repl at eof; runtimes without the machinery evaluate piped stdin whole-buffer with honest exit codes and fail fast on console stdin. The subcommand-family contract (tclsh/script/shell/punk/shellspy) is documented as punk::args definitions in `src/modules/punk/args/moduledoc/punkexe-999999.0a1.0.tm` (ids `(script)::punkexe` + per-subcommand; view via `punk::args::usage`), consumable by the future launcher help wiring (G-032). Pipe-testable behaviour pinned by `src/tests/shell/testsuites/punkexe/tclshcmd.test`.
- **`bin/` launch surface.** Built kits plus polyglot `.cmd` utilities (`punk-runtime`, `punk-getzig`, `punk-tclargs`, `dtplite`) generated from `src/scriptapps/` sources by the `punk::mix` scriptwrap machinery - outputs are never hand-edited. `bin/punk-runtime.cmd` fetches/lists/selects plain runtimes under `bin/runtime/<platform>/` from the punkbin artifact server with sha1 verification. Source: `bin/AGENTS.md`.
## Interp and thread topology

19
CHANGELOG.md

@ -5,6 +5,25 @@ The latest `## [X.Y.Z]` header must match the `version` field in `punkproject.to
Entries are newest-first; one bullet per notable change. See the root `AGENTS.md`
"Project Versioning" section for the bump policy.
## [0.20.1] - 2026-07-25
- Launch subcommand family documentation (G-118 item 10): new module
`punk::args::moduledoc::punkexe` carries the punk executable launch contract as punk::args
definitions - ids `(script)::punkexe` (dispatch: package modes, subcommand enumeration,
default script/shell reclassification) and `(script)::punkexe::tclsh/script/shell/punk/shellspy`.
The tclsh definition is the full contract: stock argument-form parity (incl. the deliberate
no `-e` one-liner boundary), `lib:` refusal, piperepl `::tclsh` launch-state array
(istty/dorepl/evalinput/inputbuffer/reopened) and env gates, plus the intended divergences
(early `tcl_interactive` link; whole-buffer piped eval with honest exit codes on
machinery-less runtimes). View via `punk::args::usage {(script)::punkexe}` in any punk shell
(repl code-interp setup loads the module; punk::repl 0.5.3). Authored G-032-compatible: the
future launcher help/parse wiring renders from these definitions.
- punk::args 0.12.7: tag-prefixed id namespaces (`(script)::...`, `(autodef)::...`) resolve
first-class in `update_definitions` - `punk::args::usage` on a registered-but-unloaded
script-level id no longer errors `no such id`, and the spurious
`warning: update_definitions received unqualified ns: (script)` stderr noise is gone.
- ARCHITECTURE.md: `tclsh` subcommand bullet added to the boot/launch chain section.
## [0.20.0] - 2026-07-24
- `tclsh` subcommand review fixes (G-118 items 3/4/5/9): no-script forms set `::argv0` to the

23
goals/G-118-tclsh-subcommand-review.md

@ -43,4 +43,25 @@ All 11 items dispositioned by the user 2026-07-24 (activation session). Items 1
- 2026-07-24 items 3/4/5/9 LANDED (punkproject 0.20.0): no-script forms set ::argv0 to [info nameofexecutable] (both repl and piped-eval paths); missing script file pre-checked with clean not-found + exit 1; machinery-absent console stdin fails fast via the app-punkscript terminal probe (piped degraded eval unchanged; patch-missing notice reworded to "note:", deliberate TCLSH_PIPEREPL=0 opt-out now quiet, old debug lines deleted); project_main.tcl carries the full mirrored dispatch (script-arg/dash/-encoding/lib: forms - previously single-arg-only with stale gate default) and both layout _config copies byte-synced. Verified: all mapvfs kits rebuilt; tclshcmd.test extended to 19 (tclsh_noscript_argv0, tclsh_script_notfound); shell/*** suite 64 pass / 2 goal-gated skips / 0 fail.
- 2026-07-24 overlap reconciliation (user-prompted review): cross-references recorded with G-025 (kit-layer stamp counterpart - see G-117 Notes for the record-survives-kit-wrap + filename-namespacing considerations), G-032 (item 10 refined: docs authored as G-032-compatible punk::args definitions), G-031 (item 9 duplication interim), G-077 (tclsh -e boundary note).
- 2026-07-24 items 1 + 7 LANDED and verified (G-117 cycle suite rebuild): reopen notice now TCLSH_PIPEREPL_DEBUG-gated with all reopen-path messages on stderr; ::tclsh(reopened) published (family_check gate probe asserts 0 at gate-open start / absent on plain+opt-out on all three family members; tclshcmd.test tclsh_pr_noarg_machinery pins it against the rebuilt punk9_beta). The console-reopen FLIP to 1 and the notice's console-side silence remain item-11 console-harness verification.
- Remaining for acceptance: item 10 definitions (G-032-compatible) also carrying the documented-as-intended records (items 2, 6, 8) and the G-077 boundary; console-driven test (item 11); ARCHITECTURE.md tclsh-subcommand bullet rides the item-10 docs change-set.
- 2026-07-25 item 10 LANDED (punkproject 0.20.1): launch-subcommand-family documentation
authored as G-032-compatible punk::args definitions in NEW module
punk::args::moduledoc::punkexe (0.1.0; deferred PUNKARGS registration, argdoc child,
make.tcl (script)::punkboot id convention): (script)::punkexe top-level (package-mode
leader documented in help text, subcommand enumeration with choicelabels, default
script/shell reclassification) + (script)::punkexe::tclsh full contract (multi-form
scriptfile/stdin with explicit synopses) + summary-level script/shell/punk/shellspy
definitions. The tclsh definition carries the documented-as-intended records: item 2
(early tcl_interactive link + load-bearing write path), item 6 (whole-buffer piped
eval with honest exit codes on machinery-less runtimes, per-command C repl loop with
machinery), item 8 (istty read-only by convention, no trace), and the G-077 boundary
(no -e one-liner - deliberate stock parity inside this subcommand). Supporting work:
punk::args 0.12.7 update_definitions handles tag-prefixed id namespaces first-class
(namespace_docpackages consulted with the tagged key; punk::args::usage on
(script)::* ids no longer errors no-such-id; spurious unqualified-ns stderr warning
gone - args/ns/repl suites 352 pass 0 fail); punk::repl 0.5.3 loads the module
catch-guarded at both code-interp setup sites (docs queryable in any punk shell);
ARCHITECTURE.md boot/launch tclsh-subcommand bullet added (architecture_lint clean).
Verified: usage-first render in fresh interp (real_id path), src + rebuilt-kit
(punk902z script probe: 0.1.0, 5298-char tclsh render) + repl-wired (piped punk
session renders (script)::punkexe without manual require).
- Remaining for acceptance: console-driven test (item 11).

2
punkproject.toml

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

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

@ -4765,8 +4765,26 @@ tcl::namespace::eval punk::args {
} else {
set needed [list]
foreach pkgns $nslist {
if {[string match (autodef)* $pkgns]} {
set pkgns [string range $pkgns 9 end]
if {[string match {(*)*} $pkgns]} {
#tag-prefixed id 'namespace' e.g (autodef)::myensemble, or a
#script-level id family e.g (script)::punkboot, (script)::punkexe.
#Not a real namespace: the scan records documenting packages under
#the TAGGED key (namespace qualifiers of the tagged id), so consult
#namespace_docpackages with the original key first, then strip the
#tag for the real-namespace probes below ((autodef) ids also map to
#a real namespace; a bare tag or tag-only qualifier has nothing more
#to probe).
if {[dict exists $namespace_docpackages $pkgns]} {
foreach docns [dict get $namespace_docpackages $pkgns] {
if {$docns ni $loaded_packages && $docns ni $needed} {
lappend needed $docns
}
}
}
set pkgns [string range $pkgns [expr {[string first ) $pkgns]+1}] end]
if {$pkgns eq ""} {
continue
}
}
if {![string match ::* $pkgns]} {
puts stderr "warning: update_definitions received unqualified ns: $pkgns"

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

@ -1,6 +1,7 @@
0.12.6
0.12.7
#First line must be a semantic version number
#all other lines are ignored.
#0.12.7 - update_definitions: tag-prefixed id 'namespaces' ((autodef)::x plus script-level id families like (script)::punkboot / (script)::punkexe - the make.tcl G-030 convention, now also the launch-dispatch doc home per G-118 item 10) are handled first-class in the nslist walk. Previously only the (autodef) tag was stripped; other tags fell through to the unqualified-ns branch, emitting a spurious "warning: update_definitions received unqualified ns: (script)" on stderr for EVERY id query and probing a garbage ::(script)... namespace - and, decisively, the namespace_docpackages association was never consulted with the TAGGED key the scan records, so real_id/usage on a registered-but-not-yet-loaded script-level id returned ""/no-such-id even though get_spec resolved it. Now: docpackages lookup with the original tagged key (loads the documenting package - punk::args::usage works for (script)::punkexe::* ids on first query), then generic tag strip for the real-namespace probes, with a bare/tag-only qualifier skipping them silently. Real unqualified namespaces still warn.
#0.12.6 - arg_error error-message placement (user direction 2026-07-18): the supplied error message and any per-form match detail it carries ("Bad arguments ... Candidate forms ..." + per-form failure lines) now render exactly once, BELOW the usage display, for both the table and string return forms. Previously the block rendered above the usage AND was appended again below it (the historical "put original error at bottom of table too"), duplicating potentially long multi-form detail. The bottom append is also now suppressed when the message is empty (usage-only calls no longer gain a trailing newline + empty line). tableobject returns are unchanged (they never carried the message). Also (same user direction, format explicitly not frozen - no external consumers yet): the string renderer's argument rows are now single-line 'name TYPE:... ?DEFAULT:...? ?MULTI:yes?' - the multi-line table-cell type constraints (-minsize/-maxsize/-range(s), previously line-broken mid-row so DEFAULT:/MULTI: landed glued to the last constraint line, e.g 'i -return string dict filter' arg vars) parenthesize onto the base type as TYPE:list(-minsize 2 -maxsize 2), empty DEFAULT/MULTI fields are omitted instead of rendering empty labels (MULTI shows 'yes' rather than the check glyph), and whitespace-only help blocks no longer emit indented filler lines. The <unnamed>/arbitrary-flag indicator rows get the same DEFAULT-omission. Choices also gain structure in the string renderer (previously a flat join left choice names and multi-line choicelabels at inconsistent depths, machine-indistinguishable once ANSI is stripped - only the table/ANSI prefix highlighting disambiguated): each choice renders as a markdown-subset bullet '- `choice`' at fixed indent 6 (the backticked token may carry a trailing choiceinfo marker glyph), the label's first line follows the closing backtick on the bullet line after ' - ', label continuations indent to 8 (2 past the bullet dash), and groups head their bullets as "Group 'name':". The resulting structural contract for parsers: column-0 lines bearing TYPE: are argument rows, indented lines are documentation, '- `...`' bullets are choices. Table cells unchanged (construction shared, restructure applied at the string-path consumption site). Feeds punk::ns 0.9.0 cmdhelp -return text (LLM-oriented plain text). Pinned in rendering.test (rendering_stringmode_singleline_argrows, rendering_stringmode_choice_bullets); errorselection.test message pins gained leading * (message no longer starts the raised string); cmdhelp.test message pins sample the last line. No API change.
#0.12.5 - eg usability: punk::args::eg resolves relative/unqualified command names (via punk::ns::cmdinfo from the calling context when punk::ns is loaded - handles subcommand words too - else global qualification). Rationale: in a namespace where punk::args::eg shadows the global 'eg' alias (e.g whilst in ::punk::args itself) 'eg list' hit the raw-id API and returned empty while 'i list' resolved - Tcl name resolution, not an alias deficiency. Unknown ids now return a message naming the id instead of empty; punk::ns::eg hands the typed name through when resolution yields no docid so the message can name it. The usage-table 'Example: eg <id>' header row (the short indication an @examples block exists) now uses scheme colour CLR(check) instead of hardcoded white - the raw id is kept (not @cmd -name, which is display text and not always invocable e.g 'Autoloading Built-in: parray'); a frame-embedded bottom-right marker awaits textblock table footer-block support (candidate goal). New examples.test pins: relative-name resolution, unknown-id message.
#0.12.5 - synopsis notation documented + internal @form -synopsis overrides retired. ::punk::args::parse and ::parse_status dropped their @form -synopsis overrides - they had gone stale (omitted -cache/-caller) and their only added value (the -form member hint) is now expressed properly via -typesynopsis {<int|formname>...} on the -form option; the auto-generated lines stay current as options are added (drift pin: synopsis.test synopsis_parse_generated). @form -synopsis remains fully supported for documentors: define's directive help now documents that it is display-only text needing no Tcl-list validity, that display helpers substitute the command head, and the known warranted case (script-level/constructed ids rendering the raw id - the G-030 lesson recorded in src/modules/AGENTS.md; head-render preference for @cmd -name remains an open generation deficiency). ::punk::args::synopsis -help gains a notation legend ([...] optional, italic argname/<type> placeholders, unitalicised literals, (a|b) alternate grouping to disambiguate from -f|--file alias pipes, {a b} multi-word literal protection, --opt=<type>, text*/*text) and a new @examples block comparing Tcl man-page ?...? style (ambiguous when nested - same delimiter both ends) with the bracket style, viewable via punk::args::eg. New synopsis.test pins: non-list custom -synopsis passthrough + ns head-replacement survival, parse generated-line drift pin, examples block presence.

343
src/modules/punk/args/moduledoc/punkexe-999999.0a1.0.tm

@ -0,0 +1,343 @@
# -*- tcl -*-
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt
# module template: punkshell/src/decktemplates/vendor/punk/modules/template_module-0.0.3.tm
#
# Please consider using a BSD or MIT style license for greatest compatibility with the Tcl ecosystem.
# Code using preferred Tcl licenses can be eligible for inclusion in Tcllib, Tklib and the punk package repository.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# (C) 2026
#
# @@ Meta Begin
# Application punk::args::moduledoc::punkexe 999999.0a1.0
# Meta platform tcl
# Meta license BSD
# @@ Meta End
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin punkshell_module_punk::args::moduledoc::punkexe 0 999999.0a1.0]
#[copyright "2026"]
#[titledesc {punk executable launch documentation}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]
#[require punk::args::moduledoc::punkexe]
#[keywords module launch subcommand tclsh]
#[description]
#[para] punk::args definitions documenting the punk executable launch dispatch
#[para] (the subcommand family implemented in the kit boot script src/vfs/_config/punk_main.tcl)
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Overview]
#[para] These definitions are the documentation home for the launch subcommand
#[para] family of the punk executables: tclsh, script, shell, punk, shellspy
#[para] (G-118 item 10). They are authored to be consumable by the future
#[para] launcher help/parse wiring (goal G-032) - rendering, option parsing and
#[para] degradation wiring stay with that goal. Id convention follows the
#[para] make.tcl precedent for script-level surfaces: (script)::punkexe and
#[para] (script)::punkexe::<subcommand>, with explicit @form -synopsis overrides
#[para] since a constructed id is not an invocable command name.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection dependencies]
#[para] packages used by punk::args::moduledoc::punkexe
#[list_begin itemized]
package require Tcl 8.6-
#*** !doctools
#[item] [package {Tcl 8.6}]
#*** !doctools
#[list_end]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section API]
tcl::namespace::eval punk::args::moduledoc::punkexe {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection {Namespace punk::args::moduledoc::punkexe}]
#[para] punk::args definitions for the punk executable launch dispatch
#[list_begin definitions]
variable PUNKARGS
namespace eval argdoc {
#Top-level launch dispatch (kit boot script punk_main.tcl, mirrored in
#project_main.tcl for generated projects). Display-first definitions:
#the dispatch itself does not parse via punk::args yet (goal G-032).
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe
@cmd -name punkexe\
-summary\
"punk executable launch: package modes and subcommand dispatch."\
-help\
"Launch surface of the punk shell executables ('<punkexe>' below
stands for any punk kit executable, e.g punk905, or a generated
project's kit).
An optional FIRST argument selects package modes: one or more of
the tokens dev, os, src, internal joined with '-' when combined
(e.g 'dev', 'src', 'dev-src'). Modes decide which module sources
the shell trusts and their precedence; 'internal' (kit-bundled
modules) is always appended when absent. Details: bin/AGENTS.md
'launch package modes' in the punkshell source tree.
The next argument selects a subcommand from the choices below.
When the first non-mode argument is not a known subcommand:
with no arguments at all the interactive punk shell is launched
('shell'); any other first argument is treated as a script
invocation (handled as for the 'script' subcommand)."
@form -synopsis "<punkexe> ?packagemode? ?subcommand? ?arg ...?"
@leaders -min 0 -max 1
subcommand -type string -optional 1 -choicerestricted 0 -choices {tclsh script shell punk shellspy} -choicelabels {
tclsh
" Run as a (near) stock tclsh - no punk modules loaded."
script
" Run a script non-interactively in the punk script environment; honest exit codes."
shell
" Interactive punk shell (repl); can run a script first and stay interactive."
punk
" punk shell launch; piped-stdin friendly (echo cmds | <punkexe> punk)."
shellspy
" Experimental shellspy command-line processor."
} -help\
"Subcommand to run. Each subcommand's own contract is documented
under its definition id (script)::punkexe::<subcommand>."
@values -min 0 -max -1
arg -type any -optional 1 -multiple 1 -help\
"Arguments for the selected subcommand."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
#tclsh subcommand: full contract (G-118). The documented-as-intended
#divergences below record G-118 item decisions: item 2 (tcl_interactive
#early link), item 6 (piped whole-buffer eval + honest exit codes),
#item 8 (istty read-only by convention). The 'no -e one-liner' note is
#the G-077 boundary: stock parity INSIDE this subcommand is deliberate;
#one-liner affordances belong to the top-level/'script' surfaces (G-077).
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe::tclsh
@cmd -name "punkexe tclsh"\
-summary\
"Run the punk executable as a (near) stock tclsh - no punk modules."\
-help\
"Run the executable as a plain tclsh: no punk modules are loaded
and behaviour matches stock 'tclsh' as closely as the kit boot
allows. The subcommand is an EXTENSION of standard tclsh
behaviour, not an exact emulator - the divergences are listed
below and are intended.
Stock argument-form parity (tclMain.c): the only recognised
leading option is '-encoding name scriptfile', and only when
scriptfile does not itself begin with '-'. Any other leading '-'
argument means NO script file: all arguments stay in ::argv and
input comes from stdin. In particular there is no -e/-c
one-liner flag - '<punkexe> tclsh -e (script)' puts '-e' and the
script text into ::argv and reads stdin, exactly like stock
tclsh. That parity is deliberate; one-liner affordances belong
to the punk-level launch surfaces, not this subcommand.
A scriptfile of the form 'lib:name' is refused with a pointer to
the 'script' subcommand: scriptlib resolution is a punk
facility and the tclsh subcommand keeps plain-tclsh semantics.
A missing scriptfile is a clean error (exit 1); errors raised by
an existing script keep their full trace.
Piperepl runtimes: kits on a 'punk' family runtime carry the
TCLSH_PIPEREPL patch (disable with env TCLSH_PIPEREPL=0; a kit
on an unpatched runtime notes the missing patch on stderr for
the forms that would use it). With the gate open the runtime
publishes launch state in the ::tclsh array before any script
runs:
istty launch-time fact: was stdin a tty? Never updated
afterwards (still 0 after a console reopen).
Read-only by convention - no readonly trace is
installed; a script write corrupts the
Tcl-visible value without affecting behaviour.
Its existence is also the patch-presence probe.
dorepl linked control: a script (or piped input) sets
this to 1 to enter the interactive repl after
the script/stdin completes - on piped launches
stdin is reopened from the console (CONIN$ on
windows, /dev/tty elsewhere).
evalinput linked control: piped input a script-arg run
did not consume is BUFFERED, not evaluated,
unless the script sets evalinput to 1.
inputbuffer set at console reopen: holds the unconsumed
piped input.
reopened 0 at gate-open startup; republished as 1 after
a successful console reopen.
Env TCLSH_PIPEREPL_DEBUG=1 enables patch diagnostics on stderr
(e.g the console-reopen notice, silent by default).
Intended divergences from stock tclsh:
- tcl_interactive: with the piperepl gate open it is linked
to the tty flag BEFORE the startup script runs; a
script-arg launch from a console therefore reads 1 where
stock reads 0 (piped launches read 0 either way). The
early link is load-bearing: a piped script that sets
dorepl writes ::tcl_interactive to opt into prompts/echo
in the reopened repl.
- piped no-arg evaluation WITHOUT the machinery (unpatched
runtime, or TCLSH_PIPEREPL=0): stdin is read to eof and
evaluated as one script - output appears at eof on slow
pipes, a mid-script error aborts the remainder, and the
exit code is honest (nonzero on error) where stock tclsh
streams per command, continues after errors and exits 0.
(With the machinery present, evaluation is the stock
per-command repl loop.) On machinery-less runtimes the
interactive form (console stdin, no script) fails fast
with a usage error instead of blocking in a console read."
@form -form {scriptfile} -synopsis "<punkexe> tclsh ?-encoding name? scriptfile ?arg ...?"
@leaders -min 0 -max 0
@opts
-encoding -type string -optional 1 -typesynopsis name -help\
"Encoding used to read scriptfile (as for 'source -encoding').
Recognised only immediately after 'tclsh' and only when the
following argument does not begin with '-'; an incomplete
-encoding form falls through to the no-script form (stock
behaviour)."
@values -min 1 -max -1
scriptfile -type string -optional 0 -help\
"Script file to source and exit. ::argv0 and 'info script' are
the (normalized) script path; remaining args are ::argv. The
script may set ::tclsh(dorepl) 1 (piperepl runtimes) to enter
the interactive repl after it completes."
arg -type any -optional 1 -multiple 1 -help\
"Arguments passed to the script in ::argv."
@form -form {stdin} -synopsis "<punkexe> tclsh ?arg ...?"
@values -min 0 -max -1
arg -type any -optional 1 -multiple 1 -help\
"With no script file all arguments (including any leading '-'
arguments) stay in ::argv; ::argv0 is the executable path.
Input comes from stdin: the interactive repl on a console
(piperepl runtimes), evaluation of piped input otherwise."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
#Sibling subcommands: summary-level contracts. Deep punk::args parse
#definitions for these surfaces are G-032's lane ('script' is its
#natural first parsed subcommand).
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe::script
@cmd -name "punkexe script"\
-summary\
"Run a script non-interactively in the punk script environment."\
-help\
"Run a Tcl script and exit with an honest exit code
(app-punkscript): script errors exit nonzero and the launch
plumbing emits nothing of its own on stdout/stderr, so
exec-style callers see only the script's output. The default
punk module/alias environment is loaded (unlike 'tclsh').
The script comes from the file argument, from piped stdin when
no argument is given (terminal stdin without a script argument
is a usage error - no interactive fallback), or via scriptlib
resolution when the argument has the form 'lib:name' (resolved
from the scriptlib locations associated with the executable,
including extensionless and shebang'd scripts)."
@form -synopsis "<punkexe> script ?scriptfile|lib:name? ?arg ...?"
@values -min 0 -max -1
scriptfile -type string -optional 1 -help\
"Script file path, or lib:name for scriptlib resolution.
Omitted: the script is read from piped stdin."
arg -type any -optional 1 -multiple 1 -help\
"Arguments passed to the script in ::argv."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe::shell
@cmd -name "punkexe shell"\
-summary\
"Interactive punk shell (repl)."\
-help\
"Launch the interactive punk shell (app-punkshell). With
arguments, a script can be run first with the interactive
shell maintained afterwards. This is also the default when the
executable is launched with no arguments at all."
@form -synopsis "<punkexe> shell ?arg ...?"
@values -min 0 -max -1
arg -type any -optional 1 -multiple 1 -help\
"Arguments passed through to the shell launch."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe::punk
@cmd -name "punkexe punk"\
-summary\
"punk shell launch; piped-stdin friendly."\
-help\
"Launch the punk shell. With arguments the app-punkshell launch
path is used (as for 'shell'); without arguments the
interactive shell is launched directly. Commands piped into
stdin are supported (e.g: echo 'puts hello' | <punkexe> punk)
and stderr is kept clean of launch chatter so exec-style
callers do not misreport failure."
@form -synopsis "<punkexe> punk ?arg ...?"
@values -min 0 -max -1
arg -type any -optional 1 -multiple 1 -help\
"Arguments passed through to the shell launch."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe::shellspy
@cmd -name "punkexe shellspy"\
-summary\
"Experimental shellspy command-line processor."\
-help\
"Pass all arguments to the experimental shellspy command-line
processor (app-shellspy). Note: 'shellspy' is only this launch
subcommand - it is not the project name (the project is
punkshell)."
@form -synopsis "<punkexe> shellspy ?arg ...?"
@values -min 0 -max -1
arg -type any -optional 1 -multiple 1 -help\
"Arguments for the shellspy processor."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
}
#*** !doctools
#[list_end] [comment {--- end definitions namespace punk::args::moduledoc::punkexe ---}]
}
# -----------------------------------------------------------------------------
# register namespace(s) to have PUNKARGS,PUNKARGS_aliases variables checked
# -----------------------------------------------------------------------------
# variable PUNKARGS
# variable PUNKARGS_aliases
namespace eval ::punk::args::register {
#use fully qualified so 8.6 doesn't find existing var in global namespace
lappend ::punk::args::register::NAMESPACES ::punk::args::moduledoc::punkexe ::punk::args::moduledoc::punkexe::argdoc
}
# -----------------------------------------------------------------------------
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready
package provide punk::args::moduledoc::punkexe [tcl::namespace::eval punk::args::moduledoc::punkexe {
variable pkg punk::args::moduledoc::punkexe
variable version
set version 999999.0a1.0
}]
return
#*** !doctools
#[manpage_end]

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

@ -0,0 +1,3 @@
0.1.0
#First line must be a semantic version number
#all other lines are ignored.

2
src/modules/punk/repl-999999.0a1.0.tm

@ -4290,6 +4290,7 @@ namespace eval repl {
package require punk::lib
package require punk::args
catch {package require punk::args::moduledoc::tclcore} ;#while tclcore is highly desirable, and should be installed with punk::args - it's not critical
catch {package require punk::args::moduledoc::punkexe} ;#launch subcommand family documentation (G-118) - not critical
package require textblock
}
@ -4470,6 +4471,7 @@ namespace eval repl {
catch {package require punk::args::moduledoc::parser}
#-----------
catch {package require punk::args::moduledoc::tclcore} ;#while tclcore is highly desirable, and should be installed with punk::args - it's not critical
catch {package require punk::args::moduledoc::punkexe} ;#launch subcommand family documentation (G-118) - not critical
} errM]} {
puts stderr "========================"
puts stderr "code interp error:"

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

@ -1,6 +1,7 @@
0.5.2
0.5.3
#First line must be a semantic version number
#all other lines are ignored.
#0.5.3 - code interp setup loads punk::args::moduledoc::punkexe (catch-guarded beside the tclcore moduledoc requires, both code-interp setup sites) so the launch subcommand family documentation ids ((script)::punkexe and (script)::punkexe::tclsh/script/shell/punk/shellspy - G-118 item 10) are queryable via punk::args::usage in any punk shell without a manual package require. Not critical - absence degrades silently like tclcore.
#0.5.2 - G-076: repl_handler now handles a dead console DELIVERED as a readable event (runtimes carrying the upstream f10d91c2d3 fix - first such 9.0-line version 9.0.5): the previously unguarded full 'chan configure' probe at handler entry errored ('couldn't read console mode: broken pipe'), backgrounding the error and leaving the repl idle with its reader inactive. The probe is now guarded, and terminal input loss routes through new repl::console_input_lost - the same teardown console_watchdog uses (cancel any watchdog schedule, deregister reader, close channel to stop the core reader thread, finish via the eof done-path; no reopen attempt). console_watchdog now shares this helper (probe unchanged, message unchanged). Verified with the G-039 kill procedure on a zig-built core-9-0-branch (9.0.5) runtime with the watchdog disarmed via the shipping gate: clean exit 0.2s after conhost kill through app-punkshell's no-console eof handling; pre-fix runtimes are unaffected (the defect never delivers the event - the watchdog remains their rescue path).
#0.5.2 - fixed the codethread seeding template in repl::start: it namespace-eval'd the full ::punk::nav::ns::ns_current VARIABLE name (creating a stray namespace of that name in every code interp - visible as a phantom 'ns_current' child when browsing the nav namespace with n/) instead of just ensuring the parent ::punk::nav::ns exists before setting the variable. Seeding semantics unchanged (the subshell namespace carry-over: a new codethread's code interp starts in the launching context's ns_current when it exists, else ::). Guarded by the new punk/repl testsuite repl/nscurrent.test (real codethread via repl::init driven with synchronous runscript sends: inscope evaluation of ns_current, retention across submissions, n/-navigation retained, auto-create-with-notice for a missing current namespace, stray-namespace absence, and a source-text guard on the template pending an end-to-end piped subshell test).
#0.5.1 - G-076: repl::start's dead-console watchdog arming now also requires punk::lib::check::has_tclbug_console_deadspin to report the runtime affected (shared version gate with the 'help tcl' warning; requires punk::lib 0.4.2+). Behaviour today is unchanged (gate variable check::tclbug_console_deadspin_fixed_in is empty = every Tcl 9 windows runtime affected); once a released Tcl containing the verified upstream fix for f10d91c2d3 is recorded there, such runtimes stop arming the watchdog.

28
src/vfs/_vfscommon.vfs/modules/punk/args-0.12.6.tm → src/vfs/_vfscommon.vfs/modules/punk/args-0.12.7.tm

@ -8,7 +8,7 @@
# (C) 2024
#
# @@ Meta Begin
# Application punk::args 0.12.6
# Application punk::args 0.12.7
# Meta platform tcl
# Meta license <unspecified>
# @@ Meta End
@ -18,7 +18,7 @@
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin punkshell_module_punk::args 0 0.12.6]
#[manpage_begin punkshell_module_punk::args 0 0.12.7]
#[copyright "2024"]
#[titledesc {args parsing}] [comment {-- Name section and table of contents description --}]
#[moddesc {args to nested dict of opts and values}] [comment {-- Description at end of page heading --}]
@ -4765,8 +4765,26 @@ tcl::namespace::eval punk::args {
} else {
set needed [list]
foreach pkgns $nslist {
if {[string match (autodef)* $pkgns]} {
set pkgns [string range $pkgns 9 end]
if {[string match {(*)*} $pkgns]} {
#tag-prefixed id 'namespace' e.g (autodef)::myensemble, or a
#script-level id family e.g (script)::punkboot, (script)::punkexe.
#Not a real namespace: the scan records documenting packages under
#the TAGGED key (namespace qualifiers of the tagged id), so consult
#namespace_docpackages with the original key first, then strip the
#tag for the real-namespace probes below ((autodef) ids also map to
#a real namespace; a bare tag or tag-only qualifier has nothing more
#to probe).
if {[dict exists $namespace_docpackages $pkgns]} {
foreach docns [dict get $namespace_docpackages $pkgns] {
if {$docns ni $loaded_packages && $docns ni $needed} {
lappend needed $docns
}
}
}
set pkgns [string range $pkgns [expr {[string first ) $pkgns]+1}] end]
if {$pkgns eq ""} {
continue
}
}
if {![string match ::* $pkgns]} {
puts stderr "warning: update_definitions received unqualified ns: $pkgns"
@ -14071,7 +14089,7 @@ package provide punk::args [tcl::namespace::eval punk::args {
tcl::namespace::path {::punk::args::lib ::punk::args::system}
variable pkg punk::args
variable version
set version 0.12.6
set version 0.12.7
}]
return

343
src/vfs/_vfscommon.vfs/modules/punk/args/moduledoc/punkexe-0.1.0.tm

@ -0,0 +1,343 @@
# -*- tcl -*-
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt
# module template: punkshell/src/decktemplates/vendor/punk/modules/template_module-0.0.3.tm
#
# Please consider using a BSD or MIT style license for greatest compatibility with the Tcl ecosystem.
# Code using preferred Tcl licenses can be eligible for inclusion in Tcllib, Tklib and the punk package repository.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# (C) 2026
#
# @@ Meta Begin
# Application punk::args::moduledoc::punkexe 0.1.0
# Meta platform tcl
# Meta license BSD
# @@ Meta End
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin punkshell_module_punk::args::moduledoc::punkexe 0 0.1.0]
#[copyright "2026"]
#[titledesc {punk executable launch documentation}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]
#[require punk::args::moduledoc::punkexe]
#[keywords module launch subcommand tclsh]
#[description]
#[para] punk::args definitions documenting the punk executable launch dispatch
#[para] (the subcommand family implemented in the kit boot script src/vfs/_config/punk_main.tcl)
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Overview]
#[para] These definitions are the documentation home for the launch subcommand
#[para] family of the punk executables: tclsh, script, shell, punk, shellspy
#[para] (G-118 item 10). They are authored to be consumable by the future
#[para] launcher help/parse wiring (goal G-032) - rendering, option parsing and
#[para] degradation wiring stay with that goal. Id convention follows the
#[para] make.tcl precedent for script-level surfaces: (script)::punkexe and
#[para] (script)::punkexe::<subcommand>, with explicit @form -synopsis overrides
#[para] since a constructed id is not an invocable command name.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection dependencies]
#[para] packages used by punk::args::moduledoc::punkexe
#[list_begin itemized]
package require Tcl 8.6-
#*** !doctools
#[item] [package {Tcl 8.6}]
#*** !doctools
#[list_end]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section API]
tcl::namespace::eval punk::args::moduledoc::punkexe {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection {Namespace punk::args::moduledoc::punkexe}]
#[para] punk::args definitions for the punk executable launch dispatch
#[list_begin definitions]
variable PUNKARGS
namespace eval argdoc {
#Top-level launch dispatch (kit boot script punk_main.tcl, mirrored in
#project_main.tcl for generated projects). Display-first definitions:
#the dispatch itself does not parse via punk::args yet (goal G-032).
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe
@cmd -name punkexe\
-summary\
"punk executable launch: package modes and subcommand dispatch."\
-help\
"Launch surface of the punk shell executables ('<punkexe>' below
stands for any punk kit executable, e.g punk905, or a generated
project's kit).
An optional FIRST argument selects package modes: one or more of
the tokens dev, os, src, internal joined with '-' when combined
(e.g 'dev', 'src', 'dev-src'). Modes decide which module sources
the shell trusts and their precedence; 'internal' (kit-bundled
modules) is always appended when absent. Details: bin/AGENTS.md
'launch package modes' in the punkshell source tree.
The next argument selects a subcommand from the choices below.
When the first non-mode argument is not a known subcommand:
with no arguments at all the interactive punk shell is launched
('shell'); any other first argument is treated as a script
invocation (handled as for the 'script' subcommand)."
@form -synopsis "<punkexe> ?packagemode? ?subcommand? ?arg ...?"
@leaders -min 0 -max 1
subcommand -type string -optional 1 -choicerestricted 0 -choices {tclsh script shell punk shellspy} -choicelabels {
tclsh
" Run as a (near) stock tclsh - no punk modules loaded."
script
" Run a script non-interactively in the punk script environment; honest exit codes."
shell
" Interactive punk shell (repl); can run a script first and stay interactive."
punk
" punk shell launch; piped-stdin friendly (echo cmds | <punkexe> punk)."
shellspy
" Experimental shellspy command-line processor."
} -help\
"Subcommand to run. Each subcommand's own contract is documented
under its definition id (script)::punkexe::<subcommand>."
@values -min 0 -max -1
arg -type any -optional 1 -multiple 1 -help\
"Arguments for the selected subcommand."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
#tclsh subcommand: full contract (G-118). The documented-as-intended
#divergences below record G-118 item decisions: item 2 (tcl_interactive
#early link), item 6 (piped whole-buffer eval + honest exit codes),
#item 8 (istty read-only by convention). The 'no -e one-liner' note is
#the G-077 boundary: stock parity INSIDE this subcommand is deliberate;
#one-liner affordances belong to the top-level/'script' surfaces (G-077).
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe::tclsh
@cmd -name "punkexe tclsh"\
-summary\
"Run the punk executable as a (near) stock tclsh - no punk modules."\
-help\
"Run the executable as a plain tclsh: no punk modules are loaded
and behaviour matches stock 'tclsh' as closely as the kit boot
allows. The subcommand is an EXTENSION of standard tclsh
behaviour, not an exact emulator - the divergences are listed
below and are intended.
Stock argument-form parity (tclMain.c): the only recognised
leading option is '-encoding name scriptfile', and only when
scriptfile does not itself begin with '-'. Any other leading '-'
argument means NO script file: all arguments stay in ::argv and
input comes from stdin. In particular there is no -e/-c
one-liner flag - '<punkexe> tclsh -e (script)' puts '-e' and the
script text into ::argv and reads stdin, exactly like stock
tclsh. That parity is deliberate; one-liner affordances belong
to the punk-level launch surfaces, not this subcommand.
A scriptfile of the form 'lib:name' is refused with a pointer to
the 'script' subcommand: scriptlib resolution is a punk
facility and the tclsh subcommand keeps plain-tclsh semantics.
A missing scriptfile is a clean error (exit 1); errors raised by
an existing script keep their full trace.
Piperepl runtimes: kits on a 'punk' family runtime carry the
TCLSH_PIPEREPL patch (disable with env TCLSH_PIPEREPL=0; a kit
on an unpatched runtime notes the missing patch on stderr for
the forms that would use it). With the gate open the runtime
publishes launch state in the ::tclsh array before any script
runs:
istty launch-time fact: was stdin a tty? Never updated
afterwards (still 0 after a console reopen).
Read-only by convention - no readonly trace is
installed; a script write corrupts the
Tcl-visible value without affecting behaviour.
Its existence is also the patch-presence probe.
dorepl linked control: a script (or piped input) sets
this to 1 to enter the interactive repl after
the script/stdin completes - on piped launches
stdin is reopened from the console (CONIN$ on
windows, /dev/tty elsewhere).
evalinput linked control: piped input a script-arg run
did not consume is BUFFERED, not evaluated,
unless the script sets evalinput to 1.
inputbuffer set at console reopen: holds the unconsumed
piped input.
reopened 0 at gate-open startup; republished as 1 after
a successful console reopen.
Env TCLSH_PIPEREPL_DEBUG=1 enables patch diagnostics on stderr
(e.g the console-reopen notice, silent by default).
Intended divergences from stock tclsh:
- tcl_interactive: with the piperepl gate open it is linked
to the tty flag BEFORE the startup script runs; a
script-arg launch from a console therefore reads 1 where
stock reads 0 (piped launches read 0 either way). The
early link is load-bearing: a piped script that sets
dorepl writes ::tcl_interactive to opt into prompts/echo
in the reopened repl.
- piped no-arg evaluation WITHOUT the machinery (unpatched
runtime, or TCLSH_PIPEREPL=0): stdin is read to eof and
evaluated as one script - output appears at eof on slow
pipes, a mid-script error aborts the remainder, and the
exit code is honest (nonzero on error) where stock tclsh
streams per command, continues after errors and exits 0.
(With the machinery present, evaluation is the stock
per-command repl loop.) On machinery-less runtimes the
interactive form (console stdin, no script) fails fast
with a usage error instead of blocking in a console read."
@form -form {scriptfile} -synopsis "<punkexe> tclsh ?-encoding name? scriptfile ?arg ...?"
@leaders -min 0 -max 0
@opts
-encoding -type string -optional 1 -typesynopsis name -help\
"Encoding used to read scriptfile (as for 'source -encoding').
Recognised only immediately after 'tclsh' and only when the
following argument does not begin with '-'; an incomplete
-encoding form falls through to the no-script form (stock
behaviour)."
@values -min 1 -max -1
scriptfile -type string -optional 0 -help\
"Script file to source and exit. ::argv0 and 'info script' are
the (normalized) script path; remaining args are ::argv. The
script may set ::tclsh(dorepl) 1 (piperepl runtimes) to enter
the interactive repl after it completes."
arg -type any -optional 1 -multiple 1 -help\
"Arguments passed to the script in ::argv."
@form -form {stdin} -synopsis "<punkexe> tclsh ?arg ...?"
@values -min 0 -max -1
arg -type any -optional 1 -multiple 1 -help\
"With no script file all arguments (including any leading '-'
arguments) stay in ::argv; ::argv0 is the executable path.
Input comes from stdin: the interactive repl on a console
(piperepl runtimes), evaluation of piped input otherwise."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
#Sibling subcommands: summary-level contracts. Deep punk::args parse
#definitions for these surfaces are G-032's lane ('script' is its
#natural first parsed subcommand).
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe::script
@cmd -name "punkexe script"\
-summary\
"Run a script non-interactively in the punk script environment."\
-help\
"Run a Tcl script and exit with an honest exit code
(app-punkscript): script errors exit nonzero and the launch
plumbing emits nothing of its own on stdout/stderr, so
exec-style callers see only the script's output. The default
punk module/alias environment is loaded (unlike 'tclsh').
The script comes from the file argument, from piped stdin when
no argument is given (terminal stdin without a script argument
is a usage error - no interactive fallback), or via scriptlib
resolution when the argument has the form 'lib:name' (resolved
from the scriptlib locations associated with the executable,
including extensionless and shebang'd scripts)."
@form -synopsis "<punkexe> script ?scriptfile|lib:name? ?arg ...?"
@values -min 0 -max -1
scriptfile -type string -optional 1 -help\
"Script file path, or lib:name for scriptlib resolution.
Omitted: the script is read from piped stdin."
arg -type any -optional 1 -multiple 1 -help\
"Arguments passed to the script in ::argv."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe::shell
@cmd -name "punkexe shell"\
-summary\
"Interactive punk shell (repl)."\
-help\
"Launch the interactive punk shell (app-punkshell). With
arguments, a script can be run first with the interactive
shell maintained afterwards. This is also the default when the
executable is launched with no arguments at all."
@form -synopsis "<punkexe> shell ?arg ...?"
@values -min 0 -max -1
arg -type any -optional 1 -multiple 1 -help\
"Arguments passed through to the shell launch."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe::punk
@cmd -name "punkexe punk"\
-summary\
"punk shell launch; piped-stdin friendly."\
-help\
"Launch the punk shell. With arguments the app-punkshell launch
path is used (as for 'shell'); without arguments the
interactive shell is launched directly. Commands piped into
stdin are supported (e.g: echo 'puts hello' | <punkexe> punk)
and stderr is kept clean of launch chatter so exec-style
callers do not misreport failure."
@form -synopsis "<punkexe> punk ?arg ...?"
@values -min 0 -max -1
arg -type any -optional 1 -multiple 1 -help\
"Arguments passed through to the shell launch."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
lappend PUNKARGS [list {
@id -id (script)::punkexe::shellspy
@cmd -name "punkexe shellspy"\
-summary\
"Experimental shellspy command-line processor."\
-help\
"Pass all arguments to the experimental shellspy command-line
processor (app-shellspy). Note: 'shellspy' is only this launch
subcommand - it is not the project name (the project is
punkshell)."
@form -synopsis "<punkexe> shellspy ?arg ...?"
@values -min 0 -max -1
arg -type any -optional 1 -multiple 1 -help\
"Arguments for the shellspy processor."
}]
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---
}
#*** !doctools
#[list_end] [comment {--- end definitions namespace punk::args::moduledoc::punkexe ---}]
}
# -----------------------------------------------------------------------------
# register namespace(s) to have PUNKARGS,PUNKARGS_aliases variables checked
# -----------------------------------------------------------------------------
# variable PUNKARGS
# variable PUNKARGS_aliases
namespace eval ::punk::args::register {
#use fully qualified so 8.6 doesn't find existing var in global namespace
lappend ::punk::args::register::NAMESPACES ::punk::args::moduledoc::punkexe ::punk::args::moduledoc::punkexe::argdoc
}
# -----------------------------------------------------------------------------
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready
package provide punk::args::moduledoc::punkexe [tcl::namespace::eval punk::args::moduledoc::punkexe {
variable pkg punk::args::moduledoc::punkexe
variable version
set version 0.1.0
}]
return
#*** !doctools
#[manpage_end]

BIN
src/vfs/_vfscommon.vfs/modules/punk/mix/templates-0.2.0.tm

Binary file not shown.

4
src/vfs/_vfscommon.vfs/modules/punk/repl-0.5.2.tm → src/vfs/_vfscommon.vfs/modules/punk/repl-0.5.3.tm

@ -4290,6 +4290,7 @@ namespace eval repl {
package require punk::lib
package require punk::args
catch {package require punk::args::moduledoc::tclcore} ;#while tclcore is highly desirable, and should be installed with punk::args - it's not critical
catch {package require punk::args::moduledoc::punkexe} ;#launch subcommand family documentation (G-118) - not critical
package require textblock
}
@ -4470,6 +4471,7 @@ namespace eval repl {
catch {package require punk::args::moduledoc::parser}
#-----------
catch {package require punk::args::moduledoc::tclcore} ;#while tclcore is highly desirable, and should be installed with punk::args - it's not critical
catch {package require punk::args::moduledoc::punkexe} ;#launch subcommand family documentation (G-118) - not critical
} errM]} {
puts stderr "========================"
puts stderr "code interp error:"
@ -4565,7 +4567,7 @@ namespace eval ::punk::args::register {
package provide punk::repl [namespace eval punk::repl {
variable version
set version 0.5.2
set version 0.5.3
}]
#repl::start $program_read_stdin_pipe
Loading…
Cancel
Save