Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

About getopt and switch 1

Status
Not open for further replies.

dewei

Programmer
Jun 8, 2022
2
TW
I have a code, if they match opt, then print opt-content
But result is not my expected:
How do I solved it?
I type:
$tclsh t.tcl -B bb -O oo
I got:

bb
bb
oo
--------
Non
--------
oo
bb
oo
--------
Non
--------

My code

package require cmdline

set parameters {
{B.arg "" "Build Dir"}
{O.arg "" "Output Dir"}
}

array set arg [cmdline::getoptions argv ${parameters}]

set requiredParameters {B O }
foreach iter ${requiredParameters} {
if {$arg(${iter}) == ""} {
error "Missing required parameter: -${iter}"
} else {
puts $arg(${iter})
puts $arg(B)
puts $arg(O)
puts "--------"
switch $arg(${iter}) {
$arg(B) {
puts $arg(${iter})
}
$arg(O) {
puts $arg(${iter})
}
default {
puts "Non"
}
}
puts "--------"
}
}
 
There are two versions of switch statement in Tcl (see:
1) unbraced switch
[pre]switch ?options? string pattern body ?pattern body ...?[/pre]

2) braced switch
[pre]switch ?options? string {pattern body ?pattern body ...?}[/pre]

In the code you posted, you are unfortunately using the braced switch, where no variable substitutions on patterns are performed, i.e. $arg(B) or $arg(O) does not work here.

Use instead the unbraced switch.
 
