Tcl Library Source Code

NAME
Login

tepam::procedure - TEPAM procedure, reference manual

Table Of Contents

SYNOPSIS

package require Tcl 8.3
package require tepam ?0.5?

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 all information that is required to generate comprehensive documentations and help support. The information is also used by an automatically invoked argument checker that validates the provided procedure arguments before the procedure body is executed. Finally, a procedure can be called interactively which will open a graphical form that allows specifying the procedure arguments.

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 (typical Tcl command style) as well as also the unnamed first, named later style (typical Tk command style). TEPAM takes care about default values for arguments, optional arguments, multiple applicable arguments, etc. and eliminates the need to check the validity of the argument inside the procedure bodies.

An informal overview of all the TEPAM procedure declaration and calling features as well as a short introduction into TEPAM is provided by tepam(n).

TERMINOLOGY

The exact meaning of several terms that are used in this document will be shortly explained to avoid any ambiguities and misunderstandings.

PROCEDURE DECLARATION

TEPAM allows declaring new Tcl procedures with the command tepam::procedure that has similar to the standard Tcl command proc also 3 arguments:

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:

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](../../../../index.md#procedure)__ {display_message} {
   -args {
      ...

Procedure Attributes

The first group of attributes affect the behavior of the declared procedure:

The next attributes allow specifying custom argument checks as well as custom error messages in case these checks are failing:

The following attribute allows controlling the logging settings for an individual procedure:

The next group of procedure attributes is just used for the purpose of documentation and help text generation:

Argument Declaration

The following example shows 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"}
   }__
} {
}

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_value_1a>  <arg_attr_name_1b> <arg_attr_value_1b> ...}
      {<argument_name_2> <arg_attr_name_2a> <arg_attr_value_2a>  <arg_attr_name_2b> <arg_attr_value_2b> ...}
      ...
   }__
} <body>

The argument names and attributes have to be used in the following way:

VARIABLES

Several variables defined inside the ::tepam namespace impact the mode of operation of the procedures that have been declared with the TEPAM procedure command.

ARGUMENT TYPES

TEPAM provides a comprehensive set of procedure argument types. They can easily be completed with application specific types if necessary.

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:

Several numerical types are defined by TEPAM. The type validation procedures are using the string is -strict commands to check the validity of the provided arguments, which assures that no empty strings are accepted as argument value. The type validation expression for the numerical types and the argument types to which this expression is applied are:

string is __<type_to_check>__ -strict

Empty strings are accepted as argument value for all the alpha numeric argument types. The argument types that are falling into this category and validation expression used for them are:

string is *<type_to_check>*

In addition to the data types checked with the string is commands, TEPAM specifies some other useful data types:

Defining Application Specific Argument Types

To add support for a new application specific argument type it is just necessary to add into the namespace tepam a validation function Validation(). This function requires one argument. It has to 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 requires values that have a character string length of exactly 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 ] Message type, default: "Warning", choices: {Info, Warning, Error} 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

If Tk has been loaded a procedure can be called with the -interactive flag to open a graphical form that allows specifying interactively all procedure arguments. 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 values. 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 values will be collected in a list. Otherwise, only the last provided attribute value 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 will be chosen if a procedure is defined while the variable tepam::named_arguments_first is set to 0, or if 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 a value 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 value will only be assigned to an unnamed argument that is optional (that has either the -optional attribute or that has a default value), if the value is not beginning with the '-' character or if no named arguments are defined. The value that starts with '-' is otherwise considered as the name of a named argument.

Argument values are assigned to an argument that has the -multiple attribute as long as the parameter value doesn't starts with the '-' character.

Values that start with the '-' character can therefore not be assigned to optional unnamed arguments, which restricts the usage of the Tcl procedure calling style. 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:'' If more parameters are provided that are not starting with the '-' character, 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 assigned, the argument manager tries to interpret the parameter as name of a named argument. The procedure call will fail if a value beginning with '-' is assigned 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 assigned 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 the 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(n), tepam::argument_dialogbox(n)

KEYWORDS

argument integrity, argument validation, arguments, procedure, subcommand

CATEGORY

Procedures, arguments, parameters, options

COPYRIGHT

Copyright © 2009-2013, Andreas Drollinger