Sujet : Re: support for built-in -opt style options for proc
De : scotty (at) *nospam* svptechnicalservices.com.au (Scott Pitcher)
Groupes : comp.lang.tclDate : 25. Jun 2024, 00:56:31
Autres entêtes
Organisation : SVP TECHNICAL SERVICES
Message-ID : <20240625095603.266e83c2@officepc>
References : 1
User-Agent : Claws Mail 3.17.5 (GTK+ 2.24.32; x86_64-pc-linux-gnu)
On Mon, 24 Jun 2024 08:11:18 +0000
Mark Summerfield <
mark@qtrac.eu> wrote:
I want to create a couple of procs with these usages:
dialog::prepare ?-parent .? ?-modal true? window
I can't use the parse_args package because I don't know how to
install it (and it has no INSTALL doc)
I can see from the wiki that there seems to be a lot of different
pure Tcl solutions, so I don't know which one to choose.
I'm using Tcl/Tk 9.0b2.
With Tcl you can do quite good option and argument processing inline
with no dependencies.
If you have a single option you can do something like this.
# Takes a single binary option "-big"
proc name {arg1 arg2 {opt ""}} {
set opts(-big) 0
if {$opt == "-big"} {
set $opts($opt) 1
} elseif {$opt != ""} {
error "name: unknown option \"$opt\""
}
...
if {$opts(-big)} {
# Some special activity when big
...
}
}
To handle multiple options both binary and with arguments:
# Takes several options
proc name {args} {
set opts(-big) 0
set opts(-small) 0
set opts(-filename) ""
set opts(-title) ""
while {[llength $args] > 0} {
set args [lassign $args opt]
switch -glob -- $opt {
-filename - -title {
# Handle any option with argument
set args [lassign $args param]
set opts($opt) $param
}
-big - -small {
# Handle any binary option.
set opts($opt) 1
}
-* {
error "name: unknown option \"$opt\""
}
default {
error "name: unknown argument \"$opt\""
}
}
}
# Check arguments here.
if {$opts(-big) == 0 && $opts(-small)} {
# Must be medium ....
}
.....
}
To handle one or more arguments (non options in other words) you can
either add them as fixed arguments to the function -
proc name {arg1 arg2 args} ....
Or, you can add argument processing to the option processor. This is
more useful when you may have a variable number of arguments -
proc name {args} {
set opts(n) 0 ; # Count of non option arguments
set opts(-big) 0
....
while {[llength $args] > 0} {
set args [lassign $args opt]
switch -glob -- $opt {
....
-* {
error "name: unknown option \"$opt\""
}
default {
set opts([incr opts(n)]) $opt
}
}
}
# Check arguments here.
if {$opts(n) == 1} {
# Special case with only single argument
} elseif {$opts(n) == 2} {
# Special case with two arguments
} else {
error "name: invalid arguments, must be name arg1 \[arg2\]
?options?"
}
.....
}
Or -
proc name {args} {
....
# Check arguments here.
if {$opts(n) != 3} {
error "name: invalid arguments, must be name arg1 arg2 arg3
?options?"
}
.....
}
You can also leave out the defaults and check for the existence of
an opt(...) variable.
By using an opts array I can share it where necessary. I've taken to
calling the global application arguments, those passed to the program,
"Opts" and making that a variable or global to be accessed by other
parts of the code. They are global options after all.
It was designed to be inline and have no dependencies, and be simple
enough to handle special cases e.g. sometimes I need to collect
arguments and lappend them to a list. It also handles short options
with an OptsMap array mapping short to long, but I won't go into that.
Kind regards,
Scott
--