Skip to content

Instantly share code, notes, and snippets.

@LeoDupont
Last active November 15, 2020 13:14
Show Gist options
  • Save LeoDupont/70d199c5cfa6b9206a41c6257d959655 to your computer and use it in GitHub Desktop.
Save LeoDupont/70d199c5cfa6b9206a41c6257d959655 to your computer and use it in GitHub Desktop.
Vim-like "Leader Key" implementation with Autohotkey
; To organize commands into "categories".
; With a little tooltip to help keeping track.
; === The Helper function ===
; - displays the tooltip
; - waits for the expected input
; - calls the "Menu function" if it exists (just a shortcut for menus which use a dedicated function)
; - or returns the input
;
; Parameters:
; - name: Display name for the tooltip
; - options: variadic parameters that can be either:
; - a single string
; - or a two-or-three-length array with the format:
; [
; "chars to type",
; "Description (and Menu function suffix if applicable)",
; "SendInput content (optional)"
; ]
WaitForChoice(name, options*) {
; === Building the Tooltip string, EndKeys parameter, and choices dictionary (for Menu functions) ===
tooltipStr := name . "`n"
menuFunctionsDict := {} ; Dictionary of "Menu functions" suffixes per choice (option[2])
sendInputDict := {} ; Dictionary of "SendInput" per choice (option[3])
for i, option in options {
if (option Is Alpha) {
; Single strings, without description:
tooltipStr .= "+ " . option
endKeys .= option
menuFunctionsDict[option] := option
}
else {
; Two-or-three-length array, with description and posisbly SendInput content:
tooltipStr .= "+ " . option[1] . " => " . option[2]
endKeys .= option[1]
menuFunctionsDict[option[1]] := option[2]
sendInputDict[option[1]] := option[3]
}
if (i < options.MaxIndex()) {
tooltipStr .= "`n"
endKeys .= ","
}
}
; === Tooltip + Wait for input ===
Tooltip %tooltipStr%
Input choice, , {Pause}{Esc}{Enter}, %endKeys%
; === Quick interpretations ===
toSend := sendInputDict[choice]
menuFunc := "Menu_" . menuFunctionsDict[choice]
; --- SendInput (option[3]) ---
if (StrLen(toSend) > 0) {
SendInput % toSend
}
; --- Menu function (option[2]) ---
else if (IsFunc(menuFunc)) {
%menuFunc%()
}
Return choice
}
; === The Leader Hotkey ===
Pause::
; Main menu:
; Each menu has its own function (see below)
WaitForChoice("Macros"
, ["t", "Tests"]
, ["w", "Windows"]
, ["m", "Mails"])
ToolTip,
Return
; === Menu functions ===
; (To keep it simple, only the top-level menus have their own functions,
; but there is no limitation: "switch cases" and "menu functions" are interoperable at every level)
Menu_Tests() {
choice := WaitForChoice("t (Tests)", "1", "2")
switch choice {
case "1": SendInput Test text 1
case "2": SendInput Test text 2
}
}
Menu_Windows() {
choice := WaitForChoice("w (Window)", ["max", "Maximize"], ["r", "Restore"])
switch choice {
case "max": WinMaximize A
case "r": WinRestore A
}
}
Menu_Mails() {
WaitForChoice("m (Mails)"
, ["p", "Pro", "pro@mail.com"]
, ["h", "Hobby", "hobby@mail.com"])
}

Leader Hotkey

This is a very simple implementation of Vim's and QMK's "Leader Key" feature (see https://thomasbaart.nl/2018/12/20/qmk-basics-leader-key/).

The "Leader Hotkey", once triggered, allows us to type a sequence of keys instead of pressing multiple keys at once to get a shortcut.

Example: we could type {Pause}, then {W}, and then {R} to call the WinRestore function.

This Gist will cover:

  • simple-leader-hotkey.ahk: The most simple way to achieve this (Proof of Concept).
  • advanced-leader-hotkey.ahk An "advanced" pattern to help organize commands into "categories" (ex: "W" for Window Management, "M" for Mail addresses...) and display a helping tooltip.

We will use the {Pause} key as an example of Leader Hotkey (but it could be anything that Autohotkey supports).

; The most simple implementation, just to get the gist of it...
Pause::
; Wait for either of "t1", "t2", "wmax", "wr", or "mp" to be typed (the "EndKeys" parameter)
; The {Esc} key can be used to cancel the waiting (the "StopKeys" parameter)
Input, choice, , {Esc}, t1,t2,wmax,wr,mp
; Action, depending on the "hidden input"
switch choice {
case "t1": SendInput Test text 1
case "t2": SendInput Test text 2
case "wmax": WinMaximize A
case "wr": WinRestore A
case "mp": SendInput pro@mail.com
}
Return
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment