Add better remappings

Add better remappings

FileEncoding, UTF-8 ; This file needs to be saved/encoded with "UTF-8 with BOM"

; Use Swedish characters on US-English keyboard
![:: Send, å
!+{:: Send, Å
!':: Send, ä
!+':: Send, Ä
!;:: Send, ö
!+;:: Send, Ö  ; does not work

; HHKB settings to mimic macOS behavior on Windows
; Leave righ hand side modifier keys at their defaults
LWin::LCtrl
<^Right:: Send, {End}
<^Left:: Send, {Home}
<^Up:: Send, {PgUp}
<^Down:: Send, {PgDn}
<^Tab::Send {LWin down}{Tab}{LWin up}

FileEncoding, UTF-8 ; This file needs to be saved/encoded with "UTF-8 with BOM"

; Use Swedish characters on US-English keyboard
![:: Send, å
!+{:: Send, Å
!':: Send, ä
!+':: Send, Ä
!;:: Send, ö
!+;:: Send, Ö  ; does not work

; HHKB settings to mimic macOS behavior on Windows
; Leave righ hand side modifier keys at their defaults

LWin::LControl

LWin & Tab:: Send {LAlt down}{Tab}
LWin Up:: Send {Alt up}

LWin & Up:: Send, {PgUp}
LWin & Down:: Send, {PgDn}
LWin & Left:: Send, {Home}
LWin & Right:: Send, {End}


RunZ: add WinRRun function

RunZ: add WinRRun function

global Arg

Functions:
    @("Help", "帮助信息")
    @("AhkRun", "使用 Ahk 的 Run 运行 `; cmd", true)
    @("CmdRun", "使用 cmd 运行 : cmd", true)
    @("WinRRun", "使用 win + r 运行", true)
    @("RunAndDisplay", "使用 cmd 运行，并显示结果", true)
    @("ReloadFiles", "重新加载需要搜索的文件")
    @("Clip", "显示剪切板内容")
    @("Calc", "计算器")
    @("SearchInWeb", "在浏览器（百度）搜索剪切板或输入内容", true)
    @("EditConfig", "编辑配置文件")
    @("ClearClipboardFormat", "清除剪切板中文字的格式")
    @("RunClipboard", "使用 ahk 的 Run 运行剪切板内容")
    @("T2S", "繁体转简体剪切板内容")
    @("ShowIp", "显示 IP")
    @("Calendar", "用浏览器打开万年历")
    @("Dictionary", "词典，依赖 bash 和 ydcv")
    @("ArgTest", "参数测试：ArgTest arg1,arg2,...")
return

Help:
    helpText := ""
        . "键入内容 搜索，回车 执行（a），Alt + 字母 执行，F1 帮助，Esc 退出`n"
        . "Tab + 字母 也可执行字母对应功能`n"
        . "Tab + 大写字母 可将字母对应功能加入到配置文件，以便优先显示`n"
        . "Ctrl + r 重新创建待搜索文件列表`n"
        . "Ctrl + j 清除编辑框内容`n"
        . "Ctrl + d 用 TC 打开第一个文件所在目录`n"
        . "Ctrl + s 显示并复制第一个文件的完整路径`n"
        . "Ctrl + x 删除第一个文件`n"
        . "F2 编辑配置文件`n`n"
        . "可直接输入网址，如 www.baidu.com`n"
        . "分号开头则使用 ahk 的 Run 运行命令，如 `;ping www.bidu.com`n"
        . "冒号开头则在 cmd 运行命令，如 :ping www.baidu.com`n"
        . "当搜索无结果时，回车 也等同 run 输入内容`n"
        . "当输入内容包含空格时，列表锁定，逗号作为命令参数的分隔符"

    DisplayResult(helpText)
return

CmdRun:
    RunWithCmd(Arg)
return

AhkRun:
    Run, %Arg%
return

Clip:
    DisplayResult("剪切板内容长度 " . StrLen(clipboard) . " ：`n`n" . clipboard)
return

EditConfig:
    Run, % g_ConfFile
return

ArgTest:
    Args := StrSplit(Arg, ",")
    result := "共有 " . Args.Length() . " 个参数。`n`n"

    for index, argument in Args
    {
        result .= "第 " . index - 1 " 个参数：" . argument . "`n"
    }

    DisplayResult(result)
return

ShowIp:
    DisplayResult(A_IPAddress1
            . "`r`n" . A_IPAddress2
            . "`r`n" . A_IPAddress3
            . "`r`n" . A_IPAddress4)
return

Dictionary:
    word := Arg
    if (word == "")
    {
        word := clipboard
    }

    DisplayResult(RunAndGetOutput("echo " . word . " | ydcv"))
return

Calendar:
    Run % "http://www.baidu.com/baidu?wd=%CD%F2%C4%EA%C0%FA"
return

T2S:
    Run, notepad
    clipboard := Kanji_t2s(clipboard)
    Send, ^v
return

ClearClipboardFormat:
    clipboard := clipboard
return

SearchInWeb:
    word := clipboard
    if (Arg != "")
    {
        word := Arg
    }

    Run, https://www.baidu.com/s?wd=%word%
return

RunClipboard:
    Run, %clipboard%
return

Calc:
    result := Eval(Arg)
    DisplayResult(result)
    clipboard := result
return

RunAndDisplay:
    DisplayResult(RunAndGetOutput(Arg))
return

WinRRun:
    Send, #r
    sleep, 100
    Send, %Arg%
    Send, {enter}
return

global Arg

Functions:
    @("Help", "帮助信息")
    @("AhkRun", "使用 Ahk 的 Run 运行 `; cmd", true)
    @("CmdRun", "使用 cmd 运行 : cmd", true)
    @("RunAndDisplay", "使用 cmd 运行，并显示结果", true)
    @("ReloadFiles", "重新加载需要搜索的文件")
    @("Clip", "显示剪切板内容")
    @("Calc", "计算器")
    @("SearchInWeb", "在浏览器（百度）搜索剪切板或输入内容", true)
    @("EditConfig", "编辑配置文件")
    @("ClearClipboardFormat", "清除剪切板中文字的格式")
    @("RunClipboard", "使用 ahk 的 Run 运行剪切板内容")
    @("T2S", "繁体转简体剪切板内容")
    @("ShowIp", "显示 IP")
    @("Calendar", "用浏览器打开万年历")
    @("Dictionary", "词典，依赖 bash 和 ydcv")
    @("ArgTest", "参数测试：ArgTest arg1,arg2,...")
return

Help:
    helpText := ""
        . "键入内容 搜索，回车 执行（a），Alt + 字母 执行，F1 帮助，Esc 退出`n"
        . "Tab + 字母 也可执行字母对应功能`n"
        . "Tab + 大写字母 可将字母对应功能加入到配置文件，以便优先显示`n"
        . "Ctrl + r 重新创建待搜索文件列表`n"
        . "Ctrl + j 清除编辑框内容`n"
        . "Ctrl + d 用 TC 打开第一个文件所在目录`n"
        . "Ctrl + s 显示并复制第一个文件的完整路径`n"
        . "Ctrl + x 删除第一个文件`n"
        . "F2 编辑配置文件`n`n"
        . "可直接输入网址，如 www.baidu.com`n"
        . "分号开头则使用 ahk 的 Run 运行命令，如 `;ping www.bidu.com`n"
        . "冒号开头则在 cmd 运行命令，如 :ping www.baidu.com`n"
        . "当搜索无结果时，回车 也等同 run 输入内容`n"
        . "当输入内容包含空格时，列表锁定，逗号作为命令参数的分隔符"

    DisplayResult(helpText)
return

CmdRun:
    RunWithCmd(Arg)
return

AhkRun:
    Run, %Arg%
return

Clip:
    DisplayResult("剪切板内容长度 " . StrLen(clipboard) . " ：`n`n" . clipboard)
return

EditConfig:
    Run, % g_ConfFile
return

ArgTest:
    Args := StrSplit(Arg, ",")
    result := "共有 " . Args.Length() . " 个参数。`n`n"

    for index, argument in Args
    {
        result .= "第 " . index - 1 " 个参数：" . argument . "`n"
    }

    DisplayResult(result)
return

ShowIp:
    DisplayResult(A_IPAddress1
            . "`r`n" . A_IPAddress2
            . "`r`n" . A_IPAddress3
            . "`r`n" . A_IPAddress4)
return

Dictionary:
    word := Arg
    if (word == "")
    {
        word := clipboard
    }

    DisplayResult(RunAndGetOutput("echo " . word . " | ydcv"))
return

Calendar:
    Run % "http://www.baidu.com/baidu?wd=%CD%F2%C4%EA%C0%FA"
return

T2S:
    Run, notepad
    clipboard := Kanji_t2s(clipboard)
    Send, ^v
return

ClearClipboardFormat:
    clipboard := clipboard
return

SearchInWeb:
    word := clipboard
    if (Arg != "")
    {
        word := Arg
    }

    Run, https://www.baidu.com/s?wd=%word%
return

RunClipboard:
    Run, %clipboard%
return

Calc:
    result := Eval(Arg)
    DisplayResult(result)
    clipboard := result
return

RunAndDisplay:
    DisplayResult(RunAndGetOutput(Arg))
return


Pass -C dir to wslbridge

Pass -C dir to wslbridge

#NoTrayIcon
#NoEnv

args = %1%
IniRead, title, %A_ScriptDir%\etc\wsl-terminal.conf, config, title, "        "
IniRead, shell, %A_ScriptDir%\etc\wsl-terminal.conf, config, shell, "bash"
IniRead, use_cbwin, %A_ScriptDir%\etc\wsl-terminal.conf, config, use_cbwin, 0
IniRead, use_tmux, %A_ScriptDir%\etc\wsl-terminal.conf, config, use_tmux, 0
IniRead, attach_tmux_locally, %A_ScriptDir%\etc\wsl-terminal.conf, config, attach_tmux_locally, 0
IniRead, icon, %A_ScriptDir%\etc\wsl-terminal.conf, config, icon, ""

bash_exe = %A_WinDir%\sysnative\bash.exe
if (!FileExist(bash_exe))
{
    bash_exe = %A_WinDir%\system32\bash.exe
}
if (!FileExist(bash_exe))
{
    MsgBox, 0x10, , Ubuntu-on-Windows must be installed.
    ExitApp, 1
}

icon_string = -i "%A_ScriptFullPath%"
if (icon != "" && FileExist(icon))
{
    icon_string = -i "%icon%"
}

cmd = %shell%
opts = -t -e SHELL="%shell%"
if (args == "-C")
{
    opts = -C "%2%" -t -e SHELL="%shell%"
}

if (args = "-a" && WinExist(title))
{
    cmd =
}
else if (!use_tmux)
{
    if (args = "-l")
    {
        cmd = %shell% -c "cd; %shell% -l"
    }
}
else
{
    if (WinExist(title))
    {
        cmd =
        Run, "%bash_exe%" -c 'tmux new-window -c "$PWD"', , Hide
    }
    else if (args = "-a")
    {
        if (attach_tmux_locally)
        {
            opts = %opts% -e USE_TMUX=1 -e ATTACH_ONLY=1
        }
        else
        {
            cmd = %shell% -c "tmux a 2>/dev/null && exit || cd && exec tmux"
        }
    }
    else
    {
        if (attach_tmux_locally)
        {
            opts = %opts% -e USE_TMUX=1
        }
        else
        {
            cmd = %shell% -c 'tmux new-window -c "$PWD" \`; a 2>/dev/null || tmux'
        }
    }
}
if (cmd)
{
    Run, "%A_ScriptDir%\bin\mintty" %icon_string% -t "%title%" -e /bin/wslbridge %opts% %cmd%
}

Loop, 5
{
    WinActivate, %title%
    if (WinActive(title))
    {
        break
    }

    Sleep, 50
}

if (use_cbwin)
{
    Process, Exist, outbash.exe

    if (ErrorLevel = 0)
    {
        Run, "%A_ScriptDir%\bin\outbash" --outbash-session -c 'exec sleep 10000000d', , Hide
    }
}
else if (use_tmux)
{
    ; Run a sleep to avoid tmux being killed.
    Process, Exist, sleep

    if (ErrorLevel = 0)
    {
        Run, "%bash_exe%" -c 'exec sleep 10000000d', , Hide
    }
}

#NoTrayIcon
#NoEnv

args = %1%
IniRead, title, %A_ScriptDir%\etc\wsl-terminal.conf, config, title, "        "
IniRead, shell, %A_ScriptDir%\etc\wsl-terminal.conf, config, shell, "bash"
IniRead, use_cbwin, %A_ScriptDir%\etc\wsl-terminal.conf, config, use_cbwin, 0
IniRead, use_tmux, %A_ScriptDir%\etc\wsl-terminal.conf, config, use_tmux, 0
IniRead, attach_tmux_locally, %A_ScriptDir%\etc\wsl-terminal.conf, config, attach_tmux_locally, 0
IniRead, icon, %A_ScriptDir%\etc\wsl-terminal.conf, config, icon, ""

bash_exe = %A_WinDir%\sysnative\bash.exe
if (!FileExist(bash_exe))
{
    bash_exe = %A_WinDir%\system32\bash.exe
}
if (!FileExist(bash_exe))
{
    MsgBox, 0x10, , Ubuntu-on-Windows must be installed.
    ExitApp, 1
}

icon_string = -i "%A_ScriptFullPath%"
if (icon != "" && FileExist(icon))
{
    icon_string = -i "%icon%"
}

if (args == "-C")
{
    SetWorkingDir, %2%
    if (ErrorLevel == 1)
    {
        MsgBox, 0x10, , %2% directory not found.
    }
}

cmd = %shell%
opts = -t -e SHELL="%shell%"
if (args = "-a" && WinExist(title))
{
    cmd =
}
else if (!use_tmux)
{
    if (args = "-l")
    {
        cmd = %shell% -c "cd; %shell% -l"
    }
}
else
{
    if (WinExist(title))
    {
        cmd =
        Run, "%bash_exe%" -c 'tmux new-window -c "$PWD"', , Hide
    }
    else if (args = "-a")
    {
        if (attach_tmux_locally)
        {
            opts = %opts% -e USE_TMUX=1 -e ATTACH_ONLY=1
        }
        else
        {
            cmd = %shell% -c "tmux a 2>/dev/null && exit || cd && exec tmux"
        }
    }
    else
    {
        if (attach_tmux_locally)
        {
            opts = %opts% -e USE_TMUX=1
        }
        else
        {
            cmd = %shell% -c 'tmux new-window -c "$PWD" \`; a 2>/dev/null || tmux'
        }
    }
}
if (cmd)
{
    Run, "%A_ScriptDir%\bin\mintty" %icon_string% -t "%title%" -e /bin/wslbridge %opts% %cmd%
}

Loop, 5
{
    WinActivate, %title%
    if (WinActive(title))
    {
        break
    }

    Sleep, 50
}

if (use_cbwin)
{
    Process, Exist, outbash.exe

    if (ErrorLevel = 0)
    {
        Run, "%A_ScriptDir%\bin\outbash" --outbash-session -c 'exec sleep 10000000d', , Hide
    }
}
else if (use_tmux)
{
    ; Run a sleep to avoid tmux being killed.
    Process, Exist, sleep

    if (ErrorLevel = 0)
    {
        Run, "%bash_exe%" -c 'exec sleep 10000000d', , Hide
    }
}


Add cmd type command

Add cmd type command

#NoEnv
#SingleInstance, Force
#NoTrayIcon

FileEncoding, utf-8
SendMode Input

; 自动生成的命令文件
global g_SearchFileList := A_ScriptDir . "\SearchFileList.txt"
; 配置文件
global g_ConfFile := A_ScriptDir . "\RunZ.ini"

if !FileExist(g_ConfFile)
{
    FileCopy, %g_ConfFile%.help.txt, %g_ConfFile%
}

global g_Conf := class_EasyINI(g_ConfFile)

; 所有命令
global g_Commands
; 当搜索无结果时使用的命令
global g_FallbackCommands
; 编辑框当前内容
global g_CurrentInput
; 当前匹配到的第一条命令
global g_CurrentCommand
; 当前匹配到的所有命令
global g_CurrentCommandList
; 是否启用 TCMatch
global g_EnableTCMatch = TCMatchOn(g_Conf.Config.TCMatchPath)
; 列表第一列的首字母或数字
global g_FirstChar := Asc(g_Conf.Gui.FirstChar)
; 列表第一列的首字母或数字
global g_DisplayRows := g_Conf.Gui.DisplayRows
; 命令使用了显示框
global g_UseDisplay
; 当前输入命令的参数，数组，为了方便没有添加 g_ 前缀
global Arg

if (FileExist(g_SearchFileList))
{
    LoadFiles()
}
else
{
    GoSub, ReloadFiles
}

Gui, Main:Font, % "s" g_Conf.Gui.FontSize, % g_Conf.Gui.FontName
Gui, Main:Add, Edit, % "gProcessInputCommand vSearchArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
Gui, Main:Add, Edit, % "ReadOnly vDisplayArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.DisplayAreaHeight
        , % SearchCommand("", true)
if (g_Conf.Gui.ShowCurrentCommand)
{
    Gui, Main:Add, Edit, % "ReadOnly"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
}
Gui, Main:Show, , RunZ
if (g_Conf.Gui.HideTitle)
{
    WinSet, Style, -0xC00000, A
}

Hotkey, IfWinActive, RunZ
Hotkey, ~enter, RunCurrentCommand
Hotkey, ^j, ClearInput
Hotkey, f1, Help
Hotkey, f2, EditConfig
Hotkey, esc, ExitRunZ
Hotkey, ^d, OpenCurrentFileDir
Hotkey, ^x, DeleteCurrentFile
Hotkey, ^s, ShowCurrentFile
Hotkey, ^r, ReloadFiles

if (g_Conf.Config.RunInBackground)
{
    Hotkey, esc, WindowMin
}

Loop, % g_DisplayRows
{
    key := Chr(g_FirstChar + A_Index - 1)
    ; lalt +
    Hotkey, <!%key%, RunSelectedCommand1
    ; tab +
    Hotkey, ~%key%, RunSelectedCommand2
    ; shift +
    Hotkey, ~+%key%, AddCustomCommand
}

if (g_Conf.Config.SaveInputText && g_Conf.Auto.InputText != "")
{
    Send, % g_Conf.Auto.InputText
}

return

ExitRunZ:
    if (g_Conf.Config.SaveInputText)
    {
        g_Conf.DeleteKey("auto", "InputText")
        g_Conf.AddKey("auto", "InputText", g_CurrentInput)
        g_Conf.Save()
    }

    ExitApp
return

WindowMin:
    WinMinimize, A
return

GenerateSearchFileList()
{
    FileDelete, %g_SearchFileList%

    searchFileType := g_Conf.Config.SearchFileType

    for dirIndex, dir in StrSplit(g_Conf.Config.SearchFileDir, " | ")
    {
        if (InStr(dir, "A_") == 1)
        {
            searchPath := %dir%
        }
        else
        {
            searchPath := dir
        }

        for extIndex, ext in StrSplit(searchFileType, " | ")
        {
            Loop, Files, %searchPath%\%ext%, R
            {
                if (g_Conf.Config.SearchFileExclude != ""
                        && RegexMatch(A_LoopFileLongPath, g_Conf.Config.SearchFileExclude))
                {
                    continue
                }
                FileAppend, file | %A_LoopFileLongPath%`n, %g_SearchFileList%,
            }
        }
    }
}

ReloadFiles:
    GenerateSearchFileList()

    LoadFiles()
return

ProcessInputCommand:
    GuiControlGet, g_CurrentInput, , SearchArea
    SearchCommand(g_CurrentInput)
return

SearchCommand(command = "", firstRun = false)
{
    result := ""
    commandPrefix := SubStr(command, 1, 1)

    if (commandPrefix ==  ";" || commandPrefix == ":")
    {
        if (commandPrefix == ";")
        {
            g_CurrentCommand := g_FallbackCommands[1]
        }
        else if (commandPrefix == ":")
        {
            g_CurrentCommand := g_FallbackCommands[2]
        }

        g_CurrentCommandList.Insert(g_CurrentCommand)
        result .= "a | " . g_CurrentCommand
        Arg := SubStr(g_CurrentInput, 2)
        DisplaySearchResult(result)
        return result
    }
    ; 用空格来判断参数
    else if (InStr(command, " ") && g_CurrentCommand != "")
    {
        Arg := SubStr(command, InStr(command, " ") + 1)
        return
    }

    g_CurrentCommandList := Object()

    order := g_FirstChar

    for index, element in g_Commands
    {
        elementToSearch := StrSplit(element, " | ")[2]

        if (InStr(element, "file | ", true, 1))
        {
            ; 只搜不带扩展名的文件名
            SplitPath, elementToSearch, , fileDir, , fileNameNoExt
            elementToShow := SubStr("file | " . fileNameNoExt, 1, 68)

            if (g_Conf.Config.SearchFullPath)
            {
                ; TCMatch 在搜索路径时只搜索文件名，强行将 \ 转成空格
                elementToSearch := StrReplace(fileDir . "\" . fileNameNoExt, "\", " ")
            }
        }
        else
        {
            elementToShow := SubStr(element, 1, 68)
        }

        if (MatchCommand(elementToSearch, command))
        {
            g_CurrentCommandList.Insert(element)

            if (order == g_FirstChar)
            {
                g_CurrentCommand := element
            }
            else
            {
                result .= "`n"
            }

            result .= Chr(order++) . " | " . elementToShow

            if (order - g_FirstChar >= g_DisplayRows)
            {
                break
            }
            ; 第一次运行只加载 function 类型
            if (firstRun && (order - g_FirstChar >= g_DisplayRows - 4))
            {
                result .= "`n`n现有 " g_Commands.Length() " 条命令。"
                result .= "`n`n键入内容 搜索，回车 执行第一条，Alt + 字母 执行，F1 帮助，Esc 退出。"

                break
            }
        }
    }

    if (result == "")
    {
        g_CurrentCommand := g_FallbackCommands[1]
        g_CurrentCommandList := g_FallbackCommands
        Arg := g_CurrentInput

        for index, element in g_FallbackCommands
        {
            if (index != 1)
            {
                result .= "`n"
            }

            result .= Chr(g_FirstChar - 1 + index++) . " | " . element
        }
    }

    DisplaySearchResult(result)
    return result
}

DisplaySearchResult(result)
{
    DisplayText(result)

    if (g_CurrentCommandList.Length() == 1 && g_Conf.Config.RunIfOnlyOne)
    {
        GoSub, RunCurrentCommand
    }

    if (g_Conf.Gui.ShowCurrentCommand)
    {
        ControlSetText, Edit3, %g_CurrentCommand%
    }
}

ClearInput:
    ControlSetText, Edit1,
return

RunCurrentCommand:
    if (g_CurrentInput != "")
    {
        g_UseDisplay := false

        RunCommand(g_CurrentCommand)
        if (g_Conf.Config.RunOnce && !g_UseDisplay)
        {
            GoSub, ExitRunZ
        }
    }
return

MatchCommand(Haystack, Needle)
{
    if (g_EnableTCMatch)
    {
        return TCMatch(Haystack, Needle)
    }

    return InStr(Haystack, Needle)
}

RunCommand(command)
{
    command := StrSplit(command, "（")[1]

    if (RegexMatch(command, "^(file|url)"))
    {
        cmd := StrSplit(command, " | ")[2]
        Run, %cmd%
    }
    else if (InStr(command, "function | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        if (IsLabel(cmd))
        {
            GoSub, %cmd%
        }
    }
    else if (InStr(command, "cmd | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        RunWithCmd(cmd)
    }
}

RunSelectedCommand1:
    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

RunSelectedCommand2:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 2, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

AddCustomCommand:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    if (g_CurrentCommandList[index] != "")
    {
        g_Conf.AddKey("command", g_CurrentCommandList[index], g_CurrentInput)

        g_Conf.Save()

        LoadFiles()
    }
return

LoadFiles()
{
    g_Commands := Object()
    g_FallbackCommands := Object()

    for key, value in g_Conf.Command
    {
        if (value != "")
        {
            g_Commands.Insert(key . "（" . value "）")
        }
        else
        {
            g_Commands.Insert(key)
        }
    }

    GoSub, InternalFunction

    userFunctionLabel := "UserFunction"
    if (IsLabel(userFunctionLabel))
    {
        GoSub, %userFunctionLabel%
    }

    Loop, Read, %g_SearchFileList%
    {
        g_Commands.Insert(A_LoopReadLine)
    }
}

DisplayText(text)
{
    textToDisplay := StrReplace(text, "`n", "`r`n")
    ControlSetText, Edit2, %textToDisplay%
}

DisplayResult(result)
{
    DisplayText(result)
    g_UseDisplay := true
}

; AddAction(label, info, fallback)
@(label, info, fallback = false)
{
    g_Commands.Insert("function | " . label . "（" . info . "）")
    if (fallback)
    {
        g_FallbackCommands.Insert("function | " . label . "（" . info . "）")
    }
}

RunAndGetOutput(command)
{
    tempFileName := "RunZ.stdout.log"
    fullCommand = bash -c "%command% &> %tempFileName%"

    if (!FileExist("c:\msys64\usr\bin\bash.exe"))
    {
        fullCommand = %ComSpec% /C "%command% > %tempFileName%"
    }

    RunWait, %fullCommand%, %A_Temp%, Hide
    FileRead, result, %A_Temp%\%tempFileName%
    FileDelete, %A_Temp%\%tempFileName%
    return result
}

RunWithCmd(command)
{
    if (FileExist("c:\msys64\usr\bin\mintty.exe"))
    {
        Run, % "mintty -e sh -c '" command "; read'"
    }
    else
    {
        Run, % ComSpec " /C " command
    }
}

OpenPath(filePath)
{
    if (!FileExist(filePath))
    {
        return
    }

    if (FileExist(g_Conf.Config.TCPath))
    {
        TCPath := g_Conf.Config.TCPath
        Run, %TCPath% /O /A /L="%filePath%"
    }
    else
    {
        SplitPath, filePath, , fileDir, ,
        Run, explorer "%fileDir%"
    }
}

OpenCurrentFileDir:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]
    OpenPath(filePath)
return

DeleteCurrentFile:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]

    if (!FileExist(filePath))
    {
        return
    }

    FileRecycle, % filePath
    GoSub, ReloadFiles
return

ShowCurrentFile:
    ToolTip, % StrSplit(g_CurrentCommand, " | ")[2]
    SetTimer, RemoveToolTip, 800
return

RemoveToolTip:
    ToolTip
    SetTimer, RemoveToolTip, Off
return

#include %A_ScriptDir%\..\lib\class_EasyIni.ahk
#include %A_ScriptDir%\lib\Kanji\Kanji.ahk
#include %A_ScriptDir%\lib\TCMatch.ahk
#include %A_ScriptDir%\lib\Eval.ahk
#include %A_ScriptDir%\Functions.ahk
; 用户自定义命令
#include *i %A_ScriptDir%\UserFunctions.ahk

#NoEnv
#SingleInstance, Force
#NoTrayIcon

FileEncoding, utf-8
SendMode Input

; 自动生成的命令文件
global g_SearchFileList := A_ScriptDir . "\SearchFileList.txt"
; 配置文件
global g_ConfFile := A_ScriptDir . "\RunZ.ini"

if !FileExist(g_ConfFile)
{
    FileCopy, %g_ConfFile%.help.txt, %g_ConfFile%
}

global g_Conf := class_EasyINI(g_ConfFile)

; 所有命令
global g_Commands
; 当搜索无结果时使用的命令
global g_FallbackCommands
; 编辑框当前内容
global g_CurrentInput
; 当前匹配到的第一条命令
global g_CurrentCommand
; 当前匹配到的所有命令
global g_CurrentCommandList
; 是否启用 TCMatch
global g_EnableTCMatch = TCMatchOn(g_Conf.Config.TCMatchPath)
; 列表第一列的首字母或数字
global g_FirstChar := Asc(g_Conf.Gui.FirstChar)
; 列表第一列的首字母或数字
global g_DisplayRows := g_Conf.Gui.DisplayRows
; 命令使用了显示框
global g_UseDisplay
; 当前输入命令的参数，数组，为了方便没有添加 g_ 前缀
global Arg

if (FileExist(g_SearchFileList))
{
    LoadFiles()
}
else
{
    GoSub, ReloadFiles
}

Gui, Main:Font, % "s" g_Conf.Gui.FontSize, % g_Conf.Gui.FontName
Gui, Main:Add, Edit, % "gProcessInputCommand vSearchArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
Gui, Main:Add, Edit, % "ReadOnly vDisplayArea"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.DisplayAreaHeight
        , % SearchCommand("", true)
if (g_Conf.Gui.ShowCurrentCommand)
{
    Gui, Main:Add, Edit, % "ReadOnly"
        . " w" g_Conf.Gui.WidgetWidth " h" g_Conf.Gui.EditHeight,
}
Gui, Main:Show, , RunZ
if (g_Conf.Gui.HideTitle)
{
    WinSet, Style, -0xC00000, A
}

Hotkey, IfWinActive, RunZ
Hotkey, ~enter, RunCurrentCommand
Hotkey, ^j, ClearInput
Hotkey, f1, Help
Hotkey, f2, EditConfig
Hotkey, esc, ExitRunZ
Hotkey, ^d, OpenCurrentFileDir
Hotkey, ^x, DeleteCurrentFile
Hotkey, ^s, ShowCurrentFile
Hotkey, ^r, ReloadFiles

if (g_Conf.Config.RunInBackground)
{
    Hotkey, esc, WindowMin
}

Loop, % g_DisplayRows
{
    key := Chr(g_FirstChar + A_Index - 1)
    ; lalt +
    Hotkey, <!%key%, RunSelectedCommand1
    ; tab +
    Hotkey, ~%key%, RunSelectedCommand2
    ; shift +
    Hotkey, ~+%key%, AddCustomCommand
}

if (g_Conf.Config.SaveInputText && g_Conf.Auto.InputText != "")
{
    Send, % g_Conf.Auto.InputText
}

return

ExitRunZ:
    if (g_Conf.Config.SaveInputText)
    {
        g_Conf.DeleteKey("auto", "InputText")
        g_Conf.AddKey("auto", "InputText", g_CurrentInput)
        g_Conf.Save()
    }

    ExitApp
return

WindowMin:
    WinMinimize, A
return

GenerateSearchFileList()
{
    FileDelete, %g_SearchFileList%

    searchFileType := g_Conf.Config.SearchFileType

    for dirIndex, dir in StrSplit(g_Conf.Config.SearchFileDir, " | ")
    {
        if (InStr(dir, "A_") == 1)
        {
            searchPath := %dir%
        }
        else
        {
            searchPath := dir
        }

        for extIndex, ext in StrSplit(searchFileType, " | ")
        {
            Loop, Files, %searchPath%\%ext%, R
            {
                if (g_Conf.Config.SearchFileExclude != ""
                        && RegexMatch(A_LoopFileLongPath, g_Conf.Config.SearchFileExclude))
                {
                    continue
                }
                FileAppend, file | %A_LoopFileLongPath%`n, %g_SearchFileList%,
            }
        }
    }
}

ReloadFiles:
    GenerateSearchFileList()

    LoadFiles()
return

ProcessInputCommand:
    GuiControlGet, g_CurrentInput, , SearchArea
    SearchCommand(g_CurrentInput)
return

SearchCommand(command = "", firstRun = false)
{
    result := ""
    commandPrefix := SubStr(command, 1, 1)

    if (commandPrefix ==  ";" || commandPrefix == ":")
    {
        if (commandPrefix == ";")
        {
            g_CurrentCommand := g_FallbackCommands[1]
        }
        else if (commandPrefix == ":")
        {
            g_CurrentCommand := g_FallbackCommands[2]
        }

        g_CurrentCommandList.Insert(g_CurrentCommand)
        result .= "a | " . g_CurrentCommand
        Arg := SubStr(g_CurrentInput, 2)
        DisplaySearchResult(result)
        return result
    }
    ; 用空格来判断参数
    else if (InStr(command, " ") && g_CurrentCommand != "")
    {
        Arg := SubStr(command, InStr(command, " ") + 1)
        return
    }

    g_CurrentCommandList := Object()

    order := g_FirstChar

    for index, element in g_Commands
    {
        elementToSearch := StrSplit(element, " | ")[2]

        if (InStr(element, "file | ", true, 1))
        {
            ; 只搜不带扩展名的文件名
            SplitPath, elementToSearch, , fileDir, , fileNameNoExt
            elementToShow := SubStr("file | " . fileNameNoExt, 1, 68)

            if (g_Conf.Config.SearchFullPath)
            {
                ; TCMatch 在搜索路径时只搜索文件名，强行将 \ 转成空格
                elementToSearch := StrReplace(fileDir . "\" . fileNameNoExt, "\", " ")
            }
        }
        else
        {
            elementToShow := SubStr(element, 1, 68)
        }

        if (MatchCommand(elementToSearch, command))
        {
            g_CurrentCommandList.Insert(element)

            if (order == g_FirstChar)
            {
                g_CurrentCommand := element
            }
            else
            {
                result .= "`n"
            }

            result .= Chr(order++) . " | " . elementToShow

            if (order - g_FirstChar >= g_DisplayRows)
            {
                break
            }
            ; 第一次运行只加载 function 类型
            if (firstRun && (order - g_FirstChar >= g_DisplayRows - 4))
            {
                result .= "`n`n现有 " g_Commands.Length() " 条命令。"
                result .= "`n`n键入内容 搜索，回车 执行第一条，Alt + 字母 执行，F1 帮助，Esc 退出。"

                break
            }
        }
    }

    if (result == "")
    {
        g_CurrentCommand := g_FallbackCommands[1]
        g_CurrentCommandList := g_FallbackCommands
        Arg := g_CurrentInput

        for index, element in g_FallbackCommands
        {
            if (index != 1)
            {
                result .= "`n"
            }

            result .= Chr(g_FirstChar - 1 + index++) . " | " . element
        }
    }

    DisplaySearchResult(result)
    return result
}

DisplaySearchResult(result)
{
    DisplayText(result)

    if (g_CurrentCommandList.Length() == 1 && g_Conf.Config.RunIfOnlyOne)
    {
        GoSub, RunCurrentCommand
    }

    if (g_Conf.Gui.ShowCurrentCommand)
    {
        ControlSetText, Edit3, %g_CurrentCommand%
    }
}

ClearInput:
    ControlSetText, Edit1,
return

RunCurrentCommand:
    if (g_CurrentInput != "")
    {
        g_UseDisplay := false

        RunCommand(g_CurrentCommand)
        if (g_Conf.Config.RunOnce && !g_UseDisplay)
        {
            GoSub, ExitRunZ
        }
    }
return

MatchCommand(Haystack, Needle)
{
    if (g_EnableTCMatch)
    {
        return TCMatch(Haystack, Needle)
    }

    return InStr(Haystack, Needle)
}

RunCommand(command)
{
    command := StrSplit(command, "（")[1]

    if (RegexMatch(command, "^(file|url)"))
    {
        cmd := StrSplit(command, " | ")[2]
        Run, %cmd%
    }
    else if (InStr(command, "function | ", true, 1))
    {
        cmd := StrSplit(command, " | ")[2]
        if (IsLabel(cmd))
        {
            GoSub, %cmd%
        }
    }
}

RunSelectedCommand1:
    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

RunSelectedCommand2:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 2, 1)) - g_FirstChar + 1

    RunCommand(g_CurrentCommandList[index])
return

AddCustomCommand:
    ControlGetFocus, ctrl,
    if (ctrl == "Edit1")
    {
        return
    }

    index := Asc(SubStr(A_ThisHotkey, 3, 1)) - g_FirstChar + 1

    if (g_CurrentCommandList[index] != "")
    {
        g_Conf.AddKey("command", g_CurrentCommandList[index], g_CurrentInput)

        g_Conf.Save()

        LoadFiles()
    }
return

LoadFiles()
{
    g_Commands := Object()
    g_FallbackCommands := Object()

    for key, value in g_Conf.Command
    {
        if (value != "")
        {
            g_Commands.Insert(key . "（" . value "）")
        }
        else
        {
            g_Commands.Insert(key)
        }
    }

    GoSub, InternalFunction

    userFunctionLabel := "UserFunction"
    if (IsLabel(userFunctionLabel))
    {
        GoSub, %userFunctionLabel%
    }

    Loop, Read, %g_SearchFileList%
    {
        g_Commands.Insert(A_LoopReadLine)
    }
}

DisplayText(text)
{
    textToDisplay := StrReplace(text, "`n", "`r`n")
    ControlSetText, Edit2, %textToDisplay%
}

DisplayResult(result)
{
    DisplayText(result)
    g_UseDisplay := true
}

; AddAction(label, info, fallback)
@(label, info, fallback = false)
{
    g_Commands.Insert("function | " . label . "（" . info . "）")
    if (fallback)
    {
        g_FallbackCommands.Insert("function | " . label . "（" . info . "）")
    }
}

RunAndGetOutput(command)
{
    tempFileName := "RunZ.stdout.log"
    fullCommand = bash -c "%command% &> %tempFileName%"

    if (!FileExist("c:\msys64\usr\bin\bash.exe"))
    {
        fullCommand = %ComSpec% /C "%command% > %tempFileName%"
    }

    RunWait, %fullCommand%, %A_Temp%, Hide
    FileRead, result, %A_Temp%\%tempFileName%
    FileDelete, %A_Temp%\%tempFileName%
    return result
}

RunWithCmd(command)
{
    if (FileExist("c:\msys64\usr\bin\mintty.exe"))
    {
        Run, % "mintty -e sh -c '" command "; read'"
    }
    else
    {
        Run, % ComSpec " /C " command
    }
}

OpenPath(filePath)
{
    if (!FileExist(filePath))
    {
        return
    }

    if (FileExist(g_Conf.Config.TCPath))
    {
        TCPath := g_Conf.Config.TCPath
        Run, %TCPath% /O /A /L="%filePath%"
    }
    else
    {
        SplitPath, filePath, , fileDir, ,
        Run, explorer "%fileDir%"
    }
}

OpenCurrentFileDir:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]
    OpenPath(filePath)
return

DeleteCurrentFile:
    filePath := StrSplit(g_CurrentCommand, " | ")[2]

    if (!FileExist(filePath))
    {
        return
    }

    FileRecycle, % filePath
    GoSub, ReloadFiles
return

ShowCurrentFile:
    ToolTip, % StrSplit(g_CurrentCommand, " | ")[2]
    SetTimer, RemoveToolTip, 800
return

RemoveToolTip:
    ToolTip
    SetTimer, RemoveToolTip, Off
return

#include %A_ScriptDir%\..\lib\class_EasyIni.ahk
#include %A_ScriptDir%\lib\Kanji\Kanji.ahk
#include %A_ScriptDir%\lib\TCMatch.ahk
#include %A_ScriptDir%\lib\Eval.ahk
#include %A_ScriptDir%\Functions.ahk
; 用户自定义命令
#include *i %A_ScriptDir%\UserFunctions.ahk


Update MBWindow.ahk

Update MBWindow.ahk

#IfWinActive ahk_exe MapInfoPro.exe ;THIS WILL NEED EXTENSION THROUGH "isMapBasicWindow()"
mbWin_enterBehaviour = 1

$Enter::    ;$ so Enter can be re-used
    If Not isMapBasicWindow() {
        send, {Enter}
        return
    }

    If (mbWin_enterBehaviour > 1) {
    	send, ^a{Enter}
    )

    ;Get the MapBasic source from the MapBasic Window
    old_clipboard := ClipboardAll
	Clipboard=
	send, ^c
	clipwait,0.1
	MBSource := clipboard
	clipboard := old_clipboard

	If (needsCompiling(MBSource)) {
	    Compile(MBSource)
	} else {
	    send,{Enter}
	}
return

isMapBasicWindow(){
    ;TO DO: This should have more (fast) checks.
    MapInfo = ComObjGet("MapInfo.Application.x64")
    return MapInfo.Eval("ActiveWindow()") = 1002
}

needsCompiling(src){
	;Separated RegEx - This may require simplifying...:
	i := 0
	i := i + regexmatch(src,"i)\bAlter\b\s+\b(Control|MapInfoDialog)\b")			;matches {Alter Control,Alter MapInfoDialog}
	i := i + regexmatch(src,"i)\bCall\b")						        ;matches Call
	i := i + regexmatch(src,"i)\bDeclare\b\s+\b(Function|Sub)\b")				;matches {Declare Function, Declare Sub}
	i := i + regexmatch(src,"i)\bDefine\b")						        ;matches Define
	i := i + regexmatch(src,"i)\bDialog\b")						        ;matches {Dialog, Dialog Preserve, Dialog Remove}
	i := i + regexmatch(src,"i)\bDim\s+\w+\s*(,\s*\w+\s*)+\s+as\b")				;matches Dim {2 variable declarations} as
	i := i + regexmatch(src,"i)\bDo\s+Case\s+(.|\s)*?\bEnd\s+Case\b")			;matches Do Case … End Case,
	i := i + regexmatch(src,"i)\bDo\b\s+(.|\s)*?\bLoop\b")				    	;matches Do … Loop
	i := i + regexmatch(src,"i)\bEnd\s+Program\b")					        ;matches End Program
	i := i + regexmatch(src,"i)\bExit\s+(Do|For|Function|Sub)\b")				;matches {Exit Do, Exit For, Exit Function, Exit Sub}
	i := i + regexmatch(src,"i)\bFor\b(.|\s)*?\bNext\b")				    	;matches For … Next,
	i := i + regexmatch(src,"i)\bFunction\b(.|\s)*\bEnd\s+Function\b")			;matches Function … End Function
	i := i + regexmatch(src,"i)\bGoTo\b")			            			;matches GoTo
	i := i + regexmatch(src,"i)\bSub\b(.|\s)*\bEnd\s+Sub\b")				;matches Sub … End Sub
	i := i + regexmatch(src,"i)\bIf\b(.|\s)*?\bThen\b(.|\s)*?\bEnd\s+If\b")			;matches If .*? then … End If
	i := i + regexmatch(src,"i)\bInclude\b\s+\b"".*""\b")				    	;matches Include “…”
	i := i + regexmatch(src,"i)\bOnError\s+GoTo\b")					        ;matches OnError GoTo
	i := i + regexmatch(src,"i)\bOpen\s+File\b")					    	;matches Open File
	i := i + regexmatch(src,"i)\bProgressBar\b")    					;matches ProgressBar
	i := i + regexmatch(src,"i)\bResume\b")			    				;matches Resume
	i := i + regexmatch(src,"i)\bSet\s+Handler\b")		    				;matches Set Handler
	i := i + regexmatch(src,"i)\bType\b(.|\s)*?\bEnd\s+Type\b") 				;matches Type … End Type
	i := i + regexmatch(src,"i)\bWhile\b(.|\s)*?\bWend\b")		    			;matches While … Wend
	return i > 0
}

#IfWinActive ahk_exe MapInfoPro.exe ;THIS WILL NEED EXTENSION THROUGH "isMapBasicWindow()"
$Enter::    ;$ so Enter can be re-used

    If Not isMapBasicWindow() {
        send, {Enter}
        return
    }

    ;Get the MapBasic source from the MapBasic Window
    old_clipboard := ClipboardAll
	Clipboard=
	send, ^c
	clipwait,0.1
	MBSource := clipboard
	clipboard := old_clipboard

	If (needsCompiling(MBSource)) {
	    Compile(MBSource)
	} else {
	    send,{Enter}
	}
return

isMapBasicWindow(){
    ;TO DO: This should have more (fast) checks.
    MapInfo = ComObjGet("MapInfo.Application.x64")
    return MapInfo.Eval("ActiveWindow()") = 1002
}

needsCompiling(src){
	;Separated RegEx - This may require simplifying...:
	i := 0
	i := i + regexmatch(src,"i)\bAlter\b\s+\b(Control|MapInfoDialog)\b")			;matches {Alter Control,Alter MapInfoDialog}
	i := i + regexmatch(src,"i)\bCall\b")						        ;matches Call
	i := i + regexmatch(src,"i)\bDeclare\b\s+\b(Function|Sub)\b")				;matches {Declare Function, Declare Sub}
	i := i + regexmatch(src,"i)\bDefine\b")						        ;matches Define
	i := i + regexmatch(src,"i)\bDialog\b")						        ;matches {Dialog, Dialog Preserve, Dialog Remove}
	i := i + regexmatch(src,"i)\bDim\s+\w+\s*(,\s*\w+\s*)+\s+as\b")				;matches Dim {2 variable declarations} as
	i := i + regexmatch(src,"i)\bDo\s+Case\s+(.|\s)*?\bEnd\s+Case\b")			;matches Do Case … End Case,
	i := i + regexmatch(src,"i)\bDo\b\s+(.|\s)*?\bLoop\b")				    	;matches Do … Loop
	i := i + regexmatch(src,"i)\bEnd\s+Program\b")					        ;matches End Program
	i := i + regexmatch(src,"i)\bExit\s+(Do|For|Function|Sub)\b")				;matches {Exit Do, Exit For, Exit Function, Exit Sub}
	i := i + regexmatch(src,"i)\bFor\b(.|\s)*?\bNext\b")				    	;matches For … Next,
	i := i + regexmatch(src,"i)\bFunction\b(.|\s)*\bEnd\s+Function\b")			;matches Function … End Function
	i := i + regexmatch(src,"i)\bGoTo\b")			            			;matches GoTo
	i := i + regexmatch(src,"i)\bSub\b(.|\s)*\bEnd\s+Sub\b")				;matches Sub … End Sub
	i := i + regexmatch(src,"i)\bIf\b(.|\s)*?\bThen\b(.|\s)*?\bEnd\s+If\b")			;matches If .*? then … End If
	i := i + regexmatch(src,"i)\bInclude\b\s+\b"".*""\b")				    	;matches Include “…”
	i := i + regexmatch(src,"i)\bOnError\s+GoTo\b")					        ;matches OnError GoTo
	i := i + regexmatch(src,"i)\bOpen\s+File\b")					    	;matches Open File
	i := i + regexmatch(src,"i)\bProgressBar\b")    					;matches ProgressBar
	i := i + regexmatch(src,"i)\bResume\b")			    				;matches Resume
	i := i + regexmatch(src,"i)\bSet\s+Handler\b")		    				;matches Set Handler
	i := i + regexmatch(src,"i)\bType\b(.|\s)*?\bEnd\s+Type\b") 				;matches Type … End Type
	i := i + regexmatch(src,"i)\bWhile\b(.|\s)*?\bWend\b")		    			;matches While … Wend
	return i > 0
}


AutoHotkey.ahk, from darwin18

AutoHotkey.ahk, from darwin18

; Tips {{{
; #: win
; !: alt
; ^: ctrl
; +: shift
; &: and
; <: only left, >: only right
; *: wildecard
; ~: pass through
; }}}

; Auto execute section is the region before any return/hotkey {{{
; Windows size
TMargin := 5
BMargin := 5
LMargin := 5
RMargin := 5 ; sidebar = 150px
MinSize := 0.7

; For Terminal/Vim
GroupAdd Terminal, ahk_class PuTTY
GroupAdd Terminal, ahk_class mintty ; cygwin
GroupAdd Terminal, ahk_class TMobaXtermForm
GroupAdd Terminal, ahk_class TFormDetachedTab
GroupAdd Terminal, ahk_class ConsoleWindowClass
GroupAdd Terminal, ahk_exe powershell.exe
GroupAdd Terminal, ahk_exe vim.exe
GroupAdd TerminalVim, ahk_group Terminal
GroupAdd TerminalVim, ahk_class Vim

; For browsers
GroupAdd, Browser, ahk_exe chrome.exe
GroupAdd, Browser, ahk_exe firefox.exe
GroupAdd, Browser, ahk_exe ApplicationFrameHost.exe ; Edge

; Mouse Gestures
GroupAdd, MouseGesture, ahk_group Broser
GroupAdd, MouseGesture, ahk_exe explorer.exe

; External files
#Include %A_LineFile%\..\submodules\vim_ahk\vim.ahk
#Include %A_LineFile%\..\AutoCorrect.ahk

Return
; }}}

;; Basic Settings, HotKeys, Functions {{{
; Settings

#UseHook On ; Make it a bit slow, but can avoid infinitude loop
            ; Same as "$" for each hotkey
#InstallKeybdHook ; For checking key history
                  ; Use ~500kB memory?

#HotkeyInterval 1000 ; Hotkey inteval (default 2000 milliseconds).
#MaxHotkeysPerInterval 100 ; Max hotkeys perinterval (default 50).

; For HHKB
vkFFsc079::RCtrl
vkFFsc07b::LCtrl
; }}}

; Terminal/Vim {{{
; ESC + IME
#IfWInActive, ahk_group TerminalVim
Esc:: ; Just send Esc at converting.
  if(VIM_IME_GET(A)){
    if(VIM_IME_GetConverting(A)){
      Send, {Esc}
    }else{
      VIM_IME_SET()
    }
  }else{
    Send, {Esc}
  }
Return

^[:: ; Go to Normal mode (for vim) with IME off even at converting.
  if(VIM_IME_GetConverting(A)){
    Send, {Esc}
    Sleep 1 ; wait 1 ms (Need to stop converting)
  }
  if(VIM_IME_GET(A)){
    VIM_IME_SET()
    Send, {Esc}
  }else{
    Send, {Esc}
  }
Return

^m::Send, ^m ; Use Ctrl-m as is

; Paste
#IfWInActive, ahk_group Terminal
!v::
  ;StringSplit, strout, clipboard, `n
  ;If(strout0>1 or InStr(clipboard, "sudo")>0){
  ;  MsgBox, 308, Clipboard, %clipboard%`n`n Do you want to paste?
  ;  IfMsgBox, No
  ;  {
  ;    Return
  ;  }
  ;}
  ;SendInput %clipboard%
  ;Return
  Sleep,200
  MouseClick, Right, 50, 50, 1
Return

#IfWInActive, ahk_class Vim
!v::Send, {Alt}ep

; Other than Terminal/Vim
#IfWInNotActive, ahk_group TerminalVim
^[::Send, {Esc}             ; Always C-[ to ESC, like vim
^d::Send, {Del}             ; Always Delete with C-d
; }}} Terminal/Vim

; Power Point {{{
#IfWInActive, ahk_class PP12FrameClass
; Subscript/Superscript
^=::Send, ^tb{Enter}
^+=::Send, ^tp{Enter}
; For JP keyboards
;^-::Send, ^tb{Enter}
;^+-::Send, ^tp{Enter}

; Fonts
^!+s::Send, ^tfsymbol{Enter}
^!+a::Send, ^tfarial{Enter}
^!+h::Send, ^tfhelvetica{Enter}
; }}} Power Point

; Word {{{
#IfWInActive, ahk_class OpusApp
^=::Send, ^tb{Enter}
^+=::Send, ^tp{Enter}
; for JP keyboards
;^-::Send, ^tb{Enter}
;^+-::Send, ^tp{Enter}
; }}} Word

; Explorer {{{
#IfWInActive, ahk_class CabinetWClass
; Next/Previous page
^i::Send, !{Right}
^o::Send, !{Left}
; }}} Explorer

; CLCL {{{
;#IfWInActive, ahk_class CLCLMain
#IfWInActive, CLCL ; both window/title do not working...
j::
  Send, {Down}
Return

K::Send, {Up}
; }}} Explorer

; Everthing {{{
#IfWinActive, ahk_class EVERYTHING
Return::
  Send, {Enter}
  Sleep, 200
  IfWinActive, ahk_class EVERYTHING
  {
    Send,{Enter}
    Sleep, 500
  }
  WinActivate, ahk_class EVERYTHING
  Sleep, 200
  Send, {Esc}
Return
; }}} Everything

; Firefox/Chrome/Edge {{{
#IfWinActive, ahk_group Browser
;^WheelDown::Send, {WheelDown}
;^WheelUp::Send, {WheelUp}
^WheelDown::Return
^WheelUp::Return
; }}} Firefox/Chrome

; Mouse Gestures {{{
#IfWinActive, ahk_group MouseGesture
;LButton & RButton::Send, ^{Tab}
;RButton & LButton::Send, ^+{Tab}

; }}} Firefox/Chrome

; Global Settings {{{
#if
; Basic Settings {{{

; Suspend
;Esc & Tab::
;  Suspend, Toggle
;  Return
; For Alt-Ctrl Swap (swapped by KeySwap)
; To assign ^Tab, need to add < or > to choose left or right
<^Tab::AltTab
;<+<^Tab::ShiftAltTab ; can not assigned...
;LCtrl & Tab::
;  if GetKeyState("Shift","P"){
;    Send, {ShiftAltTab}
;  }else{
;    Send, {AltTab}
;  }
;Return
;Alt & Tab::
;  if GetKeyState("Shift","P"){
;    Send, ^+{taB}
;  }else{
;    Send, ^{Tab}
;  }
;Return
!Tab::Send, ^{Tab}
!+Tab::Send, ^+{Tab}

;!m::Send, ^m
;^m::Send, !m
;>^m::Send, !m
;Ctrl & Left::Send, !{Left}
;Ctrl & Right::Send, !{Right}

; Virtual desktop
^!+h::Send, #^{Left}
^!+l::Send, #^{Right}

; Cortana
!^f::Send, #s

; CLCL
#c::Send, !c

; Other basic settings
!Space::Send, {vkF3sc029} ; IME by A-Space
^Space::Send, {vkF3sc029} ; IME by C-Space
;{vkF3sc029}               ; 変換
;{vk1Dsc07B}               ; 無変換
!^a::Send, !{Space}n       ; Minimize window
!4::Send, !{F4}           ; Close window
^4::Send, !{F4}           ; Close window
!d::Send, {Del}           ; Always Delete with A-d
;^o::Send,!{Left}          ; Go to previous page
;^i::Send,!{Right}         ; Go to nexe page
^Space::!`                ; IME

^h::Send, {BS}            ; Always BS with C-h
;^h::
;  While GetKeyState("h","p"){
;    Send {BS}
;    TrayTip,Start:,%n%,10,,
;    Sleep 50
;  }
;  return

;^j::Send,{Enter}      ; C-j to Enter

; For HHKB
; ESC to ` like normal keyboard (ESC is placed on the left of 1 in HHKB)
!1::!`                ; IME

; Disable alt to menu
~LAlt Up::
~LAlt::
return
; }}} Basic Settings

; Cursor, Mouse, Window move/size {{{
; Cursor {{{
!^h::Send, {Left}
!^j::Send, {Down}
!^k::Send, {Up}
!^l::Send, {Right}
; }}} Cursor

; Mouse {{{
; Mouse Move
^+h::MouseMove, -10, 0, 0, R
^+j::MouseMove, 0, 10, 0, R
^+k::MouseMove, 0, -10, 0, R
^+l::MouseMove, 10, 0, 0, R

; Click
^+n::MouseClick, Left
^+p::MouseClick, Right
; Right click on current window

; Mouse wheel
!^m::MouseClick, WheelDown, , , 2
!^,::MouseClick, WheelUp, , , 2
; }}} Mouse

; Window move {{{

; Move a little
^+y::
  WinGetPos, X, Y, , , A ;A for Active Window
  WinMove, A, ,X-20, Y,
Return

^+u::
  WinGetPos, X, Y, , , A
  WinMove, A, , X, Y+20
Return

^+i::
  WinGetPos, X, Y, , , A
  WinMove, A, , X, Y-20
Return

^+o::
  WinGetPos, X, Y, , , A
  WinMove, A, , X+20, Y
Return

; Move to a different screen
!^+y:: Send, #+{Left}
!^+u:: Send, #+{Down}
!^+i:: Send, #+{Up}
!^+o:: Send, #+{Right}

; }}} Window move

; Window size {{{

; Almost full
^!Enter::
!+Enter::
  ;WinGetPos, X, Y, W, H, Program Manager ; Full Desktop
  ;Msgbox, Pos At %X% %Y% %W% %H%
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  ;Msgbox, %MWALeft% %MWATop% %MWARight% %MWABottom%
  WinMove, A, , MWALeft+LMargin, MWATop+TMargin
    , MWARight-MWALeft-LMargin-RMargin
    , MWABottom-MWATop-TMargin-BMargin
Return

; Minsize
^!+Enter::
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  WinMove, A, , MWALeft+LMargin, MWATop+TMargin
    , (MWARight-MWALeft-LMargin-RMargin)*Minsize
    , (MWABottom-MWATop-TMargin-BMargin)*Minsize
Return

; Half size
!+h::
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  WinMove, A, , MWALeft+LMargin, MWATop+TMargin
    , (MWARight-MWALeft-LMargin-RMargin)*0.5
    , MWABottom-MWATop-TMargin-BMargin
Return

!+j::
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  WinMove, A, , MWALeft+LMargin
    , MWATop+(MWABottom-MWATop)*0.5
    , MWARight-MWALeft-LMargin-RMargin
    , (MWABottom-MWATop-TMargin-BMargin)*0.5
Return

!+k::
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  WinMove, A, , MWALeft+LMargin, MWATop+TMargin
    , MWARight-MWALeft-LMargin-RMargin
    , (MWABottom-MWATop-TMargin-BMargin)*0.5
Return

!+l::
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  WinMove, A, , MWALeft+(MWARight-MWALeft)*0.5
    , MWATop+TMargin
    , (MWARight-MWALeft-LMargin-RMargin)*0.5
    , MWABottom-MWATop-TMargin-BMargin
Return

; Resize
!+y::
  WinGetPos, X, Y, W, H, A
  WinMove, A, ,X, Y, W-20, H
Return

!+u::
  WinGetPos, X, Y, W, H, A
  WinMove, A, ,X, Y, W, H+20
Return

!+i::
  WinGetPos, X, Y, W, H, A
  WinMove, A, ,X, Y, W, H-20
Return

!+o::
  WinGetPos, X, Y, W, H, A
  WinMove, A, ,X, Y, W+20, H
Return

; }}} Window size
; }}} Cursor, Mouse, Window move
; }}} Global Settings

