|
7 Commands: Tcl
This is the first part of the SMM++ command index. The commands
described here aren't SMM++ commands in particular, but tcl
commands, which were made accessible in the SMM++ parser (which is
the tcl shell).
|
Note: |
Please, don't underestimate the importance of the commands described here!
They build up the basis of all scripting: setting/unsetting
variables/arrays/lists/strings, various control structures like
if/switch/for, various string operations,
definition of procedures and much more.
|
This section will only introduce the most important
commands. Further more they will be introduced only very briefly
to give you quickly a good
overview and basic knowledge, so you can imediatly start
scripting. This is the main intention of this chapter. The more
you get used to the syntax and want to script more complicated
scripts you should refer to the tcl man pages, which are
included in the SMM++ documentation.
At some point you should in any case have a look at them, as tcl
is very powerful and there may be easy solutions for problems,
you didn't thought they will be solvable at all.
The tcl man pages can be found at
Appendix B.
|
Note: |
Some commands offer depending on their arguments various ways of
usage. The descriptions here may not include all possible ways
of their usage. Again, please, refer to
Appendix B.
|
In case of problems with tcl dont hesitate to post on the forum
boards or in the mailing list. Others may have encountered the
same problems, but for any reason didn't ask. So all would
profit from your question.
Abort a looping command
Syntax:
::break
Description:
- ::break
- This command is typically invoked inside the body of a looping command
such as for or foreach or while. The exception causes the current
script to be aborted out to the innermost containing loop command, which
then aborts its execution and returns normally.
Example: |
::set i 0
::while {1} {
::incr i
::smm::showme "$i. loop,..."
# the next command stops the loop, when i is equal to 10
::if {$i==10} { ::break }
}
|
Evaluate script and trap exceptional returns
Syntax:
::catch script ?varName?
Description:
- ::catch script ?varName?
- The catch command may be used to prevent errors from aborting
command interpretation. Catch calls the Tcl interpreter recursively to
execute script, and always returns a TCL_OK code, regardless of any
errors that might occur while executing script. The return value from
catch is a decimal string giving the code returned by the Tcl interpreter
after executing script. This will be 0 (TCL_OK) if there were no errors in
script; otherwise it will have a non-zero value corresponding to one of the
exceptional return codes (see tcl.h for the definitions of code values). If the
varName argument is given, then it gives the name of a variable; catch will
set the variable to the string returned from script (either a result or an error
message).
Note that catch catches all exceptions, including those generated by
break and continue as well as errors.
Example: |
::if {[::catch {::smm::showme "value of a: $a"}]} {
# The code here will be executed, if an error in the
# catched script/command occurs. Here in our case,
# this could happen, when no variable a is defined.
::smm::showme "There is no variable a defined"
}
# you can use catch also without the "if", if you just want
# to prevent errors to be reported.
::catch {::smm::showme "value of a: $a"}
|
Skip to the next iteration of a loop
Syntax:
::continue
Description:
- ::continue
- This command is typically invoked inside the body of a looping command
such as for or foreach or while. It causes the
current script to be aborted out to the innermost containing loop command,
which then continues with the next iteration of the loop.
Example: |
# loop from 0 to 9, just skip 5. loop
::for {::set i 0} {$i<10} {::incr i} {
::if {$i==5} { ::continue }
::smm::showme "$i. loop,.."
}
|
Generate an error
Syntax:
::error message
Description:
- ::error message
- Raises an error, , which causes command interpretation to be
unwound. Message is a string that is returned to the application to indicate
what went wrong. Errors can be caught with the catch command in scripts.
Example: |
::switch -- $pet {
horse -
donkey {
::tomud "mount $pet"
}
default {
::error "You cannot mount $pet."
}
}
|
Evaluate a Tcl script
Syntax:
::eval arg ?arg ...?
Description:
- ::eval arg ?arg ...?
- Eval takes one or more arguments, which together comprise a Tcl script
containing one or more commands. Eval concatenates all its arguments in
the same fashion as the concat command, passes the concatenated string
to the Tcl interpreter recursively, and returns the result of that evaluation
(or any error generated by it).
Example: |
# this sets the variable a to 5
::set com "::set a 5"
::eval $com
|
Invoke subprocess(es)
Syntax:
::exec arg ?arg ...?
Description:
- ::exec arg ?arg ...?
- Concatenates all args, executes them in the system shell and returns
their output. For more details about exec, please refer to the tcl manual.
Example: |
# this shows all current processes (linux)
::smm::showme "current processes:"
::smm::showme [::exec ps xau]
|
for loop.
Syntax:
::for start test next body
Description:
- ::for start test next body
- For is a looping command, similar in structure to the C for
statement.
Example: |
::for {::set i 0} {$i<10} {::incr i} {
::smm::showme "$i. loop,.."
}
|
Iterate over all elements in one list (or in more lists, pleae
refer to the tcl manual).
Syntax:
::foreach varname list body
Description:
- ::foreach varname list body
- An example makes it easily clear.
Example: |
# the following command
::foreach item {sword sword sword armor boots skin} {
::tomud "sell $item"
}
# sends
# sell sword
# sell sword
# sell sword
# sell armor
# sell boots
# sell skin
# to the mud.
|
Execute scripts conditionally
Syntax:
::if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
Description:
- ::if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
- The if command evaluates expr1 as an expression (in the same way that
expr evaluates its argument). The value of the expression must be a
boolean (a numeric value, where 0 is false and anything is true, or a string
value such as true or yes for true and false or no for false); if it is true then
body1 is executed by passing it to the Tcl interpreter. Otherwise expr2 is
evaluated as an expression and if it is true then body2 is executed, and so
on. If none of the expressions evaluates to true then bodyN is executed.
The then and else arguments are optional ``noise words'' to make the
command easier to read. There may be any number of elseif clauses,
including zero. BodyN may also be omitted as long as else is omitted too.
The return value from the command is the result of the body script that
was executed, or an empty string if none of the expressions was non-zero
and there was no bodyN.
Example: |
::set q 0
::if {$q!=0} {
::set a [expr 3/$q]
}
::if {1<2} {
::smm::showme "1 is smaller"
} else {
::smm::showme "2 is smaller"
}
set q 0
set p 0
::if {$q!=0} {
::set a [::expr $p/$q]
} elseif {$p!=0} {
::set a [::expr $q/$p]
} else {
::set a 1
}
# the last example can be also written as:
::set a [::if {$q!=0} {
::expr $p/$q
} elseif {$p!=0} {
::expr $q/$p
} else {
1
}]
|
Create a Tcl procedure.
|
Note: |
This is one of the most important commands for you. It holds the
place of the classical "alias" command.
The description here is quite lengthly, but as proc is a command of
major importance, please, try to understand as much as possible.
The examples should make quite a lot things clear; may be you want
to have a look at them in parallel.
| Syntax:
::proc name args body
Description:
- ::proc name args body
- The proc command creates a new Tcl procedure named name, replacing
any existing command or procedure there may have been by that name.
Whenever the new command is invoked, the contents of body will be
executed by the Tcl interpreter. Args
specifies the formal arguments to the procedure. It consists of a list,
possibly empty, each of whose elements specifies one argument. Each
argument specifier is also a list with either one or two fields. If there is only
a single field in the specifier then it is the name of the argument; if there are
two fields, then the first is the argument name and the second is its default
value.
When name is invoked a local variable will be created for each of the
formal arguments to the procedure; its value will be the value of
corresponding argument in the invoking command or the argument's
default value. Arguments with default values need not be specified in a
procedure invocation. However, there must be enough actual arguments
for all the formal arguments that don't have defaults, and there must not be
any extra actual arguments. There is one special case to permit
procedures with variable numbers of arguments. If the last formal
argument has the name args, then a call to the procedure may contain
more actual arguments than the procedure has formals. In this case, all of
the actual arguments starting at the one that would be assigned to args are
combined into a list (as if the list command had been used); this combined
value is assigned to the local variable args.
When body is being executed, variable names normally refer to local
variables, which are created automatically when referenced and deleted
when the procedure returns. One local variable is automatically created
for each of the procedure's arguments. Global variables can only be
accessed by invoking the global command.
The proc command returns an empty string. When a procedure is invoked,
the procedure's return value is the value specified in a return command. If
the procedure doesn't execute an explicit return, then its return value is
the value of the last command executed in the procedure's body. If an
error occurs while executing the procedure body, then the
procedure-as-a-whole will return that same error.
Example: |
# define a proc with no arguments
::proc ga {} { ::tomud "get all" }
# every time you type 'ga' 'get all' is send to the mud.
# there is also a shorter version
::proc ga {} {get all}
# define a proc with one argument
::proc mm {aTarget} { ::tomud "cast magic missle $aTarget" }
# e.g.: mm gnome
# define a proc with 2 arguments
::proc gt {aWhat aWhome} {
::tomud "get $aWhat from backpack"
::tomud "give $aWhat to $aWhome"
}
# e.g.: gt torch fred
# define the same proc above with a default
# parameter;lets say Barnie is your best friend
::proc gt {aWhat {aWhome "Barnie"}} {
::tomud "get $aWhat from backpack"
::tomud "give $aWhat to $aWhome"
}
# e.g.: gt torch fred
# would still give the torch to fred
# but: gt torch
# would give the torch to barnie
# define a proc with variable number of arguments
::proc powersell {args} {
# args is a list (probably emtpy)
::foreach item $args {
::tomud "get $item from backpack"
::tomud "sell $item"
}
}
# e.g.: powersell sword sword armor torch
# or: powersell skin boots
# define a proc with required and default arguments
::proc pgt {aWhome args} {
# args is a list (probably emtpy)
# args must always be the last argument
::foreach item $args {
::tomud "get $item from backpack"
::tomud "give $item to $aWhome"
}
}
# proc using global variables
# e.g. lets say a global variable 'hp' holds your current
# number of health points
::proc savekill {aTarget} {
::variable hp
::if {$hp<30} {
::smm::showme "Not enough hp!"
::return ; # this stops the procedure here
# you can also consider raising an error here!
#
# lets say savekill is used within another proc.
# With return all commands after savekill would
# still be executed!
# With error they wouldnt. Script execution
# would be stopped.
}
::tomud "kill $aTarget"
}
# proc with return value
# lets say the global variable 'exp' holds your
# current experience points
# and the global variable 'expLevel' holds the number of
# experience point needed for the next level
::proc expneeded {} {
::variable exp, expLevel
::return [::expr $expLevel - exp]
}
# e.g.: ::smm::showme "For next level you need [expneeded] exp."
|
Rename or delete a command/proc/alias
|
Note: |
If you dont really understand how the tcl shell works and
are unlucky you can build actions for commands, that
can destroy parts of your system; e.g. delete files.
If you know, that you dont need system or file access, you
should delete the commands ::exec, ::file and ::socket. They give
you access to your system resources.
| Syntax:
::rename oldName newName
Description:
- ::rename oldName newName
- Rename the command that used to be called oldName so that it is now
called newName. If newName is an empty string then oldName is deleted.
The rename command returns an empty string as result.
Example: |
# delete exec and file command
::rename ::exec {}
::rename ::file {}
::proc ga {} { ::tomud "get all" }
# if you are even to lazy to type 'ga':
:rename ga g
|
Return from a procedure
Syntax:
::return ?string?
Description:
- ::return ?string?
- Returns directly from a procedure and the return value of the
procedure will be string. If no string is specified it will
be the empty string.
Example: |
# this procedure always returns 1
::proc ret1 {} {
::return 1
}
|
Evaluate one of several scripts, depending on a
given value
|
Note: |
I put this note here, as you might have some C background and
expect switch to be fast. In fact switch is one of the slowest tcl
commands. It becomes slower the larger the switch is. You
shouldn't hesitate to use switch statements whenever you
them, but you should know at least.
| Syntax:
::switch ?options? string {pattern body ?pattern body ...?}
Description:
- ::switch ?options? string {pattern body ?pattern body ...?}
- The switch command matches its string argument against each of the
pattern arguments in order. As soon as it finds a pattern that matches
string it evaluates the following body argument by passing it recursively to
the Tcl interpreter and returns the result of that evaluation. If the last
pattern argument is default then it matches anything. If no pattern
argument matches string and no default is given, then the switch
command returns an empty string.
If the initial arguments to switch start with - then they are treated as
options. The following options are currently supported:
-exact |
Use exact matching when comparing string to a pattern. This is the
default.
|
-glob |
When matching string to the patterns, use glob-style matching (i.e.
the same as implemented by the string match command).
|
-regexp |
When matching string to the patterns, use regular expression
matching (i.e. the same as implemented by the regexp command).
|
-- |
Marks the end of options. The argument following this one will be
treated as string even if it starts with a -.
|
If a body is specified as ``-'', it means that the body for the next pattern
should also be used as the body for this pattern (if the next pattern also has
a body of ``-'' then the body after this is used, and so on). This feature
makes it possible to share a single body among several patterns.
Example: |
::switch abc {
a - b {::format 1}
abc {::format 2}
default {::format 3}
}
# will return 2,
::switch -regexp aaab {
^a.*b$ -
b {::format 1}
a* {::format 2}
default {::format 3}
}
# will return 1, and
::switch xyz {
a
-
b
{::format 1}
a*
{::format 2}
default
{::format 3}
}
# will return 3.
# instead of returning a value and using it, you can
# just invoke other commands and dont care about
# the return value
::set target "Dumbo"
::switch -exact -- $target {
Bambi -
Dumbo {
::tomud "kill $target"
}
"Elite Guard" -
Dragon {
::tomud "flee"
}
default {
::tomud "look at $target"
}
}
|
Execute script repeatedly as long as a condition is met
Syntax:
::while test body
Description:
- ::while test body
- The while command evaluates test as an expression (in the same way
that expr evaluates its argument). The value of the expression must a
proper boolean value; if it is a true value then body is executed by passing
it to the Tcl interpreter. Once body has been executed then test is
evaluated again, and the process repeats until eventually test evaluates to
a false boolean value. Continue commands may be executed inside body
to terminate the current iteration of the loop, and break commands may be
executed inside body to cause immediate termination of the while
command. The while command always returns an empty string.
Note: test should almost always be enclosed in braces. If not, variable
substitutions will be made before the while command starts executing,
which means that variable changes made by the loop body will not be
considered in the expression. This is likely to result in an infinite loop. If
test is enclosed in braces, variable substitutions are delayed until the
expression is evaluated (before each loop iteration), so changes in the
variables will be visible. For an example, try the following script with and
without the braces around $x<10:
Example: |
::set x 0
::while {$x<10} {
::smm::showme "x is $x"
::incr x
}
|
Manipulate/query array variables
Syntax:
::array exists arrayName
::array names arrayName ?pattern?
::array size arrayName
Description:
- ::array exists arrayName
- Returns 1 if arrayName is an array variable, 0 if there is no variable
by that name or if it is a scalar variable.
- ::array names arrayName ?pattern?
- Returns a list containing the names of all of the elements in the
array that match pattern (using the glob-style matching rules of
string match). If pattern is omitted then the command returns all
of the element names in the array. If there are no (matching)
elements in the array, or if arrayName isn't the name of an array
variable, then an empty string is returned.
- ::array size arrayName
- Returns a decimal string giving the number of elements in the array.
If arrayName isn't the name of an array then 0 is returned.
Example: |
# build an array
::set cost(jacket) "3 gold"
::set cost(sword) "1 platin"
::set cost(bread) "3 copper"
# show all known costs
::if {[::array exists cost]} {
::foreach item [::array names cost] {
::smm::showme "$item costs $cost($item)."
}
}
|
Access global variables
|
Note: |
Usually you shouldn't use global, but variable (see below please).
| Syntax:
::global varname ?varname ...?
Description:
- ::global varname ?varname ...?
- This command is ignored unless a Tcl procedure is being interpreted. If so
then it declares the given varname's to be global variables rather than local
ones. Global variables are variables in the global namespace. For the
duration of the current procedure (and only while executing in the current
procedure), any reference to any of the varnames will refer to the global
variable by the same name.
Example: |
::global a
::set a 5
::proc f1 {} {
# this will cause an error, because in this
# procedure no variable a is known.
::incr a
}
::proc f2 {} {
::global a
# this is ok, as the variable a is the
# one set to 5 (see above).
::incr a
}
|
Return information about the state of the Tcl
interpreter.
There is more to know about the info command; please,
refer to the tcl manal pages.
Syntax:
::info exists varName
::info globals ?pattern?
::info procs ?pattern?
::info vars ?pattern?
Description:
- ::info exists varName
- Returns 1 if the variable named varName exists in the current
context (either as a global or local variable), returns 0 otherwise.
- ::info globals ?pattern?
- If pattern isn't specified, returns a list of all the names of
currently-defined global variables. Global variables are variables in
the global namespace. If pattern is specified, only those names
matching pattern are returned. Matching is determined using the
same rules as for string match.
- ::info procs ?pattern?
- If pattern isn't specified, returns a list of all the names of Tcl
command procedures in the current namespace. If pattern is
specified, only those procedure names in the current namespace
matching pattern are returned. Matching is determined using the
same rules as for string match.
- ::info vars ?pattern?
- If pattern isn't specified, returns a list of all the names of
currently-visible variables. This includes locals and
currently-visible globals. If pattern is specified, only those names
matching pattern are returned. Matching is determined using the
same rules as for string match.
Example: |
::set a 1
::if {[::info exists a]} {
::smm::showme "variable a exists."
} else {
::smm::showme "variable a doesn't exist."
}
# one can also query array variables
# (not the arrays themself; for quering arrays
# please refer to the array command).
::set b(3) 1
::if {[::info exists b(3)]} {
::smm::showme "variable b(3) exists."
} else {
::smm::showme "variable b(3) doesn't exist."
}
|
Read and write variables
Syntax:
::set varName ?value?
Description:
- ::set varName ?value?
- Returns the value of variable varName. If value is specified, then set the
value of varName to value, creating a new variable if one doesn't already
exist, and return its value. If varName contains an open parenthesis and
ends with a close parenthesis, then it refers to an array element: the
characters before the first open parenthesis are the name of the array, and
the characters between the parentheses are the index within the array.
Otherwise varName refers to a scalar variable.
Example: |
# variables can be numbers or strings
::set a 5
::set b "Road to Nowhere"
# arrays
::set array(1) 5
::set array(2) 34
# array indices may be strings (in principal they always are)
::set array(sword) 23
# tcl arrays are always 1 dimensional, but one can easily
# simulate 2d behaviour
::set array(1,1) 24
::set array(1,2) 29
# btw:
::set array(1) 5
::set array( 1) 23
# are different variables;
# remember? arrays always have string indices
|
Delete variables
Syntax:
::unset name ?name name ...?
Description:
- ::unset name ?name name ...?
- This command removes one or more variables. Each name is a variable
name, specified in any of the ways acceptable to the set command. If a
name refers to an element of an array then that element is removed
without affecting the rest of the array. If a name consists of an array name
with no parenthesized index, then the entire array is deleted. The unset
command returns an empty string as result. An error occurs if any of the
variables doesn't exist, and any variables after the non-existent one are
not deleted.
Example: |
# deletes one variable
::unset a
# deletes the variables a, b and c
::unset a b c
# deletes one element from the array
::unset array(index)
# deletes the entire array
::unset array
|
create and initialize a variable
Syntax:
::variable name
Description:
- ::variable name
- Use this command to link a variable within a procedure with a
global variable. (In reality variable doesnt link to global
variables in tcl-sense, but feel free to think so. The variable
command is closely related to namespaces)
Example: |
::set a 5
::proc showA {} {
::variable a
::smm::showme "Value of a: $a"
}
|
Join lists together
Syntax:
::concat ?arg arg ...?
Description:
- ::concat ?arg arg ...?
- This command treats each argument as a list and concatenates them into a
single list. It also eliminates leading and trailing spaces in the arg's and
adds a single separator space between arg's. It permits any number of
arguments. If no args are supplied, the result is an empty string.
Example: |
# For example, the command
::concat a b {c d e} {f {g h}}
# will return
# a b c d e f {g h}
# as its result.
|
Create a string by joining together list elements
Syntax:
::join list ?joinString?
Description:
- ::join list ?joinString?
- The list argument must be a valid Tcl list. This command returns the string
formed by joining all of the elements of list together with joinString
separating each adjacent pair of elements. The joinString argument
defaults to a space character.
Example: |
::set mylist fred barney wilma
::set myliststring [::join $mylist --]
# myliststring has now the following content:
# fred--barney--wilma
|
Append list elements onto a variable
Syntax:
::lappend varName ?value value value ...?
Description:
- ::lappend varName ?value value value ...?
- This command treats the variable given by varName as a list and appends
each of the value arguments to that list as a separate element, with spaces
between elements. If varName doesn't exist, it is created as a list with
elements given by the value arguments. Lappend is similar to append
except that the values are appended as list elements rather than raw text.
Example: |
::set mylist [::list a]
::lappend mylist b
::lappend mylist c
|
Retrieve an element from a list
Syntax:
::lindex list index
Description:
- ::lindex list index
- This command treats list as a Tcl list and returns the index'th element
from it (0 refers to the first element of the list). In extracting the element,
lindex observes the same rules concerning braces and quotes and
backslashes as the Tcl command interpreter; however, variable
substitution and command substitution do not occur. If index is negative or
greater than or equal to the number of elements in value, then an empty
string is returned. If index has the value end, it refers to the last element in
the list.
Example: |
::set mylist [::list a b c d e]
::set itemFirst [::lindex $mylist 0]
::set item2 [::lindex $mylist 1]
::set itemEnd [::lindex $mylist end]
|
Insert elements into a list
Syntax:
::linsert list index element ?element element ...?
Description:
- ::linsert list index element ?element element ...?
- This command produces a new list from list by inserting all of the element
arguments just before the indexth element of list. Each element argument
will become a separate element of the new list. If index is less than or
equal to zero, then the new elements are inserted at the beginning of the
list. If index has the value end, or if it is greater than or equal to the number
of elements in the list, then the new elements are appended to the list.
Example: |
::set mylist [::list a b c d e]
::set list2 [::linsert $list 1 X Y]
# list2 is now: a X Y b c d e
|
Create a list
Syntax:
::list ?arg arg ...?
Description:
- ::list ?arg arg ...?
- This command returns a list comprised of all the args, or an empty string if
no args are specified. Braces and backslashes get added as necessary, so
that the index command may be used on the result to re-extract the
original arguments, and also so that eval may be used to execute the
resulting list.
Example: |
::set emptyList [::list]
::set someList [::list a b c]
|
Count the number of elements in a list
Syntax:
::llength list
Description:
- ::llength list
- Treats list as a list and returns a decimal string giving the number of
elements in it.
Example: |
::set mylist [::list a b c]
::set n [::llength $mylist]
|
Return one or more adjacent elements from a list
Syntax:
::lrange list first last
Description:
- ::lrange list first last
- List must be a valid Tcl list. This command will return a new list consisting
of elements first through last, inclusive. First or last may be end (or any
abbreviation of it) to refer to the last element of the list.
Example: |
::set mylist [::list a b c d e f]
::set mysublist [::lrange $mylist 2 4]
# mysublist will be: c d e
|
Replace elements in a list with new elements
Syntax:
::lreplace list first last ?element element ...?
Description:
- ::lreplace list first last ?element element ...?
- lreplace returns a new list formed by replacing one or more elements of
list with the element arguments. First gives the index in list of the first
element to be replaced (0 refers to the first element). If first is less than
zero then it refers to the first element of list; the element indicated by first
must exist in the list. Last gives the index in list of the last element to be
replaced. If last is less than first then no elements are deleted; the new
elements are simply inserted before first. First or last may be end (or any
abbreviation of it) to refer to the last element of the list. The element
arguments specify zero or more new arguments to be added to the list in
place of those that were deleted. Each element argument will become a
separate element of the list. If no element arguments are specified, then
the elements between first and last are simply deleted.
Example: |
::set mylist [::list a b c d e f g h]
# remove element 'c' from list
::set mylist [::lreplace $mylist 2 2]
# mylist is now: a b d e f g h
# replace the elements 'd', 'e' and 'f'
# by the elements 'V', 'W', 'X', 'Y' and 'Z'
::set mylist [::lreplace $mylist 2 4 V W X Y Z]
# mylist is now: a b V W X Y Z g h
|
See if a list contains a particular element
Syntax:
::lsearch ?mode? list pattern
Description:
- ::lsearch ?mode? list pattern
- This command searches the elements of list to see if one of them matches
pattern. If so, the command returns the index of the first matching element.
If not, the command returns -1. The mode argument indicates how the
elements of the list are to be matched against pattern and it must have one
of the following values:
- -exact
-
The list element must contain exactly the same string as pattern.
- -glob
-
Pattern is a glob-style pattern which is matched against each list
element using the same rules as the string match command.
- -regexp
-
Pattern is treated as a regular expression and matched against
each list element using the same rules as the regexp command.
If mode is omitted then it defaults to -glob.
Example: |
::set mylist [::list a1 a2 a3 b1 b2 b3]
# search for exactly an element
::set index [::lsearch -exact $mylist b2]
::if {$index<0} {
::smm:showme "mylist doesnt contain element b2"
}
# search for an element that start with 'b'
::set index [::lsearch $mylist b*]
::if {$index<0} {
::smm:showme "mylist doesnt contain searched element."
} else {
::set elem [::lindex $mylist $index]
::smm:showme "element found: $elem"
}
|
Sort the elements of a list. For more detailed information, please
refer to the tcl manual pages.
Syntax:
::lsort ?options? list
Description:
- ::lsort ?options? list
- This command sorts the elements of list, returning a new list in sorted
order. By default ASCII sorting is used with the result returned in
increasing order. However, any of the following options may be specified
before list to control the sorting process (unique abbreviations are
accepted):
- -ascii
-
Use string comparison with ASCII collation order. This is the
default.
- -integer
-
Convert list elements to integers and use integer comparison.
- -real
-
Convert list elements to floating-point values and use floating
comparison.
- -increasing
-
Sort the list in increasing order (``smallest'' items first). This is the
default.
- -decreasing
-
Sort the list in decreasing order (``largest'' items first).
Example: |
::set mylist [::list g d a c e f b]
::smm::showme "unsorted list: $mylist"
::smm::showme "sorted list: [::lsort $mylist]"
|
Split a string into a proper Tcl list
Syntax:
::split string ?splitChars?
Description:
- ::split string ?splitChars?
- Returns a list created by splitting string at each character that is in the
splitChars argument. Each element of the result list will consist of the
characters from string that lie between instances of the characters in
splitChars. Empty list elements will be generated if string contains
adjacent characters in splitChars, or if the first or last character of string is
in splitChars. If splitChars is an empty string then each character of string
becomes a separate element of the result list. SplitChars defaults to the
standard white-space characters.
Example: |
::split "comp.unix.misc" .
# returns "comp unix misc"
::split "Hello world" {}
# returns "H e l l o { } w o r l d".
|
Append to variable
Syntax:
::append varName ?value value value ...?
Description:
- ::append varName ?value value value ...?
- Append all of the value arguments to the current value
of variable varName. If varName doesn't exist, it is
given a value equal to the concatenation of all the value
arguments. This command provides an efficient way to
build up long variables incrementally.
For example, ``append a $b'' is much more efficient
than ``set a $a$b'' if $a is long.
Example: |
::set a ab ; # variable a is set to 'ab'
::append a cd ; # variable a is now 'abcd'
|
Format a string in the style of sprintf
Syntax:
::format formatString ?arg arg ...?
Description:
- ::format formatString ?arg arg ...?
- This command generates a formatted string in the same way as the ANSI
C sprintf procedure (it uses sprintf in its implementation). FormatString
indicates how to format the result, using % conversion specifiers as in
sprintf, and the additional arguments, if any, provide values to be
substituted into the result. The return value from format is the formatted
string. For more information, please refer to the tcl manual.
Example: |
::smm::showme [::format "%5.3f" 3.2]
|
Match a regular expression against a string. Determines whether
the regular expression exp matches part or all of
string and returns 1 if it does, 0 if it doesn't.
Regular expressions
may seem complicated at first sight, but there is nothing more
powerful than them.
Syntax:
::regexp ?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?
Description:
- ::regexp ?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?
- As I dont want to repeat the regexp manual page, I'll be very
brief here. You should really read the regexp manual page.
The only thing I want to say about regular expressions
here is to list its special characters. Please follow the
examples too, I hope they will make lots of things clear.
\ |
shields the following character; that means the
character following a '\'
looses its special meaning.
|
any single chacter |
matches exactly this character (a single character is one possibility of an atom)
|
. |
matches any character (a '.' is one possibility of an atom)
|
[chars] |
Matches any character in the set given by
chars. If a sequence of the form x-y
appears in chars, then any character
between x and y, inclusive, will match.
If the chars start with '^' the set of character will
be an anti-set. (a character set is an atom too)
|
( |
starts a submatch. (a submatch is one possibility of an atom)
|
) |
ends a submatch
|
| |
separates branches of regular expressions
|
* |
matches 0 or more atoms
|
+ |
matches 1 or more atoms
|
? |
matches 0 or 1 atom
|
^ |
means the start of line
|
$ |
means the end of line
|
Example: |
# lets say the variable aStr holds a string
# usually one uses regexp within an if-statement
::if {[::regexp {abc} $aStr]} {
# do something
}
# search for an exact string
::regexp {Bambi} $aStr
::regexp {Dumbo} $aStr
# searching for exits (e.g. an automapper implementation)
# assume, that the exits are sometimes displayed as
# "-North" and sometimes as "-north" and sometimes as
# "-N" and sometimes as "-n"
# So provide 4 if/regexps to detect this
::if {[::regexp {-North} $aStr]} { do something }
::if {[::regexp {-north} $aStr]} { do something }
::if {[::regexp {-N} $aStr]} { do something }
::if {[::regexp {-n} $aStr]} { do something }
# a more efficient and straight on forward implementation
::if {[::regexp {-North|-north|-N|-n} $aStr]} {
do something
}
# the '|' means or: either match the one or the other
# or the other or the other regular expression
# if you want to know which one has matched, provide an
# variable (name 'a'), that will hold what has matched.
::if {[::regexp {-North|-north|-N|-n} $aStr a]} {
::smm::showme "$a"
# a will be either -North, -north, -N or -n
do something else
}
# ok, now we dense all even more, first we just put two and two
# expression together:
::if {[::regexp {-[nN]orth|-[nN]} $aStr]} { do something }
# [nN] means a single character (atom) either being a 'n'
# or a 'N'
# BTW: [0-9] means just numbers, [a-z] just lower letters,
# [A-Z] just capital letters, [0-9a-zA-Z] alpha numeric
# characters only
# and now at last we dense it all together
::if {[::regexp {-[nN](orth)?} $aStr]} { do something }
# the (..) is a submatch (remember: submatches are atoms!)
# and the '?' requires 0 or 1 times the atom.
# ok,.. there is still a bug in it:
# the expressions above will also match a string like:
# Dumbo says "------no------"
# the "-n" match will match it,.. so we will also require a
# space at the end of the match
::if {[::regexp {-[nN](orth)? } { do something }
# using machting variables
# just one simple example, which will make everything clear
# hopefully,..
::if {[::regexp {^(.*) tells you "(.*)"$} $aStr dummy who what]} {
::tomud "tell $who Dont tell me '$what'!!!"
}
# remember the '.' means any character and the '*' mean as
# many as matches (till the ' tells you') and the '()'
# groups them into a submatch, so you get the result back in
# a variable.
# The '^' means start of string and '$' means end of string.
|
Perform substitutions based on regular expression pattern
matching. There is more information about regsub in the
tcl manual pages.
Syntax:
::regsub ?switches? exp string subSpec varName
Description:
- ::regsub ?switches? exp string subSpec varName
- This command matches the regular expression exp against string, and it
copies string to the variable whose name is given by varName. If there is a
match, then while copying string to varName the portion of string that
matched exp is replaced with subSpec.
If the initial arguments to regexp start with - then they are treated as
switches. The following switches are currently supported:
- -all
-
All ranges in string that match exp are found and substitution is
performed for each of these ranges. Without this switch only the
first matching range is found and substituted. If -all is specified,
then ``&'' and ``\n'' sequences are handled for each substitution
using the information from the corresponding match.
- -nocase
-
Upper-case characters in string will be converted to lower-case
before matching against exp; however, substitutions specified by
subSpec use the original unconverted form of string.
- --
-
Marks the end of switches. The argument following this one will be
treated as exp even if it starts with a -.
The command returns a count of the number of matching ranges that were
found and replaced. See the manual entry for regexp for details on the
interpretation of regular expressions.
Example: |
::set aStr "This is an expamle string."
::regsub {is} $aStr {**IS**} a
# variable a will be: "Th**IS** is an expamle string."
::regsub -all {is} $aStr {**IS**} a
# variable a will be: "Th**IS** **IS** an expamle string."
|
Parse string using conversion specifiers in the style of sscanf
Syntax:
::scan string format varName ?varName ...?
Description:
- ::scan string format varName ?varName ...?
- This command parses fields from an input string in the same fashion as the
ANSI C sscanf procedure and returns a count of the number of
conversions performed, or -1 if the end of the input string is reached
before any conversions have been performed. String gives the input to be
parsed and format indicates how to parse it, using % conversion specifiers
as in sscanf. Each varName gives the name of a variable; when a field is
scanned from string the result is converted back into a string and assigned
to the corresponding variable. For more information please refer
to the tcl manual pages.
Example: |
::set line "Dumbo offers you 5 gold"
::scan $line {%s %s %s %d} who dummy1 dummy2 amount
::if {$amount<10} {
::tomud "tell $who $amount is to less!
} else {
::tomud "tell $who ok!
}
|
Manipulate strings
Syntax:
::string compare string1 string2
::string first string1 string2
::string index string charIndex
::string last string1 string2
::string length string
::string match pattern string
::string range string first last
::string tolower string
::string toupper string
::string trim string ?chars?
::string trimleft string ?chars?
::string trimright string ?chars?
::string wordend string index
::string wordstart string index
Description:
- ::string compare string1 string2
- Perform a character-by-character comparison of strings string1
and string2 in the same way as the C strcmp procedure. Return
-1, 0, or 1, depending on whether string1 is lexicographically less
than, equal to, or greater than string2.
- ::string first string1 string2
- Search string2 for a sequence of characters that exactly match the
characters in string1. If found, return the index of the first character
in the first such match within string2. If not found, return -1.
- ::string index string charIndex
- Returns the charIndex'th character of the string argument. A
charIndex of 0 corresponds to the first character of the string. If
charIndex is less than 0 or greater than or equal to the length of the
string then an empty string is returned.
- ::string last string1 string2
- Search string2 for a sequence of characters that exactly match the
characters in string1. If found, return the index of the first character
in the last such match within string2. If there is no match, then
return -1.
- ::string length string
- Returns a decimal string giving the number of characters in string.
- ::string match pattern string
- See if pattern matches string; return 1 if it does, 0 if it doesn't.
Matching is done in a fashion similar to that used by the C-shell.
For the two strings to match, their contents must be identical except
that the following special sequences may appear in pattern:
* |
Matches any sequence of characters in string, including a
null string.
|
? |
Matches any single character in string.
|
[chars] |
Matches any character in the set given by chars. If a
sequence of the form x-y appears in chars, then any
character between x and y, inclusive, will match.
|
\x |
Matches the single character x. This provides a way of
avoiding the special interpretation of the characters *?[]\ in
pattern.
|
- ::string range string first last
- Returns a range of consecutive characters from string, starting with
the character whose index is first and ending with the character
whose index is last. An index of 0 refers to the first character of the
string. An index of end (or any abbreviation of it) refers to the last
character of the string. If first is less than zero then it is treated as if
it were zero, and if last is greater than or equal to the length of the
string then it is treated as if it were end. If first is greater than last
then an empty string is returned.
- ::string tolower string
- Returns a value equal to string except that all upper case letters
have been converted to lower case.
- ::string toupper string
- Returns a value equal to string except that all lower case letters
have been converted to upper case.
- ::string trim string ?chars?
- Returns a value equal to string except that any leading or trailing
characters from the set given by chars are removed. If chars is not
specified then white space is removed (spaces, tabs, newlines, and
carriage returns).
- ::string trimleft string ?chars?
- Returns a value equal to string except that any leading characters
from the set given by chars are removed. If chars is not specified
then white space is removed (spaces, tabs, newlines, and carriage
returns).
- ::string trimright string ?chars?
- Returns a value equal to string except that any trailing characters
from the set given by chars are removed. If chars is not specified
then white space is removed (spaces, tabs, newlines, and carriage
returns).
- ::string wordend string index
- Returns the index of the character just after the last one in the word
containing character index of string. A word is considered to be
any contiguous range of alphanumeric or underscore characters, or
any single character other than these.
- ::string wordstart string index
- Returns the index of the first character in the word containing
character index of string. A word is considered to be any
contiguous range of alphanumeric or underscore characters, or any
single character other than these.
Example: |
::set a "Hey, Dumbo!"
# strike all characters
::smm::showme [::string toupper $a]
# check if string contains Dumbo
::if {[::string match {*Dumbo*} $a]} {
::smm::showme "Ahh,.. a Dumbo string."
}
|
Evaluate an (mathematical) expression.
Syntax:
::expr arg ?arg arg ...?
Description:
- ::expr arg ?arg arg ...?
- Concatenates all args and executes the expression. This is the
handle for you to calculate mathematical expressions.
I urgently advise you to have a look at the tcl manual, as all
the possibilities of expr are explained there: e.g. string
operations, binary operations, logical operations, etc.,...
Example: |
::set sum [::expr 1 + 2 + 3 + 4]
|
Increment the value of a variable
Syntax:
::incr varName ?increment?
Description:
- ::incr varName ?increment?
- Increments the value stored in the variable whose name is varName. The
value of the variable must be an integer. If increment is supplied then its
value (which must be an integer) is added to the value of variable
varName; otherwise 1 is added to varName. The new value is stored as a
decimal string in variable varName and also returned as result.
Example: |
::set a 1
::incr a
::smm::showme "$a"
::set b [::incr a]
::smm::showme "$a -- $b"
|
This command delays execution of the script.
Syntax:
::after milliseconds
Description:
- ::after milliseconds
- milliseconds must be an integer giving a
time in milliseconds. The command sleeps for ms milliseconds and
then returns. While the command is sleeping the application does
not respond to events.
Example: |
# stop execution of the script for 5 seconds
::after 5000
|
Obtain and manipulate time
Syntax:
::clock clicks
::clock format clockValue
::clock scan dateString
::clock seconds
Description:
- ::clock clicks
- Return a high-resolution time value as a system-dependent integer
value. The unit of the value is system-dependent but should be the
highest resolution clock available on the system such as a CPU
cycle counter. This value should only be used for the relative
measurement of elapsed time.
- ::clock format clockValue
- Converts an integer time value, typically returned by clock
seconds, clock scan, or the atime, mtime, or ctime options of the
file command, to human-readable form. The output format can be
controlled via the -format argument. Please refer to the tcl manual.
- ::clock scan dateString
- Convert dateString to an integer clock value (see clock seconds).
This command can parse and convert virtually any standard date
and/or time string, which can include standard time zone
mnemonics. If only a time is specified, the current date is assumed.
For detailed information please refer to the tcl manual.
- ::clock seconds
- Return the current date and time as a system-dependent integer
value. The unit of the value is seconds, allowing it to be used for
relative time calculations. The value is usually defined as total
elapsed time from an ``epoch''. You shouldn't assume the value of
the epoch.
Example: |
::set seconds [::clock seconds]
::set timeString [::clock format $seconds]
::smm::showme "current time: $timeString"
|
|