cmdr
Check-in [d2a2bc511f]
Not logged in
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to tclconference@googlegroups.com
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Reworked the interaction for entry of scalar, and general calculation of the value - Show validation error message for proper feedback - Trap ^C properly, as done for the list-case already. Scalar was forgotten. - Report the ^C as 'undefined value' - Remember the undefined-ness and have additional attempts to retrieve the value abort early This prevents retries of computing the value where we cannot succeed. It also prevents additional attempts at interaction. Bumped version to 0.10.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:d2a2bc511f32ee5cbfb83b79a7f9ae0ef79b4fe3
User & Date: andreask 2013-11-04 17:38:54
Context
2013-11-04
22:44
Filled out docs for cmdr::config check-in: 2bb154df7f user: andreask tags: trunk
17:38
Reworked the interaction for entry of scalar, and general calculation of the value - Show validation error message for proper feedback - Trap ^C properly, as done for the list-case already. Scalar was forgotten. - Report the ^C as 'undefined value' - Remember the undefined-ness and have additional attempts to retrieve the value abort early This prevents retries of computing the value where we cannot succeed. It also prevents additional attempts at interaction. Bumped version to 0.10. check-in: d2a2bc511f user: andreask tags: trunk
2013-11-03
07:18
Updated embedded documentation check-in: b4bc5bcb6e user: aku tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to actor.tcl.

309
310
311
312
313
314
315
316

    ##
    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::actor 0.9







|
309
310
311
312
313
314
315
316

    ##
    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::actor 0.10

Changes to cmdr.tcl.

71
72
73
74
75
76
77
78
proc ::cmdr::interactive? {} {
    variable interactive
    return  $interactive
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr 0.9







|
71
72
73
74
75
76
77
78
proc ::cmdr::interactive? {} {
    variable interactive
    return  $interactive
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr 0.10

Changes to config.tcl.

1350
1351
1352
1353
1354
1355
1356
1357
    }

    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::config 0.9







|
1350
1351
1352
1353
1354
1355
1356
1357
    }

    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::config 0.10

Changes to help.tcl.

510
511
512
513
514
515
516
517

    return $categories
}


# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::help 0.9







|
510
511
512
513
514
515
516
517

    return $categories
}


# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::help 0.10

Changes to officer.tcl.

612
613
614
615
616
617
618
619
	myreplexit myhandler

    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::officer 0.9







|
612
613
614
615
616
617
618
619
	myreplexit myhandler

    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::officer 0.10

Changes to parameter.tcl.

102
103
104
105
106
107
108

109
110
111
112
113
114
115
...
644
645
646
647
648
649
650

651
652
653
654
655
656
657
...
929
930
931
932
933
934
935

936
937






938
939
940
941
942
943
944
945
946
947

948
949
950
951
952
953
954
...
957
958
959
960
961
962
963


964
965
966
967
968

969


970
971
972
973
974

975


976
977
978

979
980
981
982
983
984

985
986
987
988

989
990
991
992
993
994
995
....
1065
1066
1067
1068
1069
1070
1071

1072

1073
1074
1075



















1076
1077
1078


1079
1080
1081
1082
1083
1084
1085
....
1090
1091
1092
1093
1094
1095
1096

1097
1098
1099
1100
1101
1102
1103
....
1132
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
	my ExecuteSpecification $valuespec

	# Start with a proper runtime state. See also method 'reset'
	# for an exported variant with cleanup, for use by cmdr::config.
	set myhasstring no
	set mystring    {}
	set myhasvalue  no

	set myvalue     {}
	set mylocker    {}

	return
    }

    # # ## ### ##### ######## #############