; Tips {{{
; #: win
; !: alt
; ^: ctrl
; +: shift
; &: and
; <: only left, >: only right
; *: wildecard
; ~: pass through
; }}}

; Auto execute section is the region before any return/hotkey {{{
; Windows size
TMargin := 5
BMargin := 5
LMargin := 5
RMargin := 5 ; sidebar = 150px
MinSize := 0.7

; For Terminal/Vim
GroupAdd Terminal, ahk_class PuTTY
GroupAdd Terminal, ahk_class mintty ; cygwin
GroupAdd Terminal, ahk_class TMobaXtermForm
GroupAdd Terminal, ahk_class TFormDetachedTab
GroupAdd Terminal, ahk_class ConsoleWindowClass
GroupAdd Terminal, ahk_exe powershell.exe
GroupAdd Terminal, ahk_exe vim.exe
GroupAdd TerminalVim, ahk_group Terminal
GroupAdd TerminalVim, ahk_class Vim

; For browsers
GroupAdd, Browser, ahk_exe chrome.exe
GroupAdd, Browser, ahk_exe firefox.exe
GroupAdd, Browser, ahk_exe ApplicationFrameHost.exe ; Edge

; Mouse Gestures
GroupAdd, MouseGesture, ahk_group Broser
GroupAdd, MouseGesture, ahk_exe explorer.exe

; External files
#Include %A_LineFile%\..\submodules\vim_ahk\vim.ahk
#Include %A_LineFile%\..\AutoCorrect.ahk

Return
; }}}

