Julian Noble
10 months ago
80 changed files with 7460 additions and 928 deletions
@ -0,0 +1,51 @@ |
|||||||
|
# -*- 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 %pkg% 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license <unspecified> |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
apply {code { #auto determine package name and version from name and placement of .tm file |
||||||
|
foreach base [tcl::tm::list] { |
||||||
|
set nsprefix "";#in case sourced directly and not in any of the .tm paths |
||||||
|
if {[string match -nocase ${base}* [info script]]} { |
||||||
|
set nsprefix [string trimleft [join [lrange [file split [string range [info script] [string length $base]+1 end]] 0 end-1] ::]:: ::] |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
set ver [join [lassign [split [file rootname [file tail [info script] ]] -] pkgtail] -] |
||||||
|
set pkgns ${nsprefix}${pkgtail} |
||||||
|
namespace eval $pkgns [string map [list <pkg> $pkgns <ver> $ver] $code] |
||||||
|
package provide $pkgns $ver;# only provide package if code evaluated without error |
||||||
|
} ::} { |
||||||
|
#-------------------------------------- |
||||||
|
variable pkg "<pkg>" |
||||||
|
variable version "<ver>" |
||||||
|
#-------------------------------------- |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
##e.g package require frobz |
||||||
|
|
||||||
|
|
||||||
|
#proc test {args} {puts "[namespace current]::test got args: $args"} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace eval [namespace current]::lib { |
||||||
|
#proc test {args} {puts "[namespace current]::test got args: $args"} |
||||||
|
} |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
} |
||||||
|
return |
||||||
|
|
@ -0,0 +1,107 @@ |
|||||||
|
# -*- tcl -*- |
||||||
|
# punk template_cli overridden - custom |
||||||
|
# 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) %year% |
||||||
|
# |
||||||
|
# @@ Meta Begin |
||||||
|
# Application %pkg% 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license %license% |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# doctools header |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[manpage_begin %project%_cli-module_%pkg% 0 999999.0a1.0] |
||||||
|
#[copyright "%year%"] |
||||||
|
#[titledesc {Command Line Interface Module}] [comment {-- Name section and table of contents description --}] |
||||||
|
#[moddesc {-}] [comment {-- Description at end of page heading --}] |
||||||
|
#[require %pkg%] |
||||||
|
#[description] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section Overview] |
||||||
|
#[para] overview of %pkg% |
||||||
|
#[subsection Concepts] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection dependencies] |
||||||
|
#[para] packages used by %pkg% |
||||||
|
#[list_begin itemized] |
||||||
|
|
||||||
|
package require Tcl 8.6 |
||||||
|
package require punk::overlay |
||||||
|
package require punk::mix::base |
||||||
|
package require punk::mix::util |
||||||
|
#*** !doctools |
||||||
|
#[item] [package {Tcl 8.6}] |
||||||
|
#[item] [package {punk::overlay}] |
||||||
|
#[item] [package {punk::mix::base}] |
||||||
|
#[item] [package {punk::mix::util}] |
||||||
|
|
||||||
|
# #package require frobz |
||||||
|
# #*** !doctools |
||||||
|
# #[item] [package {frobz}] |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] |
||||||
|
|
||||||
|
namespace eval %pkg% { |
||||||
|
namespace ensemble create |
||||||
|
#package require punk::overlay |
||||||
|
#punk::overlay::import_commandset debug . ::punk:mix::commandset::debug |
||||||
|
|
||||||
|
|
||||||
|
proc help {args} { |
||||||
|
set basehelp [punk::mix::base help {*}$args] |
||||||
|
return $basehelp |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval %pkg%::lib { |
||||||
|
namespace path ::punk::mix::util ;#askuser, do_in_path, foreach-file etc |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval %pkg% { |
||||||
|
proc _cli {args} { |
||||||
|
#don't use tailcall - base uses info level to determine caller |
||||||
|
::punk::mix::base::_cli {*}$args |
||||||
|
} |
||||||
|
variable default_command help |
||||||
|
punk::overlay::custom_from_base [namespace current] ::punk::mix::base |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
package provide %pkg% [namespace eval %pkg% { |
||||||
|
variable version |
||||||
|
set version 999999.0a1.0 |
||||||
|
}] |
||||||
|
return |
||||||
|
|
||||||
|
|
@ -0,0 +1,51 @@ |
|||||||
|
# -*- 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 %pkg% 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license <unspecified> |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
apply {code { #auto determine package name and version from name and placement of .tm file |
||||||
|
foreach base [tcl::tm::list] { |
||||||
|
set nsprefix "";#in case sourced directly and not in any of the .tm paths |
||||||
|
if {[string match -nocase ${base}* [info script]]} { |
||||||
|
set nsprefix [string trimleft [join [lrange [file split [string range [info script] [string length $base]+1 end]] 0 end-1] ::]:: ::] |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
set ver [join [lassign [split [file rootname [file tail [info script] ]] -] pkgtail] -] |
||||||
|
set pkgns ${nsprefix}${pkgtail} |
||||||
|
namespace eval $pkgns [string map [list <pkg> $pkgns <ver> $ver] $code] |
||||||
|
package provide $pkgns $ver;# only provide package if code evaluated without error |
||||||
|
} ::} { |
||||||
|
#-------------------------------------- |
||||||
|
variable pkg "<pkg>" |
||||||
|
variable version "<ver>" |
||||||
|
#-------------------------------------- |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
##e.g package require frobz |
||||||
|
|
||||||
|
|
||||||
|
#proc test {args} {puts "[namespace current]::test got args: $args"} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace eval [namespace current]::lib { |
||||||
|
#proc test {args} {puts "[namespace current]::test got args: $args"} |
||||||
|
} |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
} |
||||||
|
return |
||||||
|
|
@ -0,0 +1,3 @@ |
|||||||
|
%Major.Minor.Level% |
||||||
|
#First line must be a semantic version number |
||||||
|
#all other lines are ignored. |
@ -0,0 +1,10 @@ |
|||||||
|
Identifier: %package% |
||||||
|
Version: %version% |
||||||
|
Title: %title% |
||||||
|
Creator: %name% <%email%> |
||||||
|
Description: %description% |
||||||
|
Rights: BSD |
||||||
|
URL: %url% |
||||||
|
Available: |
||||||
|
Architecture: tcl |
||||||
|
Subject: |
@ -0,0 +1,51 @@ |
|||||||
|
# -*- 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 %pkg% 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license <unspecified> |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
apply {code { #auto determine package name and version from name and placement of .tm file |
||||||
|
foreach base [tcl::tm::list] { |
||||||
|
set nsprefix "";#in case sourced directly and not in any of the .tm paths |
||||||
|
if {[string match -nocase ${base}* [info script]]} { |
||||||
|
set nsprefix [string trimleft [join [lrange [file split [string range [info script] [string length $base]+1 end]] 0 end-1] ::]:: ::] |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
set ver [join [lassign [split [file rootname [file tail [info script] ]] -] pkgtail] -] |
||||||
|
set pkgns ${nsprefix}${pkgtail} |
||||||
|
namespace eval $pkgns [string map [list <pkg> $pkgns <ver> $ver] $code] |
||||||
|
package provide $pkgns $ver;# only provide package if code evaluated without error |
||||||
|
} ::} { |
||||||
|
#-------------------------------------- |
||||||
|
variable pkg "<pkg>" |
||||||
|
variable version "<ver>" |
||||||
|
#-------------------------------------- |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
##e.g package require frobz |
||||||
|
|
||||||
|
|
||||||
|
#proc test {args} {puts "[namespace current]::test got args: $args"} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace eval [namespace current]::lib { |
||||||
|
#proc test {args} {puts "[namespace current]::test got args: $args"} |
||||||
|
} |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
} |
||||||
|
return |
||||||
|
|
@ -0,0 +1,51 @@ |
|||||||
|
# -*- 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 %pkg% 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license <unspecified> |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
apply {code { #auto determine package name and version from name and placement of .tm file |
||||||
|
foreach base [tcl::tm::list] { |
||||||
|
set nsprefix "";#in case sourced directly and not in any of the .tm paths |
||||||
|
if {[string match -nocase ${base}* [info script]]} { |
||||||
|
set nsprefix [string trimleft [join [lrange [file split [string range [info script] [string length $base]+1 end]] 0 end-1] ::]:: ::] |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
set ver [join [lassign [split [file rootname [file tail [info script] ]] -] pkgtail] -] |
||||||
|
set pkgns ${nsprefix}${pkgtail} |
||||||
|
namespace eval $pkgns [string map [list <pkg> $pkgns <ver> $ver] $code] |
||||||
|
package provide $pkgns $ver;# only provide package if code evaluated without error |
||||||
|
} ::} { |
||||||
|
#-------------------------------------- |
||||||
|
variable pkg "<pkg>" |
||||||
|
variable version "<ver>" |
||||||
|
#-------------------------------------- |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
##e.g package require frobz |
||||||
|
|
||||||
|
|
||||||
|
#proc test {args} {puts "[namespace current]::test got args: $args"} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace eval [namespace current]::lib { |
||||||
|
#proc test {args} {puts "[namespace current]::test got args: $args"} |
||||||
|
} |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
} |
||||||
|
return |
||||||
|
|
@ -0,0 +1,106 @@ |
|||||||
|
# -*- 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) %year% |
||||||
|
# |
||||||
|
# @@ Meta Begin |
||||||
|
# Application %pkg% 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license %license% |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# doctools header |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[manpage_begin %project%_cli-module_%pkg% 0 999999.0a1.0] |
||||||
|
#[copyright "%year%"] |
||||||
|
#[titledesc {Command Line Interface Module}] [comment {-- Name section and table of contents description --}] |
||||||
|
#[moddesc {-}] [comment {-- Description at end of page heading --}] |
||||||
|
#[require %pkg%] |
||||||
|
#[description] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section Overview] |
||||||
|
#[para] overview of %pkg% |
||||||
|
#[subsection Concepts] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection dependencies] |
||||||
|
#[para] packages used by %pkg% |
||||||
|
#[list_begin itemized] |
||||||
|
|
||||||
|
package require Tcl 8.6 |
||||||
|
package require punk::overlay |
||||||
|
package require punk::mix::base |
||||||
|
package require punk::mix::util |
||||||
|
#*** !doctools |
||||||
|
#[item] [package {Tcl 8.6}] |
||||||
|
#[item] [package {punk::overlay}] |
||||||
|
#[item] [package {punk::mix::base}] |
||||||
|
#[item] [package {punk::mix::util}] |
||||||
|
|
||||||
|
# #package require frobz |
||||||
|
# #*** !doctools |
||||||
|
# #[item] [package {frobz}] |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] |
||||||
|
|
||||||
|
namespace eval %pkg% { |
||||||
|
namespace ensemble create |
||||||
|
#package require punk::overlay |
||||||
|
#punk::overlay::import_commandset debug . ::punk:mix::commandset::debug |
||||||
|
|
||||||
|
|
||||||
|
proc help {args} { |
||||||
|
set basehelp [punk::mix::base help {*}$args] |
||||||
|
return $basehelp |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval %pkg%::lib { |
||||||
|
namespace path ::punk::mix::util ;#askuser, do_in_path, foreach-file etc |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval %pkg% { |
||||||
|
proc _cli {args} { |
||||||
|
#don't use tailcall - base uses info level to determine caller |
||||||
|
::punk::mix::base::_cli {*}$args |
||||||
|
} |
||||||
|
variable default_command help |
||||||
|
punk::overlay::custom_from_base [namespace current] ::punk::mix::base |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
package provide %pkg% [namespace eval %pkg% { |
||||||
|
variable version |
||||||
|
set version 999999.0a1.0 |
||||||
|
}] |
||||||
|
return |
||||||
|
|
||||||
|
|
@ -0,0 +1,175 @@ |
|||||||
|
# -*- 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) %year% |
||||||
|
# |
||||||
|
# @@ Meta Begin |
||||||
|
# Application %pkg% 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license %license% |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# doctools header |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[manpage_begin %project%_module_%pkg% 0 999999.0a1.0] |
||||||
|
#[copyright "%year%"] |
||||||
|
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}] |
||||||
|
#[moddesc {-}] [comment {-- Description at end of page heading --}] |
||||||
|
#[require %pkg%] |
||||||
|
#[keywords module] |
||||||
|
#[description] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section Overview] |
||||||
|
#[para] overview of %pkg% |
||||||
|
#[subsection Concepts] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection dependencies] |
||||||
|
#[para] packages used by %pkg% |
||||||
|
#[list_begin itemized] |
||||||
|
|
||||||
|
package require Tcl 8.6 |
||||||
|
#*** !doctools |
||||||
|
#[item] [package {Tcl 8.6}] |
||||||
|
|
||||||
|
# #package require frobz |
||||||
|
# #*** !doctools |
||||||
|
# #[item] [package {frobz}] |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section API] |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# oo::class namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval %pkg%::class { |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace %pkg%::class}] |
||||||
|
#[para] class definitions |
||||||
|
if {[info commands [namespace current]::interface_sample1] eq ""} { |
||||||
|
#*** !doctools |
||||||
|
#[list_begin enumerated] |
||||||
|
|
||||||
|
# oo::class create interface_sample1 { |
||||||
|
# #*** !doctools |
||||||
|
# #[enum] CLASS [class interface_sample1] |
||||||
|
# #[list_begin definitions] |
||||||
|
|
||||||
|
# method test {arg1} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call class::interface_sample1 [method test] [arg arg1]] |
||||||
|
# #[para] test method |
||||||
|
# puts "test: $arg1" |
||||||
|
# } |
||||||
|
|
||||||
|
# #*** !doctools |
||||||
|
# #[list_end] [comment {-- end definitions interface_sample1}] |
||||||
|
# } |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end class enumeration ---}] |
||||||
|
} |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# Base namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval %pkg% { |
||||||
|
namespace export * |
||||||
|
#variable xyz |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace %pkg%}] |
||||||
|
#[para] Core API functions for %pkg% |
||||||
|
#[list_begin definitions] |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#proc sample1 {p1 args} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call [fun sample1] [arg p1] [opt {?option value...?}]] |
||||||
|
# #[para]Description of sample1 |
||||||
|
# return "ok" |
||||||
|
#} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end definitions namespace %pkg% ---}] |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# Secondary API namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval %pkg%::lib { |
||||||
|
namespace export * |
||||||
|
namespace path [namespace parent] |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace %pkg%::lib}] |
||||||
|
#[para] Secondary functions that are part of the API |
||||||
|
#[list_begin definitions] |
||||||
|
|
||||||
|
#proc utility1 {p1 args} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call lib::[fun utility1] [arg p1] [opt {?option value...?}]] |
||||||
|
# #[para]Description of utility1 |
||||||
|
# return 1 |
||||||
|
#} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end definitions namespace %pkg%::lib ---}] |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[section Internal] |
||||||
|
namespace eval %pkg%::system { |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace %pkg%::system}] |
||||||
|
#[para] Internal functions that are not part of the API |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
package provide %pkg% [namespace eval %pkg% { |
||||||
|
variable pkg %pkg% |
||||||
|
variable version |
||||||
|
set version 999999.0a1.0 |
||||||
|
}] |
||||||
|
return |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[manpage_end] |
||||||
|
|
@ -0,0 +1,176 @@ |
|||||||
|
# -*- tcl -*- |
||||||
|
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'pmix make' or bin/punkmake to update from <pkg>-buildversion.txt |
||||||
|
# module template: %moduletemplate% |
||||||
|
# |
||||||
|
# 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) %year% |
||||||
|
# |
||||||
|
# @@ Meta Begin |
||||||
|
# Application %pkg% 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license %license% |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# doctools header |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[manpage_begin %project%_module_%pkg% 0 999999.0a1.0] |
||||||
|
#[copyright "%year%"] |
||||||
|
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}] |
||||||
|
#[moddesc {-}] [comment {-- Description at end of page heading --}] |
||||||
|
#[require %pkg%] |
||||||
|
#[keywords module] |
||||||
|
#[description] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section Overview] |
||||||
|
#[para] overview of %pkg% |
||||||
|
#[subsection Concepts] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection dependencies] |
||||||
|
#[para] packages used by %pkg% |
||||||
|
#[list_begin itemized] |
||||||
|
|
||||||
|
package require Tcl 8.6 |
||||||
|
#*** !doctools |
||||||
|
#[item] [package {Tcl 8.6}] |
||||||
|
|
||||||
|
# #package require frobz |
||||||
|
# #*** !doctools |
||||||
|
# #[item] [package {frobz}] |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section API] |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# oo::class namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval %pkg%::class { |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace %pkg%::class}] |
||||||
|
#[para] class definitions |
||||||
|
if {[info commands [namespace current]::interface_sample1] eq ""} { |
||||||
|
#*** !doctools |
||||||
|
#[list_begin enumerated] |
||||||
|
|
||||||
|
# oo::class create interface_sample1 { |
||||||
|
# #*** !doctools |
||||||
|
# #[enum] CLASS [class interface_sample1] |
||||||
|
# #[list_begin definitions] |
||||||
|
|
||||||
|
# method test {arg1} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call class::interface_sample1 [method test] [arg arg1]] |
||||||
|
# #[para] test method |
||||||
|
# puts "test: $arg1" |
||||||
|
# } |
||||||
|
|
||||||
|
# #*** !doctools |
||||||
|
# #[list_end] [comment {-- end definitions interface_sample1}] |
||||||
|
# } |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end class enumeration ---}] |
||||||
|
} |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# Base namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval %pkg% { |
||||||
|
namespace export * |
||||||
|
#variable xyz |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace %pkg%}] |
||||||
|
#[para] Core API functions for %pkg% |
||||||
|
#[list_begin definitions] |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#proc sample1 {p1 args} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call [fun sample1] [arg p1] [opt {option value...}]] |
||||||
|
# #[para]Description of sample1 |
||||||
|
# return "ok" |
||||||
|
#} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end definitions namespace %pkg% ---}] |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# Secondary API namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval %pkg%::lib { |
||||||
|
namespace export * |
||||||
|
namespace path [namespace parent] |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace %pkg%::lib}] |
||||||
|
#[para] Secondary functions that are part of the API |
||||||
|
#[list_begin definitions] |
||||||
|
|
||||||
|
#proc utility1 {p1 args} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call lib::[fun utility1] [arg p1] [opt {?option value...?}]] |
||||||
|
# #[para]Description of utility1 |
||||||
|
# return 1 |
||||||
|
#} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end definitions namespace %pkg%::lib ---}] |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[section Internal] |
||||||
|
namespace eval %pkg%::system { |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace %pkg%::system}] |
||||||
|
#[para] Internal functions that are not part of the API |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
package provide %pkg% [namespace eval %pkg% { |
||||||
|
variable pkg %pkg% |
||||||
|
variable version |
||||||
|
set version 999999.0a1.0 |
||||||
|
}] |
||||||
|
return |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[manpage_end] |
||||||
|
|
@ -1,52 +1,45 @@ |
|||||||
# -*- tcl -*- |
# -*- 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. |
||||||
# 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. |
||||||
# Code using preferred Tcl licenses can be eligible for inclusion in Tcllib, Tklib and the punk package repository. |
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
# (C) %year% |
||||||
# (C) %year% |
# |
||||||
# |
# @@ Meta Begin |
||||||
# @@ Meta Begin |
# Application %pkg% %version% |
||||||
# Application %pkg% 999999.0a1.0 |
# Meta platform tcl |
||||||
# Meta platform tcl |
# Meta license %license% |
||||||
# Meta license %license% |
# @@ Meta End |
||||||
# @@ Meta End |
|
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
## Requirements |
||||||
## Requirements |
##e.g package require frobz |
||||||
##e.g package require frobz |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
namespace eval %pkg% { |
||||||
namespace eval %pkg% { |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
package provide %pkg% [namespace eval %pkg% { |
||||||
|
variable version |
||||||
|
set version %version% |
||||||
|
}] |
||||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
||||||
## Ready |
|
||||||
package provide %pkg% [namespace eval %pkg% { |
|
||||||
variable pkg %pkg% |
|
||||||
variable version |
|
||||||
set version 999999.0a1.0 |
|
||||||
}] |
|
||||||
return |
return |
@ -0,0 +1,560 @@ |
|||||||
|
'\" |
||||||
|
'\" Generated from file '_module_ansi-0\&.1\&.0\&.tm\&.man' by tcllib/doctools with format 'nroff' |
||||||
|
'\" Copyright (c) 2023 |
||||||
|
'\" |
||||||
|
.TH "punkshell_module_punk::ansi" 0 0\&.1\&.0 doc "punk Ansi library" |
||||||
|
.\" The -*- nroff -*- definitions below are for supplemental macros used |
||||||
|
.\" in Tcl/Tk manual entries. |
||||||
|
.\" |
||||||
|
.\" .AP type name in/out ?indent? |
||||||
|
.\" Start paragraph describing an argument to a library procedure. |
||||||
|
.\" type is type of argument (int, etc.), in/out is either "in", "out", |
||||||
|
.\" or "in/out" to describe whether procedure reads or modifies arg, |
||||||
|
.\" and indent is equivalent to second arg of .IP (shouldn't ever be |
||||||
|
.\" needed; use .AS below instead) |
||||||
|
.\" |
||||||
|
.\" .AS ?type? ?name? |
||||||
|
.\" Give maximum sizes of arguments for setting tab stops. Type and |
||||||
|
.\" name are examples of largest possible arguments that will be passed |
||||||
|
.\" to .AP later. If args are omitted, default tab stops are used. |
||||||
|
.\" |
||||||
|
.\" .BS |
||||||
|
.\" Start box enclosure. From here until next .BE, everything will be |
||||||
|
.\" enclosed in one large box. |
||||||
|
.\" |
||||||
|
.\" .BE |
||||||
|
.\" End of box enclosure. |
||||||
|
.\" |
||||||
|
.\" .CS |
||||||
|
.\" Begin code excerpt. |
||||||
|
.\" |
||||||
|
.\" .CE |
||||||
|
.\" End code excerpt. |
||||||
|
.\" |
||||||
|
.\" .VS ?version? ?br? |
||||||
|
.\" Begin vertical sidebar, for use in marking newly-changed parts |
||||||
|
.\" of man pages. The first argument is ignored and used for recording |
||||||
|
.\" the version when the .VS was added, so that the sidebars can be |
||||||
|
.\" found and removed when they reach a certain age. If another argument |
||||||
|
.\" is present, then a line break is forced before starting the sidebar. |
||||||
|
.\" |
||||||
|
.\" .VE |
||||||
|
.\" End of vertical sidebar. |
||||||
|
.\" |
||||||
|
.\" .DS |
||||||
|
.\" Begin an indented unfilled display. |
||||||
|
.\" |
||||||
|
.\" .DE |
||||||
|
.\" End of indented unfilled display. |
||||||
|
.\" |
||||||
|
.\" .SO ?manpage? |
||||||
|
.\" Start of list of standard options for a Tk widget. The manpage |
||||||
|
.\" argument defines where to look up the standard options; if |
||||||
|
.\" omitted, defaults to "options". The options follow on successive |
||||||
|
.\" lines, in three columns separated by tabs. |
||||||
|
.\" |
||||||
|
.\" .SE |
||||||
|
.\" End of list of standard options for a Tk widget. |
||||||
|
.\" |
||||||
|
.\" .OP cmdName dbName dbClass |
||||||
|
.\" Start of description of a specific option. cmdName gives the |
||||||
|
.\" option's name as specified in the class command, dbName gives |
||||||
|
.\" the option's name in the option database, and dbClass gives |
||||||
|
.\" the option's class in the option database. |
||||||
|
.\" |
||||||
|
.\" .UL arg1 arg2 |
||||||
|
.\" Print arg1 underlined, then print arg2 normally. |
||||||
|
.\" |
||||||
|
.\" .QW arg1 ?arg2? |
||||||
|
.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation). |
||||||
|
.\" |
||||||
|
.\" .PQ arg1 ?arg2? |
||||||
|
.\" Print an open parenthesis, arg1 in quotes, then arg2 normally |
||||||
|
.\" (for trailing punctuation) and then a closing parenthesis. |
||||||
|
.\" |
||||||
|
.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. |
||||||
|
.if t .wh -1.3i ^B |
||||||
|
.nr ^l \n(.l |
||||||
|
.ad b |
||||||
|
.\" # Start an argument description |
||||||
|
.de AP |
||||||
|
.ie !"\\$4"" .TP \\$4 |
||||||
|
.el \{\ |
||||||
|
. ie !"\\$2"" .TP \\n()Cu |
||||||
|
. el .TP 15 |
||||||
|
.\} |
||||||
|
.ta \\n()Au \\n()Bu |
||||||
|
.ie !"\\$3"" \{\ |
||||||
|
\&\\$1 \\fI\\$2\\fP (\\$3) |
||||||
|
.\".b |
||||||
|
.\} |
||||||
|
.el \{\ |
||||||
|
.br |
||||||
|
.ie !"\\$2"" \{\ |
||||||
|
\&\\$1 \\fI\\$2\\fP |
||||||
|
.\} |
||||||
|
.el \{\ |
||||||
|
\&\\fI\\$1\\fP |
||||||
|
.\} |
||||||
|
.\} |
||||||
|
.. |
||||||
|
.\" # define tabbing values for .AP |
||||||
|
.de AS |
||||||
|
.nr )A 10n |
||||||
|
.if !"\\$1"" .nr )A \\w'\\$1'u+3n |
||||||
|
.nr )B \\n()Au+15n |
||||||
|
.\" |
||||||
|
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n |
||||||
|
.nr )C \\n()Bu+\\w'(in/out)'u+2n |
||||||
|
.. |
||||||
|
.AS Tcl_Interp Tcl_CreateInterp in/out |
||||||
|
.\" # BS - start boxed text |
||||||
|
.\" # ^y = starting y location |
||||||
|
.\" # ^b = 1 |
||||||
|
.de BS |
||||||
|
.br |
||||||
|
.mk ^y |
||||||
|
.nr ^b 1u |
||||||
|
.if n .nf |
||||||
|
.if n .ti 0 |
||||||
|
.if n \l'\\n(.lu\(ul' |
||||||
|
.if n .fi |
||||||
|
.. |
||||||
|
.\" # BE - end boxed text (draw box now) |
||||||
|
.de BE |
||||||
|
.nf |
||||||
|
.ti 0 |
||||||
|
.mk ^t |
||||||
|
.ie n \l'\\n(^lu\(ul' |
||||||
|
.el \{\ |
||||||
|
.\" Draw four-sided box normally, but don't draw top of |
||||||
|
.\" box if the box started on an earlier page. |
||||||
|
.ie !\\n(^b-1 \{\ |
||||||
|
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' |
||||||
|
.\} |
||||||
|
.el \}\ |
||||||
|
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' |
||||||
|
.\} |
||||||
|
.\} |
||||||
|
.fi |
||||||
|
.br |
||||||
|
.nr ^b 0 |
||||||
|
.. |
||||||
|
.\" # VS - start vertical sidebar |
||||||
|
.\" # ^Y = starting y location |
||||||
|
.\" # ^v = 1 (for troff; for nroff this doesn't matter) |
||||||
|
.de VS |
||||||
|
.if !"\\$2"" .br |
||||||
|
.mk ^Y |
||||||
|
.ie n 'mc \s12\(br\s0 |
||||||
|
.el .nr ^v 1u |
||||||
|
.. |
||||||
|
.\" # VE - end of vertical sidebar |
||||||
|
.de VE |
||||||
|
.ie n 'mc |
||||||
|
.el \{\ |
||||||
|
.ev 2 |
||||||
|
.nf |
||||||
|
.ti 0 |
||||||
|
.mk ^t |
||||||
|
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' |
||||||
|
.sp -1 |
||||||
|
.fi |
||||||
|
.ev |
||||||
|
.\} |
||||||
|
.nr ^v 0 |
||||||
|
.. |
||||||
|
.\" # Special macro to handle page bottom: finish off current |
||||||
|
.\" # box/sidebar if in box/sidebar mode, then invoked standard |
||||||
|
.\" # page bottom macro. |
||||||
|
.de ^B |
||||||
|
.ev 2 |
||||||
|
'ti 0 |
||||||
|
'nf |
||||||
|
.mk ^t |
||||||
|
.if \\n(^b \{\ |
||||||
|
.\" Draw three-sided box if this is the box's first page, |
||||||
|
.\" draw two sides but no top otherwise. |
||||||
|
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c |
||||||
|
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c |
||||||
|
.\} |
||||||
|
.if \\n(^v \{\ |
||||||
|
.nr ^x \\n(^tu+1v-\\n(^Yu |
||||||
|
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c |
||||||
|
.\} |
||||||
|
.bp |
||||||
|
'fi |
||||||
|
.ev |
||||||
|
.if \\n(^b \{\ |
||||||
|
.mk ^y |
||||||
|
.nr ^b 2 |
||||||
|
.\} |
||||||
|
.if \\n(^v \{\ |
||||||
|
.mk ^Y |
||||||
|
.\} |
||||||
|
.. |
||||||
|
.\" # DS - begin display |
||||||
|
.de DS |
||||||
|
.RS |
||||||
|
.nf |
||||||
|
.sp |
||||||
|
.. |
||||||
|
.\" # DE - end display |
||||||
|
.de DE |
||||||
|
.fi |
||||||
|
.RE |
||||||
|
.sp |
||||||
|
.. |
||||||
|
.\" # SO - start of list of standard options |
||||||
|
.de SO |
||||||
|
'ie '\\$1'' .ds So \\fBoptions\\fR |
||||||
|
'el .ds So \\fB\\$1\\fR |
||||||
|
.SH "STANDARD OPTIONS" |
||||||
|
.LP |
||||||
|
.nf |
||||||
|
.ta 5.5c 11c |
||||||
|
.ft B |
||||||
|
.. |
||||||
|
.\" # SE - end of list of standard options |
||||||
|
.de SE |
||||||
|
.fi |
||||||
|
.ft R |
||||||
|
.LP |
||||||
|
See the \\*(So manual entry for details on the standard options. |
||||||
|
.. |
||||||
|
.\" # OP - start of full description for a single option |
||||||
|
.de OP |
||||||
|
.LP |
||||||
|
.nf |
||||||
|
.ta 4c |
||||||
|
Command-Line Name: \\fB\\$1\\fR |
||||||
|
Database Name: \\fB\\$2\\fR |
||||||
|
Database Class: \\fB\\$3\\fR |
||||||
|
.fi |
||||||
|
.IP |
||||||
|
.. |
||||||
|
.\" # CS - begin code excerpt |
||||||
|
.de CS |
||||||
|
.RS |
||||||
|
.nf |
||||||
|
.ta .25i .5i .75i 1i |
||||||
|
.. |
||||||
|
.\" # CE - end code excerpt |
||||||
|
.de CE |
||||||
|
.fi |
||||||
|
.RE |
||||||
|
.. |
||||||
|
.\" # UL - underline word |
||||||
|
.de UL |
||||||
|
\\$1\l'|0\(ul'\\$2 |
||||||
|
.. |
||||||
|
.\" # QW - apply quotation marks to word |
||||||
|
.de QW |
||||||
|
.ie '\\*(lq'"' ``\\$1''\\$2 |
||||||
|
.\"" fix emacs highlighting |
||||||
|
.el \\*(lq\\$1\\*(rq\\$2 |
||||||
|
.. |
||||||
|
.\" # PQ - apply parens and quotation marks to word |
||||||
|
.de PQ |
||||||
|
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3 |
||||||
|
.\"" fix emacs highlighting |
||||||
|
.el (\\*(lq\\$1\\*(rq\\$2)\\$3 |
||||||
|
.. |
||||||
|
.\" # QR - quoted range |
||||||
|
.de QR |
||||||
|
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3 |
||||||
|
.\"" fix emacs highlighting |
||||||
|
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3 |
||||||
|
.. |
||||||
|
.\" # MT - "empty" string |
||||||
|
.de MT |
||||||
|
.QW "" |
||||||
|
.. |
||||||
|
.BS |
||||||
|
.SH NAME |
||||||
|
punkshell_module_punk::ansi \- Ansi string functions |
||||||
|
.SH SYNOPSIS |
||||||
|
package require \fBpunk::ansi \fR |
||||||
|
.sp |
||||||
|
\fBstripansi\fR \fItext\fR |
||||||
|
.sp |
||||||
|
\fBa?\fR ?ansicode\&.\&.\&.? |
||||||
|
.sp |
||||||
|
\fBa+\fR ?ansicode\&.\&.\&.? |
||||||
|
.sp |
||||||
|
\fBa\fR ?ansicode\&.\&.\&.? |
||||||
|
.sp |
||||||
|
\fBget_code_name\fR \fIcode\fR |
||||||
|
.sp |
||||||
|
\fBreset\fR |
||||||
|
.sp |
||||||
|
\fBreset_soft\fR |
||||||
|
.sp |
||||||
|
\fBreset_colour\fR |
||||||
|
.sp |
||||||
|
\fBclear\fR |
||||||
|
.sp |
||||||
|
\fBclear_above\fR |
||||||
|
.sp |
||||||
|
\fBclear_below\fR |
||||||
|
.sp |
||||||
|
\fBcursor_on\fR |
||||||
|
.sp |
||||||
|
\fBcursor_off\fR |
||||||
|
.sp |
||||||
|
\fBmove\fR \fIrow\fR \fIcol\fR |
||||||
|
.sp |
||||||
|
\fBmove_emit\fR \fIrow\fR \fIcol\fR \fIdata\fR ?row col data\&.\&.\&.? |
||||||
|
.sp |
||||||
|
\fBmove_forward\fR \fIn\fR |
||||||
|
.sp |
||||||
|
\fBmove_back\fR \fIn\fR |
||||||
|
.sp |
||||||
|
\fBmove_up\fR \fIn\fR |
||||||
|
.sp |
||||||
|
\fBmove_down\fR \fIn\fR |
||||||
|
.sp |
||||||
|
\fBerase_line\fR |
||||||
|
.sp |
||||||
|
\fBerase_sol\fR |
||||||
|
.sp |
||||||
|
\fBerase_eol\fR |
||||||
|
.sp |
||||||
|
\fBcursor_pos\fR |
||||||
|
.sp |
||||||
|
\fBtitleset\fR \fIwindowtitles\fR |
||||||
|
.sp |
||||||
|
\fBdetect\fR \fItext\fR |
||||||
|
.sp |
||||||
|
\fBdetect_csi\fR \fItext\fR |
||||||
|
.sp |
||||||
|
\fBdetect_sgr\fR \fItext\fR |
||||||
|
.sp |
||||||
|
\fBstrip\fR \fItext\fR |
||||||
|
.sp |
||||||
|
\fBlength\fR \fItext\fR |
||||||
|
.sp |
||||||
|
.BE |
||||||
|
.SH DESCRIPTION |
||||||
|
.PP |
||||||
|
Ansi based terminal control string functions |
||||||
|
.PP |
||||||
|
See \fBpunk::ansi::console\fR for related functions for controlling a console |
||||||
|
.SH OVERVIEW |
||||||
|
.PP |
||||||
|
overview of punk::ansi |
||||||
|
.PP |
||||||
|
punk::ansi functions return their values - no implicit emission to console/stdout |
||||||
|
.SS CONCEPTS |
||||||
|
.PP |
||||||
|
Ansi codes can be used to control most terminals on most platforms in an 'almost' standard manner |
||||||
|
.PP |
||||||
|
There are many differences in terminal implementations - but most should support a core set of features |
||||||
|
.PP |
||||||
|
punk::ansi does not contain any code for direct terminal manipulation via the local system APIs\&. |
||||||
|
.PP |
||||||
|
Sticking to ansi codes where possible may be better for cross-platform and remote operation where such APIs are unlikely to be useable\&. |
||||||
|
.SS DEPENDENCIES |
||||||
|
.PP |
||||||
|
packages used by punk::ansi |
||||||
|
.IP \(bu |
||||||
|
\fBTcl 8\&.6\fR |
||||||
|
.PP |
||||||
|
.SH API |
||||||
|
.SS "NAMESPACE PUNK::ANSI" |
||||||
|
.PP |
||||||
|
Core API functions for punk::ansi |
||||||
|
.TP |
||||||
|
\fBstripansi\fR \fItext\fR |
||||||
|
.sp |
||||||
|
Return a string with ansi codes stripped out |
||||||
|
.TP |
||||||
|
\fBa?\fR ?ansicode\&.\&.\&.? |
||||||
|
.sp |
||||||
|
Return an ansi string representing a table of codes and a panel showing the colours |
||||||
|
.TP |
||||||
|
\fBa+\fR ?ansicode\&.\&.\&.? |
||||||
|
.sp |
||||||
|
Returns the ansi code to apply those from the supplied list - without any reset being performed first |
||||||
|
.sp |
||||||
|
e\&.g to set foreground red and bold |
||||||
|
.sp |
||||||
|
punk::ansi::a red bold |
||||||
|
.sp |
||||||
|
to set background red |
||||||
|
.sp |
||||||
|
punk::ansi::a Red |
||||||
|
.sp |
||||||
|
see \fBpunk::ansi::a?\fR to display a list of codes |
||||||
|
.TP |
||||||
|
\fBa\fR ?ansicode\&.\&.\&.? |
||||||
|
.sp |
||||||
|
Returns the ansi code to reset any current settings and apply those from the supplied list |
||||||
|
.sp |
||||||
|
by calling punk::ansi::a with no arguments - the result is a reset to plain text |
||||||
|
.sp |
||||||
|
e\&.g to set foreground red and bold |
||||||
|
.sp |
||||||
|
punk::ansi::a red bold |
||||||
|
.sp |
||||||
|
to set background red |
||||||
|
.sp |
||||||
|
punk::ansi::a Red |
||||||
|
.sp |
||||||
|
see \fBpunk::ansi::a?\fR to display a list of codes |
||||||
|
.TP |
||||||
|
\fBget_code_name\fR \fIcode\fR |
||||||
|
.sp |
||||||
|
for example |
||||||
|
.sp |
||||||
|
get_code_name red will return 31 |
||||||
|
.sp |
||||||
|
get_code_name 31 will return red |
||||||
|
.TP |
||||||
|
\fBreset\fR |
||||||
|
.sp |
||||||
|
reset console |
||||||
|
.TP |
||||||
|
\fBreset_soft\fR |
||||||
|
.TP |
||||||
|
\fBreset_colour\fR |
||||||
|
.sp |
||||||
|
reset colour only |
||||||
|
.TP |
||||||
|
\fBclear\fR |
||||||
|
.TP |
||||||
|
\fBclear_above\fR |
||||||
|
.TP |
||||||
|
\fBclear_below\fR |
||||||
|
.TP |
||||||
|
\fBcursor_on\fR |
||||||
|
.TP |
||||||
|
\fBcursor_off\fR |
||||||
|
.TP |
||||||
|
\fBmove\fR \fIrow\fR \fIcol\fR |
||||||
|
.sp |
||||||
|
Return an ansi sequence to move to row,col |
||||||
|
.sp |
||||||
|
aka cursor home |
||||||
|
.TP |
||||||
|
\fBmove_emit\fR \fIrow\fR \fIcol\fR \fIdata\fR ?row col data\&.\&.\&.? |
||||||
|
.sp |
||||||
|
Return an ansi string representing a move to row col with data appended |
||||||
|
.sp |
||||||
|
row col data can be repeated any number of times to return a string representing the output of the data elements at all those points |
||||||
|
.sp |
||||||
|
Compare to punk::console::move_emit which calls this function - but writes it to stdout |
||||||
|
.sp |
||||||
|
punk::console::move_emit_return will also return the cursor to the original position |
||||||
|
.sp |
||||||
|
There is no punk::ansi::move_emit_return because in a standard console there is no ansi string which can represent a jump back to starting position\&. |
||||||
|
.sp |
||||||
|
There is an ansi code to write the current cursor position to stdin (which will generally display on the console) - this is not quite the same thing\&. |
||||||
|
.sp |
||||||
|
punk::console::move_emit_return does it by emitting that code and starting a loop to read stdin |
||||||
|
.sp |
||||||
|
punk::ansi could implement a move_emit_return using the punk::console mechanism - but the resulting string would capture the cursor position at the time the string is built - which is not necessarily when the string is used\&. |
||||||
|
.sp |
||||||
|
The following example shows how to do this manually, emitting the string blah at screen position 10,10 and emitting DONE back at the line we started: |
||||||
|
.sp |
||||||
|
.CS |
||||||
|
|
||||||
|
punk::ansi::move_emit 10 10 blah {*}[punk::console::get_cursor_pos_list] DONE |
||||||
|
.CE |
||||||
|
.sp |
||||||
|
A string created by any move_emit_return for punk::ansi would not behave in an intuitive manner compared to other punk::ansi move functions - so is deliberately omitted\&. |
||||||
|
.TP |
||||||
|
\fBmove_forward\fR \fIn\fR |
||||||
|
.TP |
||||||
|
\fBmove_back\fR \fIn\fR |
||||||
|
.TP |
||||||
|
\fBmove_up\fR \fIn\fR |
||||||
|
.TP |
||||||
|
\fBmove_down\fR \fIn\fR |
||||||
|
.TP |
||||||
|
\fBerase_line\fR |
||||||
|
.TP |
||||||
|
\fBerase_sol\fR |
||||||
|
.sp |
||||||
|
Erase to start of line, leaving cursor position alone\&. |
||||||
|
.TP |
||||||
|
\fBerase_eol\fR |
||||||
|
.TP |
||||||
|
\fBcursor_pos\fR |
||||||
|
.sp |
||||||
|
cursor_pos unlikely to be useful on it's own like this as when written to the terminal, this sequence causes the terminal to emit the row;col sequence to stdin |
||||||
|
.sp |
||||||
|
The output on screen will look something like ^[[47;3R |
||||||
|
.sp |
||||||
|
Use punk::console::get_cursor_pos or punk::console::get_cursor_pos_list instead\&. |
||||||
|
.sp |
||||||
|
These functions will emit the code - but read it in from stdin so that it doesn't display, and then return the row and column as a colon-delimited string or list respectively\&. |
||||||
|
.sp |
||||||
|
The punk::ansi::cursor_pos function is used by punk::console::get_cursor_pos and punk::console::get_cursor_pos_list |
||||||
|
.TP |
||||||
|
\fBtitleset\fR \fIwindowtitles\fR |
||||||
|
.sp |
||||||
|
Returns the code to set the title of the terminal window to windowtitle |
||||||
|
.sp |
||||||
|
This may not work on terminals which have multiple panes/windows |
||||||
|
.PP |
||||||
|
.SS "NAMESPACE PUNK::ANSI::TA" |
||||||
|
.PP |
||||||
|
text ansi functions |
||||||
|
.PP |
||||||
|
based on but not identical to the Perl Text Ansi module: |
||||||
|
.PP |
||||||
|
https://github\&.com/perlancar/perl-Text-ANSI-Util/blob/master/lib/Text/ANSI/BaseUtil\&.pm |
||||||
|
.TP |
||||||
|
\fBdetect\fR \fItext\fR |
||||||
|
.sp |
||||||
|
Return a boolean indicating whether Ansi codes were detected in text |
||||||
|
.sp |
||||||
|
.TP |
||||||
|
\fBdetect_csi\fR \fItext\fR |
||||||
|
.sp |
||||||
|
Return a boolean indicating whether an Ansi Control Sequence Introducer (CSI) was detected in text |
||||||
|
.sp |
||||||
|
The csi is often represented in code as \\x1b or \\033 followed by a left bracket [ |
||||||
|
.sp |
||||||
|
The initial byte or escape is commonly referenced as ESC in Ansi documentation |
||||||
|
.sp |
||||||
|
There is also a multi-byte escape sequence \\u009b |
||||||
|
.sp |
||||||
|
This is less commonly used but is also detected here |
||||||
|
.sp |
||||||
|
(This function is not in perl ta) |
||||||
|
.TP |
||||||
|
\fBdetect_sgr\fR \fItext\fR |
||||||
|
.sp |
||||||
|
Return a boolean indicating whether an ansi Select Graphics Rendition code was detected\&. |
||||||
|
.sp |
||||||
|
This is the set of CSI sequences ending in 'm' |
||||||
|
.sp |
||||||
|
This is most commonly an Ansi colour code - but also things such as underline and italics |
||||||
|
.sp |
||||||
|
An SGR with empty or a single zero argument is a reset of the SGR features - this is also detected\&. |
||||||
|
.sp |
||||||
|
(This function is not in perl ta) |
||||||
|
.TP |
||||||
|
\fBstrip\fR \fItext\fR |
||||||
|
.sp |
||||||
|
Return text stripped of Ansi codes |
||||||
|
.sp |
||||||
|
This is a tailcall to punk::ansi::stripansi |
||||||
|
.TP |
||||||
|
\fBlength\fR \fItext\fR |
||||||
|
.sp |
||||||
|
Return the character length after stripping ansi codes - not the printing length |
||||||
|
.PP |
||||||
|
.SS "NAMESPACE PUNK::ANSI::ANSISTRING" |
||||||
|
.PP |
||||||
|
punk::ansi::string ensemble |
||||||
|
.PP |
||||||
|
.SH KEYWORDS |
||||||
|
ansi, console, module, string, terminal |
||||||
|
.SH COPYRIGHT |
||||||
|
.nf |
||||||
|
Copyright (c) 2023 |
||||||
|
|
||||||
|
.fi |
@ -0,0 +1,400 @@ |
|||||||
|
'\" |
||||||
|
'\" Generated from file '_module_args-0\&.1\&.0\&.tm\&.man' by tcllib/doctools with format 'nroff' |
||||||
|
'\" Copyright (c) 2024 |
||||||
|
'\" |
||||||
|
.TH "punkshell_module_punk::args" 0 0\&.1\&.0 doc "args to option-value dict and values dict" |
||||||
|
.\" The -*- nroff -*- definitions below are for supplemental macros used |
||||||
|
.\" in Tcl/Tk manual entries. |
||||||
|
.\" |
||||||
|
.\" .AP type name in/out ?indent? |
||||||
|
.\" Start paragraph describing an argument to a library procedure. |
||||||
|
.\" type is type of argument (int, etc.), in/out is either "in", "out", |
||||||
|
.\" or "in/out" to describe whether procedure reads or modifies arg, |
||||||
|
.\" and indent is equivalent to second arg of .IP (shouldn't ever be |
||||||
|
.\" needed; use .AS below instead) |
||||||
|
.\" |
||||||
|
.\" .AS ?type? ?name? |
||||||
|
.\" Give maximum sizes of arguments for setting tab stops. Type and |
||||||
|
.\" name are examples of largest possible arguments that will be passed |
||||||
|
.\" to .AP later. If args are omitted, default tab stops are used. |
||||||
|
.\" |
||||||
|
.\" .BS |
||||||
|
.\" Start box enclosure. From here until next .BE, everything will be |
||||||
|
.\" enclosed in one large box. |
||||||
|
.\" |
||||||
|
.\" .BE |
||||||
|
.\" End of box enclosure. |
||||||
|
.\" |
||||||
|
.\" .CS |
||||||
|
.\" Begin code excerpt. |
||||||
|
.\" |
||||||
|
.\" .CE |
||||||
|
.\" End code excerpt. |
||||||
|
.\" |
||||||
|
.\" .VS ?version? ?br? |
||||||
|
.\" Begin vertical sidebar, for use in marking newly-changed parts |
||||||
|
.\" of man pages. The first argument is ignored and used for recording |
||||||
|
.\" the version when the .VS was added, so that the sidebars can be |
||||||
|
.\" found and removed when they reach a certain age. If another argument |
||||||
|
.\" is present, then a line break is forced before starting the sidebar. |
||||||
|
.\" |
||||||
|
.\" .VE |
||||||
|
.\" End of vertical sidebar. |
||||||
|
.\" |
||||||
|
.\" .DS |
||||||
|
.\" Begin an indented unfilled display. |
||||||
|
.\" |
||||||
|
.\" .DE |
||||||
|
.\" End of indented unfilled display. |
||||||
|
.\" |
||||||
|
.\" .SO ?manpage? |
||||||
|
.\" Start of list of standard options for a Tk widget. The manpage |
||||||
|
.\" argument defines where to look up the standard options; if |
||||||
|
.\" omitted, defaults to "options". The options follow on successive |
||||||
|
.\" lines, in three columns separated by tabs. |
||||||
|
.\" |
||||||
|
.\" .SE |
||||||
|
.\" End of list of standard options for a Tk widget. |
||||||
|
.\" |
||||||
|
.\" .OP cmdName dbName dbClass |
||||||
|
.\" Start of description of a specific option. cmdName gives the |
||||||
|
.\" option's name as specified in the class command, dbName gives |
||||||
|
.\" the option's name in the option database, and dbClass gives |
||||||
|
.\" the option's class in the option database. |
||||||
|
.\" |
||||||
|
.\" .UL arg1 arg2 |
||||||
|
.\" Print arg1 underlined, then print arg2 normally. |
||||||
|
.\" |
||||||
|
.\" .QW arg1 ?arg2? |
||||||
|
.\" Print arg1 in quotes, then arg2 normally (for trailing punctuation). |
||||||
|
.\" |
||||||
|
.\" .PQ arg1 ?arg2? |
||||||
|
.\" Print an open parenthesis, arg1 in quotes, then arg2 normally |
||||||
|
.\" (for trailing punctuation) and then a closing parenthesis. |
||||||
|
.\" |
||||||
|
.\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. |
||||||
|
.if t .wh -1.3i ^B |
||||||
|
.nr ^l \n(.l |
||||||
|
.ad b |
||||||
|
.\" # Start an argument description |
||||||
|
.de AP |
||||||
|
.ie !"\\$4"" .TP \\$4 |
||||||
|
.el \{\ |
||||||
|
. ie !"\\$2"" .TP \\n()Cu |
||||||
|
. el .TP 15 |
||||||
|
.\} |
||||||
|
.ta \\n()Au \\n()Bu |
||||||
|
.ie !"\\$3"" \{\ |
||||||
|
\&\\$1 \\fI\\$2\\fP (\\$3) |
||||||
|
.\".b |
||||||
|
.\} |
||||||
|
.el \{\ |
||||||
|
.br |
||||||
|
.ie !"\\$2"" \{\ |
||||||
|
\&\\$1 \\fI\\$2\\fP |
||||||
|
.\} |
||||||
|
.el \{\ |
||||||
|
\&\\fI\\$1\\fP |
||||||
|
.\} |
||||||
|
.\} |
||||||
|
.. |
||||||
|
.\" # define tabbing values for .AP |
||||||
|
.de AS |
||||||
|
.nr )A 10n |
||||||
|
.if !"\\$1"" .nr )A \\w'\\$1'u+3n |
||||||
|
.nr )B \\n()Au+15n |
||||||
|
.\" |
||||||
|
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n |
||||||
|
.nr )C \\n()Bu+\\w'(in/out)'u+2n |
||||||
|
.. |
||||||
|
.AS Tcl_Interp Tcl_CreateInterp in/out |
||||||
|
.\" # BS - start boxed text |
||||||
|
.\" # ^y = starting y location |
||||||
|
.\" # ^b = 1 |
||||||
|
.de BS |
||||||
|
.br |
||||||
|
.mk ^y |
||||||
|
.nr ^b 1u |
||||||
|
.if n .nf |
||||||
|
.if n .ti 0 |
||||||
|
.if n \l'\\n(.lu\(ul' |
||||||
|
.if n .fi |
||||||
|
.. |
||||||
|
.\" # BE - end boxed text (draw box now) |
||||||
|
.de BE |
||||||
|
.nf |
||||||
|
.ti 0 |
||||||
|
.mk ^t |
||||||
|
.ie n \l'\\n(^lu\(ul' |
||||||
|
.el \{\ |
||||||
|
.\" Draw four-sided box normally, but don't draw top of |
||||||
|
.\" box if the box started on an earlier page. |
||||||
|
.ie !\\n(^b-1 \{\ |
||||||
|
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' |
||||||
|
.\} |
||||||
|
.el \}\ |
||||||
|
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' |
||||||
|
.\} |
||||||
|
.\} |
||||||
|
.fi |
||||||
|
.br |
||||||
|
.nr ^b 0 |
||||||
|
.. |
||||||
|
.\" # VS - start vertical sidebar |
||||||
|
.\" # ^Y = starting y location |
||||||
|
.\" # ^v = 1 (for troff; for nroff this doesn't matter) |
||||||
|
.de VS |
||||||
|
.if !"\\$2"" .br |
||||||
|
.mk ^Y |
||||||
|
.ie n 'mc \s12\(br\s0 |
||||||
|
.el .nr ^v 1u |
||||||
|
.. |
||||||
|
.\" # VE - end of vertical sidebar |
||||||
|
.de VE |
||||||
|
.ie n 'mc |
||||||
|
.el \{\ |
||||||
|
.ev 2 |
||||||
|
.nf |
||||||
|
.ti 0 |
||||||
|
.mk ^t |
||||||
|
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' |
||||||
|
.sp -1 |
||||||
|
.fi |
||||||
|
.ev |
||||||
|
.\} |
||||||
|
.nr ^v 0 |
||||||
|
.. |
||||||
|
.\" # Special macro to handle page bottom: finish off current |
||||||
|
.\" # box/sidebar if in box/sidebar mode, then invoked standard |
||||||
|
.\" # page bottom macro. |
||||||
|
.de ^B |
||||||
|
.ev 2 |
||||||
|
'ti 0 |
||||||
|
'nf |
||||||
|
.mk ^t |
||||||
|
.if \\n(^b \{\ |
||||||
|
.\" Draw three-sided box if this is the box's first page, |
||||||
|
.\" draw two sides but no top otherwise. |
||||||
|
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c |
||||||
|
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c |
||||||
|
.\} |
||||||
|
.if \\n(^v \{\ |
||||||
|
.nr ^x \\n(^tu+1v-\\n(^Yu |
||||||
|
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c |
||||||
|
.\} |
||||||
|
.bp |
||||||
|
'fi |
||||||
|
.ev |
||||||
|
.if \\n(^b \{\ |
||||||
|
.mk ^y |
||||||
|
.nr ^b 2 |
||||||
|
.\} |
||||||
|
.if \\n(^v \{\ |
||||||
|
.mk ^Y |
||||||
|
.\} |
||||||
|
.. |
||||||
|
.\" # DS - begin display |
||||||
|
.de DS |
||||||
|
.RS |
||||||
|
.nf |
||||||
|
.sp |
||||||
|
.. |
||||||
|
.\" # DE - end display |
||||||
|
.de DE |
||||||
|
.fi |
||||||
|
.RE |
||||||
|
.sp |
||||||
|
.. |
||||||
|
.\" # SO - start of list of standard options |
||||||
|
.de SO |
||||||
|
'ie '\\$1'' .ds So \\fBoptions\\fR |
||||||
|
'el .ds So \\fB\\$1\\fR |
||||||
|
.SH "STANDARD OPTIONS" |
||||||
|
.LP |
||||||
|
.nf |
||||||
|
.ta 5.5c 11c |
||||||
|
.ft B |
||||||
|
.. |
||||||
|
.\" # SE - end of list of standard options |
||||||
|
.de SE |
||||||
|
.fi |
||||||
|
.ft R |
||||||
|
.LP |
||||||
|
See the \\*(So manual entry for details on the standard options. |
||||||
|
.. |
||||||
|
.\" # OP - start of full description for a single option |
||||||
|
.de OP |
||||||
|
.LP |
||||||
|
.nf |
||||||
|
.ta 4c |
||||||
|
Command-Line Name: \\fB\\$1\\fR |
||||||
|
Database Name: \\fB\\$2\\fR |
||||||
|
Database Class: \\fB\\$3\\fR |
||||||
|
.fi |
||||||
|
.IP |
||||||
|
.. |
||||||
|
.\" # CS - begin code excerpt |
||||||
|
.de CS |
||||||
|
.RS |
||||||
|
.nf |
||||||
|
.ta .25i .5i .75i 1i |
||||||
|
.. |
||||||
|
.\" # CE - end code excerpt |
||||||
|
.de CE |
||||||
|
.fi |
||||||
|
.RE |
||||||
|
.. |
||||||
|
.\" # UL - underline word |
||||||
|
.de UL |
||||||
|
\\$1\l'|0\(ul'\\$2 |
||||||
|
.. |
||||||
|
.\" # QW - apply quotation marks to word |
||||||
|
.de QW |
||||||
|
.ie '\\*(lq'"' ``\\$1''\\$2 |
||||||
|
.\"" fix emacs highlighting |
||||||
|
.el \\*(lq\\$1\\*(rq\\$2 |
||||||
|
.. |
||||||
|
.\" # PQ - apply parens and quotation marks to word |
||||||
|
.de PQ |
||||||
|
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3 |
||||||
|
.\"" fix emacs highlighting |
||||||
|
.el (\\*(lq\\$1\\*(rq\\$2)\\$3 |
||||||
|
.. |
||||||
|
.\" # QR - quoted range |
||||||
|
.de QR |
||||||
|
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3 |
||||||
|
.\"" fix emacs highlighting |
||||||
|
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3 |
||||||
|
.. |
||||||
|
.\" # MT - "empty" string |
||||||
|
.de MT |
||||||
|
.QW "" |
||||||
|
.. |
||||||
|
.BS |
||||||
|
.SH NAME |
||||||
|
punkshell_module_punk::args \- args parsing |
||||||
|
.SH SYNOPSIS |
||||||
|
package require \fBpunk::args \fR |
||||||
|
.sp |
||||||
|
\fBopts_values\fR \fIoptionspecs\fR \fIrawargs\fR ?option value\&.\&.\&.? |
||||||
|
.sp |
||||||
|
.BE |
||||||
|
.SH DESCRIPTION |
||||||
|
.PP |
||||||
|
Utilities for parsing proc args |
||||||
|
.SH OVERVIEW |
||||||
|
.PP |
||||||
|
overview of punk::args |
||||||
|
.SS CONCEPTS |
||||||
|
.PP |
||||||
|
There are 2 main conventions for parsing a proc args list |
||||||
|
.IP [1] |
||||||
|
.sp |
||||||
|
leading option-value pairs followed by a list of values (Tk style) |
||||||
|
.IP [2] |
||||||
|
.sp |
||||||
|
leading list of values followed by option-value pairs (Tcl style) |
||||||
|
.PP |
||||||
|
.PP |
||||||
|
punk::args is focused on the 1st convention (Tk style): parsing of args in leading option-value pair style - even for non-Tk usage\&. |
||||||
|
.PP |
||||||
|
The proc can still contain some leading required values e\&.g |
||||||
|
.CS |
||||||
|
|
||||||
|
proc dostuff {arg1 arg2 args} {\&.\&.\&.}} |
||||||
|
.CE |
||||||
|
.PP |
||||||
|
but having the core values elements at the end of args is more generally useful - especially in cases where the number of trailing values is unknown and/or the proc is to be called in a functional 'pipeline' style\&. |
||||||
|
.PP |
||||||
|
The basic principle is that a call to punk::args::opts_vals is made near the beginning of the proc e\&.g |
||||||
|
.CS |
||||||
|
|
||||||
|
|
||||||
|
proc dofilestuff {args} { |
||||||
|
lassign [dict values [punk::args { |
||||||
|
-directory -default "" |
||||||
|
-translation -default binary |
||||||
|
} $args]] opts values |
||||||
|
|
||||||
|
puts "translation is [dict get $opts -translation]" |
||||||
|
foreach f [dict values $values] { |
||||||
|
puts "doing stuff with file: $f" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.CE |
||||||
|
.SS NOTES |
||||||
|
.PP |
||||||
|
There are alternative args parsing packages such as: |
||||||
|
.IP [1] |
||||||
|
argp |
||||||
|
.IP [2] |
||||||
|
The tcllib set of TEPAM modules |
||||||
|
.sp |
||||||
|
TEPAM requires an alternative procedure declaration syntax instead of proc - but has support for Tk and documentation generation\&. |
||||||
|
.PP |
||||||
|
.PP |
||||||
|
punk::args was designed initially without specific reference to TEPAM - and to handle some edge cases in specific projects where TEPAM wasn't suitable\&. |
||||||
|
.PP |
||||||
|
In subsequent revisions of punk::args - some features were made to operate in a way that is similar to TEPAM - to avoid gratuitous differences where possible, but of course there are differences |
||||||
|
.PP |
||||||
|
and those used TEPAM or mixing TEPAM and punk::args should take care to assess the differences\&. |
||||||
|
.PP |
||||||
|
TEPAM is a mature solution and is widely available as it is included in tcllib\&. |
||||||
|
.PP |
||||||
|
Serious consideration should be given to using TEPAM if suitable for your project\&. |
||||||
|
.SS DEPENDENCIES |
||||||
|
.PP |
||||||
|
packages used by punk::args |
||||||
|
.IP \(bu |
||||||
|
\fBTcl 8\&.6\fR |
||||||
|
.PP |
||||||
|
.SH API |
||||||
|
.SS "NAMESPACE PUNK::ARGS::CLASS" |
||||||
|
.PP |
||||||
|
class definitions |
||||||
|
.PP |
||||||
|
.SS "NAMESPACE PUNK::ARGS" |
||||||
|
.PP |
||||||
|
Core API functions for punk::args |
||||||
|
.TP |
||||||
|
\fBopts_values\fR \fIoptionspecs\fR \fIrawargs\fR ?option value\&.\&.\&.? |
||||||
|
.sp |
||||||
|
Parse rawargs as a sequence of zero or more option-value pairs followed by zero or more values |
||||||
|
.sp |
||||||
|
Returns a dict of the form: opts <options_dict> values <values_dict> |
||||||
|
.sp |
||||||
|
ARGUMENTS: |
||||||
|
.RS |
||||||
|
.TP |
||||||
|
multiline-string \fIoptionspecs\fR |
||||||
|
.sp |
||||||
|
This a block of text with records delimited by newlines (lf or crlf) |
||||||
|
.sp |
||||||
|
Each optionspec line must be of the form: |
||||||
|
.sp |
||||||
|
-optionname -key val -key2 val2\&.\&.\&. |
||||||
|
.sp |
||||||
|
where the valid keys for each option specification are: -default -type -range -choices -optional |
||||||
|
.TP |
||||||
|
list \fIrawargs\fR |
||||||
|
.sp |
||||||
|
This is a list of the arguments to parse\&. Usually it will be the \\$args value from the containing proc |
||||||
|
.RE |
||||||
|
.sp |
||||||
|
.PP |
||||||
|
.SS "NAMESPACE PUNK::ARGS::LIB" |
||||||
|
.PP |
||||||
|
Secondary functions that are part of the API |
||||||
|
.PP |
||||||
|
.SH INTERNAL |
||||||
|
.SS "NAMESPACE PUNK::ARGS::SYSTEM" |
||||||
|
.PP |
||||||
|
Internal functions that are not part of the API |
||||||
|
.SH KEYWORDS |
||||||
|
args, arguments, module, parse, proc |
||||||
|
.SH COPYRIGHT |
||||||
|
.nf |
||||||
|
Copyright (c) 2024 |
||||||
|
|
||||||
|
.fi |
@ -1 +1 @@ |
|||||||
{file {{doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline}} repl {{doc/files/project_intro.md punkshell__project_intro} {doc/files/project_changes.md punkshell__project_changes} {doc/files/main.md punkshell}} text {{doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline}} shell {{doc/files/project_intro.md punkshell__project_intro} {doc/files/project_changes.md punkshell__project_changes} {doc/files/main.md punkshell}} changelog {{doc/files/project_changes.md punkshell__project_changes}} capability {{doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap}} parse {{doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline}} filesystem {{doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path}} path {{doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path}} module {{doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} {doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap} {doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path} {doc/files/punk/_module_flib-0.1.0.tm.md shellspy_module_punk::flib}} punk {{doc/files/project_intro.md punkshell__project_intro} {doc/files/project_changes.md punkshell__project_changes} {doc/files/main.md punkshell}} plugin {{doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap}}} {{shell doc/files/project_changes.md punkshell__project_changes} . {changelog doc/files/project_changes.md punkshell__project_changes} . {shell doc/files/main.md punkshell} . {text doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} . {repl doc/files/project_intro.md punkshell__project_intro} . {module doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap} . {plugin doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap} . {filesystem doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path} . {path doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path} . {module doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path} . {punk doc/files/project_changes.md punkshell__project_changes} . {shell doc/files/project_intro.md punkshell__project_intro} . {parse doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} . {punk doc/files/main.md punkshell} . {module doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} . {module doc/files/punk/_module_flib-0.1.0.tm.md shellspy_module_punk::flib} . {repl doc/files/project_changes.md punkshell__project_changes} . {punk doc/files/project_intro.md punkshell__project_intro} . {file doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} . {repl doc/files/main.md punkshell} . {capability doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap} .} 12 {file file repl repl text text shell shell changelog changelog capability capability parse parse filesystem filesystem path path module module punk punk plugin plugin} |
{file {{doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline}} console {{doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi}} repl {{doc/files/project_intro.md punkshell__project_intro} {doc/files/project_changes.md punkshell__project_changes} {doc/files/main.md punkshell}} text {{doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline}} arguments {{doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args}} changelog {{doc/files/project_changes.md punkshell__project_changes}} shell {{doc/files/project_intro.md punkshell__project_intro} {doc/files/project_changes.md punkshell__project_changes} {doc/files/main.md punkshell}} capability {{doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap}} ansi {{doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi}} parse {{doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} {doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args}} terminal {{doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi}} proc {{doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args}} path {{doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path}} filesystem {{doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path}} args {{doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args}} punk {{doc/files/project_intro.md punkshell__project_intro} {doc/files/project_changes.md punkshell__project_changes} {doc/files/main.md punkshell}} module {{doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} {doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap} {doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path} {doc/files/punk/_module_flib-0.1.0.tm.md punkshell_module_punk::flib} {doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args} {doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi}} plugin {{doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap}} string {{doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi}}} {{module doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi} . {shell doc/files/project_changes.md punkshell__project_changes} . {changelog doc/files/project_changes.md punkshell__project_changes} . {shell doc/files/main.md punkshell} . {string doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi} . {parse doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args} . {text doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} . {repl doc/files/project_intro.md punkshell__project_intro} . {proc doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args} . {module doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap} . {path doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path} . {filesystem doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path} . {args doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args} . {plugin doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap} . {module doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path} . {module doc/files/punk/_module_flib-0.1.0.tm.md punkshell_module_punk::flib} . {module doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args} . {console doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi} . {shell doc/files/project_intro.md punkshell__project_intro} . {punk doc/files/project_changes.md punkshell__project_changes} . {parse doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} . {punk doc/files/main.md punkshell} . {module doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} . {repl doc/files/project_changes.md punkshell__project_changes} . {punk doc/files/project_intro.md punkshell__project_intro} . {file doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline} . {arguments doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args} . {repl doc/files/main.md punkshell} . {ansi doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi} . {capability doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap} . {terminal doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi} .} 19 {file file repl repl console console text text arguments arguments shell shell changelog changelog capability capability parse parse ansi ansi proc proc terminal terminal filesystem filesystem path path args args module module punk punk plugin plugin string string} |
@ -1 +1 @@ |
|||||||
doc {doc/toc {{doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline {file line-handling utilities}} {doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap {capability provider and handler plugin system}} {doc/files/project_intro.md punkshell__project_intro {Introduction to punkshell}} {doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path {Filesystem path utilities}} {doc/files/punk/_module_flib-0.1.0.tm.md shellspy_module_punk::flib {Module API}} {doc/files/project_changes.md punkshell__project_changes {punkshell Changes}} {doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md punkshell_module_punk::mix::commandset::project {pmix commandset - project}} {doc/files/main.md punkshell {punkshell - Core}}}} |
doc {doc/toc {{doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::fileline {file line-handling utilities}} {doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::cap {capability provider and handler plugin system}} {doc/files/project_intro.md punkshell__project_intro {Introduction to punkshell}} {doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::path {Filesystem path utilities}} {doc/files/punk/_module_flib-0.1.0.tm.md punkshell_module_punk::flib {Module API}} {doc/files/punk/_module_args-0.1.0.tm.md punkshell_module_punk::args {args parsing}} {doc/files/project_changes.md punkshell__project_changes {punkshell Changes}} {doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md punkshell_module_punk::mix::commandset::project {pmix commandset - project}} {doc/files/punk/_module_ansi-0.1.0.tm.md punkshell_module_punk::ansi {Ansi string functions}} {doc/files/main.md punkshell {punkshell - Core}}}} |
@ -1 +1 @@ |
|||||||
kw,capability {index.md capability} punkshell_module_punk::path(0) doc/files/punk/_module_path-0.1.0.tm.md sa,punkshell_module_punk::mix::commandset::project(0) doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md {punkshell Changes} doc/files/project_changes.md {Introduction to punkshell} doc/files/project_intro.md sa,punkshell_module_punk::fileline(0) doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::mix::commandset::project(0) doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md sa,punkshell(n) doc/files/main.md filesystem {index.md filesystem} sa,punkshell doc/files/main.md kw,shell {index.md shell} sa,punkshell_module_punk::cap doc/files/punk/_module_cap-0.1.0.tm.md sa,punkshell_module_punk::cap(0) doc/files/punk/_module_cap-0.1.0.tm.md kw,parse {index.md parse} sa,punkshell__project_changes(n) doc/files/project_changes.md kw,path {index.md path} kw,module {index.md module} punkshell_module_punk::fileline(0) doc/files/punk/_module_fileline-0.1.0.tm.md punkshell(n) doc/files/main.md kw,plugin {index.md plugin} punkshell doc/files/main.md kw,file {index.md file} punkshell_module_punk::cap doc/files/punk/_module_cap-0.1.0.tm.md changelog {index.md changelog} punkshell_module_punk::cap(0) doc/files/punk/_module_cap-0.1.0.tm.md punkshell__project_changes(n) doc/files/project_changes.md sa,punkshell__project_changes doc/files/project_changes.md path {index.md path} sa,shellspy_module_punk::flib(0) doc/files/punk/_module_flib-0.1.0.tm.md file {index.md file} sa,punkshell_module_punk::path doc/files/punk/_module_path-0.1.0.tm.md punkshell__project_changes doc/files/project_changes.md kw,filesystem {index.md filesystem} sa,punkshell_module_punk::mix::commandset::project doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md shellspy_module_punk::flib(0) doc/files/punk/_module_flib-0.1.0.tm.md {Module API} doc/files/punk/_module_flib-0.1.0.tm.md shell {index.md shell} punkshell_module_punk::path doc/files/punk/_module_path-0.1.0.tm.md kw,repl {index.md repl} capability {index.md capability} kw,text {index.md text} parse {index.md parse} sa,punkshell_module_punk::fileline doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::mix::commandset::project doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md {punkshell - Core} doc/files/main.md {pmix commandset - project} doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md {capability provider and handler plugin system} doc/files/punk/_module_cap-0.1.0.tm.md repl {index.md repl} punkshell_module_punk::fileline doc/files/punk/_module_fileline-0.1.0.tm.md kw,punk {index.md punk} sa,punkshell__project_intro(n) doc/files/project_intro.md text {index.md text} sa,punkshell__project_intro doc/files/project_intro.md {Filesystem path utilities} doc/files/punk/_module_path-0.1.0.tm.md sa,shellspy_module_punk::flib doc/files/punk/_module_flib-0.1.0.tm.md sa,punkshell_module_punk::path(0) doc/files/punk/_module_path-0.1.0.tm.md punkshell__project_intro(n) doc/files/project_intro.md {file line-handling utilities} doc/files/punk/_module_fileline-0.1.0.tm.md punkshell__project_intro doc/files/project_intro.md kw,changelog {index.md changelog} module {index.md module} punk {index.md punk} shellspy_module_punk::flib doc/files/punk/_module_flib-0.1.0.tm.md plugin {index.md plugin} |
kw,capability {index.md capability} punkshell_module_punk::flib doc/files/punk/_module_flib-0.1.0.tm.md punkshell_module_punk::path(0) doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::args(0) doc/files/punk/_module_args-0.1.0.tm.md kw,proc {index.md proc} sa,punkshell_module_punk::mix::commandset::project(0) doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md {punkshell Changes} doc/files/project_changes.md punkshell_module_punk::ansi doc/files/punk/_module_ansi-0.1.0.tm.md {Introduction to punkshell} doc/files/project_intro.md proc {index.md proc} sa,punkshell_module_punk::fileline(0) doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::mix::commandset::project(0) doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md sa,punkshell(n) doc/files/main.md filesystem {index.md filesystem} sa,punkshell doc/files/main.md kw,shell {index.md shell} sa,punkshell_module_punk::cap doc/files/punk/_module_cap-0.1.0.tm.md sa,punkshell_module_punk::cap(0) doc/files/punk/_module_cap-0.1.0.tm.md kw,parse {index.md parse} sa,punkshell_module_punk::flib(0) doc/files/punk/_module_flib-0.1.0.tm.md sa,punkshell__project_changes(n) doc/files/project_changes.md kw,terminal {index.md terminal} kw,args {index.md args} kw,path {index.md path} kw,module {index.md module} punkshell_module_punk::fileline(0) doc/files/punk/_module_fileline-0.1.0.tm.md punkshell(n) doc/files/main.md kw,string {index.md string} kw,plugin {index.md plugin} punkshell doc/files/main.md kw,file {index.md file} punkshell_module_punk::cap doc/files/punk/_module_cap-0.1.0.tm.md changelog {index.md changelog} punkshell_module_punk::cap(0) doc/files/punk/_module_cap-0.1.0.tm.md punkshell_module_punk::flib(0) doc/files/punk/_module_flib-0.1.0.tm.md punkshell__project_changes(n) doc/files/project_changes.md sa,punkshell__project_changes doc/files/project_changes.md kw,arguments {index.md arguments} terminal {index.md terminal} args {index.md args} path {index.md path} file {index.md file} sa,punkshell_module_punk::path doc/files/punk/_module_path-0.1.0.tm.md sa,punkshell_module_punk::args doc/files/punk/_module_args-0.1.0.tm.md {args parsing} doc/files/punk/_module_args-0.1.0.tm.md punkshell__project_changes doc/files/project_changes.md {Ansi string functions} doc/files/punk/_module_ansi-0.1.0.tm.md kw,filesystem {index.md filesystem} sa,punkshell_module_punk::mix::commandset::project doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md {Module API} doc/files/punk/_module_flib-0.1.0.tm.md sa,punkshell_module_punk::ansi(0) doc/files/punk/_module_ansi-0.1.0.tm.md shell {index.md shell} punkshell_module_punk::path doc/files/punk/_module_path-0.1.0.tm.md punkshell_module_punk::args doc/files/punk/_module_args-0.1.0.tm.md kw,repl {index.md repl} capability {index.md capability} kw,text {index.md text} parse {index.md parse} sa,punkshell_module_punk::fileline doc/files/punk/_module_fileline-0.1.0.tm.md punkshell_module_punk::mix::commandset::project doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md {punkshell - Core} doc/files/main.md {pmix commandset - project} doc/files/punk/mix/commandset/_module_project-0.1.0.tm.md punkshell_module_punk::ansi(0) doc/files/punk/_module_ansi-0.1.0.tm.md kw,ansi {index.md ansi} {capability provider and handler plugin system} doc/files/punk/_module_cap-0.1.0.tm.md console {index.md console} repl {index.md repl} punkshell_module_punk::fileline doc/files/punk/_module_fileline-0.1.0.tm.md kw,punk {index.md punk} sa,punkshell__project_intro(n) doc/files/project_intro.md text {index.md text} sa,punkshell__project_intro doc/files/project_intro.md {Filesystem path utilities} doc/files/punk/_module_path-0.1.0.tm.md arguments {index.md arguments} sa,punkshell_module_punk::flib doc/files/punk/_module_flib-0.1.0.tm.md kw,console {index.md console} sa,punkshell_module_punk::path(0) doc/files/punk/_module_path-0.1.0.tm.md sa,punkshell_module_punk::args(0) doc/files/punk/_module_args-0.1.0.tm.md ansi {index.md ansi} punkshell__project_intro(n) doc/files/project_intro.md {file line-handling utilities} doc/files/punk/_module_fileline-0.1.0.tm.md punkshell__project_intro doc/files/project_intro.md kw,changelog {index.md changelog} module {index.md module} punk {index.md punk} sa,punkshell_module_punk::ansi doc/files/punk/_module_ansi-0.1.0.tm.md string {index.md string} plugin {index.md plugin} |
@ -0,0 +1,333 @@ |
|||||||
|
|
||||||
|
[//000000001]: # (punkshell\_module\_punk::ansi \- punk Ansi library) |
||||||
|
[//000000002]: # (Generated from file '\_module\_ansi\-0\.1\.0\.tm\.man' by tcllib/doctools with format 'markdown') |
||||||
|
[//000000003]: # (Copyright © 2023) |
||||||
|
[//000000004]: # (punkshell\_module\_punk::ansi\(0\) 0\.1\.0 doc "punk Ansi library") |
||||||
|
|
||||||
|
<hr> [ <a href="../../../toc.md">Main Table Of Contents</a> | <a |
||||||
|
href="../../toc.md">Table Of Contents</a> | <a |
||||||
|
href="../../../index.md">Keyword Index</a> ] <hr> |
||||||
|
|
||||||
|
# NAME |
||||||
|
|
||||||
|
punkshell\_module\_punk::ansi \- Ansi string functions |
||||||
|
|
||||||
|
# <a name='toc'></a>Table Of Contents |
||||||
|
|
||||||
|
- [Table Of Contents](#toc) |
||||||
|
|
||||||
|
- [Synopsis](#synopsis) |
||||||
|
|
||||||
|
- [Description](#section1) |
||||||
|
|
||||||
|
- [Overview](#section2) |
||||||
|
|
||||||
|
- [Concepts](#subsection1) |
||||||
|
|
||||||
|
- [dependencies](#subsection2) |
||||||
|
|
||||||
|
- [API](#section3) |
||||||
|
|
||||||
|
- [Namespace punk::ansi](#subsection3) |
||||||
|
|
||||||
|
- [Namespace punk::ansi::ta](#subsection4) |
||||||
|
|
||||||
|
- [Namespace punk::ansi::ansistring](#subsection5) |
||||||
|
|
||||||
|
- [Keywords](#keywords) |
||||||
|
|
||||||
|
- [Copyright](#copyright) |
||||||
|
|
||||||
|
# <a name='synopsis'></a>SYNOPSIS |
||||||
|
|
||||||
|
package require punk::ansi |
||||||
|
|
||||||
|
[__stripansi__ *text*](#1) |
||||||
|
[__a?__ ?ansicode\.\.\.?](#2) |
||||||
|
[__a\+__ ?ansicode\.\.\.?](#3) |
||||||
|
[__a__ ?ansicode\.\.\.?](#4) |
||||||
|
[__get\_code\_name__ *code*](#5) |
||||||
|
[__reset__](#6) |
||||||
|
[__reset\_soft__](#7) |
||||||
|
[__reset\_colour__](#8) |
||||||
|
[__clear__](#9) |
||||||
|
[__clear\_above__](#10) |
||||||
|
[__clear\_below__](#11) |
||||||
|
[__cursor\_on__](#12) |
||||||
|
[__cursor\_off__](#13) |
||||||
|
[__move__ *row* *col*](#14) |
||||||
|
[__move\_emit__ *row* *col* *data* ?row col data\.\.\.?](#15) |
||||||
|
[__move\_forward__ *n*](#16) |
||||||
|
[__move\_back__ *n*](#17) |
||||||
|
[__move\_up__ *n*](#18) |
||||||
|
[__move\_down__ *n*](#19) |
||||||
|
[__erase\_line__](#20) |
||||||
|
[__erase\_sol__](#21) |
||||||
|
[__erase\_eol__](#22) |
||||||
|
[__cursor\_pos__](#23) |
||||||
|
[__titleset__ *windowtitles*](#24) |
||||||
|
[__detect__ *text*](#25) |
||||||
|
[__detect\_csi__ *text*](#26) |
||||||
|
[__detect\_sgr__ *text*](#27) |
||||||
|
[__strip__ *text*](#28) |
||||||
|
[__length__ *text*](#29) |
||||||
|
|
||||||
|
# <a name='description'></a>DESCRIPTION |
||||||
|
|
||||||
|
Ansi based terminal control string functions |
||||||
|
|
||||||
|
See __punk::ansi::console__ for related functions for controlling a console |
||||||
|
|
||||||
|
# <a name='section2'></a>Overview |
||||||
|
|
||||||
|
overview of punk::ansi |
||||||
|
|
||||||
|
punk::ansi functions return their values \- no implicit emission to |
||||||
|
console/stdout |
||||||
|
|
||||||
|
## <a name='subsection1'></a>Concepts |
||||||
|
|
||||||
|
Ansi codes can be used to control most terminals on most platforms in an |
||||||
|
'almost' standard manner |
||||||
|
|
||||||
|
There are many differences in terminal implementations \- but most should support |
||||||
|
a core set of features |
||||||
|
|
||||||
|
punk::ansi does not contain any code for direct terminal manipulation via the |
||||||
|
local system APIs\. |
||||||
|
|
||||||
|
Sticking to ansi codes where possible may be better for cross\-platform and |
||||||
|
remote operation where such APIs are unlikely to be useable\. |
||||||
|
|
||||||
|
## <a name='subsection2'></a>dependencies |
||||||
|
|
||||||
|
packages used by punk::ansi |
||||||
|
|
||||||
|
- __Tcl 8\.6__ |
||||||
|
|
||||||
|
# <a name='section3'></a>API |
||||||
|
|
||||||
|
## <a name='subsection3'></a>Namespace punk::ansi |
||||||
|
|
||||||
|
Core API functions for punk::ansi |
||||||
|
|
||||||
|
- <a name='1'></a>__stripansi__ *text* |
||||||
|
|
||||||
|
Return a string with ansi codes stripped out |
||||||
|
|
||||||
|
- <a name='2'></a>__a?__ ?ansicode\.\.\.? |
||||||
|
|
||||||
|
Return an ansi string representing a table of codes and a panel showing the |
||||||
|
colours |
||||||
|
|
||||||
|
- <a name='3'></a>__a\+__ ?ansicode\.\.\.? |
||||||
|
|
||||||
|
Returns the ansi code to apply those from the supplied list \- without any |
||||||
|
reset being performed first |
||||||
|
|
||||||
|
e\.g to set foreground red and bold |
||||||
|
|
||||||
|
punk::ansi::a red bold |
||||||
|
|
||||||
|
to set background red |
||||||
|
|
||||||
|
punk::ansi::a Red |
||||||
|
|
||||||
|
see __punk::ansi::a?__ to display a list of codes |
||||||
|
|
||||||
|
- <a name='4'></a>__a__ ?ansicode\.\.\.? |
||||||
|
|
||||||
|
Returns the ansi code to reset any current settings and apply those from the |
||||||
|
supplied list |
||||||
|
|
||||||
|
by calling punk::ansi::a with no arguments \- the result is a reset to plain |
||||||
|
text |
||||||
|
|
||||||
|
e\.g to set foreground red and bold |
||||||
|
|
||||||
|
punk::ansi::a red bold |
||||||
|
|
||||||
|
to set background red |
||||||
|
|
||||||
|
punk::ansi::a Red |
||||||
|
|
||||||
|
see __punk::ansi::a?__ to display a list of codes |
||||||
|
|
||||||
|
- <a name='5'></a>__get\_code\_name__ *code* |
||||||
|
|
||||||
|
for example |
||||||
|
|
||||||
|
get\_code\_name red will return 31 |
||||||
|
|
||||||
|
get\_code\_name 31 will return red |
||||||
|
|
||||||
|
- <a name='6'></a>__reset__ |
||||||
|
|
||||||
|
reset console |
||||||
|
|
||||||
|
- <a name='7'></a>__reset\_soft__ |
||||||
|
|
||||||
|
- <a name='8'></a>__reset\_colour__ |
||||||
|
|
||||||
|
reset colour only |
||||||
|
|
||||||
|
- <a name='9'></a>__clear__ |
||||||
|
|
||||||
|
- <a name='10'></a>__clear\_above__ |
||||||
|
|
||||||
|
- <a name='11'></a>__clear\_below__ |
||||||
|
|
||||||
|
- <a name='12'></a>__cursor\_on__ |
||||||
|
|
||||||
|
- <a name='13'></a>__cursor\_off__ |
||||||
|
|
||||||
|
- <a name='14'></a>__move__ *row* *col* |
||||||
|
|
||||||
|
Return an ansi sequence to move to row,col |
||||||
|
|
||||||
|
aka cursor home |
||||||
|
|
||||||
|
- <a name='15'></a>__move\_emit__ *row* *col* *data* ?row col data\.\.\.? |
||||||
|
|
||||||
|
Return an ansi string representing a move to row col with data appended |
||||||
|
|
||||||
|
row col data can be repeated any number of times to return a string |
||||||
|
representing the output of the data elements at all those points |
||||||
|
|
||||||
|
Compare to punk::console::move\_emit which calls this function \- but writes |
||||||
|
it to stdout |
||||||
|
|
||||||
|
punk::console::move\_emit\_return will also return the cursor to the original |
||||||
|
position |
||||||
|
|
||||||
|
There is no punk::ansi::move\_emit\_return because in a standard console there |
||||||
|
is no ansi string which can represent a jump back to starting position\. |
||||||
|
|
||||||
|
There is an ansi code to write the current cursor position to stdin \(which |
||||||
|
will generally display on the console\) \- this is not quite the same thing\. |
||||||
|
|
||||||
|
punk::console::move\_emit\_return does it by emitting that code and starting a |
||||||
|
loop to read stdin |
||||||
|
|
||||||
|
punk::ansi could implement a move\_emit\_return using the punk::console |
||||||
|
mechanism \- but the resulting string would capture the cursor position at |
||||||
|
the time the string is built \- which is not necessarily when the string is |
||||||
|
used\. |
||||||
|
|
||||||
|
The following example shows how to do this manually, emitting the string |
||||||
|
blah at screen position 10,10 and emitting DONE back at the line we started: |
||||||
|
|
||||||
|
punk::ansi::move_emit 10 10 blah {*}[punk::console::get_cursor_pos_list] DONE |
||||||
|
|
||||||
|
A string created by any move\_emit\_return for punk::ansi would not behave in |
||||||
|
an intuitive manner compared to other punk::ansi move functions \- so is |
||||||
|
deliberately omitted\. |
||||||
|
|
||||||
|
- <a name='16'></a>__move\_forward__ *n* |
||||||
|
|
||||||
|
- <a name='17'></a>__move\_back__ *n* |
||||||
|
|
||||||
|
- <a name='18'></a>__move\_up__ *n* |
||||||
|
|
||||||
|
- <a name='19'></a>__move\_down__ *n* |
||||||
|
|
||||||
|
- <a name='20'></a>__erase\_line__ |
||||||
|
|
||||||
|
- <a name='21'></a>__erase\_sol__ |
||||||
|
|
||||||
|
Erase to start of line, leaving cursor position alone\. |
||||||
|
|
||||||
|
- <a name='22'></a>__erase\_eol__ |
||||||
|
|
||||||
|
- <a name='23'></a>__cursor\_pos__ |
||||||
|
|
||||||
|
cursor\_pos unlikely to be useful on it's own like this as when written to |
||||||
|
the terminal, this sequence causes the terminal to emit the row;col sequence |
||||||
|
to stdin |
||||||
|
|
||||||
|
The output on screen will look something like ^\[\[47;3R |
||||||
|
|
||||||
|
Use punk::console::get\_cursor\_pos or punk::console::get\_cursor\_pos\_list |
||||||
|
instead\. |
||||||
|
|
||||||
|
These functions will emit the code \- but read it in from stdin so that it |
||||||
|
doesn't display, and then return the row and column as a colon\-delimited |
||||||
|
string or list respectively\. |
||||||
|
|
||||||
|
The punk::ansi::cursor\_pos function is used by punk::console::get\_cursor\_pos |
||||||
|
and punk::console::get\_cursor\_pos\_list |
||||||
|
|
||||||
|
- <a name='24'></a>__titleset__ *windowtitles* |
||||||
|
|
||||||
|
Returns the code to set the title of the terminal window to windowtitle |
||||||
|
|
||||||
|
This may not work on terminals which have multiple panes/windows |
||||||
|
|
||||||
|
## <a name='subsection4'></a>Namespace punk::ansi::ta |
||||||
|
|
||||||
|
text ansi functions |
||||||
|
|
||||||
|
based on but not identical to the Perl Text Ansi module: |
||||||
|
|
||||||
|
https://github\.com/perlancar/perl\-Text\-ANSI\-Util/blob/master/lib/Text/ANSI/BaseUtil\.pm |
||||||
|
|
||||||
|
- <a name='25'></a>__detect__ *text* |
||||||
|
|
||||||
|
Return a boolean indicating whether Ansi codes were detected in text |
||||||
|
|
||||||
|
- <a name='26'></a>__detect\_csi__ *text* |
||||||
|
|
||||||
|
Return a boolean indicating whether an Ansi Control Sequence Introducer |
||||||
|
\(CSI\) was detected in text |
||||||
|
|
||||||
|
The csi is often represented in code as \\x1b or \\033 followed by a left |
||||||
|
bracket \[ |
||||||
|
|
||||||
|
The initial byte or escape is commonly referenced as ESC in Ansi |
||||||
|
documentation |
||||||
|
|
||||||
|
There is also a multi\-byte escape sequence \\u009b |
||||||
|
|
||||||
|
This is less commonly used but is also detected here |
||||||
|
|
||||||
|
\(This function is not in perl ta\) |
||||||
|
|
||||||
|
- <a name='27'></a>__detect\_sgr__ *text* |
||||||
|
|
||||||
|
Return a boolean indicating whether an ansi Select Graphics Rendition code |
||||||
|
was detected\. |
||||||
|
|
||||||
|
This is the set of CSI sequences ending in 'm' |
||||||
|
|
||||||
|
This is most commonly an Ansi colour code \- but also things such as |
||||||
|
underline and italics |
||||||
|
|
||||||
|
An SGR with empty or a single zero argument is a reset of the SGR features \- |
||||||
|
this is also detected\. |
||||||
|
|
||||||
|
\(This function is not in perl ta\) |
||||||
|
|
||||||
|
- <a name='28'></a>__strip__ *text* |
||||||
|
|
||||||
|
Return text stripped of Ansi codes |
||||||
|
|
||||||
|
This is a tailcall to punk::ansi::stripansi |
||||||
|
|
||||||
|
- <a name='29'></a>__length__ *text* |
||||||
|
|
||||||
|
Return the character length after stripping ansi codes \- not the printing |
||||||
|
length |
||||||
|
|
||||||
|
## <a name='subsection5'></a>Namespace punk::ansi::ansistring |
||||||
|
|
||||||
|
punk::ansi::string ensemble |
||||||
|
|
||||||
|
# <a name='keywords'></a>KEYWORDS |
||||||
|
|
||||||
|
[ansi](\.\./\.\./\.\./index\.md\#ansi), [console](\.\./\.\./\.\./index\.md\#console), |
||||||
|
[module](\.\./\.\./\.\./index\.md\#module), [string](\.\./\.\./\.\./index\.md\#string), |
||||||
|
[terminal](\.\./\.\./\.\./index\.md\#terminal) |
||||||
|
|
||||||
|
# <a name='copyright'></a>COPYRIGHT |
||||||
|
|
||||||
|
Copyright © 2023 |
@ -0,0 +1,177 @@ |
|||||||
|
|
||||||
|
[//000000001]: # (punkshell\_module\_punk::args \- args to option\-value dict and values dict) |
||||||
|
[//000000002]: # (Generated from file '\_module\_args\-0\.1\.0\.tm\.man' by tcllib/doctools with format 'markdown') |
||||||
|
[//000000003]: # (Copyright © 2024) |
||||||
|
[//000000004]: # (punkshell\_module\_punk::args\(0\) 0\.1\.0 doc "args to option\-value dict and values dict") |
||||||
|
|
||||||
|
<hr> [ <a href="../../../toc.md">Main Table Of Contents</a> | <a |
||||||
|
href="../../toc.md">Table Of Contents</a> | <a |
||||||
|
href="../../../index.md">Keyword Index</a> ] <hr> |
||||||
|
|
||||||
|
# NAME |
||||||
|
|
||||||
|
punkshell\_module\_punk::args \- args parsing |
||||||
|
|
||||||
|
# <a name='toc'></a>Table Of Contents |
||||||
|
|
||||||
|
- [Table Of Contents](#toc) |
||||||
|
|
||||||
|
- [Synopsis](#synopsis) |
||||||
|
|
||||||
|
- [Description](#section1) |
||||||
|
|
||||||
|
- [Overview](#section2) |
||||||
|
|
||||||
|
- [Concepts](#subsection1) |
||||||
|
|
||||||
|
- [Notes](#subsection2) |
||||||
|
|
||||||
|
- [dependencies](#subsection3) |
||||||
|
|
||||||
|
- [API](#section3) |
||||||
|
|
||||||
|
- [Namespace punk::args::class](#subsection4) |
||||||
|
|
||||||
|
- [Namespace punk::args](#subsection5) |
||||||
|
|
||||||
|
- [Namespace punk::args::lib](#subsection6) |
||||||
|
|
||||||
|
- [Internal](#section4) |
||||||
|
|
||||||
|
- [Namespace punk::args::system](#subsection7) |
||||||
|
|
||||||
|
- [Keywords](#keywords) |
||||||
|
|
||||||
|
- [Copyright](#copyright) |
||||||
|
|
||||||
|
# <a name='synopsis'></a>SYNOPSIS |
||||||
|
|
||||||
|
package require punk::args |
||||||
|
|
||||||
|
[__opts\_values__ *optionspecs* *rawargs* ?option value\.\.\.?](#1) |
||||||
|
|
||||||
|
# <a name='description'></a>DESCRIPTION |
||||||
|
|
||||||
|
Utilities for parsing proc args |
||||||
|
|
||||||
|
# <a name='section2'></a>Overview |
||||||
|
|
||||||
|
overview of punk::args |
||||||
|
|
||||||
|
## <a name='subsection1'></a>Concepts |
||||||
|
|
||||||
|
There are 2 main conventions for parsing a proc args list |
||||||
|
|
||||||
|
1. leading option\-value pairs followed by a list of values \(Tk style\) |
||||||
|
|
||||||
|
1. leading list of values followed by option\-value pairs \(Tcl style\) |
||||||
|
|
||||||
|
punk::args is focused on the 1st convention \(Tk style\): parsing of args in |
||||||
|
leading option\-value pair style \- even for non\-Tk usage\. |
||||||
|
|
||||||
|
The proc can still contain some leading required values e\.g |
||||||
|
|
||||||
|
proc dostuff {arg1 arg2 args} {...}} |
||||||
|
|
||||||
|
but having the core values elements at the end of args is more generally useful |
||||||
|
\- especially in cases where the number of trailing values is unknown and/or the |
||||||
|
proc is to be called in a functional 'pipeline' style\. |
||||||
|
|
||||||
|
The basic principle is that a call to punk::args::opts\_vals is made near the |
||||||
|
beginning of the proc e\.g |
||||||
|
|
||||||
|
proc dofilestuff {args} { |
||||||
|
lassign [dict values [punk::args { |
||||||
|
-directory -default "" |
||||||
|
-translation -default binary |
||||||
|
} $args]] opts values |
||||||
|
|
||||||
|
puts "translation is [dict get $opts -translation]" |
||||||
|
foreach f [dict values $values] { |
||||||
|
puts "doing stuff with file: $f" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
## <a name='subsection2'></a>Notes |
||||||
|
|
||||||
|
There are alternative args parsing packages such as: |
||||||
|
|
||||||
|
1. argp |
||||||
|
|
||||||
|
1. The tcllib set of TEPAM modules |
||||||
|
|
||||||
|
TEPAM requires an alternative procedure declaration syntax instead of proc |
||||||
|
\- but has support for Tk and documentation generation\. |
||||||
|
|
||||||
|
punk::args was designed initially without specific reference to TEPAM \- and to |
||||||
|
handle some edge cases in specific projects where TEPAM wasn't suitable\. |
||||||
|
|
||||||
|
In subsequent revisions of punk::args \- some features were made to operate in a |
||||||
|
way that is similar to TEPAM \- to avoid gratuitous differences where possible, |
||||||
|
but of course there are differences |
||||||
|
|
||||||
|
and those used TEPAM or mixing TEPAM and punk::args should take care to assess |
||||||
|
the differences\. |
||||||
|
|
||||||
|
TEPAM is a mature solution and is widely available as it is included in tcllib\. |
||||||
|
|
||||||
|
Serious consideration should be given to using TEPAM if suitable for your |
||||||
|
project\. |
||||||
|
|
||||||
|
## <a name='subsection3'></a>dependencies |
||||||
|
|
||||||
|
packages used by punk::args |
||||||
|
|
||||||
|
- __Tcl 8\.6__ |
||||||
|
|
||||||
|
# <a name='section3'></a>API |
||||||
|
|
||||||
|
## <a name='subsection4'></a>Namespace punk::args::class |
||||||
|
|
||||||
|
class definitions |
||||||
|
|
||||||
|
## <a name='subsection5'></a>Namespace punk::args |
||||||
|
|
||||||
|
- <a name='1'></a>__opts\_values__ *optionspecs* *rawargs* ?option value\.\.\.? |
||||||
|
|
||||||
|
Parse rawargs as a sequence of zero or more option\-value pairs followed by |
||||||
|
zero or more values |
||||||
|
|
||||||
|
Returns a dict of the form: opts <options\_dict> values <values\_dict> |
||||||
|
|
||||||
|
ARGUMENTS: |
||||||
|
|
||||||
|
* multiline\-string *optionspecs* |
||||||
|
|
||||||
|
This a block of text with records delimited by newlines \(lf or crlf\) |
||||||
|
|
||||||
|
Each optionspec line must be of the form: |
||||||
|
|
||||||
|
\-optionname \-key val \-key2 val2\.\.\. |
||||||
|
|
||||||
|
where the valid keys for each option specification are: \-default \-type |
||||||
|
\-range \-choices \-optional |
||||||
|
|
||||||
|
* list *rawargs* |
||||||
|
|
||||||
|
This is a list of the arguments to parse\. Usually it will be the \\$args |
||||||
|
value from the containing proc |
||||||
|
|
||||||
|
## <a name='subsection6'></a>Namespace punk::args::lib |
||||||
|
|
||||||
|
Secondary functions that are part of the API |
||||||
|
|
||||||
|
# <a name='section4'></a>Internal |
||||||
|
|
||||||
|
## <a name='subsection7'></a>Namespace punk::args::system |
||||||
|
|
||||||
|
# <a name='keywords'></a>KEYWORDS |
||||||
|
|
||||||
|
[args](\.\./\.\./\.\./index\.md\#args), |
||||||
|
[arguments](\.\./\.\./\.\./index\.md\#arguments), |
||||||
|
[module](\.\./\.\./\.\./index\.md\#module), [parse](\.\./\.\./\.\./index\.md\#parse), |
||||||
|
[proc](\.\./\.\./\.\./index\.md\#proc) |
||||||
|
|
||||||
|
# <a name='copyright'></a>COPYRIGHT |
||||||
|
|
||||||
|
Copyright © 2024 |
@ -1 +1 @@ |
|||||||
{file {{doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline}} repl {{doc/files/project_intro.html punkshell__project_intro} {doc/files/project_changes.html punkshell__project_changes} {doc/files/main.html punkshell}} text {{doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline}} shell {{doc/files/project_intro.html punkshell__project_intro} {doc/files/project_changes.html punkshell__project_changes} {doc/files/main.html punkshell}} changelog {{doc/files/project_changes.html punkshell__project_changes}} capability {{doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap}} parse {{doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline}} filesystem {{doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path}} path {{doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path}} module {{doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} {doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap} {doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path} {doc/files/punk/_module_flib-0.1.0.tm.html shellspy_module_punk::flib}} punk {{doc/files/project_intro.html punkshell__project_intro} {doc/files/project_changes.html punkshell__project_changes} {doc/files/main.html punkshell}} plugin {{doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap}}} {{repl doc/files/main.html punkshell} . {file doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} . {punk doc/files/project_intro.html punkshell__project_intro} . {capability doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap} . {shell doc/files/project_changes.html punkshell__project_changes} . {changelog doc/files/project_changes.html punkshell__project_changes} . {shell doc/files/main.html punkshell} . {text doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} . {repl doc/files/project_intro.html punkshell__project_intro} . {module doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap} . {path doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path} . {plugin doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap} . {filesystem doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path} . {module doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path} . {shell doc/files/project_intro.html punkshell__project_intro} . {punk doc/files/project_changes.html punkshell__project_changes} . {parse doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} . {punk doc/files/main.html punkshell} . {module doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} . {module doc/files/punk/_module_flib-0.1.0.tm.html shellspy_module_punk::flib} . {repl doc/files/project_changes.html punkshell__project_changes} .} 12 {file file repl repl text text shell shell changelog changelog capability capability parse parse filesystem filesystem path path module module punk punk plugin plugin} |
{file {{doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline}} console {{doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi}} repl {{doc/files/project_intro.html punkshell__project_intro} {doc/files/project_changes.html punkshell__project_changes} {doc/files/main.html punkshell}} text {{doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline}} arguments {{doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args}} changelog {{doc/files/project_changes.html punkshell__project_changes}} shell {{doc/files/project_intro.html punkshell__project_intro} {doc/files/project_changes.html punkshell__project_changes} {doc/files/main.html punkshell}} capability {{doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap}} ansi {{doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi}} parse {{doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} {doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args}} terminal {{doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi}} proc {{doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args}} path {{doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path}} filesystem {{doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path}} args {{doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args}} punk {{doc/files/project_intro.html punkshell__project_intro} {doc/files/project_changes.html punkshell__project_changes} {doc/files/main.html punkshell}} module {{doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} {doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap} {doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path} {doc/files/punk/_module_flib-0.1.0.tm.html punkshell_module_punk::flib} {doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args} {doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi}} plugin {{doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap}} string {{doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi}}} {{repl doc/files/main.html punkshell} . {arguments doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args} . {file doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} . {punk doc/files/project_intro.html punkshell__project_intro} . {ansi doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi} . {terminal doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi} . {capability doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap} . {module doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi} . {shell doc/files/project_changes.html punkshell__project_changes} . {changelog doc/files/project_changes.html punkshell__project_changes} . {repl doc/files/project_intro.html punkshell__project_intro} . {text doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} . {parse doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args} . {shell doc/files/main.html punkshell} . {string doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi} . {module doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap} . {proc doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args} . {path doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path} . {filesystem doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path} . {plugin doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap} . {args doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args} . {module doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path} . {module doc/files/punk/_module_flib-0.1.0.tm.html punkshell_module_punk::flib} . {module doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args} . {console doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi} . {shell doc/files/project_intro.html punkshell__project_intro} . {punk doc/files/project_changes.html punkshell__project_changes} . {parse doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} . {punk doc/files/main.html punkshell} . {module doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline} . {repl doc/files/project_changes.html punkshell__project_changes} .} 19 {file file repl repl console console text text arguments arguments shell shell changelog changelog capability capability parse parse ansi ansi proc proc terminal terminal filesystem filesystem path path args args module module punk punk plugin plugin string string} |
@ -1 +1 @@ |
|||||||
doc {doc/toc {{doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline {file line-handling utilities}} {doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap {capability provider and handler plugin system}} {doc/files/project_intro.html punkshell__project_intro {Introduction to punkshell}} {doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path {Filesystem path utilities}} {doc/files/punk/_module_flib-0.1.0.tm.html shellspy_module_punk::flib {Module API}} {doc/files/project_changes.html punkshell__project_changes {punkshell Changes}} {doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html punkshell_module_punk::mix::commandset::project {pmix commandset - project}} {doc/files/main.html punkshell {punkshell - Core}}}} |
doc {doc/toc {{doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::fileline {file line-handling utilities}} {doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::cap {capability provider and handler plugin system}} {doc/files/project_intro.html punkshell__project_intro {Introduction to punkshell}} {doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::path {Filesystem path utilities}} {doc/files/punk/_module_flib-0.1.0.tm.html punkshell_module_punk::flib {Module API}} {doc/files/punk/_module_args-0.1.0.tm.html punkshell_module_punk::args {args parsing}} {doc/files/project_changes.html punkshell__project_changes {punkshell Changes}} {doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html punkshell_module_punk::mix::commandset::project {pmix commandset - project}} {doc/files/punk/_module_ansi-0.1.0.tm.html punkshell_module_punk::ansi {Ansi string functions}} {doc/files/main.html punkshell {punkshell - Core}}}} |
@ -1 +1 @@ |
|||||||
kw,capability {index.html capability} punkshell_module_punk::path(0) doc/files/punk/_module_path-0.1.0.tm.html sa,punkshell_module_punk::mix::commandset::project(0) doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html {punkshell Changes} doc/files/project_changes.html {Introduction to punkshell} doc/files/project_intro.html sa,punkshell_module_punk::fileline(0) doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::mix::commandset::project(0) doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html sa,punkshell(n) doc/files/main.html filesystem {index.html filesystem} sa,punkshell doc/files/main.html kw,shell {index.html shell} sa,punkshell_module_punk::cap doc/files/punk/_module_cap-0.1.0.tm.html sa,punkshell_module_punk::cap(0) doc/files/punk/_module_cap-0.1.0.tm.html kw,parse {index.html parse} sa,punkshell__project_changes(n) doc/files/project_changes.html kw,path {index.html path} kw,module {index.html module} punkshell_module_punk::fileline(0) doc/files/punk/_module_fileline-0.1.0.tm.html punkshell(n) doc/files/main.html kw,plugin {index.html plugin} punkshell doc/files/main.html kw,file {index.html file} punkshell_module_punk::cap doc/files/punk/_module_cap-0.1.0.tm.html changelog {index.html changelog} punkshell_module_punk::cap(0) doc/files/punk/_module_cap-0.1.0.tm.html punkshell__project_changes(n) doc/files/project_changes.html sa,punkshell__project_changes doc/files/project_changes.html path {index.html path} sa,shellspy_module_punk::flib(0) doc/files/punk/_module_flib-0.1.0.tm.html file {index.html file} sa,punkshell_module_punk::path doc/files/punk/_module_path-0.1.0.tm.html punkshell__project_changes doc/files/project_changes.html kw,filesystem {index.html filesystem} sa,punkshell_module_punk::mix::commandset::project doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html shellspy_module_punk::flib(0) doc/files/punk/_module_flib-0.1.0.tm.html {Module API} doc/files/punk/_module_flib-0.1.0.tm.html shell {index.html shell} punkshell_module_punk::path doc/files/punk/_module_path-0.1.0.tm.html kw,repl {index.html repl} capability {index.html capability} kw,text {index.html text} parse {index.html parse} sa,punkshell_module_punk::fileline doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::mix::commandset::project doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html {punkshell - Core} doc/files/main.html {pmix commandset - project} doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html {capability provider and handler plugin system} doc/files/punk/_module_cap-0.1.0.tm.html repl {index.html repl} punkshell_module_punk::fileline doc/files/punk/_module_fileline-0.1.0.tm.html kw,punk {index.html punk} sa,punkshell__project_intro(n) doc/files/project_intro.html text {index.html text} sa,punkshell__project_intro doc/files/project_intro.html {Filesystem path utilities} doc/files/punk/_module_path-0.1.0.tm.html sa,shellspy_module_punk::flib doc/files/punk/_module_flib-0.1.0.tm.html sa,punkshell_module_punk::path(0) doc/files/punk/_module_path-0.1.0.tm.html punkshell__project_intro(n) doc/files/project_intro.html {file line-handling utilities} doc/files/punk/_module_fileline-0.1.0.tm.html punkshell__project_intro doc/files/project_intro.html kw,changelog {index.html changelog} module {index.html module} punk {index.html punk} shellspy_module_punk::flib doc/files/punk/_module_flib-0.1.0.tm.html plugin {index.html plugin} |
kw,capability {index.html capability} punkshell_module_punk::flib doc/files/punk/_module_flib-0.1.0.tm.html punkshell_module_punk::path(0) doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::args(0) doc/files/punk/_module_args-0.1.0.tm.html kw,proc {index.html proc} sa,punkshell_module_punk::mix::commandset::project(0) doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html {punkshell Changes} doc/files/project_changes.html punkshell_module_punk::ansi doc/files/punk/_module_ansi-0.1.0.tm.html {Introduction to punkshell} doc/files/project_intro.html proc {index.html proc} sa,punkshell_module_punk::fileline(0) doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::mix::commandset::project(0) doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html sa,punkshell(n) doc/files/main.html filesystem {index.html filesystem} sa,punkshell doc/files/main.html kw,shell {index.html shell} sa,punkshell_module_punk::cap doc/files/punk/_module_cap-0.1.0.tm.html sa,punkshell_module_punk::cap(0) doc/files/punk/_module_cap-0.1.0.tm.html kw,parse {index.html parse} sa,punkshell_module_punk::flib(0) doc/files/punk/_module_flib-0.1.0.tm.html sa,punkshell__project_changes(n) doc/files/project_changes.html kw,terminal {index.html terminal} kw,args {index.html args} kw,path {index.html path} kw,module {index.html module} punkshell_module_punk::fileline(0) doc/files/punk/_module_fileline-0.1.0.tm.html punkshell(n) doc/files/main.html kw,string {index.html string} kw,plugin {index.html plugin} punkshell doc/files/main.html kw,file {index.html file} punkshell_module_punk::cap doc/files/punk/_module_cap-0.1.0.tm.html changelog {index.html changelog} punkshell_module_punk::cap(0) doc/files/punk/_module_cap-0.1.0.tm.html punkshell_module_punk::flib(0) doc/files/punk/_module_flib-0.1.0.tm.html punkshell__project_changes(n) doc/files/project_changes.html sa,punkshell__project_changes doc/files/project_changes.html kw,arguments {index.html arguments} terminal {index.html terminal} args {index.html args} path {index.html path} file {index.html file} sa,punkshell_module_punk::path doc/files/punk/_module_path-0.1.0.tm.html sa,punkshell_module_punk::args doc/files/punk/_module_args-0.1.0.tm.html {args parsing} doc/files/punk/_module_args-0.1.0.tm.html punkshell__project_changes doc/files/project_changes.html {Ansi string functions} doc/files/punk/_module_ansi-0.1.0.tm.html kw,filesystem {index.html filesystem} sa,punkshell_module_punk::mix::commandset::project doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html {Module API} doc/files/punk/_module_flib-0.1.0.tm.html sa,punkshell_module_punk::ansi(0) doc/files/punk/_module_ansi-0.1.0.tm.html shell {index.html shell} punkshell_module_punk::path doc/files/punk/_module_path-0.1.0.tm.html punkshell_module_punk::args doc/files/punk/_module_args-0.1.0.tm.html kw,repl {index.html repl} capability {index.html capability} kw,text {index.html text} parse {index.html parse} sa,punkshell_module_punk::fileline doc/files/punk/_module_fileline-0.1.0.tm.html punkshell_module_punk::mix::commandset::project doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html {punkshell - Core} doc/files/main.html {pmix commandset - project} doc/files/punk/mix/commandset/_module_project-0.1.0.tm.html punkshell_module_punk::ansi(0) doc/files/punk/_module_ansi-0.1.0.tm.html kw,ansi {index.html ansi} {capability provider and handler plugin system} doc/files/punk/_module_cap-0.1.0.tm.html console {index.html console} repl {index.html repl} punkshell_module_punk::fileline doc/files/punk/_module_fileline-0.1.0.tm.html kw,punk {index.html punk} sa,punkshell__project_intro(n) doc/files/project_intro.html text {index.html text} sa,punkshell__project_intro doc/files/project_intro.html {Filesystem path utilities} doc/files/punk/_module_path-0.1.0.tm.html arguments {index.html arguments} sa,punkshell_module_punk::flib doc/files/punk/_module_flib-0.1.0.tm.html kw,console {index.html console} sa,punkshell_module_punk::path(0) doc/files/punk/_module_path-0.1.0.tm.html sa,punkshell_module_punk::args(0) doc/files/punk/_module_args-0.1.0.tm.html ansi {index.html ansi} punkshell__project_intro(n) doc/files/project_intro.html {file line-handling utilities} doc/files/punk/_module_fileline-0.1.0.tm.html punkshell__project_intro doc/files/project_intro.html kw,changelog {index.html changelog} module {index.html module} punk {index.html punk} sa,punkshell_module_punk::ansi doc/files/punk/_module_ansi-0.1.0.tm.html string {index.html string} plugin {index.html plugin} |
@ -0,0 +1,312 @@ |
|||||||
|
<!DOCTYPE html><html><head> |
||||||
|
<title>punkshell_module_punk::ansi - punk Ansi library</title> |
||||||
|
<style type="text/css"><!-- |
||||||
|
HTML { |
||||||
|
background: #FFFFFF; |
||||||
|
color: black; |
||||||
|
} |
||||||
|
BODY { |
||||||
|
background: #FFFFFF; |
||||||
|
color: black; |
||||||
|
} |
||||||
|
DIV.doctools { |
||||||
|
margin-left: 10%; |
||||||
|
margin-right: 10%; |
||||||
|
} |
||||||
|
DIV.doctools H1,DIV.doctools H2 { |
||||||
|
margin-left: -5%; |
||||||
|
} |
||||||
|
H1, H2, H3, H4 { |
||||||
|
margin-top: 1em; |
||||||
|
font-family: sans-serif; |
||||||
|
font-size: large; |
||||||
|
color: #005A9C; |
||||||
|
background: transparent; |
||||||
|
text-align: left; |
||||||
|
} |
||||||
|
H1.doctools_title { |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
UL,OL { |
||||||
|
margin-right: 0em; |
||||||
|
margin-top: 3pt; |
||||||
|
margin-bottom: 3pt; |
||||||
|
} |
||||||
|
UL LI { |
||||||
|
list-style: disc; |
||||||
|
} |
||||||
|
OL LI { |
||||||
|
list-style: decimal; |
||||||
|
} |
||||||
|
DT { |
||||||
|
padding-top: 1ex; |
||||||
|
} |
||||||
|
UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL { |
||||||
|
font: normal 12pt/14pt sans-serif; |
||||||
|
list-style: none; |
||||||
|
} |
||||||
|
LI.doctools_section, LI.doctools_subsection { |
||||||
|
list-style: none; |
||||||
|
margin-left: 0em; |
||||||
|
text-indent: 0em; |
||||||
|
padding: 0em; |
||||||
|
} |
||||||
|
PRE { |
||||||
|
display: block; |
||||||
|
font-family: monospace; |
||||||
|
white-space: pre; |
||||||
|
margin: 0%; |
||||||
|
padding-top: 0.5ex; |
||||||
|
padding-bottom: 0.5ex; |
||||||
|
padding-left: 1ex; |
||||||
|
padding-right: 1ex; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
PRE.doctools_example { |
||||||
|
color: black; |
||||||
|
background: #f5dcb3; |
||||||
|
border: 1px solid black; |
||||||
|
} |
||||||
|
UL.doctools_requirements LI, UL.doctools_syntax LI { |
||||||
|
list-style: none; |
||||||
|
margin-left: 0em; |
||||||
|
text-indent: 0em; |
||||||
|
padding: 0em; |
||||||
|
} |
||||||
|
DIV.doctools_synopsis { |
||||||
|
color: black; |
||||||
|
background: #80ffff; |
||||||
|
border: 1px solid black; |
||||||
|
font-family: serif; |
||||||
|
margin-top: 1em; |
||||||
|
margin-bottom: 1em; |
||||||
|
} |
||||||
|
UL.doctools_syntax { |
||||||
|
margin-top: 1em; |
||||||
|
border-top: 1px solid black; |
||||||
|
} |
||||||
|
UL.doctools_requirements { |
||||||
|
margin-bottom: 1em; |
||||||
|
border-bottom: 1px solid black; |
||||||
|
} |
||||||
|
--></style> |
||||||
|
</head> |
||||||
|
<!-- Generated from file '_module_ansi-0.1.0.tm.man' by tcllib/doctools with format 'html' |
||||||
|
--> |
||||||
|
<!-- Copyright &copy; 2023 |
||||||
|
--> |
||||||
|
<!-- punkshell_module_punk::ansi.0 |
||||||
|
--> |
||||||
|
<body><hr> [ |
||||||
|
<a href="../../../toc.html">Main Table Of Contents</a> |
||||||
|
| <a href="../../toc.html">Table Of Contents</a> |
||||||
|
| <a href="../../../index.html">Keyword Index</a> |
||||||
|
] <hr> |
||||||
|
<div class="doctools"> |
||||||
|
<h1 class="doctools_title">punkshell_module_punk::ansi(0) 0.1.0 doc "punk Ansi library"</h1> |
||||||
|
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2> |
||||||
|
<p>punkshell_module_punk::ansi - Ansi string functions</p> |
||||||
|
</div> |
||||||
|
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2> |
||||||
|
<ul class="doctools_toc"> |
||||||
|
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li> |
||||||
|
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li> |
||||||
|
<li class="doctools_section"><a href="#section1">Description</a></li> |
||||||
|
<li class="doctools_section"><a href="#section2">Overview</a> |
||||||
|
<ul> |
||||||
|
<li class="doctools_subsection"><a href="#subsection1">Concepts</a></li> |
||||||
|
<li class="doctools_subsection"><a href="#subsection2">dependencies</a></li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
<li class="doctools_section"><a href="#section3">API</a> |
||||||
|
<ul> |
||||||
|
<li class="doctools_subsection"><a href="#subsection3">Namespace punk::ansi</a></li> |
||||||
|
<li class="doctools_subsection"><a href="#subsection4">Namespace punk::ansi::ta</a></li> |
||||||
|
<li class="doctools_subsection"><a href="#subsection5">Namespace punk::ansi::ansistring</a></li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
<li class="doctools_section"><a href="#keywords">Keywords</a></li> |
||||||
|
<li class="doctools_section"><a href="#copyright">Copyright</a></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2> |
||||||
|
<div class="doctools_synopsis"> |
||||||
|
<ul class="doctools_requirements"> |
||||||
|
<li>package require <b class="pkgname">punk::ansi</b></li> |
||||||
|
</ul> |
||||||
|
<ul class="doctools_syntax"> |
||||||
|
<li><a href="#1"><b class="function">stripansi</b> <i class="arg">text</i></a></li> |
||||||
|
<li><a href="#2"><b class="function">a?</b> <span class="opt">?ansicode...?</span></a></li> |
||||||
|
<li><a href="#3"><b class="function">a+</b> <span class="opt">?ansicode...?</span></a></li> |
||||||
|
<li><a href="#4"><b class="function">a</b> <span class="opt">?ansicode...?</span></a></li> |
||||||
|
<li><a href="#5"><b class="function">get_code_name</b> <i class="arg">code</i></a></li> |
||||||
|
<li><a href="#6"><b class="function">reset</b></a></li> |
||||||
|
<li><a href="#7"><b class="function">reset_soft</b></a></li> |
||||||
|
<li><a href="#8"><b class="function">reset_colour</b></a></li> |
||||||
|
<li><a href="#9"><b class="function">clear</b></a></li> |
||||||
|
<li><a href="#10"><b class="function">clear_above</b></a></li> |
||||||
|
<li><a href="#11"><b class="function">clear_below</b></a></li> |
||||||
|
<li><a href="#12"><b class="function">cursor_on</b></a></li> |
||||||
|
<li><a href="#13"><b class="function">cursor_off</b></a></li> |
||||||
|
<li><a href="#14"><b class="function">move</b> <i class="arg">row</i> <i class="arg">col</i></a></li> |
||||||
|
<li><a href="#15"><b class="function">move_emit</b> <i class="arg">row</i> <i class="arg">col</i> <i class="arg">data</i> <span class="opt">?row col data...?</span></a></li> |
||||||
|
<li><a href="#16"><b class="function">move_forward</b> <i class="arg">n</i></a></li> |
||||||
|
<li><a href="#17"><b class="function">move_back</b> <i class="arg">n</i></a></li> |
||||||
|
<li><a href="#18"><b class="function">move_up</b> <i class="arg">n</i></a></li> |
||||||
|
<li><a href="#19"><b class="function">move_down</b> <i class="arg">n</i></a></li> |
||||||
|
<li><a href="#20"><b class="function">erase_line</b></a></li> |
||||||
|
<li><a href="#21"><b class="function">erase_sol</b></a></li> |
||||||
|
<li><a href="#22"><b class="function">erase_eol</b></a></li> |
||||||
|
<li><a href="#23"><b class="function">cursor_pos</b></a></li> |
||||||
|
<li><a href="#24"><b class="function">titleset</b> <i class="arg">windowtitles</i></a></li> |
||||||
|
<li><a href="#25"><b class="function">detect</b> <i class="arg">text</i></a></li> |
||||||
|
<li><a href="#26"><b class="function">detect_csi</b> <i class="arg">text</i></a></li> |
||||||
|
<li><a href="#27"><b class="function">detect_sgr</b> <i class="arg">text</i></a></li> |
||||||
|
<li><a href="#28"><b class="function">strip</b> <i class="arg">text</i></a></li> |
||||||
|
<li><a href="#29"><b class="function">length</b> <i class="arg">text</i></a></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2> |
||||||
|
<p>Ansi based terminal control string functions</p> |
||||||
|
<p>See <b class="package">punk::ansi::console</b> for related functions for controlling a console</p> |
||||||
|
</div> |
||||||
|
<div id="section2" class="doctools_section"><h2><a name="section2">Overview</a></h2> |
||||||
|
<p>overview of punk::ansi</p> |
||||||
|
<p>punk::ansi functions return their values - no implicit emission to console/stdout</p> |
||||||
|
<div id="subsection1" class="doctools_subsection"><h3><a name="subsection1">Concepts</a></h3> |
||||||
|
<p>Ansi codes can be used to control most terminals on most platforms in an 'almost' standard manner</p> |
||||||
|
<p>There are many differences in terminal implementations - but most should support a core set of features</p> |
||||||
|
<p>punk::ansi does not contain any code for direct terminal manipulation via the local system APIs.</p> |
||||||
|
<p>Sticking to ansi codes where possible may be better for cross-platform and remote operation where such APIs are unlikely to be useable.</p> |
||||||
|
</div> |
||||||
|
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">dependencies</a></h3> |
||||||
|
<p>packages used by punk::ansi</p> |
||||||
|
<ul class="doctools_itemized"> |
||||||
|
<li><p><b class="package">Tcl 8.6</b></p></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div id="section3" class="doctools_section"><h2><a name="section3">API</a></h2> |
||||||
|
<div id="subsection3" class="doctools_subsection"><h3><a name="subsection3">Namespace punk::ansi</a></h3> |
||||||
|
<p>Core API functions for punk::ansi</p> |
||||||
|
<dl class="doctools_definitions"> |
||||||
|
<dt><a name="1"><b class="function">stripansi</b> <i class="arg">text</i></a></dt> |
||||||
|
<dd><p>Return a string with ansi codes stripped out</p></dd> |
||||||
|
<dt><a name="2"><b class="function">a?</b> <span class="opt">?ansicode...?</span></a></dt> |
||||||
|
<dd><p>Return an ansi string representing a table of codes and a panel showing the colours</p></dd> |
||||||
|
<dt><a name="3"><b class="function">a+</b> <span class="opt">?ansicode...?</span></a></dt> |
||||||
|
<dd><p>Returns the ansi code to apply those from the supplied list - without any reset being performed first</p> |
||||||
|
<p>e.g to set foreground red and bold</p> |
||||||
|
<p>punk::ansi::a red bold</p> |
||||||
|
<p>to set background red</p> |
||||||
|
<p>punk::ansi::a Red</p> |
||||||
|
<p>see <b class="cmd">punk::ansi::a?</b> to display a list of codes</p></dd> |
||||||
|
<dt><a name="4"><b class="function">a</b> <span class="opt">?ansicode...?</span></a></dt> |
||||||
|
<dd><p>Returns the ansi code to reset any current settings and apply those from the supplied list</p> |
||||||
|
<p>by calling punk::ansi::a with no arguments - the result is a reset to plain text</p> |
||||||
|
<p>e.g to set foreground red and bold</p> |
||||||
|
<p>punk::ansi::a red bold</p> |
||||||
|
<p>to set background red</p> |
||||||
|
<p>punk::ansi::a Red</p> |
||||||
|
<p>see <b class="cmd">punk::ansi::a?</b> to display a list of codes</p></dd> |
||||||
|
<dt><a name="5"><b class="function">get_code_name</b> <i class="arg">code</i></a></dt> |
||||||
|
<dd><p>for example</p> |
||||||
|
<p>get_code_name red will return 31</p> |
||||||
|
<p>get_code_name 31 will return red</p></dd> |
||||||
|
<dt><a name="6"><b class="function">reset</b></a></dt> |
||||||
|
<dd><p>reset console</p></dd> |
||||||
|
<dt><a name="7"><b class="function">reset_soft</b></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="8"><b class="function">reset_colour</b></a></dt> |
||||||
|
<dd><p>reset colour only</p></dd> |
||||||
|
<dt><a name="9"><b class="function">clear</b></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="10"><b class="function">clear_above</b></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="11"><b class="function">clear_below</b></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="12"><b class="function">cursor_on</b></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="13"><b class="function">cursor_off</b></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="14"><b class="function">move</b> <i class="arg">row</i> <i class="arg">col</i></a></dt> |
||||||
|
<dd><p>Return an ansi sequence to move to row,col</p> |
||||||
|
<p>aka cursor home</p></dd> |
||||||
|
<dt><a name="15"><b class="function">move_emit</b> <i class="arg">row</i> <i class="arg">col</i> <i class="arg">data</i> <span class="opt">?row col data...?</span></a></dt> |
||||||
|
<dd><p>Return an ansi string representing a move to row col with data appended</p> |
||||||
|
<p>row col data can be repeated any number of times to return a string representing the output of the data elements at all those points</p> |
||||||
|
<p>Compare to punk::console::move_emit which calls this function - but writes it to stdout</p> |
||||||
|
<p>punk::console::move_emit_return will also return the cursor to the original position</p> |
||||||
|
<p>There is no punk::ansi::move_emit_return because in a standard console there is no ansi string which can represent a jump back to starting position.</p> |
||||||
|
<p>There is an ansi code to write the current cursor position to stdin (which will generally display on the console) - this is not quite the same thing.</p> |
||||||
|
<p>punk::console::move_emit_return does it by emitting that code and starting a loop to read stdin</p> |
||||||
|
<p>punk::ansi could implement a move_emit_return using the punk::console mechanism - but the resulting string would capture the cursor position at the time the string is built - which is not necessarily when the string is used.</p> |
||||||
|
<p>The following example shows how to do this manually, emitting the string blah at screen position 10,10 and emitting DONE back at the line we started:</p> |
||||||
|
<pre class="doctools_example">punk::ansi::move_emit 10 10 blah {*}[punk::console::get_cursor_pos_list] DONE</pre> |
||||||
|
<p>A string created by any move_emit_return for punk::ansi would not behave in an intuitive manner compared to other punk::ansi move functions - so is deliberately omitted.</p></dd> |
||||||
|
<dt><a name="16"><b class="function">move_forward</b> <i class="arg">n</i></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="17"><b class="function">move_back</b> <i class="arg">n</i></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="18"><b class="function">move_up</b> <i class="arg">n</i></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="19"><b class="function">move_down</b> <i class="arg">n</i></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="20"><b class="function">erase_line</b></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="21"><b class="function">erase_sol</b></a></dt> |
||||||
|
<dd><p>Erase to start of line, leaving cursor position alone.</p></dd> |
||||||
|
<dt><a name="22"><b class="function">erase_eol</b></a></dt> |
||||||
|
<dd></dd> |
||||||
|
<dt><a name="23"><b class="function">cursor_pos</b></a></dt> |
||||||
|
<dd><p>cursor_pos unlikely to be useful on it's own like this as when written to the terminal, this sequence causes the terminal to emit the row;col sequence to stdin</p> |
||||||
|
<p>The output on screen will look something like ^[[47;3R</p> |
||||||
|
<p>Use punk::console::get_cursor_pos or punk::console::get_cursor_pos_list instead.</p> |
||||||
|
<p>These functions will emit the code - but read it in from stdin so that it doesn't display, and then return the row and column as a colon-delimited string or list respectively.</p> |
||||||
|
<p>The punk::ansi::cursor_pos function is used by punk::console::get_cursor_pos and punk::console::get_cursor_pos_list</p></dd> |
||||||
|
<dt><a name="24"><b class="function">titleset</b> <i class="arg">windowtitles</i></a></dt> |
||||||
|
<dd><p>Returns the code to set the title of the terminal window to windowtitle</p> |
||||||
|
<p>This may not work on terminals which have multiple panes/windows</p></dd> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
<div id="subsection4" class="doctools_subsection"><h3><a name="subsection4">Namespace punk::ansi::ta</a></h3> |
||||||
|
<p>text ansi functions</p> |
||||||
|
<p>based on but not identical to the Perl Text Ansi module:</p> |
||||||
|
<p>https://github.com/perlancar/perl-Text-ANSI-Util/blob/master/lib/Text/ANSI/BaseUtil.pm</p> |
||||||
|
<dl class="doctools_definitions"> |
||||||
|
<dt><a name="25"><b class="function">detect</b> <i class="arg">text</i></a></dt> |
||||||
|
<dd><p>Return a boolean indicating whether Ansi codes were detected in text</p></dd> |
||||||
|
<dt><a name="26"><b class="function">detect_csi</b> <i class="arg">text</i></a></dt> |
||||||
|
<dd><p>Return a boolean indicating whether an Ansi Control Sequence Introducer (CSI) was detected in text</p> |
||||||
|
<p>The csi is often represented in code as \x1b or \033 followed by a left bracket [</p> |
||||||
|
<p>The initial byte or escape is commonly referenced as ESC in Ansi documentation</p> |
||||||
|
<p>There is also a multi-byte escape sequence \u009b</p> |
||||||
|
<p>This is less commonly used but is also detected here</p> |
||||||
|
<p>(This function is not in perl ta)</p></dd> |
||||||
|
<dt><a name="27"><b class="function">detect_sgr</b> <i class="arg">text</i></a></dt> |
||||||
|
<dd><p>Return a boolean indicating whether an ansi Select Graphics Rendition code was detected.</p> |
||||||
|
<p>This is the set of CSI sequences ending in 'm'</p> |
||||||
|
<p>This is most commonly an Ansi colour code - but also things such as underline and italics</p> |
||||||
|
<p>An SGR with empty or a single zero argument is a reset of the SGR features - this is also detected.</p> |
||||||
|
<p>(This function is not in perl ta)</p></dd> |
||||||
|
<dt><a name="28"><b class="function">strip</b> <i class="arg">text</i></a></dt> |
||||||
|
<dd><p>Return text stripped of Ansi codes</p> |
||||||
|
<p>This is a tailcall to punk::ansi::stripansi</p></dd> |
||||||
|
<dt><a name="29"><b class="function">length</b> <i class="arg">text</i></a></dt> |
||||||
|
<dd><p>Return the character length after stripping ansi codes - not the printing length</p></dd> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
<div id="subsection5" class="doctools_subsection"><h3><a name="subsection5">Namespace punk::ansi::ansistring</a></h3> |
||||||
|
<p>punk::ansi::string ensemble</p> |
||||||
|
<dl class="doctools_definitions"> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2> |
||||||
|
<p><a href="../../../index.html#ansi">ansi</a>, <a href="../../../index.html#console">console</a>, <a href="../../../index.html#module">module</a>, <a href="../../../index.html#string">string</a>, <a href="../../../index.html#terminal">terminal</a></p> |
||||||
|
</div> |
||||||
|
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2> |
||||||
|
<p>Copyright © 2023</p> |
||||||
|
</div> |
||||||
|
</div></body></html> |
@ -0,0 +1,238 @@ |
|||||||
|
<!DOCTYPE html><html><head> |
||||||
|
<title>punkshell_module_punk::args - args to option-value dict and values dict</title> |
||||||
|
<style type="text/css"><!-- |
||||||
|
HTML { |
||||||
|
background: #FFFFFF; |
||||||
|
color: black; |
||||||
|
} |
||||||
|
BODY { |
||||||
|
background: #FFFFFF; |
||||||
|
color: black; |
||||||
|
} |
||||||
|
DIV.doctools { |
||||||
|
margin-left: 10%; |
||||||
|
margin-right: 10%; |
||||||
|
} |
||||||
|
DIV.doctools H1,DIV.doctools H2 { |
||||||
|
margin-left: -5%; |
||||||
|
} |
||||||
|
H1, H2, H3, H4 { |
||||||
|
margin-top: 1em; |
||||||
|
font-family: sans-serif; |
||||||
|
font-size: large; |
||||||
|
color: #005A9C; |
||||||
|
background: transparent; |
||||||
|
text-align: left; |
||||||
|
} |
||||||
|
H1.doctools_title { |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
UL,OL { |
||||||
|
margin-right: 0em; |
||||||
|
margin-top: 3pt; |
||||||
|
margin-bottom: 3pt; |
||||||
|
} |
||||||
|
UL LI { |
||||||
|
list-style: disc; |
||||||
|
} |
||||||
|
OL LI { |
||||||
|
list-style: decimal; |
||||||
|
} |
||||||
|
DT { |
||||||
|
padding-top: 1ex; |
||||||
|
} |
||||||
|
UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL { |
||||||
|
font: normal 12pt/14pt sans-serif; |
||||||
|
list-style: none; |
||||||
|
} |
||||||
|
LI.doctools_section, LI.doctools_subsection { |
||||||
|
list-style: none; |
||||||
|
margin-left: 0em; |
||||||
|
text-indent: 0em; |
||||||
|
padding: 0em; |
||||||
|
} |
||||||
|
PRE { |
||||||
|
display: block; |
||||||
|
font-family: monospace; |
||||||
|
white-space: pre; |
||||||
|
margin: 0%; |
||||||
|
padding-top: 0.5ex; |
||||||
|
padding-bottom: 0.5ex; |
||||||
|
padding-left: 1ex; |
||||||
|
padding-right: 1ex; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
PRE.doctools_example { |
||||||
|
color: black; |
||||||
|
background: #f5dcb3; |
||||||
|
border: 1px solid black; |
||||||
|
} |
||||||
|
UL.doctools_requirements LI, UL.doctools_syntax LI { |
||||||
|
list-style: none; |
||||||
|
margin-left: 0em; |
||||||
|
text-indent: 0em; |
||||||
|
padding: 0em; |
||||||
|
} |
||||||
|
DIV.doctools_synopsis { |
||||||
|
color: black; |
||||||
|
background: #80ffff; |
||||||
|
border: 1px solid black; |
||||||
|
font-family: serif; |
||||||
|
margin-top: 1em; |
||||||
|
margin-bottom: 1em; |
||||||
|
} |
||||||
|
UL.doctools_syntax { |
||||||
|
margin-top: 1em; |
||||||
|
border-top: 1px solid black; |
||||||
|
} |
||||||
|
UL.doctools_requirements { |
||||||
|
margin-bottom: 1em; |
||||||
|
border-bottom: 1px solid black; |
||||||
|
} |
||||||
|
--></style> |
||||||
|
</head> |
||||||
|
<!-- Generated from file '_module_args-0.1.0.tm.man' by tcllib/doctools with format 'html' |
||||||
|
--> |
||||||
|
<!-- Copyright &copy; 2024 |
||||||
|
--> |
||||||
|
<!-- punkshell_module_punk::args.0 |
||||||
|
--> |
||||||
|
<body><hr> [ |
||||||
|
<a href="../../../toc.html">Main Table Of Contents</a> |
||||||
|
| <a href="../../toc.html">Table Of Contents</a> |
||||||
|
| <a href="../../../index.html">Keyword Index</a> |
||||||
|
] <hr> |
||||||
|
<div class="doctools"> |
||||||
|
<h1 class="doctools_title">punkshell_module_punk::args(0) 0.1.0 doc "args to option-value dict and values dict"</h1> |
||||||
|
<div id="name" class="doctools_section"><h2><a name="name">Name</a></h2> |
||||||
|
<p>punkshell_module_punk::args - args parsing</p> |
||||||
|
</div> |
||||||
|
<div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2> |
||||||
|
<ul class="doctools_toc"> |
||||||
|
<li class="doctools_section"><a href="#toc">Table Of Contents</a></li> |
||||||
|
<li class="doctools_section"><a href="#synopsis">Synopsis</a></li> |
||||||
|
<li class="doctools_section"><a href="#section1">Description</a></li> |
||||||
|
<li class="doctools_section"><a href="#section2">Overview</a> |
||||||
|
<ul> |
||||||
|
<li class="doctools_subsection"><a href="#subsection1">Concepts</a></li> |
||||||
|
<li class="doctools_subsection"><a href="#subsection2">Notes</a></li> |
||||||
|
<li class="doctools_subsection"><a href="#subsection3">dependencies</a></li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
<li class="doctools_section"><a href="#section3">API</a> |
||||||
|
<ul> |
||||||
|
<li class="doctools_subsection"><a href="#subsection4">Namespace punk::args::class</a></li> |
||||||
|
<li class="doctools_subsection"><a href="#subsection5">Namespace punk::args</a></li> |
||||||
|
<li class="doctools_subsection"><a href="#subsection6">Namespace punk::args::lib</a></li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
<li class="doctools_section"><a href="#section4">Internal</a> |
||||||
|
<ul> |
||||||
|
<li class="doctools_subsection"><a href="#subsection7">Namespace punk::args::system</a></li> |
||||||
|
</ul> |
||||||
|
</li> |
||||||
|
<li class="doctools_section"><a href="#keywords">Keywords</a></li> |
||||||
|
<li class="doctools_section"><a href="#copyright">Copyright</a></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2> |
||||||
|
<div class="doctools_synopsis"> |
||||||
|
<ul class="doctools_requirements"> |
||||||
|
<li>package require <b class="pkgname">punk::args</b></li> |
||||||
|
</ul> |
||||||
|
<ul class="doctools_syntax"> |
||||||
|
<li><a href="#1"><b class="function">opts_values</b> <i class="arg">optionspecs</i> <i class="arg">rawargs</i> <span class="opt">?option value...?</span></a></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2> |
||||||
|
<p>Utilities for parsing proc args</p> |
||||||
|
</div> |
||||||
|
<div id="section2" class="doctools_section"><h2><a name="section2">Overview</a></h2> |
||||||
|
<p>overview of punk::args</p> |
||||||
|
<div id="subsection1" class="doctools_subsection"><h3><a name="subsection1">Concepts</a></h3> |
||||||
|
<p>There are 2 main conventions for parsing a proc args list</p> |
||||||
|
<ol class="doctools_enumerated"> |
||||||
|
<li><p>leading option-value pairs followed by a list of values (Tk style)</p></li> |
||||||
|
<li><p>leading list of values followed by option-value pairs (Tcl style)</p></li> |
||||||
|
</ol> |
||||||
|
<p>punk::args is focused on the 1st convention (Tk style): parsing of args in leading option-value pair style - even for non-Tk usage.</p> |
||||||
|
<p>The proc can still contain some leading required values e.g</p> |
||||||
|
<pre class="doctools_example">proc dostuff {arg1 arg2 args} {...}}</pre> |
||||||
|
<p>but having the core values elements at the end of args is more generally useful - especially in cases where the number of trailing values is unknown and/or the proc is to be called in a functional 'pipeline' style.</p> |
||||||
|
<p>The basic principle is that a call to punk::args::opts_vals is made near the beginning of the proc e.g</p> |
||||||
|
<pre class="doctools_example"> |
||||||
|
proc dofilestuff {args} { |
||||||
|
lassign [dict values [punk::args { |
||||||
|
-directory -default "" |
||||||
|
-translation -default binary |
||||||
|
} $args]] opts values |
||||||
|
puts "translation is [dict get $opts -translation]" |
||||||
|
foreach f [dict values $values] { |
||||||
|
puts "doing stuff with file: $f" |
||||||
|
} |
||||||
|
} |
||||||
|
</pre> |
||||||
|
</div> |
||||||
|
<div id="subsection2" class="doctools_subsection"><h3><a name="subsection2">Notes</a></h3> |
||||||
|
<p>There are alternative args parsing packages such as:</p> |
||||||
|
<ol class="doctools_enumerated"> |
||||||
|
<li><p>argp</p></li> |
||||||
|
<li><p>The tcllib set of TEPAM modules</p> |
||||||
|
<p>TEPAM requires an alternative procedure declaration syntax instead of proc - but has support for Tk and documentation generation.</p></li> |
||||||
|
</ol> |
||||||
|
<p>punk::args was designed initially without specific reference to TEPAM - and to handle some edge cases in specific projects where TEPAM wasn't suitable.</p> |
||||||
|
<p>In subsequent revisions of punk::args - some features were made to operate in a way that is similar to TEPAM - to avoid gratuitous differences where possible, but of course there are differences</p> |
||||||
|
<p>and those used TEPAM or mixing TEPAM and punk::args should take care to assess the differences.</p> |
||||||
|
<p>TEPAM is a mature solution and is widely available as it is included in tcllib.</p> |
||||||
|
<p>Serious consideration should be given to using TEPAM if suitable for your project.</p> |
||||||
|
</div> |
||||||
|
<div id="subsection3" class="doctools_subsection"><h3><a name="subsection3">dependencies</a></h3> |
||||||
|
<p>packages used by punk::args</p> |
||||||
|
<ul class="doctools_itemized"> |
||||||
|
<li><p><b class="package">Tcl 8.6</b></p></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div id="section3" class="doctools_section"><h2><a name="section3">API</a></h2> |
||||||
|
<div id="subsection4" class="doctools_subsection"><h3><a name="subsection4">Namespace punk::args::class</a></h3> |
||||||
|
<p>class definitions</p> |
||||||
|
<ol class="doctools_enumerated"> |
||||||
|
</ol> |
||||||
|
</div> |
||||||
|
<div id="subsection5" class="doctools_subsection"><h3><a name="subsection5">Namespace punk::args</a></h3> |
||||||
|
<p>Core API functions for punk::args</p> |
||||||
|
<dl class="doctools_definitions"> |
||||||
|
<dt><a name="1"><b class="function">opts_values</b> <i class="arg">optionspecs</i> <i class="arg">rawargs</i> <span class="opt">?option value...?</span></a></dt> |
||||||
|
<dd><p>Parse rawargs as a sequence of zero or more option-value pairs followed by zero or more values</p> |
||||||
|
<p>Returns a dict of the form: opts <options_dict> values <values_dict></p> |
||||||
|
<p>ARGUMENTS:</p> |
||||||
|
<dl class="doctools_arguments"> |
||||||
|
<dt>multiline-string <i class="arg">optionspecs</i></dt> |
||||||
|
<dd><p>This a block of text with records delimited by newlines (lf or crlf)</p> |
||||||
|
<p>Each optionspec line must be of the form:</p> |
||||||
|
<p>-optionname -key val -key2 val2...</p> |
||||||
|
<p>where the valid keys for each option specification are: -default -type -range -choices -optional</p></dd> |
||||||
|
<dt>list <i class="arg">rawargs</i></dt> |
||||||
|
<dd><p>This is a list of the arguments to parse. Usually it will be the \$args value from the containing proc</p></dd> |
||||||
|
</dl></dd> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
<div id="subsection6" class="doctools_subsection"><h3><a name="subsection6">Namespace punk::args::lib</a></h3> |
||||||
|
<p>Secondary functions that are part of the API</p> |
||||||
|
<dl class="doctools_definitions"> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div id="section4" class="doctools_section"><h2><a name="section4">Internal</a></h2> |
||||||
|
<div id="subsection7" class="doctools_subsection"><h3><a name="subsection7">Namespace punk::args::system</a></h3> |
||||||
|
<p>Internal functions that are not part of the API</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2> |
||||||
|
<p><a href="../../../index.html#args">args</a>, <a href="../../../index.html#arguments">arguments</a>, <a href="../../../index.html#module">module</a>, <a href="../../../index.html#parse">parse</a>, <a href="../../../index.html#proc">proc</a></p> |
||||||
|
</div> |
||||||
|
<div id="copyright" class="doctools_section"><h2><a name="copyright">Copyright</a></h2> |
||||||
|
<p>Copyright © 2024</p> |
||||||
|
</div> |
||||||
|
</div></body></html> |
@ -0,0 +1,596 @@ |
|||||||
|
# -*- tcl -*- |
||||||
|
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'pmix make' or bin/punkmake to update from <pkg>-buildversion.txt |
||||||
|
# module template: shellspy/src/decktemplates/vendor/punk/modules/template_module-0.0.2.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) 2024 |
||||||
|
# |
||||||
|
# @@ Meta Begin |
||||||
|
# Application punk::args 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license <unspecified> |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# doctools header |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[manpage_begin punkshell_module_punk::args 0 999999.0a1.0] |
||||||
|
#[copyright "2024"] |
||||||
|
#[titledesc {args parsing}] [comment {-- Name section and table of contents description --}] |
||||||
|
#[moddesc {args to option-value dict and values dict}] [comment {-- Description at end of page heading --}] |
||||||
|
#[require punk::args] |
||||||
|
#[keywords module proc args arguments parse] |
||||||
|
#[description] |
||||||
|
#[para]Utilities for parsing proc args |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section Overview] |
||||||
|
#[para] overview of punk::args |
||||||
|
#[subsection Concepts] |
||||||
|
#[para]There are 2 main conventions for parsing a proc args list |
||||||
|
#[list_begin enumerated] |
||||||
|
#[enum] |
||||||
|
#[para]leading option-value pairs followed by a list of values (Tk style) |
||||||
|
#[enum] |
||||||
|
#[para]leading list of values followed by option-value pairs (Tcl style) |
||||||
|
#[list_end] |
||||||
|
#[para]punk::args is focused on the 1st convention (Tk style): parsing of args in leading option-value pair style - even for non-Tk usage. |
||||||
|
#[para]The proc can still contain some leading required values e.g [example "proc dostuff {arg1 arg2 args} {...}}"] |
||||||
|
#[para]but having the core values elements at the end of args is more generally useful - especially in cases where the number of trailing values is unknown and/or the proc is to be called in a functional 'pipeline' style. |
||||||
|
#[para]The basic principle is that a call to punk::args::opts_vals is made near the beginning of the proc e.g |
||||||
|
#[example_begin] |
||||||
|
# proc dofilestuff {args} { |
||||||
|
# lassign [lb]dict values [lb]punk::args { |
||||||
|
# -directory -default "" |
||||||
|
# -translation -default binary |
||||||
|
# } $args[rb][rb] opts values |
||||||
|
# |
||||||
|
# puts "translation is [lb]dict get $opts -translation[rb]" |
||||||
|
# foreach f [lb]dict values $values[rb] { |
||||||
|
# puts "doing stuff with file: $f" |
||||||
|
# } |
||||||
|
# } |
||||||
|
#[example_end] |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection Notes] |
||||||
|
#[para]There are alternative args parsing packages such as: |
||||||
|
#[list_begin enumerated] |
||||||
|
#[enum]argp |
||||||
|
#[enum]The tcllib set of TEPAM modules |
||||||
|
#[para]TEPAM requires an alternative procedure declaration syntax instead of proc - but has support for Tk and documentation generation. |
||||||
|
#[list_end] |
||||||
|
#[para]punk::args was designed initially without specific reference to TEPAM - and to handle some edge cases in specific projects where TEPAM wasn't suitable. |
||||||
|
#[para]In subsequent revisions of punk::args - some features were made to operate in a way that is similar to TEPAM - to avoid gratuitous differences where possible, but of course there are differences |
||||||
|
#[para]and those used TEPAM or mixing TEPAM and punk::args should take care to assess the differences. |
||||||
|
#[para]TEPAM is a mature solution and is widely available as it is included in tcllib. |
||||||
|
#[para]Serious consideration should be given to using TEPAM if suitable for your project. |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection dependencies] |
||||||
|
#[para] packages used by punk::args |
||||||
|
#[list_begin itemized] |
||||||
|
|
||||||
|
package require Tcl 8.6 |
||||||
|
#*** !doctools |
||||||
|
#[item] [package {Tcl 8.6}] |
||||||
|
|
||||||
|
# #package require frobz |
||||||
|
# #*** !doctools |
||||||
|
# #[item] [package {frobz}] |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section API] |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# oo::class namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval punk::args::class { |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::args::class}] |
||||||
|
#[para] class definitions |
||||||
|
if {[info commands [namespace current]::interface_sample1] eq ""} { |
||||||
|
#*** !doctools |
||||||
|
#[list_begin enumerated] |
||||||
|
|
||||||
|
# oo::class create interface_sample1 { |
||||||
|
# #*** !doctools |
||||||
|
# #[enum] CLASS [class interface_sample1] |
||||||
|
# #[list_begin definitions] |
||||||
|
|
||||||
|
# method test {arg1} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call class::interface_sample1 [method test] [arg arg1]] |
||||||
|
# #[para] test method |
||||||
|
# puts "test: $arg1" |
||||||
|
# } |
||||||
|
|
||||||
|
# #*** !doctools |
||||||
|
# #[list_end] [comment {-- end definitions interface_sample1}] |
||||||
|
# } |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end class enumeration ---}] |
||||||
|
} |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# Base namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval punk::args { |
||||||
|
namespace export * |
||||||
|
#variable xyz |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::args}] |
||||||
|
#[para] Core API functions for punk::args |
||||||
|
#[list_begin definitions] |
||||||
|
|
||||||
|
|
||||||
|
#generally we expect values to contain leading dashes only if -- specified. Otherwise no reliable way determine difference between bad flags and values |
||||||
|
#If no eopts (--) specified we stop looking for opts at the first nondash encountered in a position we'd expect a dash - so without eopt, values could contain dashes - but not in first position after flags. |
||||||
|
#only supports -flag val pairs, not solo options |
||||||
|
#If an option is supplied multiple times - only the last value is used. |
||||||
|
proc opts_values {optionspecs rawargs args} { |
||||||
|
#*** !doctools |
||||||
|
#[call [fun opts_values] [arg optionspecs] [arg rawargs] [opt {option value...}]] |
||||||
|
#[para]Parse rawargs as a sequence of zero or more option-value pairs followed by zero or more values |
||||||
|
#[para]Returns a dict of the form: opts <options_dict> values <values_dict> |
||||||
|
#[para]ARGUMENTS: |
||||||
|
#[list_begin arguments] |
||||||
|
#[arg_def multiline-string optionspecs] |
||||||
|
#[para] This a block of text with records delimited by newlines (lf or crlf) |
||||||
|
#[para]Each optionspec line must be of the form: |
||||||
|
#[para]-optionname -key val -key2 val2... |
||||||
|
#[para]where the valid keys for each option specification are: -default -type -range -choices -optional |
||||||
|
#[arg_def list rawargs] |
||||||
|
#[para] This is a list of the arguments to parse. Usually it will be the \$args value from the containing proc |
||||||
|
#[list_end] |
||||||
|
#[para] |
||||||
|
|
||||||
|
|
||||||
|
set optionspecs [string map [list \r\n \n] $optionspecs] |
||||||
|
set known_argspecs [list -default -type -range -choices -nocase -optional -multiple -validate_without_ansi -allow_ansi -strip_ansi] |
||||||
|
set optspec_defaults [dict create\ |
||||||
|
-optional 1\ |
||||||
|
-allow_ansi 1\ |
||||||
|
-validate_without_ansi 0\ |
||||||
|
-strip_ansi 0\ |
||||||
|
-nocase 0\ |
||||||
|
] |
||||||
|
set required_opts [list] |
||||||
|
set required_vals [list] |
||||||
|
set arg_info [dict create] |
||||||
|
set defaults_dict [dict create] |
||||||
|
#first process dashed and non-dashed argspecs without regard to whether non-dashed are at the beginning or end |
||||||
|
set value_names [list] |
||||||
|
foreach ln [split $optionspecs \n] { |
||||||
|
set trimln [string trim $ln] |
||||||
|
if {$trimln eq ""} { |
||||||
|
continue |
||||||
|
} |
||||||
|
if {[string index $trimln 0] eq "#"} { |
||||||
|
continue |
||||||
|
} |
||||||
|
set argname [lindex $trimln 0] |
||||||
|
set argspecs [lrange $trimln 1 end] |
||||||
|
if {[string match -* $argname]} { |
||||||
|
dict set argspecs -ARGTYPE option |
||||||
|
set is_opt 1 |
||||||
|
} else { |
||||||
|
dict set argspecs -ARGTYPE value |
||||||
|
lappend value_names $argname |
||||||
|
set is_opt 0 |
||||||
|
} |
||||||
|
if {[llength $argspecs] %2 != 0} { |
||||||
|
error "punk::args::opts_values - bad optionspecs line for argument '$argname' Remaining items on line must be in paired option-value format - received '$argspecs'" |
||||||
|
} |
||||||
|
dict for {spec specval} $argspecs { |
||||||
|
if {$spec ni [concat $known_argspecs -ARGTYPE]} { |
||||||
|
error "punk::args::opts_values - unrecognised key '$spec' in specifications for argument '$argname' Known option specification keys: $known_argspecs" |
||||||
|
} |
||||||
|
} |
||||||
|
set argspecs [dict merge $optspec_defaults $argspecs] |
||||||
|
dict set arg_info $argname $argspecs |
||||||
|
if {![dict get $argspecs -optional]} { |
||||||
|
if {$is_opt} { |
||||||
|
lappend required_opts $argname |
||||||
|
} else { |
||||||
|
lappend required_vals $argname |
||||||
|
} |
||||||
|
} |
||||||
|
if {[dict exists $arg_info $argname -default]} { |
||||||
|
dict set defaults_dict $argname [dict get $arg_info $argname -default] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#puts "--> [info frame -2] <--" |
||||||
|
set cmdinfo [dict get [info frame -2] cmd] |
||||||
|
#we can't treat cmdinfo as a list - it may be something like {command {*}$args} in which case lindex $cmdinfo 0 won't work |
||||||
|
#hopefully first word is a plain proc name if this function was called in the normal manner - directly from a proc |
||||||
|
#we will break at first space and assume the lhs of that will give enough info to be reasonable - (alternatively we could use entire cmdinfo - but it might be big and ugly) |
||||||
|
set caller [regexp -inline {\S+} $cmdinfo] |
||||||
|
|
||||||
|
#if called from commandline or some other contexts such as outside of a proc in a namespace - caller may just be "namespace" |
||||||
|
if {$caller eq "namespace"} { |
||||||
|
set caller "punk::args::opts_values called from namespace" |
||||||
|
} |
||||||
|
|
||||||
|
# ------------------------------ |
||||||
|
if {$caller ne "punk::args::opts_values"} { |
||||||
|
#check our own args |
||||||
|
lassign [punk::args::opts_values "-anyopts -default 0\n -minvalues -default 0\n -maxvalues -default -1" $args] _o ownopts _v ownvalues |
||||||
|
if {[llength $ownvalues] > 0} { |
||||||
|
error "punk::args::opts_values expected: a multiline text block of option-specifications, a list of args and at most three option pairs -minvalues <int>, -maxvalues <int>, -anyopts true|false - got extra arguments: '$ownvalues'" |
||||||
|
} |
||||||
|
set opt_minvalues [dict get $ownopts -minvalues] |
||||||
|
set opt_maxvalues [dict get $ownopts -maxvalues] |
||||||
|
set opt_anyopts [dict get $ownopts -anyopts] |
||||||
|
} else { |
||||||
|
#don't check our own args if we called ourself |
||||||
|
set opt_minvalues 0 |
||||||
|
set opt_maxvalues 0 |
||||||
|
set opt_anyopts 0 |
||||||
|
} |
||||||
|
# ------------------------------ |
||||||
|
|
||||||
|
if {[set eopts [lsearch $rawargs "--"]] >= 0} { |
||||||
|
set values [lrange $rawargs $eopts+1 end] |
||||||
|
set arglist [lrange $rawargs 0 $eopts-1] |
||||||
|
} else { |
||||||
|
if {[lsearch $rawargs -*] >= 0} { |
||||||
|
#to support option values with leading dash e.g -offset -1 , we can't just take the last flagindex |
||||||
|
set i 0 |
||||||
|
foreach {k v} $rawargs { |
||||||
|
if {![string match -* $k]} { |
||||||
|
break |
||||||
|
} |
||||||
|
if {$i+1 >= [llength $rawargs]} { |
||||||
|
#no value for last flag |
||||||
|
error "bad options for $caller. No value supplied for last option $k" |
||||||
|
} |
||||||
|
incr i 2 |
||||||
|
} |
||||||
|
set arglist [lrange $rawargs 0 $i-1] |
||||||
|
set values [lrange $rawargs $i end] |
||||||
|
} else { |
||||||
|
set values $rawargs ;#no -flags detected |
||||||
|
set arglist [list] |
||||||
|
} |
||||||
|
} |
||||||
|
#confirm any valnames before last don't have -multiple key |
||||||
|
foreach valname [lrange $value_names 0 end-1] { |
||||||
|
if {[dict exists $arg_info $valname -multiple ]} { |
||||||
|
error "bad key -multiple on argument spec for '$valname'. Only the last value argument specification can be marked -multiple" |
||||||
|
} |
||||||
|
} |
||||||
|
set values_dict [dict create] |
||||||
|
set validx 0 |
||||||
|
set in_multiple "" |
||||||
|
foreach valname $value_names val $values { |
||||||
|
if {$validx+1 > [llength $values]} { |
||||||
|
break |
||||||
|
} |
||||||
|
if {$valname ne ""} { |
||||||
|
if {[dict exists $arg_info $valname -multiple] && [dict get $arg_info $valname -multiple]} { |
||||||
|
dict lappend values_dict $valname $val |
||||||
|
set in_multiple $valname |
||||||
|
} else { |
||||||
|
dict set values_dict $valname $val |
||||||
|
} |
||||||
|
} else { |
||||||
|
if {$in_multiple ne ""} { |
||||||
|
dict lappend values_dict $in_multiple $val |
||||||
|
} else { |
||||||
|
dict set values_dict $validx $val |
||||||
|
} |
||||||
|
} |
||||||
|
incr validx |
||||||
|
} |
||||||
|
|
||||||
|
if {$opt_maxvalues == -1} { |
||||||
|
#only check min |
||||||
|
if {[llength $values] < $opt_minvalues} { |
||||||
|
error "bad number of trailing values for $caller. Got [llength $values] values. Expected at least $opt_minvalues" |
||||||
|
} |
||||||
|
} else { |
||||||
|
if {[llength $values] < $opt_minvalues || [llength $values] > $opt_maxvalues} { |
||||||
|
if {$opt_minvalues == $opt_maxvalues} { |
||||||
|
error "bad number of trailing values for $caller. Got [llength $values] values. Expected exactly $opt_minvalues" |
||||||
|
} else { |
||||||
|
error "bad number of trailing values for $caller. Got [llength $values] values. Expected between $opt_minvalues and $opt_maxvalues inclusive" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#opts explicitly marked as -optional 0 must be present - regardless of -anyopts (which allows us to ignore additional opts to pass on to next call) |
||||||
|
#however - if -anyopts is true, there is a risk we will treat a shortened option name as matching our default - when it was intended for the next call |
||||||
|
#We will always require exact matches for all required opts to avoid this risk, even though an ultimately-called function may not require the full-length option-name REVIEW |
||||||
|
#The aim is to allow a wrapper function to specify a default value for an option (and/or other changes/restrictions to a particular option or two) - without having to re-specify all the options for the underlying function. |
||||||
|
#without full respecification in the wrapper - we can't know that a supplied prefix is unambiguous at the next level |
||||||
|
#For this reason we need to pass on full-length opts for any defined options in the wrapper even if anyopts is true |
||||||
|
foreach r $required_opts { |
||||||
|
if {$r ni [dict keys $arglist]} { |
||||||
|
error "Required option missing for $caller. '$r' is marked with -optional false - so must be present in its full-length form" |
||||||
|
} |
||||||
|
} |
||||||
|
foreach r $required_vals { |
||||||
|
if {$r ni [dict keys $values_dict]} { |
||||||
|
error "Required value missing for $caller. '$r' is marked with -optional false - so must be present" |
||||||
|
} |
||||||
|
} |
||||||
|
if {!$opt_anyopts} { |
||||||
|
set checked_args [dict create] |
||||||
|
for {set i 0} {$i < [llength $arglist]} {incr i} { |
||||||
|
#allow this to error out with message indicating expected flags |
||||||
|
set val [lindex $arglist $i+1] |
||||||
|
set fullopt [tcl::prefix match -message "options for $caller. Unexpected option" [dict keys $arg_info] [lindex $arglist $i]] |
||||||
|
if {[dict exists $arg_info $fullopt -multiple] && [dict get $arg_info $fullopt -multiple]} { |
||||||
|
dict lappend checked_args $fullopt $val |
||||||
|
} else { |
||||||
|
dict set checked_args $fullopt $val |
||||||
|
} |
||||||
|
incr i ;#skip val |
||||||
|
} |
||||||
|
} else { |
||||||
|
#still need to use tcl::prefix match to normalize - but don't raise an error |
||||||
|
set checked_args [dict create] |
||||||
|
dict for {k v} $arglist { |
||||||
|
if {![catch {tcl::prefix::match [dict keys $arg_info] $k} fullopt]} { |
||||||
|
if {[dict exists $arg_info $fullopt -multiple] && [dict get $arg_info $fullopt -multiple]} { |
||||||
|
dict lappend checked_args $fullopt $v |
||||||
|
} else { |
||||||
|
dict set checked_args $fullopt $v |
||||||
|
} |
||||||
|
} else { |
||||||
|
#opt was unspecified |
||||||
|
dict set checked_args $k $v |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
set opts [dict merge $defaults_dict $checked_args] |
||||||
|
#assert - checked_args keys are full-length option names if -anyopts was false or if the supplied option as a shortname matched one of our defined options |
||||||
|
|
||||||
|
#todo - allow defaults outside of choices/ranges |
||||||
|
|
||||||
|
#check types,ranges,choices |
||||||
|
set opts_and_values [concat $opts $values_dict] |
||||||
|
dict for {o v} $opts_and_values { |
||||||
|
if {[dict exists $arg_info $o -multiple] && [dict get $arg_info $o -multiple]} { |
||||||
|
set vlist $v |
||||||
|
} else { |
||||||
|
set vlist [list $v] |
||||||
|
} |
||||||
|
|
||||||
|
if {[dict exists $arg_info $o -validate_without_ansi] && [dict get $arg_info $o -validate_without_ansi]} { |
||||||
|
set validate_without_ansi 1 |
||||||
|
package require punk::ansi |
||||||
|
} else { |
||||||
|
set validate_without_ansi 0 |
||||||
|
} |
||||||
|
if {[dict exists $arg_info $o -allow_ansi] && [dict get $arg_info $o -allow_ansi]} { |
||||||
|
set allow_ansi 1 |
||||||
|
} else { |
||||||
|
package require punk::ansi |
||||||
|
set allow_ansi 0 |
||||||
|
} |
||||||
|
|
||||||
|
foreach e $vlist { |
||||||
|
if {!$allow_ansi} { |
||||||
|
if {[punk::ansi::ta::detect $e]} { |
||||||
|
error "Option $o for $caller contains ansi - but -allow_ansi is false. Received: '$e'" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
set vlist_check [list] |
||||||
|
foreach e $vlist { |
||||||
|
if {$validate_without_ansi} { |
||||||
|
lappend vlist_check [punk::ansi::stripansi $e] |
||||||
|
} else { |
||||||
|
lappend vlist_check $e |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
set is_default 0 |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {[dict exists $defaults_dict $o] && ($e_check eq [dict get $defaults_dict $o])} { |
||||||
|
incr is_default |
||||||
|
} |
||||||
|
} |
||||||
|
if {$is_default eq [llength $vlist]} { |
||||||
|
set is_default true |
||||||
|
} |
||||||
|
#we want defaults to pass through - even if they don't pass the checks that would be required for a specified value |
||||||
|
#If the caller manually specified a value that happens to match the default - we don't detect that as any different from an unspecified value - Review. |
||||||
|
if {!$is_default} { |
||||||
|
if {[dict exists $arg_info $o -type]} { |
||||||
|
set type [dict get $arg_info $o -type] |
||||||
|
if {[string tolower $type] in {int integer double}} { |
||||||
|
if {[string tolower $type] in {int integer}} { |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {![string is integer -strict $e_check]} { |
||||||
|
error "Option $o for $caller requires type 'integer'. Received: '$e'" |
||||||
|
} |
||||||
|
} |
||||||
|
} elseif {[string tolower $type] in {double}} { |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {![string is double -strict $e_check]} { |
||||||
|
error "Option $o for $caller requires type 'double'. Received: '$e'" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#todo - small-value double comparisons with error-margin? review |
||||||
|
if {[dict exists $arg_info $o -range]} { |
||||||
|
lassign [dict get $arg_info $o -range] low high |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {$e_check < $low || $e_check > $high} { |
||||||
|
error "Option $o for $caller must be between $low and $high. Received: '$e'" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} elseif {[string tolower $type] in {bool boolean}} { |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {![string is boolean -strict $e_check]} { |
||||||
|
error "Option $o for $caller requires type 'boolean'. Received: '$e'" |
||||||
|
} |
||||||
|
} |
||||||
|
} elseif {[string tolower $type] in {alnum alpha ascii control digit graph lower print punct space upper wordchar xdigit}} { |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {![string is [string tolower $type] $e_check]} { |
||||||
|
error "Option $o for $caller requires type '[string tolower $type]'. Received: '$e'" |
||||||
|
} |
||||||
|
} |
||||||
|
} elseif {[string tolower $type] in {file directory existingfile existingdirectory}} { |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {!([string length $e_check]>0 && ![regexp {[\"*?<>\;]} $e_check])} { |
||||||
|
error "Option $o for $caller requires type '[string tolower $type]'. Received: '$e' which doesn't look like it could be a file or directory" |
||||||
|
} |
||||||
|
} |
||||||
|
if {[string tolower $type] in {existingfile}} { |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {![file exists $e_check]} { |
||||||
|
error "Option $o for $caller requires type '[string tolower $type]'. Received: '$e' which is not an existing file" |
||||||
|
} |
||||||
|
} |
||||||
|
} elseif {[string tolower $type] in {existingdirectory}} { |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {![file isdirectory $e_check]} { |
||||||
|
error "Option $o for $caller requires type '[string tolower $type]'. Received: '$e' which is not an existing directory" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} elseif {[string tolower $type] in {char character}} { |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {[string length != 1]} { |
||||||
|
error "Option $o for $caller requires type '[string tolower $type]'. Received: '$e' which is not a single character" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if {[dict exists $arg_info $o -choices]} { |
||||||
|
set choices [dict get $arg_info $o -choices] |
||||||
|
set nocase [dict get $arg_info $o -nocase] |
||||||
|
foreach e $vlist e_check $vlist_check { |
||||||
|
if {$nocase} { |
||||||
|
set casemsg "(case insensitive)" |
||||||
|
set choices_test [string tolower $choices] |
||||||
|
set v_test [string tolower $e_check] |
||||||
|
} else { |
||||||
|
set casemsg "(case sensitive)" |
||||||
|
set v_test $e_check |
||||||
|
set choices_test $choices |
||||||
|
} |
||||||
|
if {$v_test ni $choices_test} { |
||||||
|
error "Option $o for $caller must be one of the listed values $choices $casemsg. Received: '$e'" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if {[dict exists $arg_info $o -strip_ansi] && [dict get $arg_info $o -strip_ansi]} { |
||||||
|
set stripped_list [list] |
||||||
|
foreach e $vlist { |
||||||
|
lappend stripped_list [punk::ansi::stripansi $e] |
||||||
|
} |
||||||
|
if {[dict exists $arg_info $o -multiple] && [dict get $arg_info $o -multiple]} { |
||||||
|
if {[dict get $arg_info $o -ARGTYPE] eq "option"} { |
||||||
|
dict set opts $o $stripped_list |
||||||
|
} else { |
||||||
|
dict set values_dict $o $stripped_list |
||||||
|
} |
||||||
|
} else { |
||||||
|
if {[dict get $arg_info $o -ARGTYPE] eq "option"} { |
||||||
|
dict set opts $o [lindex $stripped_list 0] |
||||||
|
} else { |
||||||
|
dict set values_dict [lindex $stripped_list 0] |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#maintain order of opts $opts values $values as caller may use lassign. |
||||||
|
return [dict create opts $opts values $values_dict] |
||||||
|
} |
||||||
|
|
||||||
|
#proc sample1 {p1 args} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call [fun sample1] [arg p1] [opt {?option value...?}]] |
||||||
|
# #[para]Description of sample1 |
||||||
|
# return "ok" |
||||||
|
#} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end definitions namespace punk::args ---}] |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# Secondary API namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval punk::args::lib { |
||||||
|
namespace export * |
||||||
|
namespace path [namespace parent] |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::args::lib}] |
||||||
|
#[para] Secondary functions that are part of the API |
||||||
|
#[list_begin definitions] |
||||||
|
|
||||||
|
#proc utility1 {p1 args} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call lib::[fun utility1] [arg p1] [opt {option value...}]] |
||||||
|
# #[para]Description of utility1 |
||||||
|
# return 1 |
||||||
|
#} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end definitions namespace punk::args::lib ---}] |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[section Internal] |
||||||
|
namespace eval punk::args::system { |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::args::system}] |
||||||
|
#[para] Internal functions that are not part of the API |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
package provide punk::args [namespace eval punk::args { |
||||||
|
variable pkg punk::args |
||||||
|
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,541 @@ |
|||||||
|
# -*- 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) 2024 |
||||||
|
# |
||||||
|
# @@ Meta Begin |
||||||
|
# Application punk::flib 999999.0a1.0 |
||||||
|
# Meta platform tcl |
||||||
|
# Meta license <unspecified> |
||||||
|
# @@ Meta End |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# doctools header |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[manpage_begin punkshell_module_punk::flib 0 999999.0a1.0] |
||||||
|
#[copyright "2024"] |
||||||
|
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}] |
||||||
|
#[moddesc {-}] [comment {-- Description at end of page heading --}] |
||||||
|
#[require punk::flib] |
||||||
|
#[keywords module] |
||||||
|
#[description] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section Overview] |
||||||
|
#[para] overview of punk::flib |
||||||
|
#[subsection Concepts] |
||||||
|
#[para] - |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Requirements |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection dependencies] |
||||||
|
#[para] packages used by punk::flib |
||||||
|
#[list_begin itemized] |
||||||
|
|
||||||
|
package require Tcl 8.6 |
||||||
|
#*** !doctools |
||||||
|
#[item] [package {Tcl 8.6}] |
||||||
|
|
||||||
|
# #package require frobz |
||||||
|
# #*** !doctools |
||||||
|
# #[item] [package {frobz}] |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[section API] |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# oo::class namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval punk::flib::class { |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::flib::class}] |
||||||
|
#[para] class definitions |
||||||
|
if {[info commands [namespace current]::interface_sample1] eq ""} { |
||||||
|
#*** !doctools |
||||||
|
#[list_begin enumerated] |
||||||
|
|
||||||
|
# oo::class create interface_sample1 { |
||||||
|
# #*** !doctools |
||||||
|
# #[enum] CLASS [class interface_sample1] |
||||||
|
# #[list_begin definitions] |
||||||
|
|
||||||
|
# method test {arg1} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call class::interface_sample1 [method test] [arg arg1]] |
||||||
|
# #[para] test method |
||||||
|
# puts "test: $arg1" |
||||||
|
# } |
||||||
|
|
||||||
|
# #*** !doctools |
||||||
|
# #[list_end] [comment {-- end definitions interface_sample1}] |
||||||
|
# } |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end class enumeration ---}] |
||||||
|
} |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# Base namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval punk::flib { |
||||||
|
namespace export * |
||||||
|
#variable xyz |
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::flib}] |
||||||
|
#[para] Core API functions for punk::flib |
||||||
|
#[list_begin definitions] |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#proc sample1 {p1 args} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call [fun sample1] [arg p1] [opt {?option value...?}]] |
||||||
|
# #[para]Description of sample1 |
||||||
|
# return "ok" |
||||||
|
#} |
||||||
|
|
||||||
|
>pattern .. Create >libpattern ;#clone to a library factory |
||||||
|
>libpattern .. Construct {args} { |
||||||
|
var o_this |
||||||
|
set o_this @this@ |
||||||
|
var o_last_child |
||||||
|
set o_last_child "" |
||||||
|
} |
||||||
|
|
||||||
|
>libpattern .. Method version {} { |
||||||
|
return 1.0.0 |
||||||
|
} |
||||||
|
|
||||||
|
>libpattern .. Method aliasprefix {pfx} { |
||||||
|
var o_this |
||||||
|
var o_last_child |
||||||
|
if {![string length $o_last_child]} { |
||||||
|
error " . aliasprefix - Create library object with . new >somename first." |
||||||
|
} |
||||||
|
set patternmethods [$o_this .. PM] |
||||||
|
set aliases [list] |
||||||
|
foreach m $patternmethods { |
||||||
|
set a ${pfx}${m} |
||||||
|
if {[llength [info commands $a]]} { |
||||||
|
puts stderr "WARNING - a command was already present at: $a" |
||||||
|
} |
||||||
|
interp alias "" $a "" [$o_last_child . $m .] |
||||||
|
lappend aliases $a |
||||||
|
} |
||||||
|
return $aliases |
||||||
|
} |
||||||
|
>libpattern .. Method new {objcmdname} { |
||||||
|
var o_this |
||||||
|
set o_this @this@ |
||||||
|
var o_last_child |
||||||
|
set nscaller [uplevel 1 [list namespace current]] |
||||||
|
if {![string match ::* $objcmdname]} { |
||||||
|
if {$nscaller eq "::"} {set nscaller ""} |
||||||
|
set objcmdname ${nscaller}::$objcmdname |
||||||
|
} |
||||||
|
uplevel 1 [list $o_this .. Create $objcmdname] |
||||||
|
set o_last_child $objcmdname |
||||||
|
} |
||||||
|
|
||||||
|
>libpattern .. Constructor {args} { |
||||||
|
var o_this |
||||||
|
set o_this @this@ |
||||||
|
} |
||||||
|
|
||||||
|
>libpattern .. Clone >ls_lib |
||||||
|
>ls_lib .. PatternMethod tail {args} { |
||||||
|
if {![llength $args]} { |
||||||
|
error "argumenterror cannot retrieve tail on an empty input list" ">ls_lib . tail $args" [list argumenterror tail empty_list] |
||||||
|
} |
||||||
|
lrange $args 1 end |
||||||
|
} |
||||||
|
>ls_lib .. PatternMethod init {args} { |
||||||
|
if {![llength $args]} { |
||||||
|
error "argumenterror cannot retrieve init on an empty input list" ">ls_lib . init $args" [list argumenterror init empty_list] |
||||||
|
} |
||||||
|
lrange $args 0 end-1 |
||||||
|
} |
||||||
|
>ls_lib .. PatternMethod head {args} { |
||||||
|
if {![llength $args]} { |
||||||
|
error "argumenterror cannot retrieve head on an empty input list" ">ls_lib . head $args" [list argumenterror head empty_list] |
||||||
|
} |
||||||
|
lindex $args 0 |
||||||
|
} |
||||||
|
>ls_lib .. PatternMethod last {args} { |
||||||
|
if {![llength $args]} { |
||||||
|
error "argumenterror cannot retrieve last on an empty input list. Use li.index end to avoid list length check" ">ls_lib . last $args" [list argumenterror last empty_list] |
||||||
|
} |
||||||
|
lindex $args end |
||||||
|
} |
||||||
|
>ls_lib .. PatternMethod elem {val args} { |
||||||
|
expr {$val in $args} |
||||||
|
} |
||||||
|
>ls_lib .. PatternMethod index {idx args} { |
||||||
|
lindex $args $idx |
||||||
|
} |
||||||
|
>ls_lib .. PatternMethod range {s e args} { |
||||||
|
lrange $args $s $e |
||||||
|
} |
||||||
|
|
||||||
|
#take/drop - haskell-like - but no lazy support REVIEW |
||||||
|
#see also https://www.haskellforall.com/2022/05/why-does-haskells-take-function-accept.html |
||||||
|
>ls_lib .. PatternMethod take {n args} { |
||||||
|
#keep basic behaviour like Haskell ie we allow returning less than n (without error) if insufficient elements |
||||||
|
lrange $args 0 $n-1 |
||||||
|
} |
||||||
|
>ls_lib .. PatternMethod drop {n args} { |
||||||
|
lrange $args $n end |
||||||
|
} |
||||||
|
|
||||||
|
>ls_lib . new >ls |
||||||
|
>ls_lib . aliasprefix "ls." |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#list item lib |
||||||
|
>libpattern .. Clone >li_lib |
||||||
|
>li_lib .. PatternMethod tail {listdata} { |
||||||
|
if {![llength $listdata]} { |
||||||
|
error "argumenterror cannot retrieve tail on an empty input list" ">li_lib . tail $listdata" [list argumenterror tail empty_list] |
||||||
|
} |
||||||
|
lrange $listdata 1 end |
||||||
|
} |
||||||
|
>li_lib .. PatternMethod init {listdata} { |
||||||
|
if {![llength $listdata]} { |
||||||
|
error "argumenterror cannot retrieve init on an empty input list" ">li_lib . init $listdata" [list argumenterror init empty_list] |
||||||
|
} |
||||||
|
lrange $listdata 0 end-1 |
||||||
|
} |
||||||
|
>li_lib .. PatternMethod head {listdata} { |
||||||
|
if {![llength $listdata]} { |
||||||
|
error "argumenterror cannot retrieve head on an empty input list" ">li_lib . head $listdata" [list argumenterror head empty_list] |
||||||
|
} |
||||||
|
lindex $listdata 0 |
||||||
|
} |
||||||
|
>li_lib .. PatternMethod last {listdata} { |
||||||
|
if {![llength $listdata]} { |
||||||
|
error "argumenterror cannot retrieve last on an empty input list. Use li.index end to avoid list length check" ">li_lib . last $listdata" [list argumenterror last empty_list] |
||||||
|
} |
||||||
|
lindex $listdata end |
||||||
|
} |
||||||
|
>li_lib .. PatternMethod elem {val listdata} { |
||||||
|
expr {$val in $listdata} |
||||||
|
} |
||||||
|
>li_lib .. PatternMethod index {idx listdata} { |
||||||
|
lindex $listdata $idx |
||||||
|
} |
||||||
|
>li_lib .. PatternMethod range {s e listdata} { |
||||||
|
lrange $listdata $s $e |
||||||
|
} |
||||||
|
|
||||||
|
#take/drop - haskell-like - but no lazy support REVIEW |
||||||
|
#see also https://www.haskellforall.com/2022/05/why-does-haskells-take-function-accept.html |
||||||
|
>li_lib .. PatternMethod take {n listdata} { |
||||||
|
#keep basic behaviour like Haskell ie we allow returning less than n (without error) if insufficient elements |
||||||
|
lrange $listdata 0 $n-1 |
||||||
|
} |
||||||
|
>li_lib .. PatternMethod drop {n listdata} { |
||||||
|
lrange $listdata $n end |
||||||
|
} |
||||||
|
#todo - takeWhile, dropWhile, takeWhileEnd, dropWhileEnd |
||||||
|
|
||||||
|
>li_lib .. PatternMethod is_list_all_in_list {a b} { |
||||||
|
package require struct::list |
||||||
|
package require struct::set |
||||||
|
set a_in_b [lsort [struct::set intersect [lsort -unique $a] $b ]] |
||||||
|
return [struct::list equal [lsort $a] $a_in_b] |
||||||
|
} |
||||||
|
>li_lib .. PatternMethod is_list_all_ni_list {a b} { |
||||||
|
package require struct::set |
||||||
|
set i [struct::set intersect $a $b] |
||||||
|
return [expr {[llength $i] == 0}] |
||||||
|
} |
||||||
|
|
||||||
|
>li_lib . new >li |
||||||
|
>li_lib . aliasprefix "li." |
||||||
|
|
||||||
|
>pattern .. Create >f_lib |
||||||
|
|
||||||
|
>f_lib .. Construct {args} { |
||||||
|
var o_this |
||||||
|
set o_this @this@ |
||||||
|
var o_last_child |
||||||
|
set o_last_child "" |
||||||
|
} |
||||||
|
>f_lib .. Method version {} { |
||||||
|
return 1.0.0 |
||||||
|
} |
||||||
|
>f_lib .. Method aliasprefix {pfx} { |
||||||
|
var o_this |
||||||
|
var o_last_child |
||||||
|
if {![string length $o_last_child]} { |
||||||
|
error ">f_lib . aliasprefix - Create library object with >f_lib . new >somename first." |
||||||
|
} |
||||||
|
set patternmethods [$o_this .. PM] |
||||||
|
set aliases [list] |
||||||
|
foreach m $patternmethods { |
||||||
|
set a ${pfx}${m} |
||||||
|
if {[llength [info commands $a]]} { |
||||||
|
puts stderr "WARNING - a command was already present at: $a" |
||||||
|
} |
||||||
|
interp alias "" $a "" [$o_last_child . $m .] |
||||||
|
lappend aliases $a |
||||||
|
} |
||||||
|
return $aliases |
||||||
|
} |
||||||
|
>f_lib .. Method new {objcmdname} { |
||||||
|
var o_this |
||||||
|
var o_last_child |
||||||
|
set nscaller [uplevel 1 [list namespace current]] |
||||||
|
if {![string match ::* $objcmdname]} { |
||||||
|
if {$nscaller eq "::"} {set nscaller ""} |
||||||
|
set objcmdname ${nscaller}::$objcmdname |
||||||
|
} |
||||||
|
uplevel 1 [list $o_this .. Create $objcmdname] |
||||||
|
set o_last_child $objcmdname |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
>f_lib .. Constructor {args} { |
||||||
|
var o_this |
||||||
|
set o_this @this@ |
||||||
|
} |
||||||
|
|
||||||
|
>f_lib .. PatternMethod foldl {total func sequence} { |
||||||
|
struct::list::Lfold $sequence $total $func |
||||||
|
} |
||||||
|
#note: foldr is not equivalent to just doing a foldl on the reversed list |
||||||
|
#todo - review/test/fix |
||||||
|
>f_lib .. PatternMethod foldr {total func sequence} { |
||||||
|
set this @this@ |
||||||
|
if {![llength $sequence]} { |
||||||
|
return $total |
||||||
|
} |
||||||
|
v,h@head,t@tail.=val $sequence |h@head,t@tail> { |
||||||
|
puts "-->$h" |
||||||
|
$func [$this . foldr $total $func $t] $h |
||||||
|
} <this@,func@,total@| $this $func $total |
||||||
|
|
||||||
|
return 0 |
||||||
|
return $v |
||||||
|
} |
||||||
|
# reduce: simplest case - list of numbers - reduce with + |
||||||
|
# more complex case: list of pipelines (e.g parsers) - reduce with 'andThen' operator of some sort. |
||||||
|
>f_lib .. PatternMethod reduce {func sequence} { |
||||||
|
struct::list::Lfold [lrange $sequence 1 end] [lindex $sequence 0] $func |
||||||
|
} |
||||||
|
>f_lib .. PatternMethod list_map {commandlist list} { |
||||||
|
tailcall lmap item $list $commandlist |
||||||
|
} |
||||||
|
>f_lib .. PatternMethod list_unique {args} { |
||||||
|
set list [concat {*}$args] |
||||||
|
set d [dict create] |
||||||
|
foreach item $list { |
||||||
|
dict set d $item "" |
||||||
|
} |
||||||
|
dict keys $d |
||||||
|
} |
||||||
|
>f_lib .. PatternMethod list_as_lines {args} { |
||||||
|
set list [concat {*}$args] |
||||||
|
join $list \n |
||||||
|
} |
||||||
|
>f_lib .. PatternMethod list_filter_cond {itemcond listval} { |
||||||
|
#maintenance - proc list_filter_cond |
||||||
|
set filtered_list [list] |
||||||
|
set binding {} |
||||||
|
if {[info level] == 1} { |
||||||
|
#up 1 is global |
||||||
|
set get_vars [list info vars] |
||||||
|
} else { |
||||||
|
set get_vars [list info locals] |
||||||
|
} |
||||||
|
set vars [uplevel 1 {*}$get_vars] |
||||||
|
set posn [lsearch $vars item] |
||||||
|
set vars [lreplace $vars $posn $posn] |
||||||
|
foreach v $vars { |
||||||
|
upvar 1 $v var |
||||||
|
if {(![array exists var]) && [info exists var]} { |
||||||
|
lappend binding [list $v $var] ;#values captured as defaults for apply args. |
||||||
|
} |
||||||
|
} |
||||||
|
#lappend binding [list item $args] |
||||||
|
|
||||||
|
#puts stderr "binding: [join $binding \n]" |
||||||
|
#apply [list $binding $pipescript [uplevel 1 namespace current]] |
||||||
|
foreach item $listval { |
||||||
|
set bindlist [list {*}$binding [list item $item]] |
||||||
|
if {[apply [list $bindlist $itemcond [uplevel 1 namespace current]] ]} { |
||||||
|
lappend filtered_list $item |
||||||
|
} |
||||||
|
} |
||||||
|
return $filtered_list |
||||||
|
} |
||||||
|
|
||||||
|
>f_lib .. PatternMethod sum_llength {total listval} { |
||||||
|
expr {$total + [llength $listval]} |
||||||
|
} |
||||||
|
>f_lib .. PatternMethod sum_length {total stringval} { |
||||||
|
expr {$total + [string length $stringval]} |
||||||
|
} |
||||||
|
>f_lib .. PatternMethod debug {total item} { |
||||||
|
puts stderr "incr tally: $total item: $item" |
||||||
|
expr {$total + 1} |
||||||
|
} |
||||||
|
>f_lib .. PatternMethod dict_walk {d key} { |
||||||
|
dict get $d $key |
||||||
|
} |
||||||
|
>f_lib .. PatternMethod sum {total num} { |
||||||
|
expr {$total + $num} |
||||||
|
} |
||||||
|
>f_lib .. PatternMethod lcomp {expression args} { |
||||||
|
#from https://wiki.tcl-lang.org/page/lcomp |
||||||
|
set __0__ "lappend __1__ \[expr [list $expression]\]" |
||||||
|
while {[llength $args] && [lindex $args 0] ni {for if with}} { |
||||||
|
append __0__ " \[expr [list [lindex $args 0]]\]" |
||||||
|
set args [lrange $args 1 end] |
||||||
|
} |
||||||
|
set tmpvar 2 |
||||||
|
set structure {} |
||||||
|
set upvars {} |
||||||
|
while {[llength $args]} { |
||||||
|
set prefix "" |
||||||
|
switch [lindex $args 0] { |
||||||
|
for { |
||||||
|
set nest [list foreach] |
||||||
|
while {[llength $nest] == 1 || [lindex $args 0] eq "and"} { |
||||||
|
if {[llength $args] < 4 || [lindex $args 2] ni {in inside}} { |
||||||
|
error "wrong # operands: must be \"for\" vars \"in?side?\"\ |
||||||
|
vals ?\"and\" vars \"in?side?\" vals? ?...?" |
||||||
|
} |
||||||
|
switch [lindex $args 2] { |
||||||
|
in { |
||||||
|
lappend nest [lindex $args 1] [lindex $args 3] |
||||||
|
} inside { |
||||||
|
lappend nest __${tmpvar}__ [lindex $args 3] |
||||||
|
append prefix "lassign \$__${tmpvar}__ [lindex $args 1]\n" |
||||||
|
incr tmpvar |
||||||
|
}} |
||||||
|
set args [lrange $args 4 end] |
||||||
|
} |
||||||
|
lappend structure $nest $prefix |
||||||
|
} if { |
||||||
|
if {[llength $args] < 2} { |
||||||
|
error "wrong # operands: must be \"if\" condition" |
||||||
|
} |
||||||
|
lappend structure [list if [lindex $args 1]] $prefix |
||||||
|
set args [lrange $args 2 end] |
||||||
|
} with { |
||||||
|
if {[llength $args] < 2} { |
||||||
|
error "wrong # operands: must be \"with\" varlist" |
||||||
|
} |
||||||
|
foreach var [lindex $args 1] { |
||||||
|
lappend upvars $var $var |
||||||
|
} |
||||||
|
set args [lrange $args 2 end] |
||||||
|
} default { |
||||||
|
error "bad opcode \"[lindex $args 0]\": must be for, if, or with" |
||||||
|
}} |
||||||
|
} |
||||||
|
foreach {prefix nest} [lreverse $structure] { |
||||||
|
set __0__ [concat $nest [list \n$prefix$__0__]] |
||||||
|
} |
||||||
|
if {[llength $upvars]} { |
||||||
|
set __0__ "upvar 1 $upvars; $__0__" |
||||||
|
} |
||||||
|
unset -nocomplain expression args tmpvar prefix nest structure var upvars |
||||||
|
set __1__ "" |
||||||
|
eval $__0__ |
||||||
|
return $__1__ |
||||||
|
} |
||||||
|
|
||||||
|
>f_lib . new ::punk::lib::>f |
||||||
|
>f_lib . aliasprefix "f." |
||||||
|
interp alias {} >f {} ::punk::lib::>f |
||||||
|
|
||||||
|
|
||||||
|
#Pattern-matching based functional operations |
||||||
|
>pattern .. Create >P |
||||||
|
>P .. Method map {pattern commandlist sequence} { |
||||||
|
#set segment [string map [list <cmd> $commandlist] {<cmd>}] |
||||||
|
|
||||||
|
set pipeline [list % {val $item} "|,item,$pattern>" $commandlist <item/0|] |
||||||
|
tailcall % list $pipeline $sequence |p/0,l/1> {lmap val $l {{*}$p $val }} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end definitions namespace punk::flib ---}] |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
# Secondary API namespace |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
namespace eval punk::flib::lib { |
||||||
|
namespace export * |
||||||
|
namespace path [namespace parent] |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::flib::lib}] |
||||||
|
#[para] Secondary functions that are part of the API |
||||||
|
#[list_begin definitions] |
||||||
|
|
||||||
|
#proc utility1 {p1 args} { |
||||||
|
# #*** !doctools |
||||||
|
# #[call lib::[fun utility1] [arg p1] [opt {?option value...?}]] |
||||||
|
# #[para]Description of utility1 |
||||||
|
# return 1 |
||||||
|
#} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#*** !doctools |
||||||
|
#[list_end] [comment {--- end definitions namespace punk::flib::lib ---}] |
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
#*** !doctools |
||||||
|
#[section Internal] |
||||||
|
namespace eval punk::flib::system { |
||||||
|
#*** !doctools |
||||||
|
#[subsection {Namespace punk::flib::system}] |
||||||
|
#[para] Internal functions that are not part of the API |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
||||||
|
## Ready |
||||||
|
package provide punk::flib [namespace eval punk::flib { |
||||||
|
variable pkg punk::flib |
||||||
|
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. |
@ -1,52 +0,0 @@ |
|||||||
# -*- 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) %year% |
|
||||||
# |
|
||||||
# @@ Meta Begin |
|
||||||
# Application %pkg% 999999.0a1.0 |
|
||||||
# Meta platform tcl |
|
||||||
# Meta license %license% |
|
||||||
# @@ Meta End |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
||||||
## Requirements |
|
||||||
##e.g package require frobz |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
||||||
namespace eval %pkg% { |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ |
|
||||||
## Ready |
|
||||||
package provide %pkg% [namespace eval %pkg% { |
|
||||||
variable pkg %pkg% |
|
||||||
variable version |
|
||||||
set version 999999.0a1.0 |
|
||||||
}] |
|
||||||
return |
|
@ -0,0 +1,112 @@ |
|||||||
|
: "[proc : args {}]" ;# *tcl shellbat - call with sh,bash,tclsh on any platform, or with cmd on windows. |
||||||
|
: <<'HIDE_FROM_BASH_AND_SH' |
||||||
|
: ;# leading colon hides from .bat, trailing slash hides next line from tcl \ |
||||||
|
@call tclsh "%~dp0%~n0.bat" %* |
||||||
|
: ;#\ |
||||||
|
@set taskexitcode=%errorlevel% & goto :exit |
||||||
|
# -*- tcl -*- |
||||||
|
# ################################################################################################# |
||||||
|
# This is a tcl shellbat file |
||||||
|
# It is tuned to run when called as a batch file, a tcl script, an sh script or a bash script, |
||||||
|
# so the specific layout and characters used are quite sensitive to change. |
||||||
|
# It can be called on unix or windows platforms with or without the interpreter being specified on the commandline. |
||||||
|
# e.g ./filename.sh.bat in sh or bash or powershell |
||||||
|
# e.g filename.sh or filename.sh.bat at windows command prompt |
||||||
|
# e.g tclsh filename.sh.bat | sh filename.sh.bat | bash filename.sh.bat |
||||||
|
# In all cases an arbitrary number of arguments are accepted |
||||||
|
# To avoid the initial commandline on stdout when calling as a batch file on windows, use: |
||||||
|
# cmd /Q /c filename.sh.bat |
||||||
|
# (because we cannot use @if to silence it, as this isn't understood by tcl,sh or bash) |
||||||
|
# ################################################################################################# |
||||||
|
#fconfigure stdout -translation crlf |
||||||
|
# --- --- --- --- --- --- --- --- --- --- --- --- ---begin Tcl Payload |
||||||
|
#puts "script : [info script]" |
||||||
|
#puts "argcount : $::argc" |
||||||
|
#puts "argvalues: $::argv" |
||||||
|
|
||||||
|
|
||||||
|
#<tcl-payload> |
||||||
|
#<tcl-payload/> |
||||||
|
|
||||||
|
# --- --- --- --- --- --- --- --- --- --- --- --- --- |
||||||
|
# only exit if needed. see exitcode notes at bottom of file and exit there for consistency across invocation methods |
||||||
|
# --- --- --- --- --- --- --- --- --- --- --- --- ---end Tcl Payload |
||||||
|
#-- |
||||||
|
#-- bash/sh code follows. |
||||||
|
#-- protect from tcl using line continuation char on the previous comment for each line, like so: \ |
||||||
|
printf "etc" |
||||||
|
#-- or alternatively place sh/bash script within the false==false block |
||||||
|
#-- whilst being careful to balance braces {} |
||||||
|
#-- For more complex needs you should call out to external scripts |
||||||
|
#-- |
||||||
|
#-- END marker for hide_from_bash_and_sh\ |
||||||
|
HIDE_FROM_BASH_AND_SH |
||||||
|
|
||||||
|
#--------------------------------------------------------- |
||||||
|
#-- This if statement hides(mostly) a sh/bash code block from Tcl |
||||||
|
if false==false # else { |
||||||
|
then |
||||||
|
: |
||||||
|
#--------------------------------------------------------- |
||||||
|
#-- leave as is if all that's required is launching the Tcl payload" |
||||||
|
#-- |
||||||
|
#-- Note that sh/bash script isn't called when running a .bat from cmd.exe on windows by default |
||||||
|
#-- adjust line 4: @call tclsh ... to something like @call sh ... @call bash .. or @call env sh ... etc as appropriate |
||||||
|
#-- if sh/bash scripting needs to run on windows too. |
||||||
|
#-- |
||||||
|
#printf "start of bash or sh code" |
||||||
|
|
||||||
|
#<shell-payload-pre-tcl> |
||||||
|
#</shell-payload-pre-tcl> |
||||||
|
|
||||||
|
|
||||||
|
#-- sh/bash launches Tcl here instead of shebang line at top |
||||||
|
#<shell-launch-tcl> |
||||||
|
#-- use exec to use exitcode (if any) directly from the tcl script |
||||||
|
exec /usr/bin/env tclsh "$0" "$@" |
||||||
|
#</shell-launch-tcl> |
||||||
|
|
||||||
|
#-- alternative - if sh/bash script required to run after the tcl call. |
||||||
|
#/usr/bin/env tclsh "$0" "$@" |
||||||
|
#tcl_exitcode=$? |
||||||
|
#echo "tcl_exitcode: ${tcl_exitcode}" |
||||||
|
|
||||||
|
#<shell-payload-post-tcl> |
||||||
|
#</shell-payload-post-tcl> |
||||||
|
|
||||||
|
#-- override exitcode example |
||||||
|
#exit 66 |
||||||
|
|
||||||
|
#printf "No need for trailing slashes for sh/bash code here\n" |
||||||
|
#--------------------------------------------------------- |
||||||
|
fi |
||||||
|
# closing brace for Tcl } |
||||||
|
#--------------------------------------------------------- |
||||||
|
|
||||||
|
#-- tcl and shell script now both active |
||||||
|
|
||||||
|
#-- comment for line sample 1 with trailing continuation slash \ |
||||||
|
#printf "tcl-invisible sh/bash line sample 1 \n" |
||||||
|
|
||||||
|
#-- comment for line sample 2 with trailing continuation slash \ |
||||||
|
#printf "tcl-invisible sh/bash line sample 2 \n" |
||||||
|
|
||||||
|
|
||||||
|
#-- Consistent exitcode from sh,bash,tclsh or cmd |
||||||
|
#-- Call exit in tcl (or sh/bash) code only if explicitly required, otherwise leave this commented out. |
||||||
|
#-- (script might be more widely useable without explicit exit. e.g in tcl: set ::argc 1; set ::argv "val"; source filename.sh.bat ) |
||||||
|
#-- exit line unprotected by trailing slash will work for tcl and/or sh/bash |
||||||
|
#exit 0 |
||||||
|
#exit 42 |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#-- make sure sh/bash/tcl all skip over .bat style exit \ |
||||||
|
: <<'shell_end' |
||||||
|
#-- .bat exit with exitcode from tcl process \ |
||||||
|
:exit |
||||||
|
: ;# \ |
||||||
|
@exit /B %taskexitcode% |
||||||
|
# .bat has exited \ |
||||||
|
shell_end |
||||||
|
|
@ -0,0 +1,49 @@ |
|||||||
|
|
||||||
|
function ParameterDefinitions { |
||||||
|
param( |
||||||
|
[Parameter()][string] $subject = 'punkshell local', |
||||||
|
[Parameter(Mandatory)][string] $friendlyname = 'test code signing', |
||||||
|
[Parameter(ValueFromRemainingArguments)] $opts |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
function psmain { |
||||||
|
[CmdletBinding()] |
||||||
|
param() |
||||||
|
dynamicparam { GetDynamicParamDictionary ParameterDefinitions } |
||||||
|
process { |
||||||
|
#called once with $PSBoundParameters dictionary |
||||||
|
#can be used to validate arguments, or set a simpler variable name for access |
||||||
|
switch ($PSBoundParameters.keys) { |
||||||
|
'subject' { |
||||||
|
Set-Variable -Name $_ -Value $PSBoundParameters."$_" |
||||||
|
} |
||||||
|
#... |
||||||
|
} |
||||||
|
} |
||||||
|
end { |
||||||
|
Write-Host "Certificate subject is: $subject" |
||||||
|
$params = @{ |
||||||
|
Subject = $subject |
||||||
|
Type = 'CodeSigningCert' |
||||||
|
KeySpec = 'Signature' |
||||||
|
KeyUsage = 'DigitalSignature' |
||||||
|
FriendlyName = $friendlyname |
||||||
|
CertStoreLocation = 'Cert:\LocalMachine\My' |
||||||
|
NotAfter = (Get-Date).AddMonths(60) |
||||||
|
} |
||||||
|
Write-Host "please wait..." |
||||||
|
#$cert = New-SelfSignedCertificate @params |
||||||
|
#Write-Host "cert: $cert" |
||||||
|
|
||||||
|
#echo "Exporting to file for import to certstore.." |
||||||
|
#Export-Certificate -FilePath exported_localmachine_new-cert.cer -Cert $cert |
||||||
|
#Import-Certificate -Filepath exported_localmachine_new-cert.cer -CertstoreLocation Cert:\LocalMachine\My |
||||||
|
#echo "Finished importing.." |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
psmain @args |
||||||
|
|
||||||
|
|
@ -0,0 +1,117 @@ |
|||||||
|
2013-02-01 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* |
||||||
|
* Released and tagged Tcllib 1.15 ======================== |
||||||
|
* |
||||||
|
|
||||||
|
2011-12-13 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* |
||||||
|
* Released and tagged Tcllib 1.14 ======================== |
||||||
|
* |
||||||
|
|
||||||
|
2011-01-24 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* |
||||||
|
* Released and tagged Tcllib 1.13 ======================== |
||||||
|
* |
||||||
|
|
||||||
|
2009-12-07 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* |
||||||
|
* Released and tagged Tcllib 1.12 ======================== |
||||||
|
* |
||||||
|
|
||||||
|
2009-03-30 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* pluginmgr.tcl: Hook into the log system of the SafeBase to get |
||||||
|
* pkgIndex.tcl: more detailed error information when a plugin |
||||||
|
* pluginmgr.man: could not be loaded. Bumped to version 0.3 |
||||||
|
|
||||||
|
2008-12-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* |
||||||
|
* Released and tagged Tcllib 1.11.1 ======================== |
||||||
|
* |
||||||
|
|
||||||
|
2008-10-16 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* |
||||||
|
* Released and tagged Tcllib 1.11 ======================== |
||||||
|
* |
||||||
|
|
||||||
|
2007-09-19 Andreas Kupries <akupries@shaw.ca> |
||||||
|
|
||||||
|
* pluginmgr.tcl (AddPaths): Fixed typo in the code converting the |
||||||
|
* pluginmgr.man: package pattern into a regular expression. A |
||||||
|
* pkgIndex.tcl: bogus space char separated * from its quoting |
||||||
|
backslash, end result was a RE pattern without capturing |
||||||
|
parentheses, so the plugin name was never properly extracted |
||||||
|
from the package name. This fixes [SF Tcllib Bug 1798210]. |
||||||
|
Thanks to Jeremy Cowgar for the report. Additionally added |
||||||
|
support for directory 'plugins' in the dot-directories |
||||||
|
(pluginmgr::path). Package version bumped to 0.2. |
||||||
|
|
||||||
|
2007-09-19 Andreas Kupries <andreask@activestate.com> |
||||||
|
|
||||||
|
* pluginmgr.man: Fixed typo in the example, used the wrong |
||||||
|
dot-path (.../plugins, should be .../plugin). Thanks to Jeremy |
||||||
|
Cowgar for finding this. |
||||||
|
|
||||||
|
2007-09-12 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* |
||||||
|
* Released and tagged Tcllib 1.10 ======================== |
||||||
|
* |
||||||
|
|
||||||
|
2007-06-22 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* pluginmgr.tcl: Replaced deprecated {expand} syntax in comments |
||||||
|
with {*}. |
||||||
|
|
||||||
|
2007-03-21 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* pluginmgr.man: Fixed all warnings due to use of now deprecated |
||||||
|
commands. Added a section about how to give feedback. |
||||||
|
|
||||||
|
2006-10-03 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* |
||||||
|
* Released and tagged Tcllib 1.9 ======================== |
||||||
|
* |
||||||
|
|
||||||
|
2005-10-06 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* |
||||||
|
* Released and tagged Tcllib 1.8 ======================== |
||||||
|
* |
||||||
|
|
||||||
|
2005-07-07 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* pluginmgr.tcl: Added and documented option -setup, |
||||||
|
* pluginmgr.man: and clone method. |
||||||
|
|
||||||
|
2005-06-17 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* pluginmgr.tcl: Validation now reports missing API commands. Set |
||||||
|
plugin name before external check, so that the callback can use |
||||||
|
'do' when inspecting the plugin. Command setup has no need for |
||||||
|
alias deletion, interpreters are always new and clean. |
||||||
|
|
||||||
|
* plugin.tcl: Changed completely to a package based approach, |
||||||
|
* plugin.man: using the safe base for proper package |
||||||
|
handling. Plugins are packages. Framework has to perform only |
||||||
|
validation and initialization, not search. |
||||||
|
|
||||||
|
2005-04-13 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* plugin.tcl: Updated to changed method names in path, added |
||||||
|
* plugin.man: method 'interpreter', and fixed bug in alias |
||||||
|
creation. |
||||||
|
|
||||||
|
2005-04-11 Andreas Kupries <andreas_kupries@users.sourceforge.net> |
||||||
|
|
||||||
|
* plugin.man: New module for the management of plugins. |
||||||
|
* plugin.tcl: |
||||||
|
* pkgIndex.tcl: |
||||||
|
|
@ -0,0 +1,2 @@ |
|||||||
|
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return} |
||||||
|
package ifneeded pluginmgr 0.4 [list source [file join $dir pluginmgr.tcl]] |
@ -0,0 +1,427 @@ |
|||||||
|
[comment {-*- tcl -*- paths manpage}] |
||||||
|
[manpage_begin pluginmgr n 0.4] |
||||||
|
[keywords {plugin management}] |
||||||
|
[keywords {plugin search}] |
||||||
|
[copyright {2005 Andreas Kupries <andreas_kupries@users.sourceforge.net>}] |
||||||
|
[moddesc {Plugin management}] |
||||||
|
[titledesc {Manage a plugin}] |
||||||
|
[category {Programming tools}] |
||||||
|
[require Tcl "8.5 9"] |
||||||
|
[require pluginmgr [opt 0.4]] |
||||||
|
[description] |
||||||
|
|
||||||
|
This package provides commands and objects for the generic management |
||||||
|
of plugins which can be loaded into an application. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
To avoid the implementation of yet another system to locate Tcl code |
||||||
|
the system provides by this package is built on top of the regular |
||||||
|
package management system. Each plugin is considered as a package and |
||||||
|
a simple invokation of [cmd {package require}] is enough to locate and |
||||||
|
load it, if it exists. The only time we will need additional paths is |
||||||
|
when a plugin manager is part of a wrapped application and has to be |
||||||
|
able to search for plugins existing outside of that application. For |
||||||
|
this situation the package provides a command to create a general set |
||||||
|
of such paths based on names for the plugin manager and/or application |
||||||
|
in question. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
The main contribution of this package is a generic framework which |
||||||
|
allows the easy declaration of |
||||||
|
|
||||||
|
[list_begin enumerated] |
||||||
|
[enum] |
||||||
|
How to translate a plugin name to the name of the package implementing |
||||||
|
it, and vice versa. |
||||||
|
|
||||||
|
[enum] |
||||||
|
The list of commands a plugin has to provide as API, and also of more |
||||||
|
complex checks as code. |
||||||
|
|
||||||
|
[enum] |
||||||
|
The list of commands expected by the plugin from the environment. |
||||||
|
|
||||||
|
[list_end] |
||||||
|
|
||||||
|
This then allows the easy generation of plugin managers customized to |
||||||
|
particular types of plugins for an application. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
It should be noted that all plugin code is considered untrusted and |
||||||
|
will always be executed within a safe interpreter. The interpreter is |
||||||
|
enabled enough to allow plugins the loading of all additional packages |
||||||
|
they may need. |
||||||
|
|
||||||
|
[section {PUBLIC API}] |
||||||
|
[subsection {PACKAGE COMMANDS}] |
||||||
|
|
||||||
|
[list_begin definitions] |
||||||
|
|
||||||
|
[call [cmd ::pluginmgr] [arg objectName] [opt [arg "option value"]...]] |
||||||
|
|
||||||
|
This command creates a new plugin manager object with an associated |
||||||
|
Tcl command whose name is [arg objectName]. This [term object] command |
||||||
|
is explained in full detail in the sections [sectref {OBJECT COMMAND}] |
||||||
|
and [sectref {OBJECT METHODS}]. The object command will be created |
||||||
|
under the current namespace if the [arg objectName] is not fully |
||||||
|
qualified, and in the specified namespace otherwise. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
The options and their values coming after the name of the object are |
||||||
|
used to set the initial configuration of the mamager object, |
||||||
|
specifying the applicable plugins and their API. |
||||||
|
|
||||||
|
[call [cmd ::pluginmgr::paths] [arg objectName] [arg name]...] |
||||||
|
|
||||||
|
This utility command adds a set of paths to the specified object, |
||||||
|
based on the given [arg name]s. |
||||||
|
|
||||||
|
It will search for: |
||||||
|
|
||||||
|
[list_begin enumerated] |
||||||
|
|
||||||
|
[enum] |
||||||
|
|
||||||
|
The environment variable [var [arg name]_PLUGINS]. Its contents will |
||||||
|
be interpreted as a list of package paths. The entries have to be |
||||||
|
separated by either [const :] (unix) or [const \;] (windows). |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
The name will be converted to upper-case letters. |
||||||
|
|
||||||
|
[enum] |
||||||
|
|
||||||
|
The registry entry "HKEY_LOCAL_MACHINE\SOFTWARE\[arg name]\PLUGINS". |
||||||
|
Its contents will be interpreted as a list of package paths. The |
||||||
|
entries have to be separated by [const \;]. This item is considered |
||||||
|
only when on Windows (tm). |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
The casing of letters is not changed. |
||||||
|
|
||||||
|
[enum] |
||||||
|
|
||||||
|
The registry entry "HKEY_CURRENT_USER\SOFTWARE\[arg name]\PLUGINS". |
||||||
|
Its contents will be interpreted as a list of package paths. The |
||||||
|
entries have to be separated by [const \;]. This item is considered |
||||||
|
only when on Windows (tm). |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
The casing of letters is not changed. |
||||||
|
|
||||||
|
[enum] |
||||||
|
|
||||||
|
The directory [file "~/.[arg name]/plugin"]. |
||||||
|
|
||||||
|
[enum] |
||||||
|
|
||||||
|
The directory [file "~/.[arg name]/plugins"]. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
The casing of letters is not changed. |
||||||
|
|
||||||
|
[list_end] |
||||||
|
[para] |
||||||
|
|
||||||
|
and add all the paths found that way to the list of package paths |
||||||
|
maintained by the object. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
If [arg name] is namespaced each item in the list will be repeated per |
||||||
|
prefix of [arg name], with conversion of :-sequences into the proper |
||||||
|
separator (underscore for environment variables, backslash for |
||||||
|
registry entries, and / for directories). |
||||||
|
|
||||||
|
[para] |
||||||
|
Examples: |
||||||
|
[para] |
||||||
|
|
||||||
|
[example { |
||||||
|
::pluginmgr::paths ::obj docidx |
||||||
|
|
||||||
|
=> env DOCIDX_PLUGINS |
||||||
|
reg HKEY_LOCAL_MACHINE\SOFTWARE\docidx\PLUGINS |
||||||
|
reg HKEY_CURRENT_USER\SOFTWARE\docidx\PLUGINS |
||||||
|
path ~/.docidx/plugins |
||||||
|
|
||||||
|
::pluginmgr::paths ::obj doctools::idx |
||||||
|
|
||||||
|
=> env DOCTOOLS_PLUGINS |
||||||
|
env DOCTOOLS_IDX_PLUGINS |
||||||
|
reg HKEY_LOCAL_MACHINE\SOFTWARE\doctools\PLUGINS |
||||||
|
reg HKEY_LOCAL_MACHINE\SOFTWARE\doctools\idx\PLUGINS |
||||||
|
reg HKEY_CURRENT_USER\SOFTWARE\doctools\PLUGINS |
||||||
|
reg HKEY_CURRENT_USER\SOFTWARE\doctools\idx\PLUGINS |
||||||
|
path ~/.doctools/plugin |
||||||
|
path ~/.doctools/idx/plugin |
||||||
|
}] |
||||||
|
|
||||||
|
[list_end] |
||||||
|
|
||||||
|
[subsection {OBJECT COMMAND}] |
||||||
|
|
||||||
|
All commands created by the command [cmd ::pluginmgr] (See section |
||||||
|
[sectref {PACKAGE COMMANDS}]) have the following general form and may |
||||||
|
be used to invoke various operations on their plugin manager object. |
||||||
|
|
||||||
|
[list_begin definitions] |
||||||
|
|
||||||
|
[call [cmd objectName] [method method] [opt [arg "arg arg ..."]]] |
||||||
|
|
||||||
|
The method [method method] and its [arg arg]'uments determine the exact |
||||||
|
behavior of the command. See section [sectref {OBJECT METHODS}] for |
||||||
|
the detailed specifications. |
||||||
|
|
||||||
|
[list_end] |
||||||
|
|
||||||
|
[subsection {OBJECT METHODS}] |
||||||
|
|
||||||
|
[list_begin definitions] |
||||||
|
|
||||||
|
[call [arg objectName] [method clone]] |
||||||
|
|
||||||
|
This method creates a new plugin management object and returns the |
||||||
|
associated object command. The generated object is a clone of the |
||||||
|
object the method was invoked on. I.e. the new object will have the |
||||||
|
same configuration as the current object. With regard to state, if the |
||||||
|
current object has a plugin loaded then this plugin and all associated |
||||||
|
state is moved to the generated clone and the current object is reset |
||||||
|
into the base state (no plugin loaded). In this manner a configured |
||||||
|
plugin manager is also a factory for loaded plugins. |
||||||
|
|
||||||
|
[call [arg objectName] [method configure]] |
||||||
|
|
||||||
|
The method returns a list of all known options and their current |
||||||
|
values when called without any arguments. |
||||||
|
|
||||||
|
[call [arg objectName] [method configure] [arg option]] |
||||||
|
|
||||||
|
The method behaves like the method [method cget] when called with a |
||||||
|
single argument and returns the value of the option specified by said |
||||||
|
argument. |
||||||
|
|
||||||
|
[call [arg objectName] [method configure] [option -option] [arg value]...] |
||||||
|
|
||||||
|
The method reconfigures the specified [option option]s of the object, |
||||||
|
setting them to the associated [arg value]s, when called with an even |
||||||
|
number of arguments, at least two. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
The legal options are described in the section |
||||||
|
[sectref {OBJECT CONFIGURATION}]. |
||||||
|
|
||||||
|
[call [arg objectName] [method cget] [option -option]] |
||||||
|
|
||||||
|
This method expects a legal configuration option as argument and will |
||||||
|
return the current value of that option for the object the method was |
||||||
|
invoked for. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
The legal configuration options are described in section |
||||||
|
[sectref {OBJECT CONFIGURATION}]. |
||||||
|
|
||||||
|
[call [arg objectName] [method destroy]] |
||||||
|
|
||||||
|
This method destroys the object it is invoked for. |
||||||
|
|
||||||
|
[call [arg objectName] [method do] [arg arg]...] |
||||||
|
|
||||||
|
This method interprets its list of arguments as the words of a command |
||||||
|
and invokes this command in the execution context of the plugin. |
||||||
|
|
||||||
|
The result of the invoked command is made the result of the method. |
||||||
|
|
||||||
|
The call will fail with an error if no valid plugin has been loaded |
||||||
|
into the manager object. |
||||||
|
|
||||||
|
[call [arg objectName] [method interpreter]] |
||||||
|
|
||||||
|
This method returns the handle of the safe interpreter the current |
||||||
|
plugin is loaded into. An empty string as return value signals that |
||||||
|
the manager currently has no valid plugin loaded. |
||||||
|
|
||||||
|
[call [arg objectName] [method plugin]] |
||||||
|
|
||||||
|
This method returns the name of the plugin currently loaded. An empty |
||||||
|
string as return value signals that the manager currently has no valid |
||||||
|
plugin loaded. |
||||||
|
|
||||||
|
[call [arg objectName] [method load] [arg string]] |
||||||
|
|
||||||
|
This method loads, validates, and initializes a named plugin into the |
||||||
|
manager object. |
||||||
|
|
||||||
|
[para] |
||||||
|
The algorithm to locate and load the plugin employed is: |
||||||
|
|
||||||
|
[list_begin enumerated] |
||||||
|
[enum] |
||||||
|
|
||||||
|
If the [arg string] contains the path to an existing file then this |
||||||
|
file is taken as the implementation of the plugin. |
||||||
|
|
||||||
|
[enum] |
||||||
|
Otherwise the plugin name is translated into a package name via the value |
||||||
|
of the option [option -pattern] and then loaded through the |
||||||
|
regular package management. |
||||||
|
|
||||||
|
[enum] |
||||||
|
The load fails. |
||||||
|
|
||||||
|
[list_end] |
||||||
|
[para] |
||||||
|
|
||||||
|
The algorithm to validate and initialize the loaded code is: |
||||||
|
|
||||||
|
[list_begin enumerated] |
||||||
|
[enum] |
||||||
|
If the option [option -api] is non-empty introspection commands are |
||||||
|
used to ascertain that the plugin provides the listed commands. |
||||||
|
|
||||||
|
[enum] |
||||||
|
If the option [option -check] is non-empty the specified command |
||||||
|
prefix is called. |
||||||
|
|
||||||
|
[enum] |
||||||
|
If either of the above fails the candidate plugin is unloaded again |
||||||
|
|
||||||
|
[enum] |
||||||
|
Otherwise all the commands specified via the option |
||||||
|
[option -cmds] are installed in the plugin. |
||||||
|
|
||||||
|
[list_end] |
||||||
|
[para] |
||||||
|
|
||||||
|
A previously loaded plugin is discarded, but only if the new plugin |
||||||
|
was found and sucessfully validated and initialized. Note that there |
||||||
|
will be no intereference between old and new plugin as both will be |
||||||
|
put into separate safe interpreters. |
||||||
|
|
||||||
|
[call [arg objectName] [method unload]] |
||||||
|
|
||||||
|
This method unloads the currently loaded plugin. It returns the empty |
||||||
|
string. The call will be silently ignored if no plugin is loaded at |
||||||
|
all. |
||||||
|
|
||||||
|
[call [arg objectName] [method list]] |
||||||
|
|
||||||
|
This method uses the contents of the option [option -pattern] to find |
||||||
|
all packages which can be plugins under the purview of this manager |
||||||
|
object. It translates their names into plugin names and returns a list |
||||||
|
containing them. |
||||||
|
|
||||||
|
[call [arg objectName] [method path] [arg path]] |
||||||
|
|
||||||
|
This methods adds the specified [arg path] to the list of additional |
||||||
|
package paths to look at when searching for a plugin. It returns the |
||||||
|
empty string. Duplicate paths are ignored, i.e. each path is added |
||||||
|
only once. Paths are made absolute, but are not normalized. |
||||||
|
|
||||||
|
[call [arg objectName] [method paths]] |
||||||
|
|
||||||
|
This method returns a list containing all additional paths which have |
||||||
|
been added to the plugin manager object since its creation. |
||||||
|
|
||||||
|
[list_end] |
||||||
|
|
||||||
|
[subsection {OBJECT CONFIGURATION}] |
||||||
|
|
||||||
|
All plugin manager objects understand the following configuration options: |
||||||
|
|
||||||
|
[list_begin options] |
||||||
|
|
||||||
|
[opt_def -pattern [arg string]] |
||||||
|
|
||||||
|
The value of this option is a glob pattern which has to contain |
||||||
|
exactly one '*'-operator. All packages whose names match this pattern |
||||||
|
are the plugins recognized by the manager object. And vice versa, the |
||||||
|
replacement of the '*'-operator with a plugin name will yield the name |
||||||
|
of the package implementing that plugin. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
This option has no default, except if option [option -name] was set. |
||||||
|
It has to be set before attempting to load a plugin, either directly, |
||||||
|
or through option [option -name]. |
||||||
|
|
||||||
|
[opt_def -api [arg list]] |
||||||
|
|
||||||
|
The value of this option is a list of command names, and any plugin |
||||||
|
loaded has to provide these commands. Names which are not fully |
||||||
|
qualified are considered to be rooted in the global namespace. |
||||||
|
|
||||||
|
If empty no expectations are made on the plugin. The default value is |
||||||
|
the empty list. |
||||||
|
|
||||||
|
[opt_def -check [arg cmdprefix]] |
||||||
|
|
||||||
|
The value of this option is interpreted as a command prefix. |
||||||
|
|
||||||
|
Its purpose is to perform complex checks on a loaded plugin package to |
||||||
|
validate it, which go beyond a simple list of provided commands. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
It is called with the manager object command as the only argument and |
||||||
|
has to return a boolean value. A value of [const true] will be |
||||||
|
interpreted to mean that the candidate plugin passed the test. |
||||||
|
|
||||||
|
The call will happen if and only if the candidate plugin already |
||||||
|
passed the basic API check specified through the option [option -api]. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
The default value is the empty list, which causes the manager object |
||||||
|
to suppress the call and to assume the candidate plugin passes. |
||||||
|
|
||||||
|
[opt_def -cmds [arg dict]] |
||||||
|
|
||||||
|
The value of this option is a dictionary. It specifies the commands |
||||||
|
which will be made available to the plugin (as keys), and the trusted |
||||||
|
commands in the environment which implement them (as values). |
||||||
|
|
||||||
|
The trusted commands will be executed in the interpreter specified by |
||||||
|
the option [option -cmdip]. |
||||||
|
|
||||||
|
The default value is the empty dictionary. |
||||||
|
|
||||||
|
[opt_def -cmdip [arg ipspec]] |
||||||
|
|
||||||
|
The value of this option is the path of the interpreter where the |
||||||
|
trusted commands given to the plugin will be executed in. |
||||||
|
|
||||||
|
The default is the empty string, referring to the current interpreter. |
||||||
|
|
||||||
|
[opt_def -setup [arg cmdprefix]] |
||||||
|
|
||||||
|
The value of this option is interpreted as a command prefix. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
It is called whenever a new safe interpreter for a plugin has been |
||||||
|
created, but before a plugin is loaded. It is provided with the |
||||||
|
manager object command and the interpreter handle as its only |
||||||
|
arguments. Any return value will be ignored. |
||||||
|
|
||||||
|
[para] |
||||||
|
|
||||||
|
Its purpose is give a user of the plugin management the ability to |
||||||
|
define commands, packages, etc. a chosen plugin may need while being |
||||||
|
loaded. |
||||||
|
|
||||||
|
[list_end] |
||||||
|
|
||||||
|
[vset CATEGORY pluginmgr] |
||||||
|
[include ../common-text/feedback.inc] |
||||||
|
[manpage_end] |
@ -0,0 +1,429 @@ |
|||||||
|
# plugin.tcl -- |
||||||
|
# |
||||||
|
# Generic plugin management. |
||||||
|
# |
||||||
|
# Copyright (c) 2005 Andreas Kupries <andreas_kupries@sourceforge.net> |
||||||
|
# |
||||||
|
# See the file "license.terms" for information on usage and redistribution |
||||||
|
# of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
||||||
|
# |
||||||
|
# RCS: @(#) $Id: pluginmgr.tcl,v 1.8 2009/03/31 02:14:40 andreas_kupries Exp $ |
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
## Description |
||||||
|
|
||||||
|
# Each instance of the plugin manager can be configured with data |
||||||
|
# which specifies where to find plugins, and how to validate |
||||||
|
# them. With that it can then be configured to load and provide access |
||||||
|
# to a specific plugin, doing all required checks and |
||||||
|
# initialization. Users for specific plugin types simply have to |
||||||
|
# encapsulate the generic class, providing all the specifics, leaving |
||||||
|
# their users only the task of naming the requested actual plugin. |
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
## Requisites |
||||||
|
|
||||||
|
package require Tcl 8.5 9 |
||||||
|
package require snit |
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
## Implementation |
||||||
|
|
||||||
|
snit::type ::pluginmgr { |
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
## Public API - Options |
||||||
|
|
||||||
|
# - Pattern to match package name. Exactly one '*'. No default. |
||||||
|
# - List of commands the plugin has to provide. Empty list default. |
||||||
|
# - Callback for additional checking after the API presence has |
||||||
|
# been verified. Empty list default. |
||||||
|
# - Dictionary of commands to put into the plugin interpreter. |
||||||
|
# Key: cmds for plugin, value is cmds to invoke for them. |
||||||
|
# - Interpreter to use for the -cmds (invoked commands). Default |
||||||
|
# is current interp. |
||||||
|
# - Callback for additional setup actions on the plugin |
||||||
|
# interpreter after its creation, but before plugin is loaded into |
||||||
|
# it. Empty list default. |
||||||
|
|
||||||
|
option -pattern {} |
||||||
|
option -api {} |
||||||
|
option -check {} |
||||||
|
option -cmds {} |
||||||
|
option -cmdip {} |
||||||
|
option -setup {} |
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
## Public API - Methods |
||||||
|
|
||||||
|
method do {args} { |
||||||
|
if {$plugin eq ""} { |
||||||
|
return -code error "No plugin defined" |
||||||
|
} |
||||||
|
return [$sip eval $args] |
||||||
|
} |
||||||
|
|
||||||
|
method interpreter {} { |
||||||
|
return $sip |
||||||
|
} |
||||||
|
|
||||||
|
method plugin {} { |
||||||
|
return $plugin |
||||||
|
} |
||||||
|
|
||||||
|
method load {name} { |
||||||
|
if {$name eq $plugin} return |
||||||
|
|
||||||
|
if {$options(-pattern) eq ""} { |
||||||
|
return -code error "Translation pattern is not configured" |
||||||
|
} |
||||||
|
|
||||||
|
set save $sip |
||||||
|
|
||||||
|
$self SetupIp |
||||||
|
if {![$self LoadPlugin $name]} { |
||||||
|
set sip $save |
||||||
|
return -code error "Unable to locate or load plugin \"$name\" ($myloaderror)" |
||||||
|
} |
||||||
|
|
||||||
|
if {![$self CheckAPI missing]} { |
||||||
|
set sip $save |
||||||
|
return -code error \ |
||||||
|
"Cannot use plugin \"$name\", API incomplete: \"$missing\" missing" |
||||||
|
} |
||||||
|
|
||||||
|
set savedname $plugin |
||||||
|
set plugin $name |
||||||
|
if {![$self CheckExternal]} { |
||||||
|
set sip $save |
||||||
|
set plugin $savedname |
||||||
|
return -code error \ |
||||||
|
"Cannot use plugin \"$name\", API bad" |
||||||
|
} |
||||||
|
$self SetupExternalCmds |
||||||
|
|
||||||
|
if {$save ne ""} {interp delete $save} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
method unload {} { |
||||||
|
if {$sip eq ""} return |
||||||
|
interp delete $sip |
||||||
|
set sip "" |
||||||
|
set plugin "" |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
method list {} { |
||||||
|
if {$options(-pattern) eq ""} { |
||||||
|
return -code error "Translation pattern is not configured" |
||||||
|
} |
||||||
|
|
||||||
|
set save $sip |
||||||
|
$self SetupIp |
||||||
|
|
||||||
|
set result {} |
||||||
|
set pattern [string map [list \ |
||||||
|
+ \\+ ? \\? \ |
||||||
|
\[ \\\[ \] \\\] \ |
||||||
|
( \\( ) \\) \ |
||||||
|
. \\. \* {(.*)} \ |
||||||
|
] $options(-pattern)] |
||||||
|
|
||||||
|
# @mdgen NODEP: bogus-package |
||||||
|
$sip eval {catch {package require bogus-package}} |
||||||
|
foreach p [$sip eval {package names}] { |
||||||
|
if {![regexp $pattern $p -> plugin]} continue |
||||||
|
lappend result $plugin |
||||||
|
} |
||||||
|
|
||||||
|
interp delete $sip |
||||||
|
set sip $save |
||||||
|
return $result |
||||||
|
} |
||||||
|
|
||||||
|
method path {path} { |
||||||
|
set path [file join [pwd] $path] |
||||||
|
if {[lsearch -exact $paths $path] < 0} { |
||||||
|
lappend paths $path |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
method paths {} { |
||||||
|
return $paths |
||||||
|
} |
||||||
|
|
||||||
|
method clone {} { |
||||||
|
set o [$type create %AUTO% \ |
||||||
|
-pattern $options(-pattern) \ |
||||||
|
-api $options(-api) \ |
||||||
|
-check $options(-check) \ |
||||||
|
-cmds $options(-cmds) \ |
||||||
|
-cmdip $options(-cmdip) \ |
||||||
|
-setup $options(-setup)] |
||||||
|
|
||||||
|
$o __clone__ $paths $sip $plugin |
||||||
|
|
||||||
|
# Clone has become owner of the interp. |
||||||
|
set sip {} |
||||||
|
set plugin {} |
||||||
|
|
||||||
|
return $o |
||||||
|
} |
||||||
|
|
||||||
|
method __clone__ {_paths _sip _plugin} { |
||||||
|
set paths $_paths |
||||||
|
set sip $_sip |
||||||
|
set plugin $_plugin |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
## Internal - Configuration and state |
||||||
|
|
||||||
|
variable paths {} ; # List of paths to provide the sip with. |
||||||
|
variable sip {} ; # Safe interp used for plugin execution. |
||||||
|
variable plugin {} ; # Name of currently loaded plugin. |
||||||
|
variable myloaderror {} ; # Last error reported by the Safe base |
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
## Internal - Object construction and descruction. |
||||||
|
|
||||||
|
constructor {args} { |
||||||
|
$self configurelist $args |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
destructor { |
||||||
|
if {$sip ne ""} {interp delete $sip} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
## Internal - Option management |
||||||
|
|
||||||
|
onconfigure -pattern {newvalue} { |
||||||
|
set current $options(-pattern) |
||||||
|
if {$newvalue eq $current} return |
||||||
|
|
||||||
|
set n [regexp -all "\\*" $newvalue] |
||||||
|
if {$n < 1} { |
||||||
|
return -code error "Invalid pattern, * missing" |
||||||
|
} elseif {$n > 1} { |
||||||
|
return -code error "Invalid pattern, too many *'s" |
||||||
|
} |
||||||
|
|
||||||
|
set options(-pattern) $newvalue |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
onconfigure -api {newvalue} { |
||||||
|
set current $options(-api) |
||||||
|
if {$newvalue eq $current} return |
||||||
|
set options(-api) $newvalue |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
onconfigure -cmds {newvalue} { |
||||||
|
set current $options(-cmds) |
||||||
|
if {$newvalue eq $current} return |
||||||
|
set options(-cmds) $newvalue |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
onconfigure -cmdip {newvalue} { |
||||||
|
set current $options(-cmdip) |
||||||
|
if {$newvalue eq $current} return |
||||||
|
set options(-cmdip) $newvalue |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
## Internal - Helper commands |
||||||
|
|
||||||
|
method SetupIp {} { |
||||||
|
set sip [::safe::interpCreate] |
||||||
|
foreach p $paths { |
||||||
|
::safe::interpAddToAccessPath $sip $p |
||||||
|
} |
||||||
|
|
||||||
|
if {![llength $options(-setup)]} return |
||||||
|
uplevel \#0 [linsert $options(-setup) end $self $sip] |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
method LoadPlugin {name} { |
||||||
|
if {[file exists $name]} { |
||||||
|
# Plugin files are loaded directly. |
||||||
|
|
||||||
|
$sip invokehidden source $name |
||||||
|
return 1 |
||||||
|
} |
||||||
|
|
||||||
|
# Otherwise the name is transformed into a package name |
||||||
|
# and loaded thorugh the package management. |
||||||
|
|
||||||
|
set pluginpackage [string map \ |
||||||
|
[list * $name] $options(-pattern)] |
||||||
|
|
||||||
|
::safe::setLogCmd [mymethod PluginError] |
||||||
|
if {[catch { |
||||||
|
$sip eval [list package require $pluginpackage] |
||||||
|
} res]} { |
||||||
|
::safe::setLogCmd {} |
||||||
|
return 0 |
||||||
|
} |
||||||
|
::safe::setLogCmd {} |
||||||
|
return 1 |
||||||
|
} |
||||||
|
|
||||||
|
method CheckAPI {mv} { |
||||||
|
upvar 1 $mv missing |
||||||
|
if {![llength $options(-api)]} {return 1} |
||||||
|
|
||||||
|
# Check the plugin for useability. |
||||||
|
|
||||||
|
foreach p $options(-api) { |
||||||
|
if {[llength [$sip eval [list info commands $p]]] == 1} continue |
||||||
|
interp delete $sip |
||||||
|
set missing $p |
||||||
|
return 0 |
||||||
|
} |
||||||
|
return 1 |
||||||
|
} |
||||||
|
|
||||||
|
method CheckExternal {} { |
||||||
|
if {![llength $options(-check)]} {return 1} |
||||||
|
return [uplevel \#0 [linsert $options(-check) end $self]] |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
method SetupExternalCmds {} { |
||||||
|
if {![llength $options(-cmds)]} return |
||||||
|
|
||||||
|
set cip $options(-cmdip) |
||||||
|
foreach {pcmd ecmd} $options(-cmds) { |
||||||
|
eval [linsert $ecmd 0 interp alias $sip $pcmd $cip] |
||||||
|
#interp alias $sip $pcmd $cip {*}$ecmd |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
method PluginError {message} { |
||||||
|
if {[string match {*script error*} $message]} return |
||||||
|
set myloaderror $message |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
|
||||||
|
proc paths {pmgr args} { |
||||||
|
if {[llength $args] == 0} { |
||||||
|
return -code error "wrong#args: Expect \"[info level 0] object name...\"" |
||||||
|
} |
||||||
|
foreach name $args { |
||||||
|
AddPaths $pmgr $name |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
proc AddPaths {pmgr name} { |
||||||
|
global env tcl_platform |
||||||
|
|
||||||
|
if {$tcl_platform(platform) eq "windows"} { |
||||||
|
set sep \; |
||||||
|
} else { |
||||||
|
set sep : |
||||||
|
} |
||||||
|
|
||||||
|
#puts "$pmgr += ($name) $sep" |
||||||
|
|
||||||
|
regsub -all {::+} [string trim $name :] \000 name |
||||||
|
set name [split $name \000] |
||||||
|
|
||||||
|
# Environment variables |
||||||
|
|
||||||
|
set prefix {} |
||||||
|
foreach part $name { |
||||||
|
lappend prefix $part |
||||||
|
set ev [string toupper [join $prefix _]]_PLUGINS |
||||||
|
|
||||||
|
#puts "+? env($ev)" |
||||||
|
|
||||||
|
if {[info exists env($ev)]} { |
||||||
|
foreach path [split $env($ev) $sep] { |
||||||
|
$pmgr path $path |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
# Windows registry |
||||||
|
|
||||||
|
if { |
||||||
|
($tcl_platform(platform) eq "windows") && |
||||||
|
![catch {package require registry}] |
||||||
|
} { |
||||||
|
foreach root { |
||||||
|
HKEY_LOCAL_MACHINE |
||||||
|
HKEY_CURRENT_USER |
||||||
|
} { |
||||||
|
set prefix {} |
||||||
|
foreach part $name { |
||||||
|
lappend prefix $part |
||||||
|
set rk $root\\SOFTWARE\\[join $prefix \\]PLUGINS |
||||||
|
|
||||||
|
#puts "+? registry($rk)" |
||||||
|
|
||||||
|
if {![catch {set data [registry get $rk {}]}]} { |
||||||
|
foreach path [split $data $sep] { |
||||||
|
$pmgr path $path |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
# Home directory dot path |
||||||
|
|
||||||
|
set prefix {} |
||||||
|
foreach part $name { |
||||||
|
lappend prefix $part |
||||||
|
if {[package vsatisfies [package present Tcl] 9]} { |
||||||
|
set pd [file join [file home] .[join $prefix /] plugin] |
||||||
|
} else { |
||||||
|
set pd [file join ~ .[join $prefix /] plugin] |
||||||
|
} |
||||||
|
|
||||||
|
#puts "+? path($pd)" |
||||||
|
|
||||||
|
if {[file exists $pd]} { |
||||||
|
$pmgr path $pd |
||||||
|
} |
||||||
|
|
||||||
|
# Cover for the goof in the example found in the docs. |
||||||
|
# Note that supporting the directory name 'plugins' is |
||||||
|
# also more consistent with the environment variables |
||||||
|
# above, where we also use plugins, plural. |
||||||
|
|
||||||
|
if {[package vsatisfies [package present Tcl] 9]} { |
||||||
|
set pd [file join [file home] .[join $prefix /] plugins] |
||||||
|
} else { |
||||||
|
set pd [file join ~ .[join $prefix /] plugins] |
||||||
|
} |
||||||
|
|
||||||
|
#puts "+? path($pd)" |
||||||
|
|
||||||
|
if {[file exists $pd]} { |
||||||
|
$pmgr path $pd |
||||||
|
} |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
# ### ### ### ######### ######### ######### |
||||||
|
## Ready |
||||||
|
|
||||||
|
package provide pluginmgr 0.4 |
Loading…
Reference in new issue