Browse Source
punk::ns 0.9.0: cmdhelp (i) gains -return text - plain-text argument
documentation for machine/LLM consumption: no ANSI, no table layout, the
argument section of every command form rendered in one output under a common
header ('i -return text after' shows all six forms), G-041 form selection
still honoured when argument words are supplied, no advisory-parse error
preamble (-return dict remains the parse-status surface). Implementation
delegates resolution to the -return dict recursion and renders per-form via
the string renderer.
punk::args 0.12.6 (user direction; string-form layout explicitly not frozen -
no external consumers yet):
- arg_error renders the error message + per-form match detail exactly once,
BELOW the usage display (was above and below); bottom append suppressed for
empty messages.
- string renderer argument rows are single-line
'name TYPE:type(constraints) ?DEFAULT:'val'? ?MULTI:yes?' - type
constraints parenthesize onto the base type instead of line-breaking
mid-row; empty DEFAULT/MULTI labels and whitespace-only help blocks omitted.
- choices render as markdown-subset bullets '- `choice` - label' with label
continuations at a fixed deeper indent - choice names are now
machine-distinguishable from label text without ANSI. Structural contract:
column-0 lines bearing TYPE: are argument rows, indented lines are
documentation, backticked bullets are choices. Table cells unchanged.
New scriptlib/developer/whatis.tcl (runtime command introspection for
agents): resolved name, subcommand-chain resolution via punk::ns::cmdinfo
('whatis string is'), kind, providing package + loaded version, origin file,
proc definition file:line, punk::args synopsis; -body appends the runtime
body with file-relative line numbers, -doc the full plain-text argdoc via
cmdhelp -return text (with fallback for older punk::ns). Backing the
cross-framework tcl-whatis agent skill: canonical .agents/skills/tcl-whatis/
(Agent Skills standard - pi/OpenCode/Codex) with byte-identical copy in
.claude/skills/ for Claude Code; .gitignore gains !.claude/skills/ with the
fossil ignore-glob comment + exception-set docs updated per the dual-VCS
contract (fossil adds staged). Root AGENTS.md: .agents/skills index entry,
whatis pointer in Repo-wide Notes, scriptlib/developer example.
Tests: new pins cmdhelp_return_text_all_forms/_argword_form_selection/
_single_form_plain_marker (cmdhelp.test), rendering_stringmode_singleline_argrows
+ rendering_stringmode_choice_bullets (rendering.test); deliberate-change pin
updates: errorselection.test message matches gained leading * and cmdhelp.test
message pins sample the last line (message placement). Full source-tree suite
963/979 pass, sole failure the pre-existing exec-14.3 baseline; make.tcl
modules clean.
Project version 0.12.42 -> 0.13.0 with CHANGELOG.md entry.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
16 changed files with 765 additions and 43 deletions
@ -0,0 +1,78 @@
|
||||
--- |
||||
name: tcl-whatis |
||||
description: Use when you need to know how to call a Tcl command in this repo (including ensemble subcommands like 'string is'), where a proc is defined (file and line number), which module version is actually loaded, or what a proc's runtime body is. Runtime introspection via punkshell - reports resolved name, kind (proc/alias/ensemble), providing package + version, origin file, def file:line, and punk::args synopsis. Cheaper and more accurate than grep+read for interface questions, and the only option for runtime-generated procs. |
||||
--- |
||||
|
||||
# tcl-whatis |
||||
|
||||
Runtime introspection for Tcl commands in the punkshell repo. Asks the live |
||||
interpreter instead of grepping source, so it resolves aliases, ensembles and |
||||
subcommand chains, autoloads the providing module, and reports which of the |
||||
repo's several module copies (src/modules vs bootsupport vs kit-internal |
||||
zipfs) is actually loaded. |
||||
|
||||
## Command |
||||
|
||||
Run from the repo root (`punk91` lives in `bin/`; any punkshell kit works): |
||||
|
||||
punk91 src script scriptlib/developer/whatis.tcl ?-body? ?-doc? <command> ?subcommand?... |
||||
|
||||
- `<command>` - Tcl command name, qualified or not (e.g. `punk::args::parse`, |
||||
`corp`). If not already loaded, the longest namespace-prefix package match |
||||
is `package require`d automatically. |
||||
- `?subcommand?...` - ensemble/subcommand words: `whatis string is` resolves |
||||
the chain to `::tcl::string::is` (via punk::ns::cmdinfo) and reports that |
||||
origin's synopsis - no prior knowledge of the implementing namespace needed. |
||||
Unresolvable trailing words are reported in a `warning:` line. |
||||
- `-body` - append the runtime proc body. Line numbers are file-relative when |
||||
the `def:` line was located, so they match the origin file exactly. |
||||
- `-doc` - append the full argument documentation as plain ANSI-free text |
||||
with the argument section of EVERY command form (punk::ns::cmdhelp |
||||
-return text). Large for big commands; prefer the default synopsis unless |
||||
you need per-argument help text, defaults and choices. |
||||
|
||||
Exit codes: 0 ok, 1 command not found, 2 usage error. |
||||
|
||||
## Output fields |
||||
|
||||
command: string is the queried words |
||||
alias: -> punk::ns::cmdhelp alias chain, if any |
||||
resolves: ::tcl::string::is chain/alias resolution target |
||||
kind: proc | ensemble | native command |
||||
package: punk::args 999999.0a1.0 providing package + loaded version |
||||
origin: C:/repo/.../src/modules/punk/args-999999.0a1.0.tm |
||||
def: <origin-file>:6528 proc definition line in origin file |
||||
synopsis: one usage line per command form (from the punk::args definition) |
||||
|
||||
Ensembles report their namespace and subcommand map instead of `def:`. |
||||
|
||||
## -doc output structure (parsing contract) |
||||
|
||||
- Column-0 lines containing `TYPE:` are argument rows, one line each: |
||||
`name TYPE:type(constraints) ?DEFAULT:'val'? ?MULTI:yes?`. Optional |
||||
arguments show as `?name?`, repeatable ones as `name...`. |
||||
- Indented lines under a row are that argument's help text (never flags, |
||||
even when a line starts with `-word`). |
||||
- Choices are markdown-style bullets: `` - `choice` - label text``, with |
||||
label continuation lines indented past the bullet dash. The backticked |
||||
token is the choice (it may carry a trailing marker glyph); everything |
||||
after the closing backtick is label/documentation. |
||||
- Multiform commands render one ` --ARGUMENTS (form 'name')-- ` section per |
||||
form under a single common header (description + all-forms synopsis). |
||||
|
||||
## Caveats |
||||
|
||||
- Keep the `src` launch argument: it loads the working-tree modules under |
||||
`src/modules` (versions like 999999.0a1.0) so `origin`/`def` point at |
||||
editable files. Without it the kit-stamped copies inside the executable are |
||||
introspected (`//zipfs:/...` paths, older versions) and the report says so |
||||
in a `warning:` line. |
||||
- Load noise ("src mode: registered ...") goes to stderr; read stdout only |
||||
(append `2>/dev/null` in bash, `2>$null` in PowerShell). |
||||
- To edit a proc, go to the `def:` file:line and Read the file there; do not |
||||
build edits from `-body` output text. |
||||
- `def: (no proc definition found ...)` means the proc was generated at |
||||
runtime - `-body` output is then the only source. |
||||
- Trust `origin:` over assumptions about which module copy is loaded; this |
||||
repo has several coexisting copies of many modules and ties do not always |
||||
resolve the way you expect. |
||||
@ -0,0 +1,78 @@
|
||||
--- |
||||
name: tcl-whatis |
||||
description: Use when you need to know how to call a Tcl command in this repo (including ensemble subcommands like 'string is'), where a proc is defined (file and line number), which module version is actually loaded, or what a proc's runtime body is. Runtime introspection via punkshell - reports resolved name, kind (proc/alias/ensemble), providing package + version, origin file, def file:line, and punk::args synopsis. Cheaper and more accurate than grep+read for interface questions, and the only option for runtime-generated procs. |
||||
--- |
||||
|
||||
# tcl-whatis |
||||
|
||||
Runtime introspection for Tcl commands in the punkshell repo. Asks the live |
||||
interpreter instead of grepping source, so it resolves aliases, ensembles and |
||||
subcommand chains, autoloads the providing module, and reports which of the |
||||
repo's several module copies (src/modules vs bootsupport vs kit-internal |
||||
zipfs) is actually loaded. |
||||
|
||||
## Command |
||||
|
||||
Run from the repo root (`punk91` lives in `bin/`; any punkshell kit works): |
||||
|
||||
punk91 src script scriptlib/developer/whatis.tcl ?-body? ?-doc? <command> ?subcommand?... |
||||
|
||||
- `<command>` - Tcl command name, qualified or not (e.g. `punk::args::parse`, |
||||
`corp`). If not already loaded, the longest namespace-prefix package match |
||||
is `package require`d automatically. |
||||
- `?subcommand?...` - ensemble/subcommand words: `whatis string is` resolves |
||||
the chain to `::tcl::string::is` (via punk::ns::cmdinfo) and reports that |
||||
origin's synopsis - no prior knowledge of the implementing namespace needed. |
||||
Unresolvable trailing words are reported in a `warning:` line. |
||||
- `-body` - append the runtime proc body. Line numbers are file-relative when |
||||
the `def:` line was located, so they match the origin file exactly. |
||||
- `-doc` - append the full argument documentation as plain ANSI-free text |
||||
with the argument section of EVERY command form (punk::ns::cmdhelp |
||||
-return text). Large for big commands; prefer the default synopsis unless |
||||
you need per-argument help text, defaults and choices. |
||||
|
||||
Exit codes: 0 ok, 1 command not found, 2 usage error. |
||||
|
||||
## Output fields |
||||
|
||||
command: string is the queried words |
||||
alias: -> punk::ns::cmdhelp alias chain, if any |
||||
resolves: ::tcl::string::is chain/alias resolution target |
||||
kind: proc | ensemble | native command |
||||
package: punk::args 999999.0a1.0 providing package + loaded version |
||||
origin: C:/repo/.../src/modules/punk/args-999999.0a1.0.tm |
||||
def: <origin-file>:6528 proc definition line in origin file |
||||
synopsis: one usage line per command form (from the punk::args definition) |
||||
|
||||
Ensembles report their namespace and subcommand map instead of `def:`. |
||||
|
||||
## -doc output structure (parsing contract) |
||||
|
||||
- Column-0 lines containing `TYPE:` are argument rows, one line each: |
||||
`name TYPE:type(constraints) ?DEFAULT:'val'? ?MULTI:yes?`. Optional |
||||
arguments show as `?name?`, repeatable ones as `name...`. |
||||
- Indented lines under a row are that argument's help text (never flags, |
||||
even when a line starts with `-word`). |
||||
- Choices are markdown-style bullets: `` - `choice` - label text``, with |
||||
label continuation lines indented past the bullet dash. The backticked |
||||
token is the choice (it may carry a trailing marker glyph); everything |
||||
after the closing backtick is label/documentation. |
||||
- Multiform commands render one ` --ARGUMENTS (form 'name')-- ` section per |
||||
form under a single common header (description + all-forms synopsis). |
||||
|
||||
## Caveats |
||||
|
||||
- Keep the `src` launch argument: it loads the working-tree modules under |
||||
`src/modules` (versions like 999999.0a1.0) so `origin`/`def` point at |
||||
editable files. Without it the kit-stamped copies inside the executable are |
||||
introspected (`//zipfs:/...` paths, older versions) and the report says so |
||||
in a `warning:` line. |
||||
- Load noise ("src mode: registered ...") goes to stderr; read stdout only |
||||
(append `2>/dev/null` in bash, `2>$null` in PowerShell). |
||||
- To edit a proc, go to the `def:` file:line and Read the file there; do not |
||||
build edits from `-body` output text. |
||||
- `def: (no proc definition found ...)` means the proc was generated at |
||||
runtime - `-body` output is then the only source. |
||||
- Trust `origin:` over assumptions about which module copy is loaded; this |
||||
repo has several coexisting copies of many modules and ties do not always |
||||
resolve the way you expect. |
||||
@ -1,4 +1,4 @@
|
||||
[project] |
||||
name = "punkshell" |
||||
version = "0.12.42" |
||||
version = "0.13.0" |
||||
license = "BSD-2-Clause" |
||||
|
||||
@ -0,0 +1,310 @@
|
||||
#!/usr/bin/env tclsh |
||||
# whatis.tcl - runtime introspection report for a command, aimed at agent/LLM use |
||||
# |
||||
# Reports for a command name (possibly unqualified, possibly followed by |
||||
# subcommand words - e.g 'string is', 'dict getdef'): |
||||
# - resolved fully-qualified name and kind (proc / alias / ensemble / native) |
||||
# - subcommand-chain resolution via punk::ns::cmdinfo (ensembles, aliases, |
||||
# nested chains) with any unresolvable trailing words reported |
||||
# - providing package + version and the origin file the loaded copy came from |
||||
# - file:line of the proc definition in that origin file (when locatable) |
||||
# - punk::args synopsis (compact usage line per form) |
||||
# Options: |
||||
# -body append the runtime proc body, numbered with file-relative line numbers |
||||
# when the definition line was located (numbers then match the origin file) |
||||
# -doc append the full argument documentation for all forms as plain text |
||||
# (punk::ns::cmdhelp -return text) |
||||
# |
||||
# Must run inside a punkshell interpreter (needs punk::args, punk::ansi, punk::ns): |
||||
# punk91 src script scriptlib/developer/whatis.tcl ?-body? ?-doc? <command> ?subcommand?... |
||||
# Use the 'src' launch argument so the working-tree modules under src/modules are |
||||
# loaded; without it the kit-stamped copies inside the executable (//zipfs:/...) |
||||
# are introspected and file:line will not refer to editable files. |
||||
# Exit 0 on success; 1 command not found; 2 usage error. |
||||
|
||||
proc strip {text} { |
||||
if {[info commands ::ansistrip] ne ""} { |
||||
return [ansistrip $text] |
||||
} elseif {![catch {package require punk::ansi}]} { |
||||
return [punk::ansi::ansistrip $text] |
||||
} |
||||
return $text |
||||
} |
||||
|
||||
proc out {key val} { |
||||
puts [format "%-9s %s" $key: [strip $val]] |
||||
} |
||||
|
||||
# longest namespace-prefix of a fully-qualified command that names a package |
||||
proc pkg_for_command {fqcmd} { |
||||
set parts [lrange [split [string trimleft $fqcmd :] ::] 0 end] |
||||
set parts [lsearch -all -inline -not $parts {}] ;# split on :: leaves empties |
||||
for {set n [expr {[llength $parts]-1}]} {$n >= 1} {incr n -1} { |
||||
set prefix [join [lrange $parts 0 $n-1] ::] |
||||
if {![catch {package present $prefix} ver]} { |
||||
return [list $prefix $ver] |
||||
} |
||||
} |
||||
return {} |
||||
} |
||||
|
||||
# attempt to load a package matching the namespace prefixes of $name |
||||
proc try_autoload {name} { |
||||
set parts [lsearch -all -inline -not [split [string trimleft $name :] ::] {}] |
||||
for {set n [expr {[llength $parts]-1}]} {$n >= 1} {incr n -1} { |
||||
set prefix [join [lrange $parts 0 $n-1] ::] |
||||
if {![catch {package require $prefix}]} { |
||||
return $prefix |
||||
} |
||||
} |
||||
return {} |
||||
} |
||||
|
||||
# origin file of a loaded package, parsed from its ifneeded script |
||||
proc pkg_origin {pkg ver} { |
||||
set script [package ifneeded $pkg $ver] |
||||
if {[regexp {[;\n]?\s*source\s+(?:-encoding\s+\S+\s+)?(.+?)\s*$} $script -> path]} { |
||||
return [string trim $path {"{}}] |
||||
} |
||||
if {[regexp {load\s+(\S+)} $script -> path]} { |
||||
return $path |
||||
} |
||||
return "" |
||||
} |
||||
|
||||
# locate the proc definition line in a source file; returns list of line numbers |
||||
proc find_def_lines {path fqcmd} { |
||||
if {$path eq "" || [catch {open $path r} fd]} { |
||||
return {} |
||||
} |
||||
set data [read $fd] |
||||
close $fd |
||||
set tail [namespace tail $fqcmd] |
||||
set noco [string trimleft $fqcmd :] |
||||
set exact {} |
||||
set bytail {} |
||||
set ln 0 |
||||
foreach line [split $data \n] { |
||||
incr ln |
||||
if {[regexp {^\s*proc\s+(:{0,2}[\w:]+)\s} $line -> pname]} { |
||||
set pclean [string trimleft $pname :] |
||||
if {$pclean eq $noco} { |
||||
lappend exact $ln |
||||
} elseif {[namespace tail $pclean] eq $tail} { |
||||
lappend bytail $ln |
||||
} |
||||
} |
||||
} |
||||
if {[llength $exact]} { |
||||
return $exact |
||||
} |
||||
return $bytail |
||||
} |
||||
|
||||
# ---------------------------------------------------------------- arg handling |
||||
set opt_body 0 |
||||
set opt_doc 0 |
||||
set names {} |
||||
foreach a $argv { |
||||
switch -- $a { |
||||
-body {set opt_body 1} |
||||
-doc {set opt_doc 1} |
||||
default {lappend names $a} |
||||
} |
||||
} |
||||
if {![llength $names]} { |
||||
puts stderr "usage: punk91 src script scriptlib/developer/whatis.tcl ?-body? ?-doc? <command> ?subcommand?..." |
||||
exit 2 |
||||
} |
||||
set name [lindex $names 0] |
||||
set subwords [lrange $names 1 end] |
||||
|
||||
# ---------------------------------------------------------------- resolution |
||||
set resolved [uplevel #0 [list namespace which -command $name]] |
||||
if {$resolved eq ""} { |
||||
set loaded [try_autoload $name] |
||||
set resolved [uplevel #0 [list namespace which -command $name]] |
||||
if {$resolved eq "" && $loaded ne ""} { |
||||
puts stderr "whatis: loaded package '$loaded' but no command '$name' appeared" |
||||
} |
||||
} |
||||
if {$resolved eq ""} { |
||||
puts stderr "whatis: command '$name' not found (and no matching package could be loaded)" |
||||
exit 1 |
||||
} |
||||
out command [join $names { }] |
||||
|
||||
set docid $resolved |
||||
if {[llength $subwords]} { |
||||
# subcommand-chain resolution (ensembles, aliases, nested chains) |
||||
if {[catch {package require punk::ns}]} { |
||||
puts stderr "whatis: subcommand chains need punk::ns (punk::ns::cmdinfo) which failed to load" |
||||
exit 1 |
||||
} |
||||
if {[catch {punk::ns::cmdinfo {*}$names} cinfo]} { |
||||
puts stderr "whatis: punk::ns::cmdinfo failed resolving '[join $names { }]': $cinfo" |
||||
exit 1 |
||||
} |
||||
set chain_origin [dict get $cinfo origin] |
||||
set args_remaining [dict get $cinfo args_remaining] |
||||
set cinfo_docid [dict get $cinfo docid] |
||||
out resolves $chain_origin |
||||
if {[llength $args_remaining]} { |
||||
out warning "trailing words '[join $args_remaining { }]' could not be resolved as subcommands (cmdtype [dict get $cinfo cmdtype])" |
||||
} |
||||
set resolved [uplevel #0 [list namespace which -command $chain_origin]] |
||||
if {$resolved eq ""} { |
||||
# documentation-only level (cmdtype doconly) or unresolvable - report what we know |
||||
set resolved $chain_origin |
||||
} |
||||
set docid [expr {$cinfo_docid ne "" ? $cinfo_docid : $resolved}] |
||||
} else { |
||||
# alias chain (repl aliases are usually registered without leading colons) |
||||
set target $resolved |
||||
for {set depth 0} {$depth < 5} {incr depth} { |
||||
set atarget {} |
||||
foreach token [list [string trimleft $target :] $target] { |
||||
set atarget [interp alias {} $token] |
||||
if {[llength $atarget]} break |
||||
} |
||||
if {![llength $atarget]} break |
||||
out alias "-> $atarget" |
||||
set target [uplevel #0 [list namespace which -command [lindex $atarget 0]]] |
||||
if {$target eq ""} break |
||||
} |
||||
if {$target ne "" && $target ne $resolved} { |
||||
out resolves $target |
||||
set resolved $target |
||||
} |
||||
set docid $resolved |
||||
# prefer cmdinfo's docid when available (handles curried aliases, doc-only ids) |
||||
if {![catch {package require punk::ns}] && ![catch {punk::ns::cmdinfo $name} cinfo]} { |
||||
set cinfo_docid [dict get $cinfo docid] |
||||
if {$cinfo_docid ne ""} { |
||||
set docid $cinfo_docid |
||||
} |
||||
} |
||||
} |
||||
|
||||
if {[info procs $resolved] ne ""} { |
||||
set kind proc |
||||
} elseif {[namespace ensemble exists $resolved]} { |
||||
set kind ensemble |
||||
} else { |
||||
set kind "native command (C-implemented or unavailable as script)" |
||||
} |
||||
out kind $kind |
||||
|
||||
# ---------------------------------------------------------------- package/origin |
||||
set pkginfo [pkg_for_command $resolved] |
||||
set origin "" |
||||
if {[llength $pkginfo]} { |
||||
lassign $pkginfo pkg ver |
||||
out package "$pkg $ver" |
||||
set origin [pkg_origin $pkg $ver] |
||||
if {$origin ne ""} { |
||||
out origin $origin |
||||
if {[string match //zipfs:* $origin]} { |
||||
out warning "origin is the kit-stamped copy inside the executable - relaunch with 'punk91 src script ...' to introspect the working tree under src/modules" |
||||
} |
||||
} |
||||
} else { |
||||
out package "(none matched - Tcl core or statically provided)" |
||||
} |
||||
|
||||
set defline 0 |
||||
if {$kind eq "proc"} { |
||||
set lines [find_def_lines $origin $resolved] |
||||
if {[llength $lines] == 1} { |
||||
set defline [lindex $lines 0] |
||||
out def $origin:$defline |
||||
} elseif {[llength $lines] > 1} { |
||||
out def "ambiguous - candidate lines [join $lines {, }] in $origin" |
||||
} elseif {$origin ne ""} { |
||||
out def "(no proc definition found in origin file - possibly generated at runtime)" |
||||
} |
||||
} |
||||
|
||||
if {$kind eq "ensemble"} { |
||||
set ns [namespace ensemble configure $resolved -namespace] |
||||
set map [namespace ensemble configure $resolved -map] |
||||
set subs [namespace ensemble configure $resolved -subcommands] |
||||
out namespace $ns |
||||
if {[dict size $map]} { |
||||
puts "map:" |
||||
dict for {sub tgt} $map { |
||||
puts [format " %-20s -> %s" $sub $tgt] |
||||
} |
||||
} elseif {[llength $subs]} { |
||||
out subcommands $subs |
||||
} else { |
||||
out subcommands "(exported commands of $ns: [join [info commands ${ns}::*] { }])" |
||||
} |
||||
} |
||||
|
||||
# ---------------------------------------------------------------- synopsis |
||||
if {![catch {package require punk::args}]} { |
||||
if {[catch {punk::args::synopsis $docid} syn]} { |
||||
set syn "" |
||||
} |
||||
if {[string trim [strip $syn]] ne ""} { |
||||
puts "synopsis:" |
||||
foreach line [split [string trim [strip $syn]] \n] { |
||||
puts " $line" |
||||
} |
||||
} else { |
||||
puts "synopsis: (no punk::args definition registered for $docid)" |
||||
} |
||||
} |
||||
|
||||
# ---------------------------------------------------------------- optional body |
||||
if {$opt_body && $kind eq "proc"} { |
||||
set argspec {} |
||||
foreach arg [info args $resolved] { |
||||
if {[info default $resolved $arg dflt]} { |
||||
lappend argspec [list $arg $dflt] |
||||
} else { |
||||
lappend argspec $arg |
||||
} |
||||
} |
||||
puts "" |
||||
if {$defline} { |
||||
puts "body (line numbers are file-relative to $origin):" |
||||
} else { |
||||
puts "body (line numbers relative to definition - file location unknown):" |
||||
} |
||||
set bodylines [split [info body $resolved] \n] |
||||
puts [format "%5d proc %s \{%s\} \{" $defline $resolved [join $argspec]] |
||||
set ln $defline |
||||
foreach bline [lrange $bodylines 1 end] { |
||||
incr ln |
||||
puts [format "%5d %s" $ln $bline] |
||||
} |
||||
} elseif {$opt_body} { |
||||
puts "\nbody: (not a proc - no script body available)" |
||||
} |
||||
|
||||
# ---------------------------------------------------------------- optional full doc |
||||
if {$opt_doc} { |
||||
puts "" |
||||
set gotdoc 0 |
||||
if {![catch {package require punk::ns}]} { |
||||
# -return text: plain text, ANSI-free, all forms (punk::ns >= 0.9.0) |
||||
if {![catch {punk::ns::cmdhelp -return text -- {*}$names} doctext]} { |
||||
set gotdoc 1 |
||||
} |
||||
} |
||||
if {!$gotdoc} { |
||||
# older punk::ns without -return text (e.g kit-stamped copy) - fall back |
||||
if {[info commands ::i] ne ""} { |
||||
set doctext [strip [i {*}$names]] |
||||
} elseif {![catch {punk::args::usage $docid} usage]} { |
||||
set doctext [strip $usage] |
||||
} else { |
||||
set doctext "doc: (no argument documentation available for $docid)" |
||||
} |
||||
} |
||||
puts $doctext |
||||
} |
||||
|
||||
exit 0 |
||||
Loading…
Reference in new issue