NAME¶
tepam::procedure - TEPAM procedure, reference manual
SYNOPSIS¶
package require
Tcl 8.3
package require
tepam ?0.2?
tepam::procedure name attributes body
DESCRIPTION¶
This package provides an alternative way to declare Tcl procedures and to manage
its arguments. There is a lot of benefit to declare a procedure with TEPAM
rather than with the Tcl standard command
proc: TEPAM allows specifying
inside the procedure declaration in a natural syntax all information that is
required to generate comprehensive documentations and help support. The
information is also used by an automatically invoked argument checker that is
validating the provided procedure arguments before the procedure body is
executed. Finally, a procedure can be called interactively which will open a
form into which the arguments can be entered interactively.
TEPAM simplifies also the handling of the different types of argument, like the
named arguments (often also called
options) and the
unnamed
arguments. TEPAM supports the
named first, unnamed later style
(used by many Tcl commands) as well as also the
unnamed first, named
later style (used by many Tk commands). TEPAM reduces the effort to use
default values, optional arguments, multiple applicable arguments, etc. to a
simply definition of an argument attributes.
An informal overview of all the TEPAM procedure declaration and calling features
as well as an informal introduction into TEPAM is provided by
tepam(3tcl).
TERMINOLOGY¶
The exact meaning of several terms that are used in this document will be
shortly explained to avoid any ambiguities and misunderstandings.
- Subcommand
- The usage of subcommands is heavily used in the Tcl
language. Several commands are incorporated into a single main command and
are selectable via the first argument.
The string command is an example of such a command that implements
for example subcommands to check a character string's length, to compare
strings, to extract substrings, etc:
string length string
string compare string string
string range string first last
...
TEPAM provides a framework that allows implementing easily such subcommands in
form of Tcl procedures. It allows not only defining a first level of
subcommands, but also a higher level of subcommands. The
string
command's class check could be implemented as independent sub-sub-commands of
the
string command:
string is alnum string
string is integer string
string is double string
...
- Procedure attribute
- TEPAM allows attaching to a declared procedure many kind of
attributes. Some of these attributes are just used for
documentation purposes, but other attributes specify the way how the
procedure has to be called. Also the procedure arguments are defined in
form of a procedure attribute.
- Argument
- TEPAM uses the term argument for the parameters of a
procedure.
The following example calls the subcommand string compare with
several arguments:
string compare -nocase -length 3 "emphasized" "emphasised"
- The following paragraphs discuss these different argument
types.
- Named argument
- Some parameters, as -length 3 of the subcommand
string compare have to be provided as pairs of argument names and
argument values. This parameter type is often also called option.
TEPAM uses the term named argument for such options as well as for
the flags (see next item).
- Flag, switch
- Another parameter type is the flag or the
switch. Flags are provided simply by naming the flag leading with
the '-' character. The -nocase of the previous string
compare example is such a flag.
Flags are considered by TEPAM like a special form of named
arguments.
- Unnamed argument
- For the other parameters, e.g. the ones for which the
argument name has not to be mentioned, TEPAM uses the term unnamed
argument. The previous string compare example uses for the two
provided character strings two unnamed arguments.
- Argument attribute
- TEPAM allows describing the purpose of each procedure
argument with argument attributes. While some of them are just
documenting the attributes, most attributes are used by an argument
manager to control and validate the arguments that are provided during a
procedure call. Argument attributes are used to specify default values,
parameter classes (integer, xdigit, font, ...), valid choices, value
ranges, etc.
- Named arguments first, unnamed arguments later
- The string compare command of the previous example
requires that the named arguments (options, flags) are provided
first. The two mandatory (unnamed) arguments have to be provided as last
argument.
This is the usual Tcl style (exceptions exist) which is referred in the
TEPAM documentation as named arguments first, unnamed arguments later
style.
- Unnamed arguments first, named arguments later
- In contrast to most Tcl commands, Tk uses generally
(exceptions exist also here) a different calling style where the
unnamed arguments have to be provided first, before the named
arguments have to be provided:
pack .ent1 .ent2 -fill x -expand yes -side left
- This style is referred in the TEPAM documentation as
unnamed arguments first, named arguments later style.
PROCEDURE DECLARATION¶
TEPAM allows declaring new Tcl procedures with the command
tepam::procedure that similar to the standard Tcl command
proc
also 3 arguments:
- tepam::procedure name attributes
body
The TEPAM procedure declaration syntax is demonstrated by the following example:
tepam::procedure {display message} {
-short_description
"Displays a simple message box"
-description
"This procedure allows displaying a configurable\
message box. The default message type that is\
created is a warning, but also errors and info can\
be generated.
The procedure accepts multiple text lines."
-example
{display message -mtype Warning "Save first your job"}
-args {
{-mtype -choices {Info Warning Error} \
-default Warning -description "Message type"}
{text -type string -multiple \
-description "Multiple text lines to display"}
}
} {
puts "Message type: $mtype"
puts "Message: $text"
}
The 3 arguments of
procedure are:
- name
- The procedure name can be used in very flexible ways. Not
only that namespaces are fully supported. By providing a two element name
list as procedure name, a subcommand of a procedure will be declared. It
is even possible to declare sub-sub-commands of a procedure by providing
name lists with three elements.
Here are some valid procedure declarations using different procedure names
(the attribute and body arguments are empty for simplicity):
# Simple procedure name:
tepam::procedure display_message {} {}
# Procedure declared in the main namespace:
tepam::procedure ::display_message {} {}
# Procedure in the namespace ::ns:
tepam::procedure ::ns::display_message {} {}
# Declaration of the subcommand message of the procedure display:
tepam::procedure {display message} {} {}
- attributes
- All procedure attributes are provided in form of an option
list that contains pairs of option names and option data. The example
above has as procedure attribute a short and a normal description, but
also the procedure arguments are defined in form of a procedure attribute.
Most procedure attributes are providing information for documentation
purposes. But some of them affect also the way how the procedure can be
called. The section Procedure Attributes discuses in detail the
available procedure attributes.
The procedure arguments are defined in form of a special procedure
attribute. Most of the information provided in the argument definition is
not just used for documentation purposes. This information is in fact used
by the TEPAM argument manager to handle and validate the various forms of
arguments that are provided during the procedure calls. The section
Argument Declaration discusses in detail all the argument
definition attributes.
- body
- This is the normal procedure body. The declared arguments
will be available to the procedure body in form of variables.
The procedure body will only be executed if the provided set of arguments
could be validated by the TEPAM argument manager.
tepam::procedure {display_message} {
-args {
{- mtype -default Warning -choices {Warning Error}}
{ text -type string}
}
} {
puts "Message type: $mtype"
puts "Message: $text"
}
The commands
procedure as well as
argument_dialogbox are exported
from the namespace
tepam. To use these commands without the
tepam:: namespace prefix, it is sufficient to import them into the main
namespace:
namespace import tepam::*
procedure {display_message} {
-args {
...
PROCEDURE ATTRIBUTES¶
The first group of procedure attributes is not affecting the behavior of the
declared procedure. These attributes are just used for the purpose of
documentation and help text generation:
- -category string
- A category can be assigned to a procedure for documentation
purposes. Any string is accepted as category.
- -short_description string
- The short description of a procedure is used in the
documentation summary of a generated procedure list as well as in the NAME
section of a generated procedure manual page.
- -description string
- The (full) description assigned to a procedure is used to
create user manual and help pages.
- -return string
- The -return attribute allows defining the expected
return value of a procedure (user for documentation purposes).
- -example string
- A help text or manual page of a procedure can be enriched
with eventual examples, using the -example attribute.
The following attributes are not relevant for the documentation and help text
generation, but they affect the behavior of the declared procedure:
- -named_arguments_first 0|1
- This attribute defines the calling style of a procedure.
TEPAM uses by default the named arguments first, unnamed arguments
later style (Tcl). This default behavior can globally be changed by
setting the variable tepam::named_arguments_first to 0. This
global calling style can be changed individually for a procedure with the
-named_arguments_first attribute.
- -auto_argument_name_completion 0|1
- The declared procedures will by default automatically try
to match eventually abbreviated argument names to the defined arguments
names. This default behavior can globally be changed by setting the
variable tepam::auto_argument_name_completion to 0. This
global setting of the automatic argument name completion can be changed
individually for a procedure with the
-auto_argument_name_completion attribute.
- -interactive_display_format
extended|short
- A procedure declared with the TEPAM procedure
command can always be called with the -interactive option. By doing
so, a graphical form will be generated that allows entering interactively
all procedure arguments. There are two display modes for these interactive
forms. While the extended mode is more adapted for small procedure
argument sets, the short form is more adequate for huge procedure
argument sets.
The choice to use short or extended forms can globally be configured via the
variable tepam::interactive_display_format. This global setting can
then be changed individually for a procedure with the
-interactive_display_format attribute.
- -args list
- The procedure's arguments are declared via the -args
attribute. An argument is defined via a list having as first element the
argument name, followed by eventual argument attributes. All these
argument definition lists are packaged themselves into a global list that
is assigned to the procedure's -args attribute.
The next sub section describes in detail the argument definition
syntax.
ARGUMENT DECLARATION¶
The following example highlights the structure that is used for the argument
definitions in the context of a procedure declaration:
tepam::procedure {display_message} {
-args {
{-mtype -default Warning -choices {Info Warning Error} -description "Message type"}
{-font -type font -default {Arial 10 italic} -description "Message text font"}
{-level -type integer -optional -range {1 10} -description "Message level"}
{-fg -type color -optional -description "Message color"}
{-log_file -type file -optional -description "Optional message log file"}
{text -type string -multiple -description "Multiple text lines to display"}
}
} {
}
So, each of the procedure arguments is declared with a list that has as first
element the argument name, followed by eventual attributes. The argument
definition syntax can be formalized in the following way:
tepam::procedure <name> {
-args {
{<argument_name_1> <arg_attr_name_1a> <arg_attr_data_1a> \
<arg_attr_name_1b> <arg_attr_data_1b> ...}
{<argument_name_2> <arg_attr_name_2a> <arg_attr_data_2a> \
<arg_attr_name_2b> <arg_attr_data_2b> ...}
...
}
} <body>
The argument names and attributes have to be used in the following way:
- Argument name (<argument_name_<n>>)
- The provided argument name specifies if the argument is an
unnamed argument or a named argument/option. In addition to
this, an argument name can also be blank to indicate an argument comment,
or it can start with # to indicate a section comment.
- "<Name>"
- This is the simplest form of an argument name: An argument
whose name is not starting with '-' is an unnamed argument. The parameter
provided during a procedure call will be assigned to a variable with the
name <Name>.
tepam::procedure {print_string} {
-args {
{ text -type string -description "This is an unnamed argument"}
}
} {
puts $text
}
print_string "Hello"
-> Hello
- "-<Name>"
- An argument whose name starts with '-' is a named argument
(also called option). The parameter provided during a procedure
call will be assigned to a variable with the name <Name> (not
-<Name>).
tepam::procedure {print_string} {
-args {
{ -text -type string -description "This is a named argument"}
}
} {
puts $text
}
print_string -text "Hello"
-> Hello
- "--"
- This flag allows clearly specifying the end of the named
arguments and the begin of the unnamed arguments, in case the named
arguments first, unnamed arguments later style (Tcl) has been
selected.
If the unnamed arguments first, named arguments later style (Tk)
style is selected, this flag is ignored when the unnamed arguments have
already been parsed. Otherwise it will be assigned to the corresponding
unnamed argument.
- "-" or ""
- A blank argument name (either '-' or '') indicates
an argument comment. All remaining characters of the argument definition
list will be considered as a comment that will be attributed to the
following attribute.
tepam::procedure {print_time} {
-args {
{hours -type integer -description "Hour"}
{minutes -type integer -description "Minute"}
{- The following arguments are optional:}
{seconds -type integer -default 0 -description "Seconds"}
{milliseconds -type integer -default 0 -description "Milliseconds"}
}
} {
puts "${hour}h${minutes}:[expr $seconds+0.001*$milliseconds]"
}
- Argument comments are basically used in the interactive
argument definition forms, when a procedure is called interactively.
- "#*"
- An argument definition list that starts with '#' is
considered as a section comment. The argument definition list will be
trimmed from the '#' characters and the remaining string will be used as
section comment.
Section comments can be used to structure visually the argument definition
code. Section comments are also used to structure the generated help texts
and the interactive argument definition forms.
tepam::procedure {complex_multiply} {
-description "This function perform a complex multiplication"
-args {
{#### First complex number ####}
{-r0 -type double -description "First number's real part"}
{-i0 -type double -description "First number's imaginary part"}
{#### Second complex number ####}
{-r1 -type double -description "Second number's real part"}
{-i1 -type double -description "Second number's imaginary part"}
}
} {
return [expr $r0*$r1 - $i0*$i1]
}
- Argument attributes (<arg_attr_name_<mn>>
<arg_attr_data_<mn>>)
- The following argument attributes are supported:
- -description string
- The description argument attribute is used for
documentation purpose. Interactive argument definition forms use this
attribute to provide comprehensible explanations for an argument.
- -type type
- The type argument attribute allows assigning the argument
either to a predefined data type, or to a application specific data type.
The argument data that are provided during a procedure call are
automatically checked for consistency with the defined argument type.
Section ARGUMENT TYPES provides a list of predefined data types and
explains how application specific types can be specified.
The argument type none has a special meaning. An argument that has
the type none is handled as a flag. A flag is always
optional and its related variable contains the logical value 0 if
the flag has been used during the procedure call, or otherwise
1.
- -default value
- Eventual default values can be defined with the -default
argument attribute. Arguments with default values are automatically
optional arguments.
- -optional|-mandatory
- Arguments are by default mandatory, unless a default value
is defined. The flag -optional transforms an argument into an
optional argument.
In case an optional argument is not defined during a procedure call, the
corresponding variable will not be defined. The flag -mandatory is
the opposite to -optional. This flag exists only for completion
reason, since an argument is anyway mandatory by default.
- -multiple
- Arguments that have the -multiple attribute can be
defined multiple times during a procedure call. The data that are provided
during a procedure call for such an argument are stored in a list. This is
even the case if such an argument is only defined once during a procedure
call.
The -multiple attribute can be attributed to unnamed arguments and to
named arguments. The pair of argument name/argument data has to be
repeated for each provided data value in case of a named argument. In case
the argument with the -multiple attribute is an unnamed argument,
this one has to be the absolute last one of all unnamed arguments.
- -choices list
- A possible set of valid argument values can be attributed
to an argument via the -choices attribute. The argument data
provided during a procedure call will be checked against the provided
choice values.
- -choicelabels list
- An evanutal short description can be attributed to each
choice option with the -choicelabels attribute. These descriptions
will be used in the generated help texts and as radio and check box labels
for the interactive calls.
The -choicelabels attribute is optional, but if it is defined, its
list needs to have the identical size as the -choices argument
list.
- -range {double double}
- Another argument constraint can be defined with the
-range attribute. The valid range is defined with a list containing
the minimum valid value and a maximum valid value. The -range
attribute has to be used only for numerical arguments, like integers and
doubles.
- -validatecommand script
- Eventual more complex argument data validations can be
performed via specific validation commands that are assigned to the
validatecommand attribute. The provided validation command can be a
complete script in which the pattern %P is replaced by the argument
data that has to be validated. An example of a validation command
declaration is:
tepam::procedure {display_message} {
-args {
{text -type string -description "Message text" \
-validatecommand "IllegalWordDetector %P"}
} {
}
- -widget string
- The widgets that allow defining the different arguments in
case of an interactive procedure call are normally selected automatically
in function of the argument type. The -widget attribute allows
specifying explicitly a certain widget type for an argument.
- -auxargs list
- In case a procedure is called interactively, additional
argument attributes can be provided to the interactive argument definition
form via the -auxargs attribute that is itself a list of attribute
name/attribute data pairs:
-auxargs {-<arg_attr_name_1a> <arg_attr_data_1a> \
-<arg_attr_name_1b> <arg_attr_data_1b>
...
}
- For example, if a procedure takes as argument a file name
it may be beneficial to specify the required file type for the interactive
argument definition form. This information can be provided via the
-auxargs attribute to the argument definition form:
tepam::procedure LoadPicture {
-args {
{FileName -type existingfile -description "Picture file" \
-auxargs {-filetypes {{"GIF" {*.gif}} {"JPG" {*.jpg}} }}}
}
} {
}
- -auxargs_commands script
- If the auxiliary argument attributes are not static but
have to be dynamically adaptable, the -auxargs_commands allows
defining them via commands that are executed during a procedure call. A
list of pairs of auxiliary attribute names and commands have to be
provided to the -auxargs_commands attribute. The provided commands
are executed in the context of the calling procedure.
-auxargs_commands {-<arg_attr_name_1a> <arg_attr_command_1a> \
-<arg_attr_name_1b> <arg_attr_command_1b>
...
}
VARIABLES¶
Several variables defined inside the
::tepam namespace are impacting the
procedures and the way how they have to be called.
- named_arguments_first
- This variable defines the general calling style of the
procedures. It is by default set to 1 which selects the named
arguments first, unnamed arguments later style (Tcl).
By setting this variable to 0, the named arguments first, unnamed
arguments later style (Tk) is globally selected:
set tepam::named_arguments_first 0
While this variable defines globally the calling style, the procedure attribute
-named_arguments_first can adapt this style individually for each
procedure.
- auto_argument_name_completion
- This variable controls globally the automatic argument name
matching mode. By default it is set to 1, meaning that the called
procedures are trying to match eventually abbreviated argument names with
the declared argument names.
By setting this variable to 0 the automatic argument name matching
mode is disabled:
set tepam::auto_argument_name_completion 0
While this variable defines globally the matching mode, the procedure attribute
-auto_argument_name_completion can adapt this mode individually for
each procedure.
- interactive_display_format
- A procedure declared via the TEPAM procedure command
can always be called with the -interactive switch. By doing so, a
graphical form will be generated that allows entering interactively all
procedure arguments.
There are two display modes for these interactive forms. The extended
mode which is the default mode is more adapted for small procedure
argument sets, while the short form is more adequate for huge
procedure argument sets:
set tepam::interactive_display_format "short"
The choice to use short or extended forms can globally be configured via this
variable
interactive_display_format. This global setting can be changed
individually for a procedure with the procedure attribute
-interactive_display_format.
- help_line_length
- The maximum line length used by the procedure help text
generator can be specified with this variable. The default length which is
set to 80 (characters) can easily be adapted to the need of an
application:
set tepam::help_line_length 120
- Since this variable is applied directly during the help
text generation, its value can continuously be adapted to the current
need.
ARGUMENT TYPES¶
Many argument types are predefined by TEPAM that can be used in the procedure
argument definition section as argument type. In case a special application
specific type is missing, it is easy to add the necessary support for such a
type.
PREDEFINED ARGUMENT TYPES¶
To remember, a type can be assigned to each specified procedure argument:
tepam::procedure {warning} {
-args {
{-font -type font -default {Arial 10 italic}}
{-severity_level -type integer -optional -range {1 10}}
{-fg -type color -optional -description "Message color"}
{text -type string -multiple -description "Multiple text lines to display"}
}
} {
...
}
There are some
special purpose types that are building the first category
of predefined argument types:
- •
- none
Flags, also called switches, are defined by specifying a
named argument with the type none. Flags are always optional and
the default value of the assigned variable is set to 0. In contrast
to the (normal) named arguments no argument data has to be provided to a
flag.
tepam::procedure flag_test {
-args {
{-flag -type none -description "This is a flag"}
}
} {
puts $flag
}
flag_test
-> 0
flag_test -flag
-> 1
Since no argument data has to be provided to a flag, also no data checks are
performed for this argument type.
- •
- string
String is a generic argument data type. Any data string can be
provided to a string type argument and no data type checks are therefore
performed.
- •
- {}
A blank argument type signifies an undefined argument type. This is
the default argument type that is used when no type has been explicitly
specified. An argument that has a blank type behaves identically
than an argument that has a string type, e.g. no argument data
checks are performed. The only difference is that the data type
string is mentioned in the generated help documentation, while this
is not the case for blank type.
Several
numerical types are defined by TEPAM. The type validation
procedures are not using only the
string is <type> commands to
check the validity of the provided arguments, but they assure also that no
empty strings are provided as argument data (the
string is <type>
commands are considering an empty string as a valid numerical parameter). The
common type validation expression is therefore:
expr [string length <argument_data>]>0 && [string is <type_to_check> <argument_data>]
- •
- boolean
- •
- integer
- •
- double
The verification of all
alpha numeric types is directly performed with
the standard Tcl string type verification command:
string is <type_to_check> <argument_data>
The following types are verified in this way:
- •
- alnum
- •
- alpha
- •
- ascii
- •
- control
- •
- digit
- •
- graph
- •
- lower
- •
- print
- •
- punct
- •
- space
- •
- upper
- •
- wordchar
- •
- xdigit
In addition to the data types checked with the
string is <type>
commands, TEPAM specifies some other useful data types:
- •
- char
Each string that has a length of 1 character meets the character
type. The type check is made with the following expression:
expr [string length <argument_data>]==1
- •
- color
Any character strings that are accepted by Tk as a color are considered as
valid color argument. Please note that the Tk package has to be loaded to
use the color type. TEPAM is using the following command to
validate the color type:
expr ![catch {winfo rgb . <argument_data>}]
- •
- font
Any character strings that are accepted by Tk as a font are considered as
valid font argument. Please note that the Tk package uas to be loaded to
use the font type. TEPAM is using the following command to validate
the color type:
expr ![catch {font measure <argument_data> ""}]
- •
- file
Any strings that are not containing one of the following characters are
considered as valid file name: * ? " < >. It is not necessary
that the file or its containing directory is existing. Zero-length strings
are not considered as valid file names.
The following expression is used to validate the file names:
expr [string length <argument_data>]>0 && ![regexp {[\"*?<>:]} <argument_data>]
- •
- existingfile
The argument is valid if it matches with an existing file. The following
check is performed to validate the arguments of this type:
file exists <argument_data>
- •
- directory
The directory argument is validated exactly in the same way as the file
arguments.
- •
- existingdirectory
The argument is valid if it matches with an existing directory. The
following check is performed to validate the arguments of this type:
file isdirectory <argument_data>
DEFINING APPLICATION SPECIFIC ARGUMENT TYPES¶
Nothing is easier than adding support for a new application specific argument
type. It is just necessary to add into the namespace
tepam a validation
function
Validation(<type>) that has one argument and that
returns
1 if the provided argument matches with the relevant data type.
The function has to return otherwise
0.
The validation command section of the "
tepam.tcl" package
provides sufficient examples of validation functions, since it implements the
ones for the standard TEPAM types.
The following additional code snippet shows the validation function for a custom
argument type that has to correspond to a character string with a length of 2:
proc tepam::Validate(two_char) {v} {expr [string length $v]==2}
PROCEDURE CALLS¶
HELP¶
Each procedure can be called with the
-help flag. The procedure will then
print a generated help text to
stdout and will then return without
performing any additional actions.
Taking the first procedure declared in
PROCEDURE CALLS, the help request
and the printed help text would be:
display message -help
->
NAME
display message - Displays a simple message box
SYNOPSIS
display message
[-mtype <mtype>]
Message type, default: "Warning", choices: {Info, Warning, Error}
<text>
Multiple text lines to display, type: string
DESCRIPTION
This procedure allows displaying a configurable message box. The default
message type that is created is a warning, but also errors and info can
be generated.
The procedure accepts multiple text lines.
EXAMPLE
display message -mtype Warning "Save first your job"
The argument manager is checking if the last provided argument is
-help
and generates the requested help message if this is the case. So, also the
following example will print the help message:
display message -mtype Info "It is 7:00" -help
On the other hand, the following call will result in an error:
display message -help -mtype Info "It is 7:00"
->
display message: Argument '-help' not known
INTERACTIVE PROCEDURE CALL¶
Calling a procedure with the
-interactive flag will open a graphical form
that allows specifying interactively all procedure arguments. The Tk library
has to be loaded to use the interactive call. The following example assures
that the Tk library is loaded and shows the command line to call interactively
the procedure declared in
PROCEDURE CALLS:
package require Tk
display message -interactive
Also the
-interactive flag has to be placed at the last argument position
as this is also required for the
-help flag. Arguments defined before
the
-interactive flag will be ignored. The following example is
therefore also a valid interactive procedure call:
display message -mtype Info "It is 7:00" -interactive
UNNAMED ARGUMENTS¶
Unnamed arguments are typically provided to the called procedure as simple
parameters. This procedure calling form requires that the provided arguments
are strictly following the order of the specified arguments. Several
parameters can be assigned to the last argument if this one has the
-multiple attribute. So, the following declared procedure ...
tepam::procedure {display_message} {
-args {
{mtype -choices {Info Warning Error}}
{text -type string -multiple}
}
} {
puts "$mtype: [join $text]"
}
... can for example be called in the following ways:
display_message Info "It is PM 7:00."
-> Info: It is PM 7:00.
display_message Info "It is PM 7:00." "You should go home."
-> Info: It is PM 7:00. You should go home.
The nice thing is that unnamed arguments can also be called as named arguments,
which can be handy, for example if the exact specified argument order is not
known to a user:
display_message -mtype Info -text "It is PM 7:00."
-> Info: It is PM 7:00.
display_message -text "It is PM 7:00." -mtype Info
-> Info: It is PM 7:00.
display_message -mtype Info -text "It is PM 7:00." -text "You should go home."
-> Info: It is PM 7:00. You should go home.
display_message -text "It is PM 7:00." -text "You should go home." -mtype Info
-> Info: It is PM 7:00. You should go home.
NAMED ARGUMENTS¶
Named arguments have to be provided to a procedure in form of a parameter pairs
composed by the argument names and the argument data. The order how they are
provided during a procedure call is irrelevant and has not to match with the
argument specification order.
The following declared procedure ...
tepam::procedure {display_message} {
-args {
{-mtype -choices {Info Warning Error}}
{-text -type string -multiple}
}
} {
puts "$mtype: [join $text]"
}
... can be called in the following ways:
display_message -mtype Info -text "It is PM 7:00."
-> Info: It is PM 7:00.
display_message -text "It is PM 7:00." -mtype Info
-> Info: It is PM 7:00.
display_message -mtype Info -text "It is PM 7:00." -text "You should go home."
-> Info: It is PM 7:00. You should go home.
display_message -text "It is PM 7:00." -text "You should go home." -mtype Info
-> Info: It is PM 7:00. You should go home.
Also named arguments that have not the
-multiple attribute can be
provided multiple times. Only the last provided argument will be retained in
such a case:
display_message -mtype Info -text "It is PM 7:00." -mtype Warning
-> Warning: It is PM 7:00.
UNNAMED ARGUMENTS FIRST, NAMED ARGUMENTS LATER (TK STYLE)¶
A procedure that has been defined while the variable
tepam::named_arguments_first was set to 1, or with the procedure
attribute
-named_arguments_first set to 1 has to be called in the Tcl
style. The following procedure declaration will be used in this section to
illustrate the meaning of this calling style:
set tepam::named_arguments_first 1
tepam::procedure my_proc {
-args {
{-n1 -default ""}
{-n2 -default ""}
{u1 -default ""}
{u2 -default ""}
}
} {
puts "n1:'$n1', n2:'$n2', u1:'$u1', u2:'$u2'"
}
The unnamed arguments are placed at the end of procedure call, after the named
arguments:
my_proc -n1 N1 -n2 N2 U1 U2
-> n1:'N1', n2:'N2', u1:'U1', u2:'U2'
The argument parser considers the first argument that doesn't start with the '-'
character as well as all following arguments as unnamed argument:
my_proc U1 U2
-> n1:'', n2:'', u1:'U1', u2:'U2'
Named arguments can be defined multiple times. If the named argument has the
-multiply attribute, all argument data will be collected in a list.
Otherwise, only the last provided attribute data will be retained:
my_proc -n1 N1 -n2 N2 -n1 M1 U1 U2
-> n1:'M1', n2:'N2', u1:'U1', u2:'U2'
The name of the first unnamed argument has therefore not to start with the '-'
character. The unnamed argument is otherwise considered as name of another
named argument. This is especially important if the first unnamed argument is
given by a variable that can contain any character strings:
my_proc -n1 N1 -n2 N2 "->" "<-"
-> my_proc: Argument '->' not known
set U1 "->"
my_proc -n1 N1 -n2 N2 $U1 U2}]
my_proc: Argument '->' not known
The '--' flag allows separating unambiguously the unnamed arguments from the
named arguments. All data after the '--' flag will be considered as unnamed
argument:
my_proc -n1 N1 -n2 N2 -- "->" "<-"
-> n1:'N1', n2:'N2', u1:'->', u2:'<-'
set U1 "->"
my_proc -n1 N1 -n2 N2 -- $U1 U2
-> n1:'N1', n2:'N2', u1:'->', u2:'<-'
NAMED ARGUMENTS FIRST, UNNAMED ARGUMENTS LATER (TCL STYLE)¶
The Tk calling style is selected when a procedure is defined while the variable
tepam::named_arguments_first is set to 0, or when the procedure
attribute
-named_arguments_first has been set to 0. The following
procedure will be used in this section to illustrate this calling style:
set tepam::named_arguments_first 0
tepam::procedure my_proc {
-args {
{-n1 -default ""}
{-n2 -default ""}
{u1}
{u2 -default "" -multiple}
}
} {
puts "n1:'$n1', n2:'$n2', u1:'$u1', u2:'$u2'"
}
The unnamed arguments have to be provided first in this case. The named
arguments are provided afterwards:
my_proc U1 U2 -n1 N1 -n2 N2
-> n1:'N1', n1:'N1', u1:'U1', u2:'U2'
The argument parser will assign to each defined unnamed argument an argument
data before it switches to read the named arguments. This default behavior
changes a bit if there are unnamed arguments that are optional or that can
take multiple values.
An argument data will only be assigned to an unnamed argument that is optional
(that has either the
-optional attribute or that has a default value),
when the data is not beginning with the '-' character or when no named
arguments are defined. The data that starts with '-' is otherwise considered
as the name of a named argument.
Argument data are assigned to an argument that has the
-multiple
attribute as long as the parameter value doesn't starts with the '-'
character.
This constraint that parameter values that start with the '-' character cannot
be assigned to optional unnamed arguments makes the Tcl procedure calling
style not suitable for all situations. The Tk style may be preferable in some
cases, since it allows separating unambiguously the named arguments from the
unnamed ones with the '--' flag.
Let's explore in a bit less theoretically the ways how the previously defined
procedure can be called: The first example calls the procedure without any
parameters, which leads to an error since
u1 is a mandatory argument:
my_proc
-> my_proc: Required argument is missing: u1
The procedure call is valid if one parameter is provided for
u1:
my_proc U1
-> n1:'', n2:'', u1:'U1', u2:''
When more parameters are provided that are not starting with the '-' character,
then they will be attributed to the unnamed arguments.
U2 will receive
3 of these parameters, since it accepts multiple values:
my_proc U1 U2 U3 U4
-> n1:'', n2:'', u1:'U1', u2:'U2 U3 U4'
As soon as one parameter starts with '-' and all unnamed arguments have been
served, the argument manager tries to interpret the parameter as name of a
named argument. The procedure call will fail if the intend was to attribute
the parameter beginning with '-' to an unnamed argument:
my_proc U1 U2 U3 U4 -U5
-> my_proc: Argument '-U5' not known
The attribution of a parameter to a named argument will fail if there are
undefined unnamed (non optional) arguments. The name specification will in
this case simply be considered as a parameter value that is attributed to the
next unnamed argument. This was certainly not the intention in the
following example:
my_proc -n1 N1
-> n1:'', n2:'', u1:'-n1', u2:'N1'
The situation is completely different if values have already been attributed to
all mandatory unnamed arguments. A parameter beginning with the '-' character
will in this case be considered as a name identifier for a named argument:
my_proc U1 -n1 N1
-> n1:'N1', n2:'', u1:'U1', u2:''
No unnamed arguments are allowed behind the named arguments:
my_proc U1 -n1 N1 U2
-> my_proc: Argument 'U2' is not an option
The '--' flag has no special meaning if not all mandatory arguments have got
assigned a value. This flag will simply be attributed to one of the unnamed
arguments:
my_proc -- -n1 N1
-> n1:'N1', n2:'', u1:'--', u2:''
But the '--' flag is simply ignored if the argument parser has started to handle
the named arguments:
my_proc U1 -- -n1 N1
-> n1:'N1', n2:'', u1:'U1', u2:''
my_proc U1 -n1 N1 -- -n2 N2
-> n1:'N1', n2:'N2', u1:'U1', u2:''
RAW ARGUMENT LIST¶
It may be necessary sometimes that the procedure body is able to access the
entire list of arguments provided during a procedure call. This can happen via
the
args variable that contains always to unprocessed argument list:
tepam::procedure {display_message} {
-args {
{-mtype -choices {Warning Error} -default Warning}
{text -type string -multiple}
}
} {
puts "args: $args"
}
display_message -mtype Warning "It is 7:00"
-> args: -mtype Warning {It is 7:00}
SEE ALSO¶
tepam(3tcl), tepam::argument_dialogbox(3tcl)
KEYWORDS¶
argument integrity, argument validation, arguments, procedure, subcommand
CATEGORY¶
Procedures, arguments, parameters, options
COPYRIGHT¶
Copyright (c) 2009/2010, Andreas Drollinger