Error processing request
Parameters
CONTENT_LENGTH | 0 |
REQUEST_METHOD | GET |
REQUEST_URI | /revision/Options+and+Arguments?V=2 |
QUERY_STRING | V=2 |
CONTENT_TYPE | |
DOCUMENT_URI | /revision/Options+and+Arguments |
DOCUMENT_ROOT | /var/www/nikit/nikit/nginx/../docroot |
SCGI | 1 |
SERVER_PROTOCOL | HTTP/1.1 |
HTTPS | on |
REMOTE_ADDR | 172.69.58.31 |
REMOTE_PORT | 16268 |
SERVER_PORT | 4443 |
SERVER_NAME | wiki.tcl-lang.org |
HTTP_HOST | wiki.tcl-lang.org |
HTTP_CONNECTION | Keep-Alive |
HTTP_ACCEPT_ENCODING | gzip, br |
HTTP_X_FORWARDED_FOR | 3.140.185.147 |
HTTP_CF_RAY | 87bf95595cb81230-ORD |
HTTP_X_FORWARDED_PROTO | https |
HTTP_CF_VISITOR | {"scheme":"https"} |
HTTP_ACCEPT | */* |
HTTP_USER_AGENT | Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected]) |
HTTP_CF_CONNECTING_IP | 3.140.185.147 |
HTTP_CDN_LOOP | cloudflare |
HTTP_CF_IPCOUNTRY | US |
Body
Error
Unknow state transition: LINE -> END
-code
1
-level
0
-errorstack
INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit {Options and Arguments} {Supporting options like the core commands do is a common itch for Tcl'ers, as evidenced by the number of pages in [Category Argument Processing]! Here's a version I found recently in an old code folder, dusted off and have adopted as my go-to. The main features are that its use should be obvious, good error messages are generated and you don't end up writing a [proc] wrapper that takes two or more multi-line arguments.
Here's a demo:
======
proc what {args} {
options {{-loud} {-colour red green blue black} {-count 5}}
arguments {this {that {}} args}
foreach name [info locals] {
puts "$name = [set $name]"
}
}
======
And the module, which is hopefully short enough to act as its own documentation (and encouragement to extend!).
======
# commented sections are questionable support for validation of arguments (not opts - conflicts with multi-value form).
namespace eval options {
proc options {args} {
while {[llength $args] > 1} {
if {[string match [lindex $args 0]* -arrayvariable]} {
set args [lassign $args _ value]
set name -arrayvariable
set options($name) $value
} else {
error "Unknown option \"[lindex $args 0]\": must be one of -arrayvariable"
}
}
if {[info exists options(-arrayvariable)]} {
set upset [format {apply {{name value} {
uplevel 2 [list set %s(-$name) $value]
}}} $value]
} else {
set upset [format {apply {{name value} {
uplevel 2 [list set $name $value]
}}}]
}
# parse optspec
set spec [lindex $args 0]
foreach optspec $spec {
set name [lindex $optspec 0]
switch [llength $optspec] {
1 {
dict set opts $name type 0 ;# flag
{*}$upset [string range $name 1 end] 0
#dict set opts $name value 0
}
2 {
dict set opts $name type 1 ;# arbitrary value
dict set opts $name default [lindex $optspec 1]
{*}$upset [string range $name 1 end] [lindex $optspec 1]
#dict set opts $name value [lindex $optspec 1]
}
default {
dict set opts $name type 2 ;# choice
dict set opts $name default [lindex $optspec 1]
dict set opts $name values [lrange $optspec 1 end]
{*}$upset [string range $name 1 end] [lindex $optspec 1]
}
}
}
# get caller's args
upvar 1 args argv
for {set i 0} {$i<[llength $argv]} {} {
set arg [lindex $argv $i]
if {![string match -* $arg]} {
break
}
incr i
if {$arg eq "--"} {
break
}
set candidates [dict filter $opts key $arg*]
switch [dict size $candidates] {
0 {
return -code error -level 2 "Unknown option $arg: must be one of [dict keys $opts]"
}
1 {
dict for {name spec} $candidates {break}
set name [string range $name 1 end]
dict with spec {} ;# look out
if {$type==0} {
set value 1
} else {
if {[llength $argv]<($i+1)} {
return -code error -level 2 "Option $name requires a value"
}
set value [lindex $argv $i]
if {$type==2} {
set is [lsearch -all -glob $values $value*]
switch [llength $is] {
1 {
set value [lindex $values $is]
}
0 {
return -code error -level 2 "Bad $name \"$value\": must be one of $values"
}
default {
return -code error -level 2 "Ambiguous $name \"$value\": could be any of [lmap i $is {lindex $values $i}]"
}
}
}
incr i
}
{*}$upset $name $value
}
default {
return -code error -level 2 "Ambiguous option $arg: maybe one of [dict keys $candidates]"
}
}
}
set argv [lrange $argv $i end]
}
proc formatArgspec {argspec} {
foreach arg $argspec {
if {[llength $arg]>1} {
lappend res "?[lindex $arg 0]?"
} elseif {$arg eq "args"} {
lappend res "?args ...?"
} else {
lappend res $arg
}
}
return [join $res " "]
}
proc arguments {argspec} {
upvar 1 args argv
for {set i 0} {$i<[llength $argv]} {incr i} {
if {$i >= [llength $argspec]} {
return -code error -level 2 "wrong # args: should be \"[lindex [info level -1] 0] [formatArgspec $argspec]\""
}
set name [lindex $argspec $i 0]
if {$name eq "args"} {
uplevel 1 [list set args [lrange $argv $i end]]
return
}
set value [lindex $argv $i]
# set test [lindex $argspec $i 2]
# if {$test != ""} {
# set valid [uplevel 1 $test $value]
# if {!$value} {
# return -code error -level 2 "Invalid $name \"$value\", must be $test"
# }
# }
}
# defaults:
for {} {$i < [llength $argspec]} {incr i} {
set as [lindex $argspec $i]
if {[llength $as]==1} {
if {$as ne "args"} {
return -code error -level 2 "wrong # args: should be \"[lindex [info level -1] 0] [formatArgspec $argspec]\""
}
upvar 1 args args
set args [lrange $argv $i end]
return
}
lassign $as name value
# set test [lindex $argspec $i 2]
# if {$test != ""} {
# set valid [uplevel 1 $test $value]
# if {!$value} {
# return -code error -level 2 "Invalid $name \"$value\", must be $test"
# }
# }
}
uplevel 1 [list set $name $value]
}
namespace export options arguments
}
namespace import options::*
<<categories>> Argument Processing} regexp2} CALL {my render {Options and Arguments} {Supporting options like the core commands do is a common itch for Tcl'ers, as evidenced by the number of pages in [Category Argument Processing]! Here's a version I found recently in an old code folder, dusted off and have adopted as my go-to. The main features are that its use should be obvious, good error messages are generated and you don't end up writing a [proc] wrapper that takes two or more multi-line arguments.
Here's a demo:
======
proc what {args} {
options {{-loud} {-colour red green blue black} {-count 5}}
arguments {this {that {}} args}
foreach name [info locals] {
puts "$name = [set $name]"
}
}
======
And the module, which is hopefully short enough to act as its own documentation (and encouragement to extend!).
======
# commented sections are questionable support for validation of arguments (not opts - conflicts with multi-value form).
namespace eval options {
proc options {args} {
while {[llength $args] > 1} {
if {[string match [lindex $args 0]* -arrayvariable]} {
set args [lassign $args _ value]
set name -arrayvariable
set options($name) $value
} else {
error "Unknown option \"[lindex $args 0]\": must be one of -arrayvariable"
}
}
if {[info exists options(-arrayvariable)]} {
set upset [format {apply {{name value} {
uplevel 2 [list set %s(-$name) $value]
}}} $value]
} else {
set upset [format {apply {{name value} {
uplevel 2 [list set $name $value]
}}}]
}
# parse optspec
set spec [lindex $args 0]
foreach optspec $spec {
set name [lindex $optspec 0]
switch [llength $optspec] {
1 {
dict set opts $name type 0 ;# flag
{*}$upset [string range $name 1 end] 0
#dict set opts $name value 0
}
2 {
dict set opts $name type 1 ;# arbitrary value
dict set opts $name default [lindex $optspec 1]
{*}$upset [string range $name 1 end] [lindex $optspec 1]
#dict set opts $name value [lindex $optspec 1]
}
default {
dict set opts $name type 2 ;# choice
dict set opts $name default [lindex $optspec 1]
dict set opts $name values [lrange $optspec 1 end]
{*}$upset [string range $name 1 end] [lindex $optspec 1]
}
}
}
# get caller's args
upvar 1 args argv
for {set i 0} {$i<[llength $argv]} {} {
set arg [lindex $argv $i]
if {![string match -* $arg]} {
break
}
incr i
if {$arg eq "--"} {
break
}
set candidates [dict filter $opts key $arg*]
switch [dict size $candidates] {
0 {
return -code error -level 2 "Unknown option $arg: must be one of [dict keys $opts]"
}
1 {
dict for {name spec} $candidates {break}
set name [string range $name 1 end]
dict with spec {} ;# look out
if {$type==0} {
set value 1
} else {
if {[llength $argv]<($i+1)} {
return -code error -level 2 "Option $name requires a value"
}
set value [lindex $argv $i]
if {$type==2} {
set is [lsearch -all -glob $values $value*]
switch [llength $is] {
1 {
set value [lindex $values $is]
}
0 {
return -code error -level 2 "Bad $name \"$value\": must be one of $values"
}
default {
return -code error -level 2 "Ambiguous $name \"$value\": could be any of [lmap i $is {lindex $values $i}]"
}
}
}
incr i
}
{*}$upset $name $value
}
default {
return -code error -level 2 "Ambiguous option $arg: maybe one of [dict keys $candidates]"
}
}
}
set argv [lrange $argv $i end]
}
proc formatArgspec {argspec} {
foreach arg $argspec {
if {[llength $arg]>1} {
lappend res "?[lindex $arg 0]?"
} elseif {$arg eq "args"} {
lappend res "?args ...?"
} else {
lappend res $arg
}
}
return [join $res " "]
}
proc arguments {argspec} {
upvar 1 args argv
for {set i 0} {$i<[llength $argv]} {incr i} {
if {$i >= [llength $argspec]} {
return -code error -level 2 "wrong # args: should be \"[lindex [info level -1] 0] [formatArgspec $argspec]\""
}
set name [lindex $argspec $i 0]
if {$name eq "args"} {
uplevel 1 [list set args [lrange $argv $i end]]
return
}
set value [lindex $argv $i]
# set test [lindex $argspec $i 2]
# if {$test != ""} {
# set valid [uplevel 1 $test $value]
# if {!$value} {
# return -code error -level 2 "Invalid $name \"$value\", must be $test"
# }
# }
}
# defaults:
for {} {$i < [llength $argspec]} {incr i} {
set as [lindex $argspec $i]
if {[llength $as]==1} {
if {$as ne "args"} {
return -code error -level 2 "wrong # args: should be \"[lindex [info level -1] 0] [formatArgspec $argspec]\""
}
upvar 1 args args
set args [lrange $argv $i end]
return
}
lassign $as name value
# set test [lindex $argspec $i 2]
# if {$test != ""} {
# set valid [uplevel 1 $test $value]
# if {!$value} {
# return -code error -level 2 "Invalid $name \"$value\", must be $test"
# }
# }
}
uplevel 1 [list set $name $value]
}
namespace export options arguments
}
namespace import options::*
<<categories>> Argument Processing}} CALL {my revision {Options and Arguments}} CALL {::oo::Obj3142165 process revision/Options+and+Arguments} CALL {::oo::Obj3142163 process}
-errorcode
NONE
-errorinfo
Unknow state transition: LINE -> END
while executing
"error $msg"
(class "::Wiki" method "render_wikit" line 6)
invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
(class "::Wiki" method "render" line 8)
invoked from within
"my render $name $C"
(class "::Wiki" method "revision" line 31)
invoked from within
"my revision $page"
(class "::Wiki" method "process" line 56)
invoked from within
"$server process [string trim $uri /]"
-errorline
4