................................................................................
    method forget {} {
	debug.cmdr/parameter {}
	# Clear a cached value.

	if {$myhasvalue} {
	    my ValueRelease $myvalue
	}

	set myhasvalue  no
	set myvalue     {}
	return
    }

    method options {} { 
	return [lsort -dict [dict keys $myflags]]
................................................................................
	#     This should not be possible actually, because of [R12],
	#     [C5], and [C6].
	#
	#
	# (6) FAIL. 

	if {$myhasvalue} {

	    return $myvalue
	}







	# Note that myvalidate and mygenerate are executed in this
	# scope, which implies the parameter instance namespace, which
	# implies access to the 'config' command, and thus the other
	# parameters. IOW, parameter generation and/or validation can
	# use the value of other parameters for their work. Catching
	# infinite loops so created are outside the scope of this
	# code.

	if {$myhasstring} {

	    # Specified on command line, string rep. Validate and
	    # transform to the int. rep.
	    #
	    # See "FillMissingValidation" on why we always have a
	    # validator command.

	    if {$myislist} {
................................................................................
		set myvalue {}
		foreach v $mystring {
		    lappend myvalue [{*}$myvalidate validate [self] $v]
		}
	    } else {
		set myvalue [{*}$myvalidate validate [self] $mystring]
	    }


	    my Value: $myvalue
	}

	if {!$stopinteraction && $myinteractive && [cmdr interactive?]} {
	    # Interaction.

	    my interact


	    return $myvalue
	}

	if {[llength $mygenerate]} {
	    # Generation callback. Result is int. rep.

	    my Value: [{*}$mygenerate [self]]


	}

	if {$myhasdefault} {

	    # A declared default value is the int. rep. No validation,
	    # no transform. Set it directly.
	    my Value: $mydefault
	}

	if {!$myisrequired} {

	    # Hardwired default int. rep if all else failed.
	    my Value: {}
	}


	my undefined!
    }

    method interact {{prompt {}}} {
	debug.cmdr/parameter {}
	# Note: ^C for prompt aborts system.
	#       ^C for list aborts loop, but not system.
................................................................................
	    debug.cmdr/parameter {/single}
	    # Prompt for a single value. We loop until a valid
	    # value was entered, or the user aborted. The latter
	    # aborts the whole operation. Completion is done through
	    # the chosen validation type.
	    set continue 1
	    while {$continue} {

		set continue 0

		set thestring [linenoise prompt \
				  -prompt $prompt \
				   -complete [::list {*}$myvalidate complete [self]]]



















		try {
		    set thevalue [{*}$myvalidate validate [self] $thestring]
		} trap {CMDR VALIDATE} {e o} {


		    set continue 1
		}
	    }

	    # Inlined 'set'. Modified to suit. No locking, nor lock
	    # check, nor forgetting, except release of a previous value.

................................................................................
	}
	return
    }

    # # ## ### ##### ######## #############

    method undefined! {} {

	debug.cmdr/parameter {}
	return -code error \
	    -errorcode {CMDR PARAMETER UNDEFINED} \
	    "Undefined: $myname"
    }

    method Value: {v} {
................................................................................

    variable myname mylabel mydescription \
	myisordered myiscmdline myislist myisrequired \
	myinteractive myprompt mydefault myhasdefault \
	mywhencomplete mywhenset mygenerate myvalidate \
	myflags mythreshold myhasstring mystring \
	myhasvalue myvalue mylocker mystopinteraction \
	myisdocumented myonlypresence myisdefered


    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::parameter 0.9







>







 







>







 







>


>
>
>
>
>
>










>







 







>
>





>

>
>





>
|
>
>



>






>




>







 







>

>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>







 







>







 







|
>






|
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
...
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
...
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
...
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
....
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
....
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
....
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
	my ExecuteSpecification $valuespec

	# Start with a proper runtime state. See also method 'reset'
	# for an exported variant with cleanup, for use by cmdr::config.
	set myhasstring no
	set mystring    {}
	set myhasvalue  no
	set myisundefined no
	set myvalue     {}
	set mylocker    {}

	return
    }

    # # ## ### ##### ######## #############
