- What are they?
- Basic principle
- Considerations
- Different implementations
- Arbitrary pair
- Positive and Negative
- Arbitrary number of values
- Examples: toggles in hotkeys
Toggles, as the name implies are a switch for a state. Is generally bound to turn on/off any given functionality. The most common usage is a binary 2-step toggle; non-binary and multiple-step toggles are less common but also seen.
You have a variable with a boolean value (1
/0
, true
/false
) and after you toggle it you change its value to the opposite state.
In Layman's terms: if the toggle is active, deactivate it; else vice versa.
test.ahk
toggle := false
if (toggle = true)
toggle := false
else
toggle := true
-
One toggle per functionality. If you have multiple functionalities that need the usage of a toggle use a variable for each one, otherwise unintended effects might occur (like one functionality left running and the other not starting).
-
Always initialize the variable. While this is not forcefully necessary is the right way to do it. If using the
#Warn
directive an alert will be shown stating that the variable is not initialized, also might be needed to start the toggle in the "on" state.-
This will show an alert:
test.ahk
#Warn if (toggle = true) toggle := false else toggle := true
-
This won't:
test.ahk
#Warn toggle := true if (toggle = true) toggle := false else toggle := true
-
We already checked the "lengthy" method that involves if
/else
combination, still, we have the:
-
test.ahk
toggle := 0 ; Integer values toggle := toggle = 1 ? 0 : 1 MsgBox % toggle ; Shows 1 ; Boolean values toggle := toggle = true ? false : true MsgBox % toggle ; Shows 0
-
test.ahk
toggle := false toggle := !toggle MsgBox % toggle ; Shows 1 toggle := !toggle MsgBox % toggle ; Shows 0
* Applies to all languages, not just scripting like AutoHotkey or JavaScript.
-
Exclusive OR (XOR):
test.ahk
toggle := 0 toggle ^= 1 MsgBox % toggle ; Shows 1 toggle ^= 1 MsgBox % toggle ; Shows 0
Sometimes values different than true
and false
are needed (eg yes
/no
, On
/Off
, 1
/2
, etc), those can be expressed with:
-
A ternary operator:
test.ahk
toggle = "Off" toggle := toggle = "On" ? "Off" : "On" MsgBox % toggle ; Shows "On" toggle := toggle = "On" ? "Off" : "On" MsgBox % toggle ; Shows "Off"
-
Or a tuple:
test.ahk
num := 2 num := [2,1][num] MsgBox % num ; Shows 1 num := [2,1][num] MsgBox % num ; Shows 2
Math is always a welcomed addition, makes it a breeze to swap values between a positive and its negative counterpart (eg, +1
/-1
):
test.ahk
num := 1
num *= -1
MsgBox % num ; Shows 1
num *= -1
MsgBox % num ; Shows -1
Bonus: display the +
sign:
test.ahk
num := 1
num *= -1
MsgBox % Format("{:+d}", num) ; Shows -1
num *= -1
MsgBox % Format("{:+d}", num) ; Shows +1
When cycling through different values there are many possible options, the most common are:
-
Having an array of the values, looping through them, validating on each iteration if we are past the last member, if so, start over.
test.ahk
sizes := ["s", "m", "l", "xl"] sizesPosition := 0 ; Last position loop 8 MsgBox % Cycle(sizes, sizesPosition) ; Shows: s, m, l, xl... s, m, l, xl... Cycle(obj, ByRef i) { if (obj.Count() = i) i := 1 else i += 1 return obj[i] } /* Compact form: Cycle(obj, ByRef i) { t := obj.Count() return obj[i += i = t ? 1 - t : 1] } */
-
Cycling through numbers starting in
0
or1
. Again, this relies on math (and the post-increment operator).test.ahk
index0 := 0 loop 6 MsgBox % "index0: " CycleFrom0(index0, 3) "`n" ; Shows: 0,1,2... 0,1,2... index1 := 1 loop 6 MsgBox % "index1: " CycleFrom1(index1, 3) "`n" ; Shows: 1,2,3... 1,2,3... CycleFrom0(ByRef var, total) { return var++ := Mod(var, total) } CycleFrom1(ByRef var, total) { return var++ := Mod(var + total - 1, total) + 1 }
This example uses F1 to toggle the swapping of the mouse buttons. As recommended, initialize the toggle before the end of auto-execute.
test.ahk
toggle := 0
return ; End of auto-execute
F1::toggle ^= 1
#If toggle
LButton::RButton
RButton::LButton
#If
The following example will place a ToolTip
that follows the pointer announcing the current time. It uses a different method for each of the hotkeys.
F1 uses a timer to avoid being blocked by an infinite loop (like the one in F2).
For F2 to be able to stop and avoid being stuck in the infinite loop, the #MaxThreadsPerHotkey is needed. Just bear in mind that the directive is positional so it will affect every hotkey declared below.
test.ahk
toggle := 0
return ; End of auto-execute
F1::
toggle ^= 1
SetTimer TimeNow, % toggle ? 1 : "Delete"
if (!toggle)
ToolTip
return
#MaxThreadsPerHotkey 2
F2::
toggle ^= 1
while (toggle)
TimeNow()
ToolTip
return
TimeNow() {
FormatTime now,, h:mm.ss tt
ToolTip % "It's: " now
}
Toggling the hotkey itself with native AHK functionality. In this case the Space will issue a message every time is pressed (you can toggle this with F1):
test.ahk
Space::MsgBox
F1::Hotkey Space, Toggle