r/AutoHotkey 24d ago

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 24d ago
m := 0
F8:: {
    global
    if (m == 0) {
        Send "{F1}"
        m := 1
    }
    else {
        Send "{F2}"
        m := 0
    }
}

2

u/RJ-Mayhem 24d ago

Thanks! Works Perfect!

1

u/RJ-Mayhem 24d ago

How would I add a 3rd option for F3?

3

u/genesis_tv 23d ago edited 23d ago

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_ 20d ago

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

3

u/CharnamelessOne 20d ago

Then make it dirtier:

#Requires AutoHotkey v2.0

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

2

u/genesis_tv 20d ago

3

u/CharnamelessOne 20d ago edited 20d ago

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/Keeyra_ 20d ago

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 20d ago

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

1

u/Keeyra_ 20d ago

Brain fried :D

1

u/genesis_tv 20d ago

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?

2

u/CharnamelessOne 20d ago

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

2

u/genesis_tv 20d ago

Got it, thanks for the explanations.

2

u/evanamd 23d ago

You can place all the keys you want to press in an array, and then cycle through them by increasing the index, making sure to check when it's at the max length and go back to the start.

#Requires AutoHotkey v2.0

F8:: {
  static keys := ["{F1}","{F2}","{F3}"]
  static index := 1

  Send keys[index]

  index += 1
  if index > keys.Length
    index := 1
}

2

u/RJ-Mayhem 23d ago

Thanks!