Here is an example which shows the diffrence between braced and unbraced switch
dewei.tcl
Code:
[COLOR=#a52a2a][b]package[/b][/color] require cmdline

[COLOR=#a52a2a][b]set[/b][/color] parameters {
  {B.arg [COLOR=#ff00ff]""[/color] [COLOR=#ff00ff]"Build Dir"[/color]}
  {O.arg [COLOR=#ff00ff]""[/color] [COLOR=#ff00ff]"Output Dir"[/color]}
}

[COLOR=#a52a2a][b]array[/b][/color] [COLOR=#a52a2a][b]set[/b][/color] arg [cmdline::getoptions argv [COLOR=#008b8b]${parameters}[/color]]

[COLOR=#a52a2a][b]set[/b][/color] requiredParameters {B O}

[COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"* using braced switch - no variable substitutions are performed:"[/color]
[COLOR=#a52a2a][b]foreach[/b][/color] iter [COLOR=#008b8b]${requiredParameters}[/color] {
  [COLOR=#a52a2a][b]if[/b][/color] {[COLOR=#008b8b]$arg[/color]([COLOR=#008b8b]${iter}[/color]) == [COLOR=#ff00ff]""[/color]} {
    [COLOR=#a52a2a][b]error[/b][/color] [COLOR=#ff00ff]"Missing required parameter: -[/color][COLOR=#008b8b]${iter}[/color][COLOR=#ff00ff]"[/color]
  } [COLOR=#a52a2a][b]else[/b][/color] {
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#6a5acd]\$[/color][COLOR=#ff00ff]iter =  [/color][COLOR=#6a5acd]\"[/color][COLOR=#008b8b]$iter[/color][COLOR=#6a5acd]\"[/color][COLOR=#ff00ff]"[/color]
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#6a5acd]\$[/color][COLOR=#ff00ff]arg([/color][COLOR=#6a5acd]\$[/color][COLOR=#ff00ff]{iter}) = [/color][COLOR=#6a5acd]\"[/color][COLOR=#008b8b]$arg[/color][COLOR=#ff00ff]([/color][COLOR=#008b8b]${iter}[/color][COLOR=#ff00ff])[/color][COLOR=#6a5acd]\"[/color][COLOR=#ff00ff]"[/color]
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#6a5acd]\$[/color][COLOR=#ff00ff]arg(B) = [/color][COLOR=#6a5acd]\"[/color][COLOR=#008b8b]$arg[/color][COLOR=#ff00ff](B)[/color][COLOR=#6a5acd]\"[/color][COLOR=#ff00ff]"[/color]
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#6a5acd]\$[/color][COLOR=#ff00ff]arg(O) = [/color][COLOR=#6a5acd]\"[/color][COLOR=#008b8b]$arg[/color][COLOR=#ff00ff](O)[/color][COLOR=#6a5acd]\"[/color][COLOR=#ff00ff]"[/color]
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"--------"[/color]
    [COLOR=#a52a2a][b]switch[/b][/color] [COLOR=#008b8b]$arg[/color]([COLOR=#008b8b]${iter}[/color]) {
      [COLOR=#008b8b]$arg[/color](B) {[COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#008b8b]$arg[/color]([COLOR=#008b8b]${iter}[/color])}
      [COLOR=#008b8b]$arg[/color](O) {[COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#008b8b]$arg[/color]([COLOR=#008b8b]${iter}[/color])}
      [COLOR=#a52a2a][b]default[/b][/color] {[COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"Non: [/color][COLOR=#008b8b]$arg[/color][COLOR=#ff00ff]([/color][COLOR=#008b8b]${iter}[/color][COLOR=#ff00ff])"[/color]}
    }
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"--------"[/color]
  }
}
[COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]" "[/color]

[COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"* using unbraced switch - with variable substitutions:"[/color]
[COLOR=#a52a2a][b]foreach[/b][/color] iter [COLOR=#008b8b]${requiredParameters}[/color] {
  [COLOR=#a52a2a][b]if[/b][/color] {[COLOR=#008b8b]$arg[/color]([COLOR=#008b8b]${iter}[/color]) == [COLOR=#ff00ff]""[/color]} {
    [COLOR=#a52a2a][b]error[/b][/color] [COLOR=#ff00ff]"Missing required parameter: -[/color][COLOR=#008b8b]${iter}[/color][COLOR=#ff00ff]"[/color]
  } [COLOR=#a52a2a][b]else[/b][/color] {
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#6a5acd]\$[/color][COLOR=#ff00ff]iter =  [/color][COLOR=#6a5acd]\"[/color][COLOR=#008b8b]$iter[/color][COLOR=#6a5acd]\"[/color][COLOR=#ff00ff]"[/color]
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#6a5acd]\$[/color][COLOR=#ff00ff]arg([/color][COLOR=#6a5acd]\$[/color][COLOR=#ff00ff]{iter}) = [/color][COLOR=#6a5acd]\"[/color][COLOR=#008b8b]$arg[/color][COLOR=#ff00ff]([/color][COLOR=#008b8b]${iter}[/color][COLOR=#ff00ff])[/color][COLOR=#6a5acd]\"[/color][COLOR=#ff00ff]"[/color]
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#6a5acd]\$[/color][COLOR=#ff00ff]arg(B) = [/color][COLOR=#6a5acd]\"[/color][COLOR=#008b8b]$arg[/color][COLOR=#ff00ff](B)[/color][COLOR=#6a5acd]\"[/color][COLOR=#ff00ff]"[/color]
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#6a5acd]\$[/color][COLOR=#ff00ff]arg(O) = [/color][COLOR=#6a5acd]\"[/color][COLOR=#008b8b]$arg[/color][COLOR=#ff00ff](O)[/color][COLOR=#6a5acd]\"[/color][COLOR=#ff00ff]"[/color]

    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"--------"[/color]
    [COLOR=#a52a2a][b]switch[/b][/color] [COLOR=#008b8b]$arg[/color]([COLOR=#008b8b]${iter}[/color]) [COLOR=#ff0000]\[/color]
      [COLOR=#008b8b]$arg[/color](B) {[COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#008b8b]$arg[/color]([COLOR=#008b8b]${iter}[/color])} [COLOR=#ff0000]\[/color]
      [COLOR=#008b8b]$arg[/color](O) {[COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#008b8b]$arg[/color]([COLOR=#008b8b]${iter}[/color])} [COLOR=#ff0000]\[/color]
      [COLOR=#a52a2a][b]default[/b][/color] {[COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"Non: [/color][COLOR=#008b8b]$arg[/color][COLOR=#ff00ff]([/color][COLOR=#008b8b]${iter}[/color][COLOR=#ff00ff])"[/color]}
    [COLOR=#a52a2a][b]puts[/b][/color] [COLOR=#ff00ff]"--------"[/color]
  }
}

Output:
Code:
$ tclsh dewei.tcl -B bb -O oo
* using braced switch - no variable substitutions are performed:
$iter =  "B"
$arg(${iter}) = "bb"
$arg(B) = "bb"
$arg(O) = "oo"
--------
Non: bb
--------
$iter =  "O"
$arg(${iter}) = "oo"
$arg(B) = "bb"
$arg(O) = "oo"
--------
Non: oo
--------
 
* using unbraced switch - with variable substitutions:
$iter =  "B"
$arg(${iter}) = "bb"
$arg(B) = "bb"
$arg(O) = "oo"
--------
bb
--------
$iter =  "O"
$arg(${iter}) = "oo"
$arg(B) = "bb"
$arg(O) = "oo"
--------
oo
--------
 
Hi @mikrom:
Many thanks!!
The devil hides in the details.

The braced switch seems to create a new namespace, which isolate outside variable.
 
I like 'tepam' package from tcllib.

With tepam, I can avoid manual validatin of parameters.

For example - simple cli application:

Code:
package require tepam
::tepam::procedure {build_script} {
    -return "This procedure return code of build result"
    -short_description "build program"
    -description "This procedure build selected project"
    -args {
        {B -description "build dir"  -type existingdirectory -mandatory}
        {O -description "output dir" -type existingdirectory -mandatory}
        {-f -description "path to Makefile" -type existingfile -optional}
    }
    -named_arguments_first 0
    -example {do_something ~/projects/some_project /tmp/build_dir
        do_something ~/projects/some_project /tmp/build_dir -f Makefile.special
    }
} {
    puts "build file 1"
    puts "build file 2"
    return -code ok "SUCCESS";
}

if {$argc == 0} {build_script -help; exit};
puts [build_script {*}$argv];

This code. started directly, produce output:
Code:
NAME
      build_script - build program
SYNOPSIS
      build_script
            <B>
               build dir, type: existingdirectory
            <O>
               output dir, type: existingdirectory
            [-f <f>]
               path to Makefile, type: existingfile
DESCRIPTION
      This procedure build selected project
EXAMPLE
      build_script ~/projects/some_project /tmp/build_dir
      build_script ~/projects/some_project /tmp/build_dir -f Makefile.special

Example of output when all parameters correct (directories are present in filesystem)
Code:
$ tclsh build_script.tcl -- ~/projects /tmp
build file 1
build file 2
SUCCESS

Example of output when directory /tmp/12 does not eists in the filesystem:
Code:
$ tclsh build_script.tcl -- ~/projects/some_project /tmp/build_dir
do_something: Argument 'O' requires type 'existingdirectory'. Provided value: '/tmp/12'
    while executing
"do_something {*}$argv"
    invoked from within
"puts [do_something {*}$argv]"
    (file "test.tcl" line 22)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top