torazaemon2016’s blog

手書き文字認識メモ開発

AutohotkeyのスクリプトからHotkeyやHotstringsの一覧表示を作成しダブルクリックでエディタ画面の該当行に行けるahkスクリプト

はじめに

Autohotkeyのおかげで快適なWindows生活を送ることができて、大変感謝しています。 しかし、Autohotkeyも、どんどん定義していくと、なにがどれだったかわからなくなったりしていきます。

そこで、Hotkeyの一覧が表示できるahkスクリプトを作成しました。

ListViewなので、タイトル行の「Key」とかをクリックすれば、ソートされるので、複数のファイルに分かれた定義での重複なども分かりやすくなりました。

Hotkey一覧表示例

Hotstrings表示例

Keyword: ahk, V2, Hotkey, Hotstrings, 一覧表示, VScode

Hotkeyの一覧表示が可能なものを探しましたが

ListHotkeys

Autohotkeyの「ListHotkeys」で一覧は出せますが、それの説明はないので、定義済みっていうことだけは、わかる。

Output list of all hotkeys used in ahk

Output list of all hotkeys used in ahk : r/AutoHotkey

V2のもので、起動するとカーソルのある位置に黒い箱でHotkeyの行が提示されるようになります。

でも、「!4」や日本語キーボードの無変換キーを使った「vk1D & 4::」などがうまく表示されていません。 いろいろと手を入れれば可能と思いますが。。。

Hotkey Help - Display Active AHK Hotkeys and Hotstrings

https://www.autohotkey.com/board/topic/93889-hotkey-help-display-active-ahk-hotkeys-and-hotstrings/

Autohotkey V1で動くもの

Win + F1 で起動したけど、Hotkey定義が殆ど出てこなかった。

Hotキーが(Shift,Alt,Ctrl,Win)決め打ちっぽいところもあるので、 Hotkeyを(日本語キーボードの)vk1C,vk1Dとかでやっているようだと、ダメっぽい。

HotKey Tool

GitHub - kunkel321/HotKey-Tool: A tool to list, filter, and launch hotkeys from running scripts.

これは、一覧を出せるし、「!g」の行をダブルクリックすると「実行」できるものです。

このほかにも、WindowsのスタートメニューなどからLinkとかも拾ってきたり、 ICON表示もあって「ラウンチャー」として使えるものなのです。

が、vk1D & のものが実行できなかったので、一覧表示というなら使えるかです。

AutoHotkeyのコメントからヘルプを作成する

https://qiita.com/draganmaistir/items/36bd90fa6c5a93736c70

これが、Hotkeyの一覧表示としてはわかりやすいものでした。

でもこれも、V1のスクリプトなので、その環境が要ること。 また、ahkスクリプト中に「指定の形式でコメント」を書いて表示するものなので、ちょっと手間がかかるものです。

なので結局、自分で作ることにしました。

作ったもの

  • 書かれているスクリプトをそのまま使って、そこからHotkeyなどを見つけて一覧にする。
  • Hotkeyの定義は「 :: 」が目印。
  • 定義と同じ行に 「 ; 」以降のコメントとして書かれたものを説明文として表示する。 vk1D & q::  ; 迷子になったカーソルを見つける

  • 一覧表示されている行を(ダブル)クリックすると、エディタのその該当行のところに飛ぶ

  • Hotstringsもtype:Hotstringsとして一覧となる。
  • 関数定義もtype:Functionとして一覧に載せる。関数の定義は、行頭からアルファベットで始まり()があり ^[a-zA-Z].*\(.*\) 、 := の記載のない行です。
  • コメントアウトしたHotkeyも一覧にtype:commentoutとして載ります。条件は行の先頭に「;」(セミコロン)が入っている「::」の行です。
  • Include も一覧にして、どのファイルをIncludeしているかもわかるようにしました。
  • 起動するたびに一覧ウィンドウが増えていくので、適宜Closeしてください。

と、「編集作業のヘルプ」としての要素が強いものになりました。

スクリプト

editor変数で、使用しているエディタを定義

最初にeditor変数にコマンドへのファイルパスを指定しています。 現在は、ユーザインストールのVScodeになっています。

エディタによって、指定行番号へ飛ぶという処理が違うので、スクリプトの最後のほうにあるEdit_file()の中も修正してください。 これにより、ダブルクリックでその該当行に飛んでいきます。

