;========================= ;= Switch/Case functions = ;========================= ; DESCRIPTION: ; Checks a list of values against a defined variable and does something upon a match. ; Processing of Case() statements stops after the first match for any Switch(). ; Case() accepts wildcards in values, allows multiple values and chained actions. ; Actions can be run immediately upon match, or after the Switch is closed. ; ; Warning: Do NOT under any circumstances use any variables starting with "_Switch" ; in your script! Do not change any of the _Switch variables manually. Just ; call these functions instead to keep the vars synced. You have been warned... ; ; USAGE: ; Switch("myVar") ; Opens the switch ; Case("Value","Action") ; Checks Value against %MyVar% and runs Action on match ; Case(...) ; If it did not match, continue checking other cases ; Case("", "Action") ; Optional, a catch-all if there were no matches before ; Switch("myVar",0) ; Closes the switch (Switch() also closes current switch) ; ; Note: Easily check if a match was found in an open Switch() by closing it in an If statement: ; If Switch() { ; ... (switch had a match) ; } Else { ; ... (switch didn't have a match) ; } ; ; RETURN VALUES ; Switch(): 1 - opened ; [Value] - closed with match, returns the matching value ; 0 - closed without a match, or failed ; ; Case(): [Value] - Case() matched and returns the matching value ; 0 - No match, or no Switch() open ; ; VALUE/ACTION SYNTAX ; Case() is fairly robust. There are many ways to specify values and actions. ; ; VALUES (Don't forget the quotes!) ; - "Value[|Value2[|...]]" - Check for one or more values (separator: |) ; - "*Value" - Check for a string ending with "Value" (wildcard: *) ; - "Val*ue" - Check for a string starting with "Val" and ending with "ue" ; - "Value**" - Check for "Value*" (two *'s override the wildcard and display one) ; - "Value1||Value2" - Check for the string "Value1|Value2" (two |'s override "or" functionality) ; ; ACTIONS (Don't forget the quotes!) ; - "Label1[|Label2[|...]]" - Jump to one or any number of sub labels in your script (separator: |) ; - "Path\To\File.ahk", "[Parameters]" - Directly run an AHK or EXE file, optionally with parameters ; ^(Even if there are no parameters you must use empty quotes to load a file) ; ^(If this is .ahk and the script is compiled, it will first check for File.exe) ; - "*Label" - Upon a match, wait to jump to Label until the Switch() is closed. (* at beginning) ; ^(This works for running scripts/exe's, too) ; - "**Label" - Upon a match jump to *Label (two *'s override the "wait" functionality) ; ; NOTES ; Programs and labels can be chained together in the same Action ; You can jump to a label with another Switch() in it as long is uses a different variable name ; You can start another Switch() and come back to the first by re-calling Switch() for the first variable ; You can start a new Switch() with the same name of a closed Switch() since it no longer exists ; You can enter any code you'd like in-between Switch()'s and Case()'s, it will not interfere ; ; USAGE EXAMPLE ; Create a menu where all objects forward to a single gLabel containing ; a Switch() for the option clicked and a Case() for each option Switch(pVar="",pEnabled=1) { local thisSwitch, thisMatch, thisAction, thisWait, thisWaitParams thisSwitch := pVar ? pVar : _SwitchOpen If Not thisSwitch Return 0 thisMatch := _Switch%thisSwitch%_Match ; The matching value, or blank if no match thisWait := _Switch%thisSwitch%_Wait ; 1 to run the action upon closing of the switch, blank if the action ran immediately thisWaitParams := _Switch%thisSwitch%_Params ; The params to run if the action is a file If Not pVar or Not pEnabled { ; Evaluate then close the switch If thisWait ; Run the action now _Switch_Action(thisAction,thisParams) ; free the globals from oppression _Switch%thisSwitch% := _Switch%thisSwitch%_Val := _Switch%thisSwitch%_Match := _Switch%thisSwitch%_Action := _Switch%thisSwitch%_ActionParams := _Switch%thisSwitch%_Wait := _Switch%thisSwitch%_WaitParams := _SwitchOpen := "" ; This officially closes the switch Return thisMatch ; Return the matching value (true), or blank (false) if there was no match } ; Open the switch If (pEnabled != 2) { _Switch%thisSwitch%_Match := _Switch%thisSwitch%_Action := _Switch%thisSwitch%_ActionParams := _Switch%thisSwitch%_Wait := _Switch%thisSwitch%_WaitParams := "" _Switch%pVar%_Val := %pVar% ; Keep the % signs, we want to use thisSwitch's value } _Switch%pVar% := _SwitchOpen := pVar ; This officially opens the switch Return 1 } Case(pVal="", pAction="", pArgs="[[none]]"){ local thisFile, thisMatches, thisRegEx, thisLoopIndex, thisParams, thisVal If Not _SwitchOpen or _Switch%_SwitchOpen%_Match ; No switch open Return 0 ; Switch is open, there has not been a match yet If pVal { pVal := StringReplace(pVal, "||", "^<>^<>^<>^", "All") Loop, Parse, pVal, | { thisVal := A_LoopField thisVal := StringReplace(thisVal, "^<>^<>^<>^", "|", "All") If InStr(thisVal, "*") { ; Match as regex instead thisRegEx := StringReplace(thisVal, "\", "\\", "All") thisRegEx := StringReplace(thisRegEx, ".", "\.", "All") thisRegEx := StringReplace(thisRegEx, "**", "^<>^<>^<>^", "All") thisRegEx := StringReplace(thisRegEx, "*", ".*", "All") thisRegEx := StringReplace(thisRegEx, "^<>^<>^<>^", "*", "All") thisRegEx := StringReplace(thisRegEx, "?", "\?", "All") thisRegEx := StringReplace(thisRegEx, "+", "\+", "All") thisRegEx := StringReplace(thisRegEx, "[", "\[", "All") thisRegEx := StringReplace(thisRegEx, "{", "\{", "All") thisRegEx := StringReplace(thisRegEx, "|", "\|", "All") thisRegEx := StringReplace(thisRegEx, "(", "\(", "All") thisRegEx := StringReplace(thisRegEx, ")", "\)", "All") thisRegEx := StringReplace(thisRegEx, "^", "\^", "All") thisRegEx := StringReplace(thisRegEx, "$", "\$", "All") RegExMatch(_Switch%_SwitchOpen%_Val,"i)" . thisRegEx,thisMatches) ; thisMatches will be blank if no match } Else { If (thisVal = _Switch%_SwitchOpen%_Val) { ; Match! thisMatches := thisVal } Else thisMatches := 0 } } } Else thisMatches := 1 ; Treat as a catch-all If thisMatches { ; set globals and process action(s) _Switch%_SwitchOpen%_Match := thisMatches If pArgs != "[[none]]" _Switch%_SwitchOpen%_Type := 1 Else _Switch%_SwitchOpen%_Type := "" _Switch%_SwitchOpen%_Params := pArgs pAction := StringReplace(pAction, "||", "^<>^<>^<>^", "All") Loop, Parse, pAction, | { thisLoopIndex := A_Index pParams := StringReplace(pParams, "||", "^<>^<>^<>^", "All") Loop, Parse, pParams, | { If (A_Index = thisLoopIndex) { thisParams := A_LoopField Break } } If (SubStr(A_LoopField,1,1) = "*") { ; Queue the action to run when the switch closes If _Switch%_SwitchOpen%_Wait _Switch%_SwitchOpen%_Wait .= "|" _Switch%_SwitchOpen%_Wait .= SubStr(A_LoopField,2) If _Switch%_SwitchOpen%_WaitParams _Switch%_SwitchOpen%_WaitParams .= "|" _Switch%_SwitchOpen%_WaitParams .= thisParams } Else { ; Queue the action to run momentarily If _Switch%_SwitchOpen%_Action _Switch%_SwitchOpen%_Action .= "|" _Switch%_SwitchOpen%_Action .= A_LoopField If _Switch%_SwitchOpen%_ActionParams _Switch%_SwitchOpen%_ActionParams .= "|" _Switch%_SwitchOpen%_ActionParams .= thisParams } } If _Switch%_SwitchOpen%_Action ; Run the actions now _Switch_Action(_Switch%_SwitchOpen%_Action, _Switch%_SwitchOpen%_ActionParams) Return 1 } Else Return 0 } _Switch_Action(pAction,pParams="") { global thisActionNum := 0 Loop, Parse, pAction, | { thisAction := A_LoopField thisAction := StringReplace(thisAction, "^<>^<>^<>^", "||", "All") thisLoopIndex := A_Index Loop, Parse, pParams, | If (A_Index = thisLoopIndex) thisParams := A_LoopField If thisParams { ; Run the file If (SubStr(thisAction,StrLen(thisAction)-3) = "ahk") { If A_IsCompiled { ; check if an exe exists for the action instead If FileExist(SubStr(thisAction, 1, StrLen(thisAction) - 3) . ".exe") thisExeInstead := 1 } Else If Not A_AhkPath ; check if an exe exists for the action instead If FileExist(SubStr(thisAction, 1, StrLen(thisAction) - 3) . ".exe") thisExeInstead := 1 If thisExeInstead { thisAction := SubStr(thisAction, 1, StrLen(thisAction) - 3) . ".exe" Run, %thisAction% %thisParams% } Else Run, AutoHotKey.exe %thisAction% %thisParams%,%A_AhkPath% } Else Run, %thisAction% %thisParams% } Else { If InStr(thisAction, "(") { ; Call the function __expr(thisAction) Else If IsLabel(thisAction) { ; Go to the label GoSub,%thisAction% } thisActionNum++ } Return thisActionNum }