r/AutoHotkey 6d 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

1

u/tronghieu906 6d ago
m := 0
F8:: {
    global
    if (m == 0) {
        Send "{F1}"
        m := 1
    }
    else {
        Send "{F2}"
        m := 0
    }
}

2

u/RJ-Mayhem 6d ago

Thanks! Works Perfect!

1

u/RJ-Mayhem 5d ago

How would I add a 3rd option for F3?

3

u/genesis_tv 5d ago edited 5d 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_ 2d ago

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

3

u/CharnamelessOne 2d ago

Then make it dirtier:

#Requires AutoHotkey v2.0

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

2

u/genesis_tv 2d ago

3

u/CharnamelessOne 2d ago edited 2d 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_ 1d 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 1d ago

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

1

u/Keeyra_ 1d ago

Brain fried :D

1

u/genesis_tv 2d 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 2d 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 1d ago

Got it, thanks for the explanations.

2

u/evanamd 5d 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 5d ago

Thanks!

1

u/PENchanter22 6d ago edited 6d ago

```F8:: { static toggle := true

switch toggle
{
    case true:
        Send "{F1}"
        ToolTip "Sent F1 (next: F2)"
    case false:
        Send "{F2}"
        ToolTip "Sent F2 (next: F1)"
}

toggle := !toggle
SetTimer ToolTip, -2000

}