VScodeの場合:

 target := "--goto `"" A_ScriptDir "\" FileName ":" Line "`""    ; VScode

Notepad++の場合:

 target := "`"" A_ScriptDir "\" Filename "`"" " -n" Line     ; notepad++

その他のエディタについては、各自で修正してみてください。

一覧にしたいahkスクリプトは、target変数にて設定

target := A_ScriptDir "\*.ahk"              ; Folder + \ + *.ahk
;target := A_ScriptDir "\Autohotkey.ahk"    ; only 1 File

ワイルドカードで指定するか、1つのファイルを指定するです。

上の場合は、ahkスクリプトのあるフォルダ内の拡張子が.ahkのものすべての一覧を作成することになります。

以下 Autohotkey-ListingHotkeys.ahk

以下のスクリプトを右上のコピーボタンを押して、クリップボードにコピーし、適当なエディタに貼り付けて、 Autohotkey-ListingHotkeys.ahk という名前で保存してください。

Autohotkey V2がインストールされていれば、保存したAutohotkey-ListingHotkeys.ahkをダブルクリックすると、起動されます。 起動したら、「Alt + 4」で一覧ウィンドウが表示されます。

表示された行をダブルクリックすると、エディタが起動して、その行のところで表示されているはずです。

; Autohotkey Listing Hotkeys and Hotstrings + Functions
; 2025-11-28 
; by torazemon2016
; https://www.autohotkey.com/docs/v2/lib/ListView.htm

#Requires AutoHotkey 2.0+
#SingleInstance Force

;;VScode
;editor := "C:\Program Files\Microsoft VS Code\Code.exe"
editor := "C:\Users\" A_UserName "\AppData\Local\Programs\Microsoft VS Code\Code.exe"
;;Notepad++
;editor := "C:\Program Files\Notepad++\notepad++.exe"

!4::    ; Autohotkey.ahk Hotkey List
{
    CreateHotkeyMapGui()
}

CreateHotkeyMapGui(*)
{
    target := A_ScriptDir "\*.ahk"              ; Folder + \ + *.ahk
    ;target := A_ScriptDir "\Autohotkey.ahk"    ; only 1 File

    title := "AHK Hotkey List"
    MyGui := Gui("+Resize",title)       ; Allow window maximizing
    MyGui.OnEvent("Close", Gui_Close)   ; _ □ X (Close)
    MyGui.OnEvent("Escape", Gui_Close)   ; Press [ESC] key (Close)
    MyGui.OnEvent("Size", Gui_Size)     ; Resize
    MyGui.SetFont("s16")                ; Font Size

    ; ListView
    LV := MyGui.Add("ListView", "+Grid r20 w1400 h600", ["Filename","Line","Type","Key", "Description"])
    ;LV.OnEvent("Click", Edit_File)         ; 
    LV.OnEvent("DoubleClick", Edit_File)    ; Run Editor

    ; Main
    Load_hotkeys(target)                

    ; The column size is not determined until after the data is loaded, so ModifyCol will be executed later.
    LV.ModifyCol()                      ; Auto-size each column to fit its contents.
    LV.ModifyCol(2, "70 Integer")       ; Line Number
    LV.ModifyCol(4, 400)                ; Type (Hotkey,Function,etc)

    MyGui.Show("x0 y200 AutoSize")      ; 

    ;----------------------------
    Load_hotkeys(files)
    {
        Loop Files, files
        {
            ;MsgBox(A_LoopFileName)
            Read_file(A_LoopFileName)
        }
    }

    Read_file(filename)
    {
        Loop read, filename ; Read line by line from a file
        {
            line := A_index

            if RegExMatch(A_LoopReadLine, '^(\s)', &m)  ; If the beginning of the line is blank
                continue                                ; next line

            if(InStr(A_LoopReadLine,"#Include") == 1)   ; ==1 If the first character is #Include
                Store_LV(filename, line, "Include", A_LoopReadLine)
            
            if(InStr(A_LoopReadLine,"::") != 0)         ; Hotkeys and Hotstrings found ('!= 0' means found)
            {
                if(InStr(A_LoopReadLine,";") == 1)      ; If the first character is ;
                    Store_LV(filename, line, "commentout", A_LoopReadLine)
                else if(InStr(A_LoopReadLine,":") == 1) ; If the first character is :
                    Store_LV(filename, line, "Hotstrings", A_LoopReadLine)
                else
                    Store_LV(filename, line, "Hotkey", A_LoopReadLine)
            }
            else if RegExMatch(A_LoopReadLine, '^[a-zA-Z].*\(.*\)', &m) ; Function found 
            {
                if(InStr(A_LoopReadLine,":=") == 0)     ; If it is not an assignment expression ('==0' means not found)
                    Store_LV(filename, line, "Function", A_LoopReadLine)
            }
        }
    }

    Store_LV(filename, line, type, str)
    {
        ;MsgBox(filename " " line " " kind " " str)
        parts := StrSplit(str, ";")
        key := ""
        comment := ""
        if(type == "commentout")    ; ex. ;F1:: ; comment1 -> parts[1] == "" ; parts[2] == F1 ; parts[3] == comment1
        {
            key := parts[2]
            if(parts.Length >= 3)
                comment := parts[3]
             else
                comment := ""
        }
        else                        ; ex. F1::  ; comment1 ; comment2 -> parts[1] == F1 ; parts[2] == comment1 ; parts[3] == comment2
        {
            key := parts[1]
            if(parts.length >= 3)
                comment := parts[2] . " " . ";" . " " . parts[3]
            else if(parts.length == 2)
                comment := parts[2]
            else
                comment := ""
        }

        LV.add(, filename, line, type, key, comment)
    }

    ;----------------------------
    Gui_Close(*)
    { 
        MyGui.Destroy()
    }


    Gui_Size(thisGui, MinMax, Width, Height)  
    {
        if(MinMax == -1)  ; The window has been minimized. No action needed.
            return
        else
            LV.Move(,, Width - 20, Height - 20) ; Expand/Shrink ListView
    }

    ;----------------------------
    Edit_File(LV, RowNumber)
    {
        FileName := LV.GetText(RowNumber, 1)
        Line := LV.GetText(RowNumber, 2)
        ;MsgBox(editor " " Filename " " Line , 0x40000)
        try
        {
            editor := "C:\Users\" A_UserName "\AppData\Local\Programs\Microsoft VS Code\Code.exe"

            target := "--goto `"" A_ScriptDir "\" FileName ":" Line "`""    ; VScode
            ;target := "`"" A_ScriptDir "\" Filename "`"" " -n" Line        ; notepad++
            Run(editor " " target)
        }
        catch
            MsgBox("Could not " editor " " target)
    }

}

Autohotkeyの学習の一環として、今回はListViewを理解することが出来ました。 (できるだけGUIとListViewの扱いがわかりやすくなるよう、クラスとかではない形で作成しています)

ご利用いただき、改良などコメントいただけると幸いです。