Created
January 20, 2020 23:40
-
-
Save stephenmm/6374ebff67a5538c9f2c2f0e6db0a198 to your computer and use it in GitHub Desktop.
Some basic utilities to .tcl a bit more bearable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
proc xdbg { } { puts $::errorInfo }; # This must be the first proc and be as simple as possible so we are always able to debug | |
# Define required globals | |
set ::xhelpMsgs [dict create] | |
set ::xVerbosity INFO | |
# Define the verbosity levels (based on python logging levels: https://verboselogs.readthedocs.io/en/latest/readme.html ) | |
set ::verbosityLevel [dict create] | |
dict append ::verbosityLevel NOTSET 0 ;# When a logger is created, the level is set to NOTSET (note that the root logger is created with level WARNING). This level isn?t intended to be used explicitly, however when a logger has its level set to NOTSET its effective level will be inherited from the parent logger. | |
dict append ::verbosityLevel DEVDBG 5 ;# Way too verbose for regular debugging, but nice to have when someone is getting desperate in a late night debugging session and decides that they want as much instrumentation as possible! :-) | |
dict append ::verbosityLevel DEBUG 10;# Detailed information, typically of interest only when diagnosing problems. Usually at this level the logging output is so low level that it?s not useful to users who are not familiar with the software?s internals. | |
dict append ::verbosityLevel VERBOSE 15;# Detailed information that should be understandable to experienced users to provide insight in the software?s behavior; a sort of high level debugging information. | |
dict append ::verbosityLevel INFO 20;# Confirmation that things are working as expected. | |
dict append ::verbosityLevel NOTICE 25;# Auditing information about things that have multiple success paths or may need to be reverted. | |
dict append ::verbosityLevel WARNING 30;# An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ?disk space low?). The software is still working as expected. | |
dict append ::verbosityLevel SUCCESS 35;# A very explicit confirmation of success. | |
dict append ::verbosityLevel ERROR 40;# Due to a more serious problem, the software has not been able to perform some function. | |
dict append ::verbosityLevel CRITICAL 50;# A serious error, indicating that the program itself may be unable to continue running. | |
############################################################# {{{ | |
proc xargExists { flag args } { | |
set helpText "Help text for proc: xargExists | |
Purpose: Short and sweet way to test if optional args were passed in: '--this' or '--that=type' | |
It will be one of the first things done in a proc. | |
Usage: xargExists flag argsRef | |
Inputs: flag: Flag to test existance for in the 'args' | |
argsRef: The list of args | |
Outputs: Flag exists, return 1 if flag is found in args | |
Flag not exists, return 0 if flag is not found in args | |
Side Effects: None other than pass by value args | |
Optional Args: None | |
Examples: if { \[xargExists --verb args] } { set verbose 1 } | |
" | |
dict append ::xhelpMsgs xargExists $helpText | |
#puts "flag:$flag args:$args" | |
set expectVal 0 | |
set cnt 0 | |
if { [string first "=" $flag] != -1 } { set expectVal 1 } | |
foreach arg $args { | |
if { $expectVal==1 } { | |
lassign [regexp -inline -- "^($flag)(\\w+)$" $arg] all flagFound val | |
} else { | |
lassign [regexp -inline -- "^($flag)(=\\w+)?$" $arg] all flagFound val | |
} | |
#puts "all:$all\t flagFound:$flagFound\t val:$val" | |
if { $flagFound != {} } { incr cnt } | |
} | |
return $cnt | |
} | |
proc _test_proc_xargExists {} { | |
proc _argExists_test { sigWithHier args } { | |
puts "sigWithHier:$sigWithHier\t args:$args" | |
puts [xargExists --val $args] | |
puts [xargExists --vala $args] | |
puts [xargExists --val= $args] | |
puts [xargExists --vala= $args] | |
} | |
_argExists_test hier.with.--sig --val | |
_argExists_test hier.with.--sig --val=1 | |
_argExists_test hier.with.--sig --vala | |
_argExists_test hier.with.--sig --vala=2 | |
} | |
############################################################# }}} | |
############################################################# {{{ | |
proc xputs { level str args } { | |
set helpText " | |
Purpose: Adding basic verbosity around .tcl puts. With the default level set to INFO | |
Usage: xputs <level> <string> \[<args>] | |
Inputs: level: In priority order: NOTSET DEVDBG DEBUG VERBOSE INFO NOTICE WARNING SUCCESS ERROR CRITICAL | |
string: string to print | |
Outputs: Retruns dict prvInf that contains information about the prove run | |
Side Effects: Creates sim directory and logs. Consumes CPU time and fpv licenses. Can be blocking or non-blocking | |
Optional Args: --help - Prints this help message. | |
--set_verbosity - Sets the minimum level that will be printed. | |
Examples: xputs INFO 'this would get printed by default' | |
xputs WARNING {} --set_verbosity | |
xputs INFO 'now you would not see this msg' | |
" | |
dict append ::xhelpMsgs xputs $helpText | |
if { [xargExists --help args] } { xhelp xputs; return 0; } | |
if {![dict exists $::verbosityLevel $level]} { | |
error "level:$level Is not a valid xverbosity level. Please use a valid level:" | |
foreach lvl [dict keys $::verbosityLevel] { puts -nonewline "$lvl,"; } | |
} | |
if { [xargExists --set_verbosity args] } { set ::xVerbosity [dict get $::verbosityLevel $level]; } | |
if { [dict get $::verbosityLevel $level] >= $::xVerbosity } { | |
puts "(XPUTS:$level) $str" | |
} | |
return $::xVerbosity | |
} | |
############################################################# }}} | |
############################################################# {{{ | |
proc xargPop { flag rtrnVar args } { | |
set helpText "Help text for proc: xargPop | |
Purpose: Short and sweet way to process proc args: '--this' or '--that=type' | |
It will be one of the first things done in a proc. | |
Usage: xargPop flag rtrnRef argsRef | |
Inputs: flag: Flag to find in args (extract value) and remove from args | |
rtrnRef: If --arg=val return the val in this reference | |
argsRef: The list of args | |
Outputs: Return the number of time flag was found in args (zero if not found) | |
Side Effects: Removes --falg from args reference | |
Optional Args: None | |
Examples: set verbose \[xargPop --verbose {} args] ;# Will set verbose to the number of times --verbose passed in | |
set tsk dfltTask; xargPop --setTask= tsk args | |
" | |
dict append ::xhelpMsgs xargPop $helpText | |
upvar $args upvarArgs | |
xputs DEVDBG "xargPop(1010): flag:$flag\t rtrnVar:$rtrnVar\t upvarArgs:$upvarArgs" | |
if { $rtrnVar != {} } { upvar $rtrnVar upvarRtrnVal } | |
set expectVal 0 | |
set i 0 | |
set cnt 0 | |
set delArgIdxs [list] | |
if { [string first "=" $flag] != -1 } { set expectVal 1 } | |
foreach arg $upvarArgs { | |
if { $expectVal==1 } { | |
lassign [regexp -inline -- "^($flag)(\\w+)$" $arg] all flagFound val | |
} else { | |
lassign [regexp -inline -- "^($flag)(=\\w+)?$" $arg] all flagFound val | |
} | |
xputs DEVDBG "xargPop(1020): arg:$arg\t all:$all\t flagFound:$flagFound\t val:$val" | |
if { $flagFound != {} } { | |
incr cnt | |
if { $rtrnVar != {} } { set upvarRtrnVal $val } | |
lappend delArgIdxs $i | |
} | |
incr i | |
} | |
xputs DEVDBG "xargPop(1030): args:$args\t upvarArgs:$upvarArgs\t rtrnVar:$rtrnVar" | |
foreach i [lreverse $delArgIdxs] { | |
set upvarArgs [lreplace $upvarArgs $i $i] | |
} | |
xputs DEVDBG "xargPop(1040): args:$args\t upvarArgs:$upvarArgs\t rtrnVar:$rtrnVar" | |
return $cnt | |
} | |
proc _test_proc_argPop {} { | |
proc _argPop_test { sigWithHier args } { | |
puts "_argPop_test(100):sigWithHier:$sigWithHier\t args:$args" | |
set myval {} | |
set argsCp $args | |
set rtn [xargPop --val {} argsCp] | |
puts "_argPop_test(101): $rtn myval: $myval args:$args argsCp:$argsCp" | |
set argsCp $args | |
set rtn [xargPop --val myval argsCp] | |
puts "_argPop_test(102): $rtn myval: $myval args:$args argsCp:$argsCp" | |
set argsCp $args | |
set rtn [xargPop --vala {} argsCp] | |
puts "_argPop_test(103): $rtn myval: $myval args:$args argsCp:$argsCp" | |
set argsCp $args | |
set rtn [xargPop --vala myval argsCp] | |
puts "_argPop_test(104): $rtn myval: $myval args:$args argsCp:$argsCp" | |
set argsCp $args | |
set rtn [xargPop --val= {} argsCp] | |
puts "_argPop_test(105): $rtn myval: $myval args:$args argsCp:$argsCp" | |
set argsCp $args | |
set rtn [xargPop --val= myval argsCp] | |
puts "_argPop_test(106): $rtn myval: $myval args:$args argsCp:$argsCp" | |
set argsCp $args | |
set rtn [xargPop --vala= {} argsCp] | |
puts "_argPop_test(107): $rtn myval: $myval args:$args argsCp:$argsCp" | |
} | |
_argPop_test hier.with.--sig --val | |
_argPop_test hier.with.--sig --val=1 | |
_argPop_test hier.with.--sig --vala | |
_argPop_test hier.with.--sig --vala=2 | |
_argPop_test hier.with.--sig --val=3 --val=4 | |
_argPop_test hier.with.--sig --val=5 --vala=6 --val | |
} | |
############################################################# }}} | |
############################################################# {{{ | |
proc xhelp { { prc {} } { str {} } } { | |
if {[string trim $prc] == ""} { | |
set helpText "Help text for proc: xhelp | |
Purpose: Procedure to display help for crus_utils_fv procs | |
Usage: xhelp \[<procName>] \[<helpString>] | |
Inputs: No inputs are required | |
Outputs: Retruns number of help msgs if successfully added or retrived help, 0 otherwise | |
Side Effects: Can append to ::xhelp | |
Optional Args: ProcName: The name of the procedure to display help on | |
helpString: Register new help msg (for advanced users only) | |
Examples: xhelp ;# Displays this msg and 'Purpose:' for procs that registered with xhelp | |
xhelp x_prove;# Displays help for x_prove | |
xhelp --add='Text to help end users' | |
" | |
puts -nonewline "$helpText" | |
puts "\nShort description/purpose for each of the procs that have help strings:" | |
foreach p [dict keys $::xhelpMsgs] { | |
set fullMsg [dict get $::xhelpMsgs $p] | |
lassign [regexp -inline -- "Purpose: +(\[^\\n]+)\\n" $fullMsg] fullMatch shortMsg | |
puts " $p purpose:\t$shortMsg"; | |
} | |
puts " " | |
} elseif { $prc == "--add" } { | |
# store a new help msg | |
set prc [lindex [info level -1] 0];# get the caller proc name | |
if {![dict exists $::xhelpMsgs $prc]} { | |
dict append ::xhelpMsgs $prc $str | |
} else { | |
puts "ERROR: trying to add a msg for a proc that already has one $prc" | |
return 0 | |
} | |
} else { | |
# Display proc help msg | |
if {[dict exists $::xhelpMsgs $prc]} { | |
puts "Help text for proc: $prc" | |
puts [dict get $::xhelpMsgs $prc] | |
} else { | |
puts "ERROR: No help msg is registered for the proc: $prc" | |
return 0 | |
} | |
} | |
return [dict size $::xhelpMsgs] | |
} | |
############################################################# }}} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment