Browse Source
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.commaster
14 changed files with 784 additions and 12 deletions
@ -1,4 +1,4 @@ |
|||||||
[project] |
[project] |
||||||
name = "punkshell" |
name = "punkshell" |
||||||
version = "0.20.0" |
version = "0.20.1" |
||||||
license = "BSD-2-Clause" |
license = "BSD-2-Clause" |
||||||
|
|||||||
@ -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] |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
0.1.0 |
||||||
|
#First line must be a semantic version number |
||||||
|
#all other lines are ignored. |
||||||
@ -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] |
||||||
Binary file not shown.
Loading…
Reference in new issue