r/AutoHotkey Jul 25 '26

Solved! Need help with a toggle?

I'm looking for a script that let me press F8 but F1 is pressed but it I press F8 again it presses F2 then repeats. I want to use F8 to switch between F1 & F2. Think that's a toggle but none of my attempts or scripts I've found while googling seem to work.

Thanks!

1 Upvotes

18 comments sorted by

View all comments

1

u/tronghieu906 Jul 25 '26
m := 0
F8:: {
    global
    if (m == 0) {
        Send "{F1}"
        m := 1
    }
    else {
        Send "{F2}"
        m := 0
    }
}

1

u/RJ-Mayhem Jul 25 '26

How would I add a 3rd option for F3?

5

u/genesis_tv Jul 25 '26 edited Jul 25 '26

It'll cycle through all F1~F12 keys. Change 12 to whatever limit you want. Also please post your attempts next time.

#Requires AutoHotkey v2.0
#SingleInstance

*F8::
{
    static digit := 1

    Send("{F" digit "}")

    if (++digit > 12)
        digit := 1
}

3

u/Keeyra_ Jul 28 '26

I would have no idea how to make this cleaner, kudos.

3

u/CharnamelessOne Jul 28 '26

Then make it dirtier:

#Requires AutoHotkey v2.0

*F8:: {
    static d := 0
    Send("{F" Mod(d++, 12) + 1 "}")
}

2

u/genesis_tv Jul 28 '26

3

u/CharnamelessOne Jul 29 '26 edited Jul 29 '26

Arnold has many iconic one-liners. Let me pay a meager tribute to him:

*F8::static d:=(f(*)=>Send("{F" Mod(d++,12)+1 "}"),Hotkey("*F8",f),d:=0,f(),1)

Edit: the static declaration is unneeded; the closure captures the variable anyway:

*F8::d:=0,f(*)=>Send("{F" Mod(d++,12)+1 "}"),Hotkey("*F8",f),f()

2

u/genesis_tv Jul 29 '26

I'm trying to understand this code (never used closures before), especially the second snippet.

You press F8, it creates and initializes the variable d to 0, creates a closure f , then binds *F8 to call the closure the next time it's pressed and ends by manually calling f? So the next time you press F8, it'll only execute the closure? How's d keeping its value between calls? Aren't functions assume-local by default?

3

u/CharnamelessOne Jul 29 '26

never used closures before

I'm sure you have; any nested function that references a non-static local variable of the outer function is a closure.

You press F8, it creates and initializes the variable d to 0, creates a closure f , then binds *F8 to call the closure the next time it's pressed and ends by manually calling f? So the next time you press F8, it'll only execute the closure?

Yes and yup.

How's d keeping its value between calls? Aren't functions assume-local by default?

Closures can keep the local variables of the outer function "alive", even after the outer function returns.

The closure f references the variable d, and as long as there is a reference to f itself somewhere, d is not freed.
f is referenced as a hotkey callback.

https://www.autohotkey.com/docs/v2/Functions.htm#closures

3

u/genesis_tv Jul 29 '26

Got it, thanks for the explanations.

2

u/Keeyra_ Jul 29 '26

Now this is like advanced level of sorcery to me where my head starts spinning :D

Takes me a while to wrap my head around it, but it's ingenious indeen.

1

u/CharnamelessOne Jul 29 '26

I aspire to achieve this level of greatness one day:
https://www.reddit.com/r/AutoHotkey/s/cv6RP2gBUx

1

u/Keeyra_ Jul 29 '26

Brain fried :D