tclcmdline-args

TCL: use "help" option from cmdline package


In my TCL script I am trying to provide input argument which will be parsed using 'cmdline' package. I have defined the following in my script:

set run_options {
{input_1.arg 8 "first input argument"}
{input_2.arg 1 "second input argument"}
{msb  "choose it if input data has msb first"}
{lsb  "choose it if input data has lsb first"}
}
set my_usage ": \n tclsh my_src \[options] ...\noptions are:"

if {[catch {array set params [::cmdline::getoptions argv $run_options $my_usage]} msg]} {
 puts "Error while parsing user options of $msg"
 exit 1

}

everything look fine except that when running my script I figured out that the 'cmdline' package defines "help" option by default, but when I run my script with "-help" option the following is the output:

Error while parsing user options of my_src : 
 tclsh my_src [options] ...
options are:
 -input_1 value       first input argument <8>
 -input_2 value       second input argument <1>
 -msb                 choose it if input data has msb first
 -lsb                 choose it if input data has lsb first
 --                   Forcibly stop option processing
 -help                Print this message
 -?                   Print this message

so, does anyone know how to use this automatically added "help" option without giving error message?


Solution

  • cmdline::getoptions doesn't differentiate between -help and an unknown option (An unrecognized option is treated like it was -?). If you want to have different messages for the two cases, you need to use one of the the lower level functions directly in a loop, or something like the following enhanced version of cmdline::getoptions:

    #!/usr/bin/env tclsh
    package require try ;# In case you're still using tcl 8.5 for some reason
    package require cmdline 1.5
    
    proc better_getoptions {arglistVar optlist usage} {
        upvar 1 $arglistVar argv
        # Warning: Internal cmdline function
        set opts [::cmdline::GetOptionDefaults $optlist result]
        while {[set err [::cmdline::getopt argv $opts opt arg]]} {
            if {$err < 0} {
                return -code error -errorcode {CMDLINE ERROR} $arg
            }
            set result($opt) $arg
        }
        if {[info exists result(?)] || [info exists result(help)]} {
            return -code error -errorcode {CMDLINE USAGE} \
                [::cmdline::usage $optlist $usage]
        }
        return [array get result]
    }
    
    set run_options {
        {input_1.arg 8 "first input argument"}
        {input_2.arg 1 "second input argument"}
        {msb  "choose it if input data has msb first"}
        {lsb  "choose it if input data has lsb first"}
    }
    set my_usage ": \n tclsh my_src \[options] ...\noptions are:"
    
    try {
        array set params [better_getoptions argv $run_options $my_usage]
        puts "All options valid"
    } trap {CMDLINE USAGE} {msg} {
        puts stderr $msg
        exit 0
    } trap {CMDLINE ERROR} {msg} {
        puts stderr "Error: $msg"
        exit 1
    }
    

    Example usage:

    $ ./example.tcl --help
    cmd : 
     tclsh my_src [options] ...
    options are:
     -input_1 value       first input argument <8>
     -input_2 value       second input argument <1>
     -msb                 choose it if input data has msb first
     -lsb                 choose it if input data has lsb first
     --                   Forcibly stop option processing
     -help                Print this message
     -?                   Print this message
    $ ./example.tcl -foo
    Error: Illegal option "-foo"
    $ ./example.tcl -input_1
    Error: Option "input_1" requires an argument
    $ ./example.tcl -msb
    All options valid