;; Basic Settings, HotKeys, Functions {{{
; Settings

#UseHook On ; Make it a bit slow, but can avoid infinitude loop
            ; Same as "$" for each hotkey
#InstallKeybdHook ; For checking key history
                  ; Use ~500kB memory?

#HotkeyInterval 1000 ; Hotkey inteval (default 2000 milliseconds).
#MaxHotkeysPerInterval 100 ; Max hotkeys perinterval (default 50).

; For HHKB
;vkFFsc079::RCtrl
;vkFFsc07b::LCtrl
; }}}

; Terminal/Vim {{{
; ESC + IME
#IfWInActive, ahk_group TerminalVim
Esc:: ; Just send Esc at converting.
  if(VIM_IME_GET(A)){
    if(VIM_IME_GetConverting(A)){
      Send, {Esc}
    }else{
      VIM_IME_SET()
    }
  }else{
    Send, {Esc}
  }
Return

^[:: ; Go to Normal mode (for vim) with IME off even at converting.
  if(VIM_IME_GetConverting(A)){
    Send, {Esc}
    Sleep 1 ; wait 1 ms (Need to stop converting)
  }
  if(VIM_IME_GET(A)){
    VIM_IME_SET()
    Send, {Esc}
  }else{
    Send, {Esc}
  }
Return

^m::Send, ^m ; Use Ctrl-m as is

; Paste
#IfWInActive, ahk_group Terminal
!v::
  ;StringSplit, strout, clipboard, `n
  ;If(strout0>1 or InStr(clipboard, "sudo")>0){
  ;  MsgBox, 308, Clipboard, %clipboard%`n`n Do you want to paste?
  ;  IfMsgBox, No
  ;  {
  ;    Return
  ;  }
  ;}
  ;SendInput %clipboard%
  ;Return
  Sleep,200
  MouseClick, Right, 50, 50, 1
Return

#IfWInActive, ahk_class Vim
!v::Send, {Alt}ep

; Other than Terminal/Vim
#IfWInNotActive, ahk_group TerminalVim
^[::Send, {Esc}             ; Always C-[ to ESC, like vim
^d::Send, {Del}             ; Always Delete with C-d
; }}} Terminal/Vim

; Power Point {{{
#IfWInActive, ahk_class PP12FrameClass
; Subscript/Superscript
^=::Send, ^tb{Enter}
^+=::Send, ^tp{Enter}
; For JP keyboards
;^-::Send, ^tb{Enter}
;^+-::Send, ^tp{Enter}

; Fonts
^!+s::Send, ^tfsymbol{Enter}
^!+a::Send, ^tfarial{Enter}
^!+h::Send, ^tfhelvetica{Enter}
; }}} Power Point

; Word {{{
#IfWInActive, ahk_class OpusApp
^=::Send, ^tb{Enter}
^+=::Send, ^tp{Enter}
; for JP keyboards
;^-::Send, ^tb{Enter}
;^+-::Send, ^tp{Enter}
; }}} Word

; Explorer {{{
#IfWInActive, ahk_class CabinetWClass
; Next/Previous page
^i::Send, !{Right}
^o::Send, !{Left}
; }}} Explorer

; CLCL {{{
;#IfWInActive, ahk_class CLCLMain
#IfWInActive, CLCL ; both window/title do not working...
j::
  Send, {Down}
Return

K::Send, {Up}
; }}} Explorer

; Everthing {{{
#IfWinActive, ahk_class EVERYTHING
Return::
  Send, {Enter}
  Sleep, 200
  IfWinActive, ahk_class EVERYTHING
  {
    Send,{Enter}
    Sleep, 500
  }
  WinActivate, ahk_class EVERYTHING
  Sleep, 200
  Send, {Esc}
Return
; }}} Everything

; Firefox/Chrome/Edge {{{
#IfWinActive, ahk_group Browser
;^WheelDown::Send, {WheelDown}
;^WheelUp::Send, {WheelUp}
^WheelDown::Return
^WheelUp::Return
; }}} Firefox/Chrome

; Mouse Gestures {{{
#IfWinActive, ahk_group MouseGesture
;LButton & RButton::Send, ^{Tab}
;RButton & LButton::Send, ^+{Tab}

; }}} Firefox/Chrome

; Global Settings {{{
#if
; Basic Settings {{{

; Suspend
;Esc & Tab::
;  Suspend, Toggle
;  Return
; For Alt-Ctrl Swap (swapped by KeySwap)
; To assign ^Tab, need to add < or > to choose left or right
<^Tab::AltTab
;<+<^Tab::ShiftAltTab ; can not assigned...
;LCtrl & Tab::
;  if GetKeyState("Shift","P"){
;    Send, {ShiftAltTab}
;  }else{
;    Send, {AltTab}
;  }
;Return
;Alt & Tab::
;  if GetKeyState("Shift","P"){
;    Send, ^+{taB}
;  }else{
;    Send, ^{Tab}
;  }
;Return
!Tab::Send, ^{Tab}
!+Tab::Send, ^+{Tab}

;!m::Send, ^m
;^m::Send, !m
;>^m::Send, !m
;Ctrl & Left::Send, !{Left}
;Ctrl & Right::Send, !{Right}

; Virtual desktop
^!+h::Send, #^{Left}
^!+l::Send, #^{Right}

; Cortana
!^f::Send, #s

; CLCL
#c::Send, !c

; Other basic settings
!Space::Send, {vkF3sc029} ; IME by A-Space
^Space::Send, {vkF3sc029} ; IME by C-Space
;{vkF3sc029}               ; 変換
;{vk1Dsc07B}               ; 無変換
!^a::Send, !{Space}n       ; Minimize window
!4::Send, !{F4}           ; Close window
^4::Send, !{F4}           ; Close window
!d::Send, {Del}           ; Always Delete with A-d
;^o::Send,!{Left}          ; Go to previous page
;^i::Send,!{Right}         ; Go to nexe page
^Space::!`                ; IME

^h::Send, {BS}            ; Always BS with C-h
;^h::
;  While GetKeyState("h","p"){
;    Send {BS}
;    TrayTip,Start:,%n%,10,,
;    Sleep 50
;  }
;  return

;^j::Send,{Enter}      ; C-j to Enter

; For HHKB
; ESC to ` like normal keyboard (ESC is placed on the left of 1 in HHKB)
!1::!`                ; IME

; Disable alt to menu
~LAlt Up::
~LAlt::
return
; }}} Basic Settings

; Cursor, Mouse, Window move/size {{{
; Cursor {{{
!^h::Send, {Left}
!^j::Send, {Down}
!^k::Send, {Up}
!^l::Send, {Right}
; }}} Cursor

; Mouse {{{
; Mouse Move
^+h::MouseMove, -10, 0, 0, R
^+j::MouseMove, 0, 10, 0, R
^+k::MouseMove, 0, -10, 0, R
^+l::MouseMove, 10, 0, 0, R

; Click
^+n::MouseClick, Left
^+p::MouseClick, Right
; Right click on current window

; Mouse wheel
!^m::MouseClick, WheelDown, , , 2
!^,::MouseClick, WheelUp, , , 2
; }}} Mouse

; Window move {{{

; Move a little
^+y::
  WinGetPos, X, Y, , , A ;A for Active Window
  WinMove, A, ,X-20, Y,
Return

^+u::
  WinGetPos, X, Y, , , A
  WinMove, A, , X, Y+20
Return

^+i::
  WinGetPos, X, Y, , , A
  WinMove, A, , X, Y-20
Return

^+o::
  WinGetPos, X, Y, , , A
  WinMove, A, , X+20, Y
Return

; Move to a different screen
!^+y:: Send, #+{Left}
!^+u:: Send, #+{Down}
!^+i:: Send, #+{Up}
!^+o:: Send, #+{Right}

; }}} Window move

; Window size {{{

; Almost full
^!Enter::
!+Enter::
  ;WinGetPos, X, Y, W, H, Program Manager ; Full Desktop
  ;Msgbox, Pos At %X% %Y% %W% %H%
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  ;Msgbox, %MWALeft% %MWATop% %MWARight% %MWABottom%
  WinMove, A, , MWALeft+LMargin, MWATop+TMargin
    , MWARight-MWALeft-LMargin-RMargin
    , MWABottom-MWATop-TMargin-BMargin
Return

; Minsize
^!+Enter::
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  WinMove, A, , MWALeft+LMargin, MWATop+TMargin
    , (MWARight-MWALeft-LMargin-RMargin)*Minsize
    , (MWABottom-MWATop-TMargin-BMargin)*Minsize
Return

; Half size
!+h::
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  WinMove, A, , MWALeft+LMargin, MWATop+TMargin
    , (MWARight-MWALeft-LMargin-RMargin)*0.5
    , MWABottom-MWATop-TMargin-BMargin
Return

!+j::
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  WinMove, A, , MWALeft+LMargin
    , MWATop+(MWABottom-MWATop)*0.5
    , MWARight-MWALeft-LMargin-RMargin
    , (MWABottom-MWATop-TMargin-BMargin)*0.5
Return

!+k::
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  WinMove, A, , MWALeft+LMargin, MWATop+TMargin
    , MWARight-MWALeft-LMargin-RMargin
    , (MWABottom-MWATop-TMargin-BMargin)*0.5
Return

!+l::
  SysGet, MWA, MonitorWorkArea ; w/o Taskbar
  WinMove, A, , MWALeft+(MWARight-MWALeft)*0.5
    , MWATop+TMargin
    , (MWARight-MWALeft-LMargin-RMargin)*0.5
    , MWABottom-MWATop-TMargin-BMargin
Return

; Resize
!+y::
  WinGetPos, X, Y, W, H, A
  WinMove, A, ,X, Y, W-20, H
Return

!+u::
  WinGetPos, X, Y, W, H, A
  WinMove, A, ,X, Y, W, H+20
Return

!+i::
  WinGetPos, X, Y, W, H, A
  WinMove, A, ,X, Y, W, H-20
Return

!+o::
  WinGetPos, X, Y, W, H, A
  WinMove, A, ,X, Y, W+20, H
Return

; }}} Window size
; }}} Cursor, Mouse, Window move
; }}} Global Settings


