2
votes

I’ve written script that contains numerous hotkeys (general structure is as below). I would like to create another one that when pressed displays a list of all of the hotkeys and their corresponding descriptions that the script contains in a nice, formatted table.

The formatting and display are tenuous since AutoHotkey’s output is limited to message-boxes, but possible. More problematic is getting the hotkeys and corresponding descriptions.

The hotkeys all call the same function with different arguments. I considered adding a variable to the function so that depending on the value, the function either performs the normal function when triggered by the normal hotkeys, or builds a string or something when triggered from the special display hotkey.

I cannot figure out a way to programmatically access the script’s hotkeys at all. I checked the docs and there don’t seem to be any A_ variables that can be used for this purpose, nor does the Hotkey command lend itself well (it can be used to test if a hotkey exists, but looping through the innumerable combinations is, at best, tedious).

Failed attempts:

  • I tried using Elliot’s suggestion of parsing the script itself (replacing the path with %A_ScriptFullPath%, and while it does work for a raw script, it does not when the script is compiled
  • I tried assigning the entire hotkey section of the script to a variable as a continuation section and then parsing the variable and creating hotkeys using the Hotkey command. This worked well right up until the last part because the Hotkey command cannot take arbitrary commands as the destination and requires existing labels.
  • The ListHotkeys command is not applicable because it only displays the hotkeys as plain text in the control window.

Does anyone know how I can display a list of the hotkeys and either their corresponding arguments or comments?


Example script:
SomeFunc(foobar)
{
  MsgBox %foobar%
}

         !^#A::SomeFunc("a") ; blah
 ^+NumpadMult::SomeFunc("c") ; blivet
        ^+!#`::SomeFunc("b") ; baz
      ^#Space::SomeFunc("d") ; ermahgerd
 …

Example desired “outputs”:

C+A+  W+ A   a    | C+ S+   NumpadMult  b
------------------+----------------------
C+A+S+W+ `   c    | C+   W+ Space       d

    or

Ctrl Alt Shift Win  Key         Action
-----------------------------------------
 ×    ×         ×   A           blah
 ×        ×         NumpadMult  baz
 ×    ×   ×     ×   `           blivet
 ×              ×   Space       ermahgerd

etc.
2

2 Answers

1
votes

The only thing I can think of is to read each line of your script individually and parse it. This code reads your script (script.ahk) one line at a time and parses it. This should get you started. Additionally, you could parse the line to check for the modifiers as well.

Loop
{
    FileReadLine, line, C:\script.ahk, %A_Index%
    if ErrorLevel
        break

    If Instr(line, "::")
    {
        StringSplit, linearray, line, ::,

        key := linearray1
        StringSplit, commandarray, linearray3, `;

        action := commandarray2

        hotkeyline := "key:  " . key . "`tAction:  " . action
        final .= hotkeyline . "`r"

    }
}
msgbox % final

return
0
votes

I found a solution. It is not perfect (or ideal), and hopefully a proper, built-in method will become available in the future, but it works well (enough) and for raw and compiled scripts.

What I did was to use the FileInstall command which tells the compiler to add a file to the executable (and extract it when run).

Sadly, the FileInstall command will not allow the use of variables for the source file, so I cannot simply include the script itself (FileInstall, %A_ScriptFullPath%, %A_Temp%\%A_ScriptName%, 1).

As a work-around, I ended up extracting all of the desired hotkeys to a second file which I then parse as Elliot suggested, then delete, and #Include at the end of my script (it must be at the end since hotkeys will terminate the autoexecute section).

;;;;; Test.ahk ;;;;;

; Add hotkey file to executable and extract to Temp directory at runtime
FileInstall, Hotkeys.ahk, %A_Temp%\Hotkeys.ahk, 1

Loop
{
  ;Read a line from the extracted hotkey script and quit if error
  FileReadLine, line, %A_Temp%\Hotkeys.ahk, %A_Index%
    if ErrorLevel
      break

  ;Trim whitespace
  line=%line%

  ; Parse the line as in Elliot’s answer, but with tweaks as necessary
  ParseHotkey(line)
  …
}

FileDelete, %A_Temp%\Hotkeys.ahk ; Delete the extracted script
DisplayHotkeys()                 ; I ended up bulding and using a GUI instead
#Include, Hotkeys.ahk            ; It is included at compile-time, so no A_Temp



;;;;; Hotkeys.ahk ;;;;;

z::MsgBox foo
y::MsgBox bar