- Still a versatile template parser
- A compact (254 sloc) wrapper for Tcl applications, with command-line and configuration-file parser
- An example of a real, live program written with Compact Code Formatting Style
Command-line parsing with active tokens and recursionThe initial command-line parser I used was a simple while loop; it makes use of the "shift" proc, which pops off an element of a list.
set params {} set cl $argv while {[llength $cl]} { set t [pop cl] switch -- $t { -h {usage; exit 0} -d {set ::loglevel [pop cl]} ... default {lappend params $t}}}This is a very simple-minded parser that requires all options and parameters to be separated by whitespace, consumes all arguments of the command line, and pushes everything that is not defined as option - arguments, hopefully - on a list for later usage. 'pop' is made in such a way that it always pops off an empty list from an empty list.Since 'while is bad' I wanted to do better and recurred to the intrinsic list processing feature of 'proc':
- every option is defined as a proc, consuming exactly the arguments it needs
- argv is processed recursively; there will not be thousands of switches on my command lines
proc options args {if [llength $args] {eval $args}}It is started with:
eval options $argvVery self-describing, isn't it? It has no syntax though, so let's make one:
proc -h args {usage; exit 0} proc -d loglevel {set ::loglevel $loglevel; eval options $args} ...If we 'eval options -d 4 -h' the following will happen:
- '-d' is called with parameters '4 -h', which sets ::loglevel to 4 and calls 'eval options -h'
- '-h' is called, which prints out the 'usage' message and goes home
proc unknown {param args} { lappend params $param; eval options $args}So Tcl handleslets put it together:
set params {} proc -h args {usage; exit 0} proc -d {loglevel args} {set ::loglevel $loglevel; eval options $args} # more options here ... proc options args {if [llength $args] {eval $args}} proc unknown {param args} { lappend ::params $param; eval options $args} eval options $argvWhile this is not really shorter than the while loop, it has some error handling built in, e.g., if you specify '-d' without a following argument, Tcl personally rants: 'wrong # args: should be "-d loglevel args"'If you specify 'set ::loglevel 8' on the command line, you get it set to 8, because the 'parameter' set is not unknown. So if you want to avoid Tcl code 'injection' from the command line you better run the parser inside a slave interpreter with only the -option commands.The command-line parser in TTP is much more elaborate, to account for some of such pitfalls. It also makes use of code introspection to generate the 'usage' message automatically. How this? In the two above examples of -option procedures you see that the argument list (minus 'args') shows as directly the number (and connotation) of the arguments of a command-line option. We can get a list of options with 'info procs -*' and the argument list of a specific option with e.g. 'info args -d'.Tcl does not supported procedure comments like, e.g., in some lisp dialects; however you could cope with this by defining your options this way:
proc -h args {# give usage message usage; exit 0}Then you can get to the option comment with 'lindex [split [info body -h] \n] 0'; of course you need to strip off the '# ' in front of the comment. From all this you can create lines like:
-h .. give usage message -d loglevel .. set loglevlelautomatically. If you add an option, you automatically get it added to the usage message.LEG
Category Application | Category Template