#170: use a login shell for run-wsl-file

#NoTrayIcon
#NoEnv

; Read ini file {{{1
ini_file = %A_ScriptDir%\etc\wsl-terminal.conf
IniRead, title, %ini_file%, config, title, "        "
IniRead, shell, %ini_file%, config, shell, "bash"
IniRead, use_tmux, %ini_file%, config, use_tmux, 0
IniRead, mintty_options, %ini_file%, config, mintty_options,
IniRead, icon, %ini_file%, config, icon,
IniRead, distro, %ini_file%, config, distro,
IniRead, keep_wsl_running, %ini_file%, config, keep_wsl_running, 0

if (mintty_options == "ERROR") {
    mintty_options =
}

; Prepare mintty_base and wslbridge2_base {{{1
icon_path = %A_ScriptFullPath%
if (icon != "" && FileExist(icon)) {
    icon_path = %icon%
}

distro_option := ""
if (distro != "ERROR") {
    distro_option = -d %distro%
}

mintty_path = "%A_ScriptDir%\bin\mintty"
mintty_base = %mintty_path% -i "%icon_path%" --rootfs=// --configdir "%A_ScriptDir%\etc"
wslbridge2_base = --WSLmode -e /bin/wslbridge2 %distro_option% -e SHELL=%shell% -e LANG -e WSL_HOST_IP
; Run as run-wsl-file or any editor {{{1
SplitPath, A_ScriptName, , , , exe_name
if (exe_name == "run-wsl-file") {
    arg = %1%

    if (arg == "") {
        MsgBox, Open .sh/.py/.pl/... with %exe_name%.exe to run it in WSL.
        ExitApp
    }

    SplitPath, arg, filename, dir
    SetWorkingDir, %dir%

    Run, %mintty_base% %mintty_options% -t "%arg%"  %wslbridge2_base% -l %shell% -c ./"%filename%"
    ExitApp
} else if (exe_name != "open-wsl" && exe_name != "cmd") {
    ; editor
    argc = %0%
    filepath := ""
    filename := ""
    options := ""

    if (argc > 0) {
        filepath := %argc%

        Loop, % argc - 1 {
            options .= " " %A_Index%
        }

        SplitPath, filepath, filename, dir
        SetWorkingDir, %dir%

        if (InStr(filename, " ")) {
            filename = "%filename%"
        }
    }

    Run, %mintty_base% %mintty_options% -t "%filepath%" %wslbridge2_base% "%exe_name%" %options% %filename%

    Loop, 5 {
        WinActivate, %filepath%
        if (WinActive(filepath)) {
            break
        }

        Sleep, 50
    }

    ExitApp
}

; Parse arguments {{{1
argc = %0%
args := []
Loop, %argc% {
    args.Insert(%A_Index%)
}

activate_window := False
change_directory := ""
distro := ""
login_shell := False
wslbridge2_options := ""
user_command := ""

i := 0
while (i++ < argc) {
    c := args[i]
    if (c == "-a") {
        activate_window := True
    } else if (c == "-C") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require directory arg.
            ExitApp, 1
        }

        change_directory := args[i]
    } else if (c == "-W") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require directory arg.
            ExitApp, 1
        }

        SetWorkingDir, % args[i]
    } else if (c == "-l") {
        login_shell := True
    } else if (c == "-d") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require distro name arg.
            ExitApp, 1
        }

        distro := args[i]
    } else if (c == "-b") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require additional wslbridge2 options arg.
            ExitApp, 1
        }

        wslbridge2_options := args[i]
    } else if (c == "-B") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require additional mintty options arg.
            ExitApp, 1
        }

        mintty_options .= " " args[i]
    } else if (c == "-c") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require command arg.
            ExitApp, 1
        }

        user_command := args[i]
    } else if (c == "-e") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require command arg.
            ExitApp, 1
        }

        user_command := shell " -c """ args[i]
        while (++i <= argc) {
            user_command .= " " args[i]
        }
        user_command .= """"
        StringReplace, user_command, user_command, `", `\`", All
    } else if (c == "-h") {
        help =
        (
        Usage: open-wsl [OPTION]...
          -a: activate an existing wsl-terminal window.
              if use_tmux=1, attach the running tmux session.
          -l: start terminal in your home directory (doesn't work with tmux).
          -c "command": run command (e.g. -c "echo a b; echo c; cat").
          -e commands: run commands (e.g. -e echo a b; echo c; cat).
          -C dir: change directory to a WSL dir (e.g. /home/username).
          -W dir: change directory to a Windows dir (e.g. c:\Users\username).
          -d distro: switch distros.
          -b "options": pass additional options to wslbridge.
          -B "options": pass additional options to mintty.
          -h: show help.
        )
        MsgBox, %help%
        ExitApp
    }
}

if (user_command != "") {
    if (change_directory != "") {
        wslbridge2_options = %wslbridge2_options% -W "%change_directory%"
    }

    Run, %mintty_base% %mintty_options% -t "%user_command%" %wslbridge2_base% %wslbridge2_options% %shell% -c "%user_command%"
    ExitApp
}

; Find bash.exe {{{1
bash_exe = %A_WinDir%\sysnative\bash.exe
if (!FileExist(bash_exe)) {
    bash_exe = %A_WinDir%\system32\bash.exe
} if (!FileExist(bash_exe)) {
    MsgBox, 0x10, , WSL(Windows Subsystem for Linux) must be installed.
    ExitApp, 1
}

; Switch distro {{{1
if (distro != "") {
    Run, % StrReplace(bash_exe, "bash.exe", "wslconfig.exe") " /s " distro
}

; Build command line {{{1
cmd =
opts = %wslbridge2_options%

if (activate_window && WinExist(title)) {
} else if (!use_tmux) {
    if (login_shell) {
        cmd = %shell% -l
        if (change_directory == "") {
            change_directory = ~
        }
    } else {
        cmd = %shell%
    }
} else {
    if (WinExist(title)) {
        Run, "%bash_exe%" -c 'tmux new-window -c "$PWD"', , Hide
    } else {
        cmd = %shell%
        opts = %opts% -e USE_TMUX=1

        if (activate_window) {
            opts = %opts% -e ATTACH_ONLY=1
        }
    }
}

if (change_directory != "") {
    opts = %opts% -W "%change_directory%"
}

if (cmd != "") {
    lnk_args = %mintty_base% %mintty_options% -t "%title%" %wslbridge2_base% %opts% %cmd%
    lnk_args := StrReplace(lnk_args, mintty_path)

    FileCreateShortcut, %A_ScriptDir%\bin\mintty.exe, %A_ScriptDir%\wsl-terminal.lnk, %A_WorkingDir%, %lnk_args%, wsl-terminal temp shortcut, %icon_path%
    Run, %A_ScriptDir%\wsl-terminal.lnk

    ;Run, %mintty_base% %mintty_options% -t "%title%" %wslbridge2_base% %opts% %cmd%
}

; Activate window {{{1

if (activate_window || use_tmux) {
    Loop, 5 {
        WinActivate, %title%
        if (WinActive(title)) {
            break
        }

        Sleep, 50
    }
}

if (keep_wsl_running) {
    Process, Exist, sleep

    if (ErrorLevel == 0) {
        Run, "%bash_exe%" -c 'exec sleep 10000000d', , Hide
    }
}

#NoTrayIcon
#NoEnv

; Read ini file {{{1
ini_file = %A_ScriptDir%\etc\wsl-terminal.conf
IniRead, title, %ini_file%, config, title, "        "
IniRead, shell, %ini_file%, config, shell, "bash"
IniRead, use_tmux, %ini_file%, config, use_tmux, 0
IniRead, mintty_options, %ini_file%, config, mintty_options,
IniRead, icon, %ini_file%, config, icon,
IniRead, distro, %ini_file%, config, distro,
IniRead, keep_wsl_running, %ini_file%, config, keep_wsl_running, 0

if (mintty_options == "ERROR") {
    mintty_options =
}

; Prepare mintty_base and wslbridge2_base {{{1
icon_path = %A_ScriptFullPath%
if (icon != "" && FileExist(icon)) {
    icon_path = %icon%
}

distro_option := ""
if (distro != "ERROR") {
    distro_option = -d %distro%
}

mintty_path = "%A_ScriptDir%\bin\mintty"
mintty_base = %mintty_path% -i "%icon_path%" --rootfs=// --configdir "%A_ScriptDir%\etc"
wslbridge2_base = --WSLmode -e /bin/wslbridge2 %distro_option% -e SHELL=%shell% -e LANG -e WSL_HOST_IP
; Run as run-wsl-file or any editor {{{1
SplitPath, A_ScriptName, , , , exe_name
if (exe_name == "run-wsl-file") {
    arg = %1%

    if (arg == "") {
        MsgBox, Open .sh/.py/.pl/... with %exe_name%.exe to run it in WSL.
        ExitApp
    }

    SplitPath, arg, filename, dir
    SetWorkingDir, %dir%

    Run, %mintty_base% %mintty_options% -t "%arg%"  %wslbridge2_base% ./"%filename%"
    ExitApp
} else if (exe_name != "open-wsl" && exe_name != "cmd") {
    ; editor
    argc = %0%
    filepath := ""
    filename := ""
    options := ""

    if (argc > 0) {
        filepath := %argc%

        Loop, % argc - 1 {
            options .= " " %A_Index%
        }

        SplitPath, filepath, filename, dir
        SetWorkingDir, %dir%

        if (InStr(filename, " ")) {
            filename = "%filename%"
        }
    }

    Run, %mintty_base% %mintty_options% -t "%filepath%" %wslbridge2_base% "%exe_name%" %options% %filename%

    Loop, 5 {
        WinActivate, %filepath%
        if (WinActive(filepath)) {
            break
        }

        Sleep, 50
    }

    ExitApp
}

; Parse arguments {{{1
argc = %0%
args := []
Loop, %argc% {
    args.Insert(%A_Index%)
}

activate_window := False
change_directory := ""
distro := ""
login_shell := False
wslbridge2_options := ""
user_command := ""

i := 0
while (i++ < argc) {
    c := args[i]
    if (c == "-a") {
        activate_window := True
    } else if (c == "-C") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require directory arg.
            ExitApp, 1
        }

        change_directory := args[i]
    } else if (c == "-W") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require directory arg.
            ExitApp, 1
        }

        SetWorkingDir, % args[i]
    } else if (c == "-l") {
        login_shell := True
    } else if (c == "-d") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require distro name arg.
            ExitApp, 1
        }

        distro := args[i]
    } else if (c == "-b") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require additional wslbridge2 options arg.
            ExitApp, 1
        }

        wslbridge2_options := args[i]
    } else if (c == "-B") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require additional mintty options arg.
            ExitApp, 1
        }

        mintty_options .= " " args[i]
    } else if (c == "-c") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require command arg.
            ExitApp, 1
        }

        user_command := args[i]
    } else if (c == "-e") {
        if (argc < ++i) {
            MsgBox, 0x10, , Require command arg.
            ExitApp, 1
        }

        user_command := shell " -c """ args[i]
        while (++i <= argc) {
            user_command .= " " args[i]
        }
        user_command .= """"
        StringReplace, user_command, user_command, `", `\`", All
    } else if (c == "-h") {
        help =
        (
        Usage: open-wsl [OPTION]...
          -a: activate an existing wsl-terminal window.
              if use_tmux=1, attach the running tmux session.
          -l: start terminal in your home directory (doesn't work with tmux).
          -c "command": run command (e.g. -c "echo a b; echo c; cat").
          -e commands: run commands (e.g. -e echo a b; echo c; cat).
          -C dir: change directory to a WSL dir (e.g. /home/username).
          -W dir: change directory to a Windows dir (e.g. c:\Users\username).
          -d distro: switch distros.
          -b "options": pass additional options to wslbridge.
          -B "options": pass additional options to mintty.
          -h: show help.
        )
        MsgBox, %help%
        ExitApp
    }
}

if (user_command != "") {
    if (change_directory != "") {
        wslbridge2_options = %wslbridge2_options% -W "%change_directory%"
    }

    Run, %mintty_base% %mintty_options% -t "%user_command%" %wslbridge2_base% %wslbridge2_options% %shell% -c "%user_command%"
    ExitApp
}

; Find bash.exe {{{1
bash_exe = %A_WinDir%\sysnative\bash.exe
if (!FileExist(bash_exe)) {
    bash_exe = %A_WinDir%\system32\bash.exe
} if (!FileExist(bash_exe)) {
    MsgBox, 0x10, , WSL(Windows Subsystem for Linux) must be installed.
    ExitApp, 1
}

; Switch distro {{{1
if (distro != "") {
    Run, % StrReplace(bash_exe, "bash.exe", "wslconfig.exe") " /s " distro
}

; Build command line {{{1
cmd =
opts = %wslbridge2_options%

if (activate_window && WinExist(title)) {
} else if (!use_tmux) {
    if (login_shell) {
        cmd = %shell% -l
        if (change_directory == "") {
            change_directory = ~
        }
    } else {
        cmd = %shell%
    }
} else {
    if (WinExist(title)) {
        Run, "%bash_exe%" -c 'tmux new-window -c "$PWD"', , Hide
    } else {
        cmd = %shell%
        opts = %opts% -e USE_TMUX=1

        if (activate_window) {
            opts = %opts% -e ATTACH_ONLY=1
        }
    }
}

if (change_directory != "") {
    opts = %opts% -W "%change_directory%"
}

if (cmd != "") {
    lnk_args = %mintty_base% %mintty_options% -t "%title%" %wslbridge2_base% %opts% %cmd%
    lnk_args := StrReplace(lnk_args, mintty_path)

    FileCreateShortcut, %A_ScriptDir%\bin\mintty.exe, %A_ScriptDir%\wsl-terminal.lnk, %A_WorkingDir%, %lnk_args%, wsl-terminal temp shortcut, %icon_path%
    Run, %A_ScriptDir%\wsl-terminal.lnk

    ;Run, %mintty_base% %mintty_options% -t "%title%" %wslbridge2_base% %opts% %cmd%
}

; Activate window {{{1

if (activate_window || use_tmux) {
    Loop, 5 {
        WinActivate, %title%
        if (WinActive(title)) {
            break
        }

        Sleep, 50
    }
}

if (keep_wsl_running) {
    Process, Exist, sleep

    if (ErrorLevel == 0) {
        Run, "%bash_exe%" -c 'exec sleep 10000000d', , Hide
    }
}


Config: Move the on-off configs to the top.

#Include, %A_ScriptDir%

; ====================================================================

WinOPlayerPlayPause := 1
GitGuiHotkeysFix := 1

DisableInsert := 1
FixPersianSymbolKeys := 1
BackTickLanguageChange := 1

; ====================================================================

Lang_Eng := 0x0409
Lang_Pes := 0x0429
Lang_Arb := 0x0401

Keybd_Eng_US := 0x04090409
Keybd_Eng_DV := 0xF0020409
Keybd_Eng_DVL := 0xF01A0409
Keybd_Eng_DVR := 0xF01B0409
Keybd_Pes := 0x04290429
Keybd_Pes_Std := 0xF03A0429
Keybd_Arb_101 := 0x04010401

KeyboardsData := [{}
	,{Keyboards: {Normal: [Keybd_Eng_DV, Keybd_Eng_US]
			,Left: [Keybd_Eng_DVL]
			,Right: [Keybd_Eng_DVR]}}
	,{Keyboards: {Normal: [Keybd_Pes_Std, Keybd_Pes, Keybd_Arb_101]
			,Left: []
			,Right: []}}
,{}]

#Include, %A_ScriptDir%

; ====================================================================

Lang_Eng := 0x0409
Lang_Pes := 0x0429
Lang_Arb := 0x0401

Keybd_Eng_US := 0x04090409
Keybd_Eng_DV := 0xF0020409
Keybd_Eng_DVL := 0xF01A0409
Keybd_Eng_DVR := 0xF01B0409
Keybd_Pes := 0x04290429
Keybd_Pes_Std := 0xF03A0429
Keybd_Arb_101 := 0x04010401

KeyboardsData := [{}
	,{Keyboards: {Normal: [Keybd_Eng_DV, Keybd_Eng_US]
			,Left: [Keybd_Eng_DVL]
			,Right: [Keybd_Eng_DVR]}}
	,{Keyboards: {Normal: [Keybd_Pes_Std, Keybd_Pes, Keybd_Arb_101]
			,Left: []
			,Right: []}}
,{}]

; ====================================================================

WinOPlayerPlayPause := 1
GitGuiHotkeysFix := 1

DisableInsert := 1
FixPersianSymbolKeys := 1
BackTickLanguageChange := 1


Delete SettingsGUI.ahk

Delete SettingsGUI.ahk

Gui,Add,GroupBox,x20 y18 w360 h55,MapBasic Application
Gui,Add,DropDownList,x30 y40 w290,DropDownList
Gui,Add,Button,x330 y40 w40 h23,Edit
Gui,Add,GroupBox,x20 y79 w360 h45,Compile Method
Gui,Add,Checkbox,x90 y100 w70 h13,'::' Prefix
Gui,Add,Checkbox,x200 y100 w90 h13,Smart Compile
Gui,Add,GroupBox,x20 y131 w360 h69,Options
Gui,Add,Checkbox,x55 y152 w140 h13,'/* ... */' Block Comment
Gui,Add,Checkbox,x55 y172 w85 h13,Auto-Declare
Gui,Add,Button,x135 y210 w50 h23,Save
Gui,Add,Button,x215 y210 w50 h23,Cancel
Gui,Show,x386 y232 w402 h244 ,
Return
GuiClose:
ExitApp
Return


add volume up/down support

add volume up/down support

;#### wheelctrl.ahk
EnvGet, DebugP, DEBUG
If (DebugP)
{
  TrayTip, Loading %A_ScriptName% , Debug Mode On
}
Else
{
  Menu, Tray, NoIcon
}
return

#Persistent
;---------------------------------------------------------------
MButton::
  Scale := 10
  MouseGetPos, X0, Y0
  fn := Func("SendWheelEvent").bind(Y0, Scale)
  SetTimer, % fn, 100
return

MButton Up::
  MouseGetPos, X1, Y1
  SetTimer, % fn, Off
  if (X1 == X0)  ; trigger middle click if cursor is not moved.
    MouseClick, Middle
return

SendWheelEvent(Y0, Scale)
{
  MouseGetPos, X, NewY
  Delta := NewY - Y0
  NumWheel := abs(Delta // Scale)
  If (NumWheel == 0)
    return
  WheelMove := (Delta > 0 ?  "WheelDown" : "WheelUp")

  Loop % NumWheel {
    Click, %WheelMove%
  }

  MouseMove, X, Y0
  ;Traytip, evt: %WheelMove% x %NumWheel%, mouse moving
  ;ListVars
  return
}

;--- some general key-bindings ---
#PgUp::Send {Volume_Up 2}
#PgDn::Send {Volume_Down 2}

#If DebugP
!^r::Reload

;#### wheelctrl.ahk
EnvGet, DebugP, DEBUG
If (DebugP)
{
  TrayTip, Loading %A_ScriptName% , Debug Mode On
}
Else
{
  Menu, Tray, NoIcon
}
return

#Persistent
;---------------------------------------------------------------
MButton::
  Scale := 10
  MouseGetPos, X0, Y0
  fn := Func("SendWheelEvent").bind(Y0, Scale)
  SetTimer, % fn, 100
return

MButton Up::
  MouseGetPos, X1, Y1
  SetTimer, % fn, Off
  if (X1 == X0)  ; trigger middle click if cursor is not moved.
    MouseClick, Middle
return

SendWheelEvent(Y0, Scale)
{
  MouseGetPos, X, NewY
  Delta := NewY - Y0
  NumWheel := abs(Delta // Scale)
  If (NumWheel == 0)
    return
  WheelMove := (Delta > 0 ?  "WheelDown" : "WheelUp")

  Loop % NumWheel {
    Click, %WheelMove%
  }

  MouseMove, X, Y0
  ;Traytip, evt: %WheelMove% x %NumWheel%, mouse moving
  ;ListVars
  return
}

#If DebugP
!^r::Reload


no message

no message

;
; Scriptlet Utility
;
#NoEnv
#NoTrayIcon
#SingleInstance Ignore
DetectHiddenWindows, On
FileEncoding, UTF-8
Menu, Tray, Icon, %A_ScriptDir%\..\toolicon.icl, 11
progName = Scriptlet Utility
scite := GetSciTEInstance()
if !scite
{
   MsgBox, 16, %progName%, SciTE COM object not found!
   ExitApp
}
textFont := scite.ResolveProp("default.text.font")
LocalSciTEPath := scite.UserDir
scitehwnd := scite.SciTEHandle
sdir = %LocalSciTEPath%\Scriptlets
IfNotExist, %sdir%
{
   MsgBox, 16, %progName%, Scriptlet folder doesn't exist!
   ExitApp
}
; Check command line
if 1 = /insert
{
   if 2 =
   {
      MsgBox, 64, %progName%, Usage: %A_ScriptName% /insert scriptletName
      ExitApp
   }
   IfNotExist, %sdir%\%2%.scriptlet
   {
      MsgBox, 52, %progName%,
      (LTrim
      Invalid scriptlet name: "%2%".
      Perhaps you have clicked on a toolbar icon whose scriptlet attached no longer exists?
      Press OK to edit the toolbar properties file.
      )
      IfMsgBox, Yes
         scite.OpenFile(LocalSciTEPath "\UserToolbar.properties")
      ExitApp
   }
   FileRead, text2insert, %sdir%\%2%.scriptlet
   gosub InsertDirect
   ExitApp
}
if 1 = /addScriptlet
{
   defaultScriptlet := scite.Selection
   if defaultScriptlet =
   {
      MsgBox, 16, %progName%, Nothing is selected!
      ExitApp
   }
   gosub AddBut ; that does it all
   if !_RC
   ExitApp ; Maybe the user has cancelled the action.
   MsgBox, 68, %progName%, Scriptlet added sucessfully. Do you want to open the scriptlet manager?
   IfMsgBox, Yes
      Reload ; no parameters are passed to script
   ExitApp
}
Gui, +MinSize Resize Owner%scitehwnd%
Gui, Add, Button, Section gAddBut, New
Gui, Add, Button, ys gRenBut, Rename
Gui, Add, Button, ys gSubBut, Delete
Gui, Add, ListBox, xs w160 h240 vMainListbox gSelectLB HScroll
Gui, Add, Button, ys Section gToolbarBut, Add to toolbar
Gui, Add, Button, ys gInsertBut, Insert into SciTE
Gui, Add, Button, ys gSaveBut, Save
Gui, Add, Button, ys gOpenInSciTE, Open in SciTE
Gui, Font, S9, %textFont%
Gui, Add, Edit, xs w320 h240 vScriptPane -Wrap WantTab HScroll
Gui, Show,, %progName%
selectQ =
defaultScriptlet =
gosub ListboxUpdate
return
GuiSize:
Anchor("MainListbox", "h")
Anchor("ScriptPane", "wh")
return
GuiGetPos(ctrl, guiId := "")
{
   guiId := guiId ? (guiId ":") : ""
   GuiControlGet, ov, %guiId%Pos, %ctrl%
   return {

   x: ovx, y: ovy, w: ovw, h: ovh }
x: ovx, y: ovy, w: ovw, h: ovh }

}
}
GuiClose:
ExitApp
SelectLB:
GuiControlGet, fname2open,, MainListbox
FileRead, scriptletText, %sdir%\%fname2open%.scriptlet
GuiControl,, ScriptPane, % scriptletText
Return
AddBut:
Gui +OwnDialogs
InputBox, fname2create, %progName%, Enter the name of the scriptlet to create:
if ErrorLevel
return
if !fname2create
return
fname2create := ValidateFilename(fname2create)
IfExist, %sdir%\%fname2create%.scriptlet
{
   gosub CompleteUpdate
   return
}
FileAppend, % defaultScriptlet, %sdir%\%fname2create%.scriptlet
gosub CompleteUpdate
_RC = 1
Return
CompleteUpdate:
selectQ = %fname2create%
gosub ListboxUpdate
selectQ =
if defaultScriptlet =
gosub SelectLB
return
SubBut:
Gui +OwnDialogs
GuiControlGet, selected,, MainListbox
if selected =
return
MsgBox, 52, %progName%, Are you sure you want to delete '%selected%'?
IfMsgBox, No
   return
FileDelete, %sdir%\%selected%.scriptlet
fname2create =
gosub CompleteUpdate
return
RenBut:
Gui +OwnDialogs
GuiControlGet, selected,, MainListbox
if selected =
return
InputBox, fname2create, %progName%, Enter the new name of the scriptlet:,,,,,,,, %selected%
if ErrorLevel
return
if !fname2create
return
if (fname2create = selected)
return
fname2create := ValidateFilename(fname2create)
IfExist, %sdir%\%fname2create%.scriptlet
{
   MsgBox, 48, %progName%, That name already exists!`nChoose another name please.
   return
}
FileMove, %sdir%\%selected%.scriptlet, %sdir%\%fname2create%.scriptlet
gosub CompleteUpdate
return
ToolbarBut:
GuiControlGet, selected,, MainListbox
if selected =
return
FileAppend, `n=Scriptlet: %selected%|`%LOCALAHK`% tools\SUtility.ahk /insert "%selected%"||`%ICONRES`%`,12, %LocalSciTEPath%\UserToolbar.properties
scite.Message(0x1000+2)
return
InsertBut:
GuiControlGet, text2insert,, ScriptPane
InsertDirect:
if text2insert =
return
WinActivate, ahk_id %scitehwnd%
scite.InsertText(text2insert)
return
SaveBut:
GuiControlGet, fname2save,, MainListbox
GuiControlGet, text2save,, ScriptPane
FileDelete, %sdir%\%fname2save%.scriptlet
FileAppend, % text2save, %sdir%\%fname2save%.scriptlet
return
OpenInSciTE:
GuiControlGet, fname2open,, MainListbox
if fname2open =
return
scite.OpenFile(sdir "\" fname2open ".scriptlet")
return
ListboxUpdate:
te =
Loop, %sdir%\*.scriptlet
{
   SplitPath, A_LoopFileName,,,, sn
   if sn =
   continue
   te = %te%|%sn%
   if selectQ = %sn%
   te .= "|"
}
GuiControl,, MainListbox, % te
return
ValidateFilename(fn)
{
   StringReplace, fn, fn, \, _, All
   StringReplace, fn, fn, /, _, All
   StringReplace, fn, fn, :, _, All
   StringReplace, fn, fn, *, _, All
   StringReplace, fn, fn, ?, _, All
   StringReplace, fn, fn, ", _, All
   StringReplace, fn, fn, <, _, All
   StringReplace, fn, fn, >, _, All
   StringReplace, fn, fn, |, _, All
    return fn
}


Fixed hardcoded path to hide.ahk

Fixed hardcoded path to hide.ahk

;Control key Ctrl- ^
;Alt key Alt- !
;Shift key Shift- +
;Windows key Win- #

#Persistent
#SingleInstance Force
DetectHiddenWindows, On
DetectHiddenText, On
SetTitleMatchMode, RegEx ;match titles and classes using regular expressions
SetTitleMatchMode Slow ;match titles and classes using regular expressions
CoordMode, Mouse, Screen
CoordMode, ToolTip, Screen
OldTicks = 0

;check for cygwin path
global CygPath
CygPath = C:\Program Files (x86)\cygwin
IfNotExist %CygPath%
	CygPath = C:\Cygwin

global BrowserPath
BrowserPath = C:\Program Files (x86)\Mozilla Firefox\firefox.exe
IfNotExist %BrowserPath%
	BrowserPath = "C:\Users\rr-\AppData\Local\Google\Chrome\Application\chrome.exe"

global IMClass
global IMPath

;pidgin
IMClass := "Buddy List"
IMPath := "C:\Program Files (x86)\pidgin\pidgin.exe"
If !FileExist(IMPath) {
	;wtw
	IMClass := "ahk_class {B993D471-D465-43f2-BBA5-DEEA18A1789E}"
	IMPath := "C:\Program Files\WTW\WTW.exe"
	If !FileExist(IMPath) {
		IMPath := "C:\Program Files\K2T\WTW\WTW.exe"
	}
}

global MonitorWorkAreaLeft
global MonitorWorkAreaRight
global MonitorWorkAreaTop
global MonitorWorkAreaBottom
SysGet, MonitorPrimary, MonitorPrimary
SysGet, MonitorWorkArea, MonitorWorkArea, %MonitorPrimary%

;disable windows+l
RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Policies\System, DisableLockWorkstation, 1

TermX := MonitorWorkAreaRight - 920
TermY := 45
RemoteTermX := 45
RemoteTermY := 45

;GroupAdd, adobe, ahk_class OWL.DocumentWindow
;GroupAdd, adobe, ahk_class illustrator
;GroupAdd, adobe, ahk_class PSViewC
;GroupAdd, adobe, ahk_class Photoshop
;GroupAdd, adobe, Photoshop

return

;replace stuff in clipboard when it changes
OnClipboardChange:
{
	if (A_EventInfo == 1) and (SubStr(clipboard, 1, 7) == "http://")
	{
		StringReplace, clipboard, clipboard, [, `%5b, All
		StringReplace, clipboard, clipboard, \, `%5c, All
		StringReplace, clipboard, clipboard, ], `%5d, All
	}
	return
}

;declare some fun functions...

AddTransparency(delta)
{
	WinGet, Transparency, Transparent, A
	if ! Transparency
		Transparency = 255
	Transparency := Transparency + delta
	if Transparency <= 10
	{
		WinSet, Transparent, 10, A
	}
	else if Transparency >= 255
	{
		WinSet, Transparent, 255, A
		WinSet, Transparent, OFF, A
	}
	else
	{
		WinSet, Transparent, %Transparency%, A
	}
	return
}

;activate/run a program
FRun(window, path, folder)
{
	if (!window or !WinExist(window))
	{
		Run, %path%, %folder%
	}
	else
	{
		WinShow
		WinActivate
	}
	return
}

;create random file name
RandomFileName()
{
	FormatTime, fileName,, yyyyMMdd_HHmmss_
	characters := "abcdefghijklmnopqrstuvwxyz"
	Loop 3
	{
		Random, rand, 1, strlen(characters)
		fileName := fileName . substr(characters, rand, 1)
	}
	return fileName
}

;calling screen script
MakeScreen(arguments)
{
	baseFileName := "Z:\" . RandomFileName() . ".png"
	RunWait, % "Z:\software\utilities\scrsh.exe --path " . baseFileName . " " . arguments, "Z:\", Hide
	SoundPlay, Z:\clutter\sounds\ping.wav
	return baseFileName
}

;focus window in given direction
DirectionalFocus(direction)
{
	DetectHiddenWindows, Off
	ActiveHwnd := WinExist("A")
	WinGetPos bx, by, _, _, ahk_id %ActiveHwnd%
	WinGet windows, List
	Loop %windows%
	{
		id := windows%A_Index%
		WinGetPos wx, wy, _, _, ahk_id %id%

		if (direction == "left")
			condition := wx < bx
		else if (direction == "right")
			condition := wx > bx
		else if (direction == "up")
			condition := wy < by
		else if (direction == "down")
			condition := wy > by
		else
		{
			MsgBox % "Bad direction"
			return
		}
		if (condition)
		{
			WinGetTitle, wtitle, ahk_id %id%
			if (wtitle != "")
			{
				WinActivate, ahk_id %id%
				break
			}
		}
	}
	DetectHiddenWindows, On
	return
}

#If FileExist(CygPath)
	;cygwin - activate/run
	#Enter::
	{
		Run, %CygPath%\bin\mintty.exe --title "Terminal" --size "110`,35" --position "%TermX%`,%TermY%" --class "mintty_thetty" --exec /bin/zsh -l, %CygPath%
		return
	}
	+^![::
	{
		Run, %CygPath%\bin\mintty.exe --title "Terminal" --size "110`,35" --position "%TermX%`,%TermY%" --class "mintty_thetty" --exec /bin/zsh -l, %CygPath%
		return
	}
	^![::
	{
		if (!WinExist("ahk_class mintty_thetty"))
		{
			Run, %CygPath%\bin\mintty.exe --title "Terminal" --size "110`,35" --position "%TermX%`,%TermY%" --class "mintty_thetty" --exec /bin/zsh -c 'while /bin/true`; do /bin/zsh -l`; cygstart "%A_AhkPath%" "%A_ScriptDir%\hide.ahk"`; clear; done', %CygPath%
			WinWait ahk_class mintty_thetty
		}
		else
		{
			WinShow
			WinActivate
		}
		return
	}
	;ssh to burza - activate/run
	+^!]::
	{
		Run, %CygPath%\bin\mintty.exe --title "Remote terminal" --size "190`,65" --position "%RemoteTermX%`,%RemoteTermY%" --class mintty_ssh --exec /bin/ssh burza, %CygPath%/bin
		return
	}
	^!]::
	{
		if (!WinExist("ahk_class mintty_ssh"))
		{
			Run, %CygPath%\bin\mintty.exe --title "Remote terminal" --size "190`,65" --position "%RemoteTermX%`,%RemoteTermY%" --class mintty_ssh --exec /bin/ssh burza, %CygPath%/bin
			WinWait ahk_class mintty_ssh
		}
		else
		{
			WinShow
			WinActivate
		}
		return
	}
	;text editor - activate/run + fix screen position
	+^!N::
	{
		IfWinExist, ahk_class Vim
		{
			WinShow
			WinActivate
		}
		else
		{
			Run, %CygPath%\bin\mintty.exe --size "180`,60" --position "100`,100" --class "Vim" --exec /bin/zsh -l -i -c /bin/vim, %CygPath%/bin
			WinWait, ahk_class Vim
		}
		return
	}
	+PrintScreen::MakeScreen("-g")
	!PrintScreen::MakeScreen("-r active-window --shift -8,-8,+16,+16 --force-gui")
	!#PrintScreen::MakeScreen("-r active-monitor")
	#PrintScreen::MakeScreen("-r all-monitors")

;explorer - activate/run
#E::FRun("ahk_class CabinetWClass", "Z:\", "Z:\")

;foobar - media shortcuts
#X::Send {Volume_Up}
+#X::Volume_Down
#C::Send {Media_Prev}
+#C::Media_Next
#V::Send {Media_Play_Pause}
+#V::FRun("ahk_class {97E27FAA-C0B3-4b8e-A693-ED7881E99FC1}", "C:\program files (x86)\foobar2000\foobar2000.exe", "C:\Program Files (x86)\foobar2000")

;im
#If FileExist(IMPath)
	;im - activate/run
	+^!M::
		if (!WinExist(IMClass))
		{
			Run, %IMPath% -x
		}
		else
		{
			WinShow
			WinActivate
		}
		return

;browser
#If FileExist(BrowserPath)
	;web browser - activate/run
	^!;::
		if WinExist("Mozilla Firefox")
		{
			WinShow
			WinActivate
			Send, !d
		}
		else if WinExist("Vimperator")
		{
			WinShow
			WinActivate
			Send, !d
		}
		else if WinExist("ahk_class Chrome_WidgetWin_1")
		{
			WinActivate
			ControlFocus, Chrome_OmniboxView1
			SendInput, {Home}+{End}
		}
		else
		{
			IfExist %BrowserPath%
				Run, %BrowserPath%
		}
		return

;windows powershell / cmd functionalities
#IfWinActive ahk_class ConsoleWindowClass
	+Insert::SendInput {Raw}%clipboard% ;paste on shift+insert
	+PgUp::SendInput ! {Up}{Up}{Up}{Right}{Up}{Up}{Enter}{PgUp}{Enter} ;scroll on shift+page up
	+PgDn::SendInput ! {Up}{Up}{Up}{Right}{Up}{Up}{Enter}{PgDn}{Enter} ;scroll on shift+page down
#IfWinActive

;other functionalities

;reload autohotkey
!F12::Reload

;maximize active window
!M::
	ActiveHwnd := WinExist("A")
	PostMessage 0x112, 0xf030 ;WM_SYSCOMMAND, SC_MAXIMIZE
	return

;restore active window
!R::
	ActiveHwnd := WinExist("A")
	PostMessage 0x112, 0xf120 ;WM_SYSCOMMAND, SC_RESTORE
	return

;minimize active window
!W::
	if WinActive("WTW$")
	{
		WinHide
	}
	else if WinActive("Buddy List")
	{
		WinHide
	}
	else
	{
		ActiveHwnd := WinExist("A")
		PostMessage 0x112, 0xF020 ;WM_SYSCOMMAND, SC_MINIMIZE
	}
	return

;always on top
!A::WinSet, AlwaysOnTop, Toggle, A

;transparency
#WheelUp::AddTransparency(16)
#WheelDown::AddTransparency(-16)
#Z::AddTransparency(-12)
+#Z::AddTransparency(12)

;explorer
#IfWinActive ahk_class CabinetWClass
	;new folder
	^n::
		SendInput {Up}{Ctrl Down}{Space}{Ctrl Up}{AppsKey}{Up}{Up}{Right}{Enter}
		return
#IfWinActive

;adobe products
#IfWinActive ahk_group adobe
	~LAlt::return
	LAlt UP::Send {Escape}
#IfWinActive

;shortcuts like in i3
;close active window
#Q::
	ActiveHwnd := WinExist("A")
	WinClose
	return
#D::
	SendInput, {LWin down}r{LWin up}
	return
#F::
	WinGet MX, MinMax, A
	if MX
		WinRestore A
	else
		WinMaximize A
	return
#H::DirectionalFocus("left")
#J::DirectionalFocus("down")
#K::DirectionalFocus("up")
#L::DirectionalFocus("right")
+#H::SendInput, {LWin down}{LShift down}{Left}{LShift up}{LWin up}
+#L::SendInput, {LWin down}{LShift down}{Right}{LShift up}{LWin up}

;Control key Ctrl- ^
;Alt key Alt- !
;Shift key Shift- +
;Windows key Win- #

#Persistent
#SingleInstance Force
DetectHiddenWindows, On
DetectHiddenText, On
SetTitleMatchMode, RegEx ;match titles and classes using regular expressions
SetTitleMatchMode Slow ;match titles and classes using regular expressions
CoordMode, Mouse, Screen
CoordMode, ToolTip, Screen
OldTicks = 0

;check for cygwin path
global CygPath
CygPath = C:\Program Files (x86)\cygwin
IfNotExist %CygPath%
	CygPath = C:\Cygwin

global BrowserPath
BrowserPath = C:\Program Files (x86)\Mozilla Firefox\firefox.exe
IfNotExist %BrowserPath%
	BrowserPath = "C:\Users\rr-\AppData\Local\Google\Chrome\Application\chrome.exe"

global IMClass
global IMPath

;pidgin
IMClass := "Buddy List"
IMPath := "C:\Program Files (x86)\pidgin\pidgin.exe"
If !FileExist(IMPath) {
	;wtw
	IMClass := "ahk_class {B993D471-D465-43f2-BBA5-DEEA18A1789E}"
	IMPath := "C:\Program Files\WTW\WTW.exe"
	If !FileExist(IMPath) {
		IMPath := "C:\Program Files\K2T\WTW\WTW.exe"
	}
}

global MonitorWorkAreaLeft
global MonitorWorkAreaRight
global MonitorWorkAreaTop
global MonitorWorkAreaBottom
SysGet, MonitorPrimary, MonitorPrimary
SysGet, MonitorWorkArea, MonitorWorkArea, %MonitorPrimary%

;disable windows+l
RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Policies\System, DisableLockWorkstation, 1

TermX := MonitorWorkAreaRight - 920
TermY := 45
RemoteTermX := 45
RemoteTermY := 45

;GroupAdd, adobe, ahk_class OWL.DocumentWindow
;GroupAdd, adobe, ahk_class illustrator
;GroupAdd, adobe, ahk_class PSViewC
;GroupAdd, adobe, ahk_class Photoshop
;GroupAdd, adobe, Photoshop

return

;replace stuff in clipboard when it changes
OnClipboardChange:
{
	if (A_EventInfo == 1) and (SubStr(clipboard, 1, 7) == "http://")
	{
		StringReplace, clipboard, clipboard, [, `%5b, All
		StringReplace, clipboard, clipboard, \, `%5c, All
		StringReplace, clipboard, clipboard, ], `%5d, All
	}
	return
}

;declare some fun functions...

AddTransparency(delta)
{
	WinGet, Transparency, Transparent, A
	if ! Transparency
		Transparency = 255
	Transparency := Transparency + delta
	if Transparency <= 10
	{
		WinSet, Transparent, 10, A
	}
	else if Transparency >= 255
	{
		WinSet, Transparent, 255, A
		WinSet, Transparent, OFF, A
	}
	else
	{
		WinSet, Transparent, %Transparency%, A
	}
	return
}

;activate/run a program
FRun(window, path, folder)
{
	if (!window or !WinExist(window))
	{
		Run, %path%, %folder%
	}
	else
	{
		WinShow
		WinActivate
	}
	return
}

;create random file name
RandomFileName()
{
	FormatTime, fileName,, yyyyMMdd_HHmmss_
	characters := "abcdefghijklmnopqrstuvwxyz"
	Loop 3
	{
		Random, rand, 1, strlen(characters)
		fileName := fileName . substr(characters, rand, 1)
	}
	return fileName
}

;calling screen script
MakeScreen(arguments)
{
	baseFileName := "Z:\" . RandomFileName() . ".png"
	RunWait, % "Z:\software\utilities\scrsh.exe --path " . baseFileName . " " . arguments, "Z:\", Hide
	SoundPlay, Z:\clutter\sounds\ping.wav
	return baseFileName
}

;focus window in given direction
DirectionalFocus(direction)
{
	DetectHiddenWindows, Off
	ActiveHwnd := WinExist("A")
	WinGetPos bx, by, _, _, ahk_id %ActiveHwnd%
	WinGet windows, List
	Loop %windows%
	{
		id := windows%A_Index%
		WinGetPos wx, wy, _, _, ahk_id %id%

		if (direction == "left")
			condition := wx < bx
		else if (direction == "right")
			condition := wx > bx
		else if (direction == "up")
			condition := wy < by
		else if (direction == "down")
			condition := wy > by
		else
		{
			MsgBox % "Bad direction"
			return
		}
		if (condition)
		{
			WinGetTitle, wtitle, ahk_id %id%
			if (wtitle != "")
			{
				WinActivate, ahk_id %id%
				break
			}
		}
	}
	DetectHiddenWindows, On
	return
}

#If FileExist(CygPath)
	;cygwin - activate/run
	#Enter::
	{
		Run, %CygPath%\bin\mintty.exe --title "Terminal" --size "110`,35" --position "%TermX%`,%TermY%" --class "mintty_thetty" --exec /bin/zsh -l, %CygPath%
		return
	}
	+^![::
	{
		Run, %CygPath%\bin\mintty.exe --title "Terminal" --size "110`,35" --position "%TermX%`,%TermY%" --class "mintty_thetty" --exec /bin/zsh -l, %CygPath%
		return
	}
	^![::
	{
		if (!WinExist("ahk_class mintty_thetty"))
		{
			Run, %CygPath%\bin\mintty.exe --title "Terminal" --size "110`,35" --position "%TermX%`,%TermY%" --class "mintty_thetty" --exec /bin/zsh -c 'while /bin/true`; do /bin/zsh -l`; cygstart "%A_AhkPath%" "Z:\src\dotfiles\hide.ahk"`; clear; done', %CygPath%
			WinWait ahk_class mintty_thetty
		}
		else
		{
			WinShow
			WinActivate
		}
		return
	}
	;ssh to burza - activate/run
	+^!]::
	{
		Run, %CygPath%\bin\mintty.exe --title "Remote terminal" --size "190`,65" --position "%RemoteTermX%`,%RemoteTermY%" --class mintty_ssh --exec /bin/ssh burza, %CygPath%/bin
		return
	}
	^!]::
	{
		if (!WinExist("ahk_class mintty_ssh"))
		{
			Run, %CygPath%\bin\mintty.exe --title "Remote terminal" --size "190`,65" --position "%RemoteTermX%`,%RemoteTermY%" --class mintty_ssh --exec /bin/ssh burza, %CygPath%/bin
			WinWait ahk_class mintty_ssh
		}
		else
		{
			WinShow
			WinActivate
		}
		return
	}
	;text editor - activate/run + fix screen position
	+^!N::
	{
		IfWinExist, ahk_class Vim
		{
			WinShow
			WinActivate
		}
		else
		{
			Run, %CygPath%\bin\mintty.exe --size "180`,60" --position "100`,100" --class "Vim" --exec /bin/zsh -l -i -c /bin/vim, %CygPath%/bin
			WinWait, ahk_class Vim
		}
		return
	}
	+PrintScreen::MakeScreen("-g")
	!PrintScreen::MakeScreen("-r active-window --shift -8,-8,+16,+16 --force-gui")
	!#PrintScreen::MakeScreen("-r active-monitor")
	#PrintScreen::MakeScreen("-r all-monitors")

;explorer - activate/run
#E::FRun("ahk_class CabinetWClass", "Z:\", "Z:\")

;foobar - media shortcuts
#X::Send {Volume_Up}
+#X::Volume_Down
#C::Send {Media_Prev}
+#C::Media_Next
#V::Send {Media_Play_Pause}
+#V::FRun("ahk_class {97E27FAA-C0B3-4b8e-A693-ED7881E99FC1}", "C:\program files (x86)\foobar2000\foobar2000.exe", "C:\Program Files (x86)\foobar2000")

;im
#If FileExist(IMPath)
	;im - activate/run
	+^!M::
		if (!WinExist(IMClass))
		{
			Run, %IMPath% -x
		}
		else
		{
			WinShow
			WinActivate
		}
		return

;browser
#If FileExist(BrowserPath)
	;web browser - activate/run
	^!;::
		if WinExist("Mozilla Firefox")
		{
			WinShow
			WinActivate
			Send, !d
		}
		else if WinExist("Vimperator")
		{
			WinShow
			WinActivate
			Send, !d
		}
		else if WinExist("ahk_class Chrome_WidgetWin_1")
		{
			WinActivate
			ControlFocus, Chrome_OmniboxView1
			SendInput, {Home}+{End}
		}
		else
		{
			IfExist %BrowserPath%
				Run, %BrowserPath%
		}
		return

;windows powershell / cmd functionalities
#IfWinActive ahk_class ConsoleWindowClass
	+Insert::SendInput {Raw}%clipboard% ;paste on shift+insert
	+PgUp::SendInput ! {Up}{Up}{Up}{Right}{Up}{Up}{Enter}{PgUp}{Enter} ;scroll on shift+page up
	+PgDn::SendInput ! {Up}{Up}{Up}{Right}{Up}{Up}{Enter}{PgDn}{Enter} ;scroll on shift+page down
#IfWinActive

;other functionalities

;reload autohotkey
!F12::Reload

;maximize active window
!M::
	ActiveHwnd := WinExist("A")
	PostMessage 0x112, 0xf030 ;WM_SYSCOMMAND, SC_MAXIMIZE
	return

;restore active window
!R::
	ActiveHwnd := WinExist("A")
	PostMessage 0x112, 0xf120 ;WM_SYSCOMMAND, SC_RESTORE
	return

;minimize active window
!W::
	if WinActive("WTW$")
	{
		WinHide
	}
	else if WinActive("Buddy List")
	{
		WinHide
	}
	else
	{
		ActiveHwnd := WinExist("A")
		PostMessage 0x112, 0xF020 ;WM_SYSCOMMAND, SC_MINIMIZE
	}
	return

;always on top
!A::WinSet, AlwaysOnTop, Toggle, A

;transparency
#WheelUp::AddTransparency(16)
#WheelDown::AddTransparency(-16)
#Z::AddTransparency(-12)
+#Z::AddTransparency(12)

;explorer
#IfWinActive ahk_class CabinetWClass
	;new folder
	^n::
		SendInput {Up}{Ctrl Down}{Space}{Ctrl Up}{AppsKey}{Up}{Up}{Right}{Enter}
		return
#IfWinActive

;adobe products
#IfWinActive ahk_group adobe
	~LAlt::return
	LAlt UP::Send {Escape}
#IfWinActive

;shortcuts like in i3
;close active window
#Q::
	ActiveHwnd := WinExist("A")
	WinClose
	return
#D::
	SendInput, {LWin down}r{LWin up}
	return
#F::
	WinGet MX, MinMax, A
	if MX
		WinRestore A
	else
		WinMaximize A
	return
#H::DirectionalFocus("left")
#J::DirectionalFocus("down")
#K::DirectionalFocus("up")
#L::DirectionalFocus("right")
+#H::SendInput, {LWin down}{LShift down}{Left}{LShift up}{LWin up}
+#L::SendInput, {LWin down}{LShift down}{Right}{LShift up}{LWin up}


Bump version to 0.2.0

Bump version to 0.2.0

/*
 * Microphone Status
 *
 * Shows the current status of the microphone (or really any device)
 *
 * Requirements:
 *     - AutoHotkey v1.1.+ (maybe)
 */

VERSION := "0.2.0"

; BUG: if some fatal error happens and app closes it doesn't close the whole
; application. Thus needs this to say only have one running.
#SingleInstance force
#NoEnv

; TODO: move to config file / create a config screen
;device_id := 8
;component_type := "Master"
IniRead, device_id, config.ini, sound_device, device_id
IniRead, component_type, config.ini, sound_device, component_type
IniRead, always_on_top, config.ini, app, always_on_top, True
IniRead, mute_hotkey, config.ini, app, mute_hotkey, ^!m

; shouldn't have to change these
refresh_rate := 2000  ; in msec, 500 is probably as low as you should go
muted_img := "img_muted.png"
unmuted_img := "img_unmuted.png"

; Error Checking
if (FileExist(muted_img) = "") {
    MsgBox, Muted image file %muted_img% does not exist
    ExitApp
}
if (FileExist(unmuted_img) = "") {
    MsgBox, Unmuted image file %unmuted_img% does not exist
    ExitApp
}

gosub GetMicrophoneStatus

gui_options := ""
if always_on_top = True
    gui_options := "+AlwaysOnTop"

Gui %gui_options%
Gui Add, Picture, vMicStatus gToggleMicOnClick, %microphone_status%
Gui Show,, Microphone Status

SetTimer, UpdateMicrophoneStatus, %refresh_rate%

Hotkey, %mute_hotkey%, ToggleMicOnHotkey

return

; Toggles the microphone status when double-clicked
ToggleMicOnClick:
    if (A_GuiEvent = "DoubleClick")
        SoundSet, +1, %component_type%, Mute, %device_id%
        gosub UpdateMicrophoneStatus
return

; Toggles the microphone status when hotkey is used
; Had to be separate function for the double click check to work
ToggleMicOnHotkey:
    SoundSet, +1, %component_type%, Mute, %device_id%
    gosub UpdateMicrophoneStatus
return

; sets the microphone_status variable
GetMicrophoneStatus:
    SoundGet, microphone_state, %component_type%, Mute, %device_id%
    if ErrorLevel {
        MsgBox, Could not get microphone state: %ErrorLevel%
        ExitApp
    }

    ; On = Mute is confusing
    if microphone_state = On
        microphone_status = %muted_img%
    else
        microphone_status = %unmuted_img%
return

; updates the status of microphone if it changed
UpdateMicrophoneStatus:
    prev_status = %microphone_status%
    ;MsgBox, Previous status: %prev_status%
    gosub GetMicrophoneStatus
    if (prev_status != microphone_status)
        GuiControl,, MicStatus, %microphone_status%
return

GuiEscape:
GuiClose:
ExitApp

/*
 * Microphone Status
 *
 * Shows the current status of the microphone (or really any device)
 *
 * Requirements:
 *     - AutoHotkey v1.1.+ (maybe)
 */

VERSION := "0.0.1"

; BUG: if some fatal error happens and app closes it doesn't close the whole
; application. Thus needs this to say only have one running.
#SingleInstance force
#NoEnv

; TODO: move to config file / create a config screen
;device_id := 8
;component_type := "Master"
IniRead, device_id, config.ini, sound_device, device_id
IniRead, component_type, config.ini, sound_device, component_type
IniRead, always_on_top, config.ini, app, always_on_top, True
IniRead, mute_hotkey, config.ini, app, mute_hotkey, ^!m

; shouldn't have to change these
refresh_rate := 2000  ; in msec, 500 is probably as low as you should go
muted_img := "img_muted.png"
unmuted_img := "img_unmuted.png"

; Error Checking
if (FileExist(muted_img) = "") {
    MsgBox, Muted image file %muted_img% does not exist
    ExitApp
}
if (FileExist(unmuted_img) = "") {
    MsgBox, Unmuted image file %unmuted_img% does not exist
    ExitApp
}

gosub GetMicrophoneStatus

gui_options := ""
if always_on_top = True
    gui_options := "+AlwaysOnTop"

Gui %gui_options%
Gui Add, Picture, vMicStatus gToggleMicOnClick, %microphone_status%
Gui Show,, Microphone Status

SetTimer, UpdateMicrophoneStatus, %refresh_rate%

Hotkey, %mute_hotkey%, ToggleMicOnHotkey

return

; Toggles the microphone status when double-clicked
ToggleMicOnClick:
    if (A_GuiEvent = "DoubleClick")
        SoundSet, +1, %component_type%, Mute, %device_id%
        gosub UpdateMicrophoneStatus
return

; Toggles the microphone status when hotkey is used
; Had to be separate function for the double click check to work
ToggleMicOnHotkey:
    SoundSet, +1, %component_type%, Mute, %device_id%
    gosub UpdateMicrophoneStatus
return

; sets the microphone_status variable
GetMicrophoneStatus:
    SoundGet, microphone_state, %component_type%, Mute, %device_id%
    if ErrorLevel {
        MsgBox, Could not get microphone state: %ErrorLevel%
        ExitApp
    }

    ; On = Mute is confusing
    if microphone_state = On
        microphone_status = %muted_img%
    else
        microphone_status = %unmuted_img%
return

; updates the status of microphone if it changed
UpdateMicrophoneStatus:
    prev_status = %microphone_status%
    ;MsgBox, Previous status: %prev_status%
    gosub GetMicrophoneStatus
    if (prev_status != microphone_status)
        GuiControl,, MicStatus, %microphone_status%
return

GuiEscape:
GuiClose:
ExitApp