................................................................................
    method forget {} {
	debug.cmdr/parameter {}
	# Clear a cached value.

	if {$myhasvalue} {
	    my ValueRelease $myvalue
	}
	set myisundefined no
	set myhasvalue  no
	set myvalue     {}
	return
    }

    method options {} { 
	return [lsort -dict [dict keys $myflags]]
................................................................................
	#     This should not be possible actually, because of [R12],
	#     [C5], and [C6].
	#
	#
	# (6) FAIL. 

	if {$myhasvalue} {
	    debug.cmdr/parameter {/cached ==> ($myvalue)}
	    return $myvalue
	}

	# Do not run the whole value generation a second time, when
	# the first already failed.
	if {$myisundefined} {
	    my undefined!
	}

	# Note that myvalidate and mygenerate are executed in this
	# scope, which implies the parameter instance namespace, which
	# implies access to the 'config' command, and thus the other
	# parameters. IOW, parameter generation and/or validation can
	# use the value of other parameters for their work. Catching
	# infinite loops so created are outside the scope of this
	# code.

	if {$myhasstring} {
	    debug.cmdr/parameter {/user}
	    # Specified on command line, string rep. Validate and
	    # transform to the int. rep.
	    #
	    # See "FillMissingValidation" on why we always have a
	    # validator command.

	    if {$myislist} {
................................................................................
		set myvalue {}
		foreach v $mystring {
		    lappend myvalue [{*}$myvalidate validate [self] $v]
		}
	    } else {
		set myvalue [{*}$myvalidate validate [self] $mystring]
	    }

	    debug.cmdr/parameter {/user ==> ($myvalue)}
	    my Value: $myvalue
	}

	if {!$stopinteraction && $myinteractive && [cmdr interactive?]} {
	    # Interaction.
	    debug.cmdr/parameter {/interact begin}
	    my interact

	    debug.cmdr/parameter {/interact ==> ($myvalue)}
	    return $myvalue
	}

	if {[llength $mygenerate]} {
	    # Generation callback. Result is int. rep.
	    debug.cmdr/parameter {/generate begin}
	    set v [{*}$mygenerate [self]]
	    debug.cmdr/parameter {/generate ==> ($v)}
	    my Value: $v
	}

	if {$myhasdefault} {
	    debug.cmdr/parameter {/default ==> ($mydefault)}
	    # A declared default value is the int. rep. No validation,
	    # no transform. Set it directly.
	    my Value: $mydefault
	}

	if {!$myisrequired} {
	    debug.cmdr/parameter {/optional, empty}
	    # Hardwired default int. rep if all else failed.
	    my Value: {}
	}

	debug.cmdr/parameter {undefined!}
	my undefined!
    }

    method interact {{prompt {}}} {
	debug.cmdr/parameter {}
	# Note: ^C for prompt aborts system.
	#       ^C for list aborts loop, but not system.
................................................................................
	    debug.cmdr/parameter {/single}
	    # Prompt for a single value. We loop until a valid
	    # value was entered, or the user aborted. The latter
	    # aborts the whole operation. Completion is done through
	    # the chosen validation type.
	    set continue 1
	    while {$continue} {
		set abort 0
		set continue 0
		try {
		    set thestring [linenoise prompt \
				       -prompt $prompt \
				       -complete [::list {*}$myvalidate complete [self]]]
		} on error {e o} {
		    debug.cmdr/parameter {trapped $e}
		    debug.cmdr/parameter {options $o}

		    if {$e eq "aborted"} {
			debug.cmdr/parameter {/abort}
			# prevent system from taking which does not exist
			set abort 1
		    } else {
			# rethrow any other error
			return {*}$o $e
		    }
		}

		if {$abort} {
		    debug.cmdr/parameter {/break on ^C}
		    my undefined!
		}

		try {
		    set thevalue [{*}$myvalidate validate [self] $thestring]
		} trap {CMDR VALIDATE} {e o} {
		    debug.cmdr/parameter {trap $e}
		    puts "$e, ignored"
		    set continue 1
		}
	    }

	    # Inlined 'set'. Modified to suit. No locking, nor lock
	    # check, nor forgetting, except release of a previous value.

................................................................................
	}
	return
    }

    # # ## ### ##### ######## #############

    method undefined! {} {
	set myisundefined yes
	debug.cmdr/parameter {}
	return -code error \
	    -errorcode {CMDR PARAMETER UNDEFINED} \
	    "Undefined: $myname"
    }

    method Value: {v} {
................................................................................

    variable myname mylabel mydescription \
	myisordered myiscmdline myislist myisrequired \
	myinteractive myprompt mydefault myhasdefault \
	mywhencomplete mywhenset mygenerate myvalidate \
	myflags mythreshold myhasstring mystring \
	myhasvalue myvalue mylocker mystopinteraction \
	myisdocumented myonlypresence myisdefered \
	myisundefined

    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::parameter 0.10

Changes to private.tcl.

165
166
167
168
169
170
171
172
    variable myarguments mycmd myinit myconfig myhandler

    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::private 0.9







|
165
166
167
168
169
170
171
172
    variable myarguments mycmd myinit myconfig myhandler

    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::private 0.10

Changes to util.tcl.

58
59
60
61
62
63
64
65
    set res {}
    foreach str $list { lappend res [format "%-*s" $maxl $str] }
    return $res
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::util 0.9







|
58
59
60
61
62
63
64
65
    set res {}
    foreach str $list { lappend res [format "%-*s" $maxl $str] }
    return $res
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::util 0.10

Changes to validate.tcl.

317
318
319
320
321
322
323
324
325
    if {![file readable    $path]} {return 0}
    if {![file writable    $path]} {return 0}
    return 1
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::validate 0.9
return







|

317
318
319
320
321
322
323
324
325
    if {![file readable    $path]} {return 0}
    if {![file writable    $path]} {return 0}
    return 1
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::validate 0.10
return

Changes to vcommon.tcl.

105
106
107
108
109
110
111
112
113

    debug.cmdr/validate/common {= [join $candidates "\n= "]} 10
    return $candidates
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::validate::common 0.9
return







|

105
106
107
108
109
110
111
112
113

    debug.cmdr/validate/common {= [join $candidates "\n= "]} 10
    return $candidates
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::validate::common 0.10
return