You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
5.7 KiB
161 lines
5.7 KiB
# -*- tcl -*- |
|
# Maintenance Instruction: leave the 999999.xxx.x as is and use 'pmix make' or src/make.tcl to update from <pkg>-buildversion.txt |
|
# |
|
# 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) 2023 |
|
# |
|
# @@ Meta Begin |
|
# Application punk::tdl 999999.0a1.0 |
|
# Meta platform tcl |
|
# Meta license <unspecified> |
|
# @@ Meta End |
|
|
|
|
|
|
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
## Requirements |
|
##e.g package require frobz |
|
|
|
|
|
|
|
|
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
namespace eval punk::tdl { |
|
# https://wiki.tcl-lang.org/page/Config+file+using+slave+interp |
|
|
|
namespace eval argdoc { |
|
variable PUNKARGS |
|
} |
|
|
|
variable sample_script { |
|
server -name bsd1 -os FreeBSD |
|
server -name p1 -os linux |
|
server -name trillion -os windows |
|
|
|
server -name vmhost1 -os FreeBSD { |
|
guest -name bsd1 -vmmanager bastille |
|
guest -name p1 -vmmanager bhyve |
|
} |
|
|
|
} |
|
|
|
|
|
|
|
namespace eval argdoc { |
|
variable PUNKARGS |
|
lappend PUNKARGS [list { |
|
@id -id ::punk::tdl::prettyparse |
|
@cmd -name punk::tdl::prettyparse\ |
|
-summary\ |
|
"Parse a Tcl-like TDL script into a nested list of dictionaries."\ |
|
-help\ |
|
"Parse a script in the Tcl Data Language style shown at |
|
https://wiki.tcl-lang.org/page/Config+file+using+slave+interp. |
|
|
|
The script is evaluated in a child interpreter. Unknown commands are captured |
|
as data objects: the command name is stored under the reserved 'tag' key, |
|
flag/value words become dictionary entries, and an odd final argument is |
|
treated as a nested body script and parsed recursively under the reserved |
|
'body' key. |
|
|
|
When safe is true a safe child interpreter is used. When safe is false a |
|
normal child interpreter is used, which allows a broader set of Tcl commands |
|
to run while parsing. This parser validates Tcl script syntax and list |
|
structure only; schema and semantic validation belong to the caller." |
|
@values -min 1 -max 2 |
|
script -type string -help\ |
|
"TDL-style Tcl script to parse." |
|
safe -type boolean -default 1 -optional 1 -help\ |
|
"Use a safe child interpreter when true, or a normal child interpreter |
|
when false." |
|
}] |
|
} |
|
proc prettyparse {script {safe 1}} { |
|
if {$safe} { |
|
set i [interp create -safe] |
|
} else { |
|
set i [interp create] |
|
} |
|
try { |
|
# $i eval {unset {*}[info vars]} |
|
# foreach command [$i eval {info commands}] {$i hide $command} |
|
# $i invokehidden namespace delete {*}[$i invokehidden namespace children] |
|
$i alias unknown apply {{i tag args} { |
|
upvar 1 result result |
|
set e [concat [list tag $tag] [lrange $args 0 [expr {([llength $args] & ~1) - 1}]]] |
|
if {[llength $args] % 2} { |
|
set saved $result |
|
set result {} |
|
$i eval [lindex $args end] |
|
lappend e body $result |
|
set result $saved |
|
} |
|
lappend result $e |
|
list |
|
}} $i |
|
set result {} |
|
$i eval $script |
|
return $result |
|
} finally { |
|
interp delete $i |
|
} |
|
} |
|
|
|
namespace eval argdoc { |
|
variable PUNKARGS |
|
lappend PUNKARGS [list { |
|
@id -id ::punk::tdl::prettyprint |
|
@cmd -name punk::tdl::prettyprint\ |
|
-summary\ |
|
"Render parsed TDL dictionaries back to a readable Tcl-like script."\ |
|
-help\ |
|
"Render the nested list of dictionaries returned by punk::tdl::prettyparse as |
|
an indented Tcl-like data script. |
|
|
|
The reserved 'tag' key supplies each command name. Remaining dictionary keys |
|
are emitted as arguments, and a non-empty reserved 'body' key is rendered |
|
recursively inside braces. Comments and original whitespace are not preserved." |
|
@values -min 1 -max 2 |
|
data -type list -help\ |
|
"Nested list of dictionaries in the representation returned by |
|
punk::tdl::prettyparse." |
|
level -type integer -default 0 -optional 1 -help\ |
|
"Initial indentation level, primarily used for recursive rendering." |
|
}] |
|
} |
|
proc prettyprint {data {level 0}} { |
|
set ind [string repeat " " $level] |
|
incr level |
|
set result {} |
|
foreach e $data { |
|
set line $ind[concat [list [dict get $e tag]] [dict remove $e tag body]] |
|
if {[dict exists $e body] && [llength [dict get $e body]]} { |
|
append line " {\n[prettyprint [dict get $e body] $level]\n$ind}" |
|
} |
|
lappend result $line |
|
} |
|
join $result \n |
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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::tdl |
|
} |
|
|
|
|
|
|
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
## Ready |
|
package provide punk::tdl [namespace eval punk::tdl { |
|
variable version |
|
set version 999999.0a1.0 |
|
}] |
|
return
|
|
|