DC 插件：增强 <DC_PrevParallelDir> 和 <DC_NextParallelDir> 的稳定性

/*
    此插件仅供自用，依赖对 DC 代码的修改以及专门的配置

    ---

    DC 的优势

    开源，免费，跨平台，可以自由改代码定制功能，很好编译
    可以改代码让所有目录中的父目录（..）消失（已完成）
    可以把按键绑定到工具栏的子菜单上，然后再通过按键触发功能
    内建 lua 解释器，方便写一些高级功能（感觉功能有限，用处不大）
    主界面和配置界面更漂亮、好用
*/

DoubleCommander:
    global DC_Class := "TTOTAL_CMD"
    global DC := "ahk_class " . DC_Class
    global DC_Dir := "c:\mine\app\doublecmd"
    global DC_Path := "c:\mine\app\doublecmd\doublecmd.exe --no-splash"
    ; 用于记录文件打开对话框所属窗体
    global DC_CallerId := 0

    DC_Name := "DoubleCommander"

    Vim.SetWin(DC_Name, DC_Class, "doublecmd.exe")
    Vim.Mode("normal", DC_Name)

    Vim.BeforeActionDo("DC_ForceInsertMode", DC_Name)
return

DC_ForceInsertMode() {
    ControlGetFocus, Ctrl
    if (InStr(Ctrl, "Edit") == 1) {
        return true
    }

    WinGet, MenuID, ID, AHK_CLASS #32768
    if (MenuID != "") {
        return true
    }

    return false
}

DC_Run(Cmd) {
    ControlSetText, Edit1, % Cmd, % DC
    ControlSend, Edit1, {Enter}, % DC
}

; 返回值 [1]: left/right [2]: 左侧面板所占比例 0-100
DC_GetPanelInfo() {
    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyPanelInfoToClip")
    ClipWait, 1

    PanelInfo := StrSplit(Clipboard, " ")
    Clipboard := ClipSaved

    return PanelInfo
}

DC_ExecuteToolbarItem(ID) {
    DC_Run("cm_ExecuteToolbarItem ToolItemID=" . ID)
}

DC_OpenPath(Path, InNewTab := true, LeftOrRight := "") {
    LeftOfRight := DC_GetPanelInfo()[1]
    if (LeftOfRight == "right") {
        LeftOrRight := "-R"
    } else {
        LeftOrRight := "-L"
    }

    if (InNewTab) {
        Run, %DC_Path% -C -T "%LeftOrRight%" "%Path%"
    } else {
        Run, %DC_Path% -C "%LeftOrRight%" "%Path%"
    }
}

; funcend

<DC_Test>:
    ; DC_ExecuteToolbarItem("{700FF494-B939-48A3-B248-8823EB366AEA}")
    DC_Run("cm_About")
return

<DC_Restart>:
    WinClose, % DC
    WinWaitClose, % DC, , 2

    Run, % DC_Path

    WinWaitActive, % DC

    if (!WinExist(DC)) {
        MsgBox, 重启失败 %ErrorMessage%
    }
return

<DC_Toggle_50_100>:
    PanelInfo := DC_GetPanelInfo()

    if (Abs(50 - PanelInfo[2]) < 10) {
        if (PanelInfo[1] == "left") {
            DC_Run("cm_PanelsSplitterPerPos splitpct=100")
        } else {
            DC_Run("cm_PanelsSplitterPerPos splitpct=0")
        }
    } else {
        DC_Run("cm_PanelsSplitterPerPos splitpct=50")
    }
return

<DC_PrevParallelDir>:
    SleepTime := 10

    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    OldPwd := Clipboard

    if (InStr(OldPwd, "\") == 1) {
        ; 网络文件系统比较慢
        SleepTime := 50
    }

    if (StrLen(OldPwd) == 3) {
        ; 在根分区

        Clipboard := ClipSaved
        ClipSaved := ""

        return
    }

    DC_Run("cm_ChangeDirToParent")
    Sleep, % SleepTime

    DC_Run("cm_GoToPrevEntry")
    Sleep, % SleepTime

    DC_Run("cm_EnterActiveDir")
    Sleep, % SleepTime

    Clipboard := ClipSaved
    ClipSaved := ""
return

<DC_NextParallelDir>:
    SleepTime := 10

    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    OldPwd := Clipboard

    if (InStr(OldPwd, "\") == 1) {
        ; 网络文件系统比较慢
        SleepTime := 50
    }

    if (StrLen(OldPwd) == 3) {
        ; 在根分区
        ; Gosub, <cm_GotoPreviousDrive>

        Clipboard := ClipSaved
        ClipSaved := ""

        return
    }

    DC_Run("cm_ChangeDirToParent")
    Sleep, % SleepTime

    DC_Run("cm_GoToNextEntry")
    Sleep, % SleepTime

    DC_Run("cm_EnterActiveDir")
    Sleep, % SleepTime

    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1
    Sleep, % SleepTime

    if (OldPwd != Clipboard && InStr(OldPwd, Clipboard) == 1) {
        ; 下一个是文件
        DC_Run("cm_ViewHistoryPrev")
    }

    Clipboard := ClipSaved
    ClipSaved := ""
return

<DC_CreateNewFile>:
    ControlGetFocus, TLB, % DC
    ControlGetPos, Xn, Yn, , , % TLB, % DC

    Menu, NewFileMenu, Add
    Menu, NewFileMenu, DeleteAll
    Menu, NewFileMenu, Add , S >> 快捷方式, <DC_CreateFileShortcut>
    Menu, NewFileMenu, Icon, S >> 快捷方式, %A_WinDir%\system32\Shell32.dll, 264
    Menu, NewFileMenu, Add

    Loop, % DC_Dir . "\shellnew\*.*" {
        Ft := SubStr(A_LoopFileName, 1, 1) . " >> " . A_LoopFileName
        Menu, NewFileMenu, Add, % Ft, DC_NewFileMenuAction
        Menu, NewFileMenu, Icon, % Ft, %A_WinDir%\system32\Shell32.dll
    }

    Menu, NewFileMenu, Show, % Xn, % Yn + 2
return

DC_NewFileMenuAction:
    Filename := RegExReplace(A_ThisMenuItem, ".\s>>\s")
    FilePath := DC_Dir . "\ShellNew\" . Filename

    Gui, Destroy
    Gui, Add, Text, x12 y20 w50 h20 +Center, 模板源
    Gui, Add, Edit, x72 y20 w300 h20 Disabled, % FilePath
    Gui, Add, Text, x12 y50 w50 h20 +Center, 新建文件
    Gui, Add, Edit, x72 y50 w300 h20, % Filename
    Gui, Add, Button, x162 y80 w90 h30 gDC_NewFileOk default, 确认(&S)
    Gui, Add, Button, x282 y80 w90 h30 gDC_NewFileClose , 取消(&C)
    Gui, Show, w400 h120, 新建文件

    if (InStr(Filename, ".")) {
        ; 只选定扩展名之外的文件名
        PostMessage, 0x0B1, 0, % InStr(Filename, ".") - 1, Edit2, A
    }
return

DC_NewFileClose:
    Gui, Destroy
return

DC_NewFileOK:
    GuiControlGet, SrcFilePath, , Edit1
    GuiControlGet, NewFilename, , Edit2

    ClipSaved := ClipboardAll
    Clipboard :=
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1
    DstPath := Clipboard
    Clipboard := ClipSaved
    ClipSaved := ""

    if (InStr(DstPath, "`r")) {
        DstPath := SubStr(DstPath, 1, InStr(DstPath, "`r") - 1)
    } else if (DstPath == "") {
        return
    }

    NewFilePath := DstPath . NewFilename
    if (FileExist(NewFilePath)) {
        MsgBox, 4, 新建文件, 新建文件已存在，是否覆盖？
        IfMsgBox No
            return
    }

    FileCopy, % SrcFilePath, % NewFilePath, 1

    ; 虽然不是完全匹配，基本也能用了
    DC_Run("cm_QuickSearch matchbeginning=on | text=" . NewFilename)

    Gui, Destroy
return

<DC_Toggle>:
    if (WinExist(DC)) {
        WinGet, Ac, MinMax, % DC
        if (Ac == -1) {
            WinActivate, % DC
        } else {
            if (!WinActive(DC)) {
                WinActivate, % DC
            } else {
                WinMinimize, % DC
            }
        }
    } else {
        Run, % DC_Path
        WinWait, % DC

        if (!WinActive(DC)) {
            WinActivate, % DC
        }
    }
return

<DC_MarkFile>:
    DC_Run("cm_EditComment")
    ; 不要在已有备注的文件使用
    Send, ^+{End}🖥{F2}
return

<DC_UnMarkFile>:
    DC_Run("cm_EditComment")
    ; 删除 DC_MarkFile 的文件标记，也可用于清空文件备注
    Send, ^+{End}{Del}{F2}
return

<DC_ToggleShowInfo>:
    Vim.GetWin(DC_Name).SetInfo(!Vim.GetWin(DC_Name).info)
return

<DC_CopyFileContent>:
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait, 1

    Fileread, Contents, % Clipboard
    Clipboard := Contents
return

<DC_CopyFilenamesOnly>:
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait, 1

    SplitPath, Clipboard, OutFileName, , , OutFilenameNoExt

    if (InStr(FileExist(Clipboard), "D")) {
        Clipboard := OutFileName
    } else if (InStr(Clipboard, ".")) {
        Clipboard := OutFilenameNoExt
    }
return

<DC_CreateFileShortcut>:
    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait

    FilePath := Clipboard
    Clipboard := ClipSaved
    ClipSaved := ""

    OutVar := FileExist(FilePath)
    if (InStr(OutVar, "D")) {
        FileCreateShortcut, % FilePath, % FilePath . ".lnk"
    } else if (OutVar != "") {
        FileCreateShortcut, % FilePath, % RegExReplace(FilePath, "\.[^.]*$", ".lnk")
    }
return

<DC_Focus>:
    IfWinExist, % DC
        Winactivate, % DC
    else {
        Run, % DC_Path
        WinWait, % DC
        IfWinNotActive, % DC
            WinActivate, % DC
    }
return

<DC_MapKeys>:
	Vim.Mode("normal", DC_Name)
    Vim.Map("<S-Enter>", "<DC_SelectedCurrentDir>", DC_Name)
    Vim.Map("<Esc>", "<DC_ReturnToCaller>", DC_Name)
return

<DC_UnMapKeys>:
	Vim.Mode("normal", DC_Name)
    Vim.Map("<S-Enter>", "<Default>", DC_Name)
    Vim.Map("<Esc>", "<Default>", DC_Name)
return

; 返回调用者
<DC_ReturnToCaller>:
    gosub <DC_UnMapKeys>

    WinActivate, ahk_id %DC_CallerId%

    DC_CallerId := 0
return

; 非 TC 窗口按下后激活 TC 窗口
; TC 窗口按下后复制当前选中文件返回原窗口后粘贴
<DC_OpenDCDialog>:
    WinGetClass, name, A

    ; 在 DC 按下快捷键时，激活调用窗体并执行粘贴操作
    if (name == DC_Class) {
        if (DC_CallerId != 0) {
            gosub <DC_Selected>
            DC_CallerId := 0
		}
    } else {
        DC_CallerId := WinExist("A")
        if (DC_CallerId == 0) {
            return
		}

        gosub <DC_Focus>
        gosub <DC_MapKeys>
    }
return

<DC_Selected>:
    gosub <DC_UnMapKeys>

    Clipboard := ""
    ; 不知道什么原因，必须加一个 MsgBox 功能才正常
    MsgBox, , , 处理中, 0.3

    DC_Run("cm_CopyCurrentPathToClip")

    ClipWait, 1
    Pwd := Clipboard

    Clipboard := ""
    DC_Run("cm_CopyNamesToClip")
    ClipWait, 1

    WinActivate, ahk_id %DC_CallerId%
    WinWait, ahk_id %DC_CallerId%
    DC_CallerId := 0

    if (!InStr(Clipboard, "`n")) {
        Clipboard := Pwd . Clipboard
        Send, {Home}
        Send, ^v
        Send, {Enter}

        return
    }

    ; 多选

    Files := ""
    Loop, parse, Clipboard, `n, `r
        Files .= """" . A_LoopField  . """ "

    ; 第一步：跳转到当前路径
    Clipboard := Pwd
    Send, ^a
    Send, ^v
    Send, {Enter}
    sleep, 100

    ; 第二步：提交文件名
    Clipboard := Files
    Send, ^v
    Send, {Enter}
return

<DC_SelectedCurrentDir>:
    gosub <DC_UnMapKeys>

    if (DC_CallerId == 0) {
        return
    }

    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait

    ; 添加默认路径不带反斜杠，添加之

    Clipboard .= "\"

    WinActivate, ahk_id %DC_CallerId%
    WinWait, ahk_id %DC_CallerId%
    DC_CallerId := 0

    Send, {Home}
    Send, ^v
    Send, {Enter}
return

<DC_FlatViewSel>:
    DC_Run("cm_FlatViewSel")
return

/*
    此插件仅供自用，依赖对 DC 代码的修改以及专门的配置

    ---

    DC 的优势

    开源，免费，跨平台，可以自由改代码定制功能，很好编译
    可以改代码让所有目录中的父目录（..）消失（已完成）
    可以把按键绑定到工具栏的子菜单上，然后再通过按键触发功能
    内建 lua 解释器，方便写一些高级功能（感觉功能有限，用处不大）
    主界面和配置界面更漂亮、好用
*/

DoubleCommander:
    global DC_Class := "TTOTAL_CMD"
    global DC := "ahk_class " . DC_Class
    global DC_Dir := "c:\mine\app\doublecmd"
    global DC_Path := "c:\mine\app\doublecmd\doublecmd.exe --no-splash"
    ; 用于记录文件打开对话框所属窗体
    global DC_CallerId := 0

    DC_Name := "DoubleCommander"

    Vim.SetWin(DC_Name, DC_Class, "doublecmd.exe")
    Vim.Mode("normal", DC_Name)

    Vim.BeforeActionDo("DC_ForceInsertMode", DC_Name)
return

DC_ForceInsertMode() {
    ControlGetFocus, Ctrl
    if (InStr(Ctrl, "Edit") == 1) {
        return true
    }

    WinGet, MenuID, ID, AHK_CLASS #32768
    if (MenuID != "") {
        return true
    }

    return false
}

DC_Run(Cmd) {
    ControlSetText, Edit1, % Cmd, % DC
    ControlSend, Edit1, {Enter}, % DC
}

; 返回值 [1]: left/right [2]: 左侧面板所占比例 0-100
DC_GetPanelInfo() {
    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyPanelInfoToClip")
    ClipWait, 1

    PanelInfo := StrSplit(Clipboard, " ")
    Clipboard := ClipSaved

    return PanelInfo
}

DC_ExecuteToolbarItem(ID) {
    DC_Run("cm_ExecuteToolbarItem ToolItemID=" . ID)
}

DC_OpenPath(Path, InNewTab := true, LeftOrRight := "") {
    LeftOfRight := DC_GetPanelInfo()[1]
    if (LeftOfRight == "right") {
        LeftOrRight := "-R"
    } else {
        LeftOrRight := "-L"
    }

    if (InNewTab) {
        Run, %DC_Path% -C -T "%LeftOrRight%" "%Path%"
    } else {
        Run, %DC_Path% -C "%LeftOrRight%" "%Path%"
    }
}

; funcend

<DC_Test>:
    ; DC_ExecuteToolbarItem("{700FF494-B939-48A3-B248-8823EB366AEA}")
    DC_Run("cm_About")
return

<DC_Restart>:
    WinClose, % DC
    WinWaitClose, % DC, , 2

    Run, % DC_Path

    WinWaitActive, % DC

    if (!WinExist(DC)) {
        MsgBox, 重启失败 %ErrorMessage%
    }
return

<DC_Toggle_50_100>:
    PanelInfo := DC_GetPanelInfo()

    if (Abs(50 - PanelInfo[2]) < 10) {
        if (PanelInfo[1] == "left") {
            DC_Run("cm_PanelsSplitterPerPos splitpct=100")
        } else {
            DC_Run("cm_PanelsSplitterPerPos splitpct=0")
        }
    } else {
        DC_Run("cm_PanelsSplitterPerPos splitpct=50")
    }
return

<DC_PreviousParallelDir>:
    SleepTime := 10

    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    OldPwd := Clipboard

    if (InStr(OldPwd, "\") == 1) {
        ; 网络文件系统比较慢
        SleepTime := 50
    }

    if (StrLen(OldPwd) == 3) {
        ; 在根分区

        Clipboard := ClipSaved
        ClipSaved := ""

        return
    }

    DC_Run("cm_ChangeDirToParent")
    Sleep, % SleepTime

    DC_Run("cm_GoToPrevEntry")
    Sleep, % SleepTime

    Send, {Right}

    Clipboard := ClipSaved
    ClipSaved := ""
return

<DC_NextParallelDir>:
    SleepTime := 10

    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    OldPwd := Clipboard

    if (InStr(OldPwd, "\") == 1) {
        ; 网络文件系统比较慢
        SleepTime := 50
    }

    if (StrLen(OldPwd) == 3) {
        ; 在根分区
        ; Gosub, <cm_GotoPreviousDrive>

        Clipboard := ClipSaved
        ClipSaved := ""

        return
    }

    DC_Run("cm_ChangeDirToParent")
    Sleep, % SleepTime

    DC_Run("cm_GoToNextEntry")
    Sleep, % SleepTime

    Send, {Right}
    Sleep, % SleepTime

    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1

    if (OldPwd != Clipboard && InStr(OldPwd, Clipboard) == 1) {
        ; 下一个是文件
        DC_Run("cm_ViewHistoryPrev")
    }

    Clipboard := ClipSaved
    ClipSaved := ""
return

<DC_CreateNewFile>:
    ControlGetFocus, TLB, % DC
    ControlGetPos, Xn, Yn, , , % TLB, % DC

    Menu, NewFileMenu, Add
    Menu, NewFileMenu, DeleteAll
    Menu, NewFileMenu, Add , S >> 快捷方式, <DC_CreateFileShortcut>
    Menu, NewFileMenu, Icon, S >> 快捷方式, %A_WinDir%\system32\Shell32.dll, 264
    Menu, NewFileMenu, Add

    Loop, % DC_Dir . "\shellnew\*.*" {
        Ft := SubStr(A_LoopFileName, 1, 1) . " >> " . A_LoopFileName
        Menu, NewFileMenu, Add, % Ft, DC_NewFileMenuAction
        Menu, NewFileMenu, Icon, % Ft, %A_WinDir%\system32\Shell32.dll
    }

    Menu, NewFileMenu, Show, % Xn, % Yn + 2
return

DC_NewFileMenuAction:
    Filename := RegExReplace(A_ThisMenuItem, ".\s>>\s")
    FilePath := DC_Dir . "\ShellNew\" . Filename

    Gui, Destroy
    Gui, Add, Text, x12 y20 w50 h20 +Center, 模板源
    Gui, Add, Edit, x72 y20 w300 h20 Disabled, % FilePath
    Gui, Add, Text, x12 y50 w50 h20 +Center, 新建文件
    Gui, Add, Edit, x72 y50 w300 h20, % Filename
    Gui, Add, Button, x162 y80 w90 h30 gDC_NewFileOk default, 确认(&S)
    Gui, Add, Button, x282 y80 w90 h30 gDC_NewFileClose , 取消(&C)
    Gui, Show, w400 h120, 新建文件

    if (InStr(Filename, ".")) {
        ; 只选定扩展名之外的文件名
        PostMessage, 0x0B1, 0, % InStr(Filename, ".") - 1, Edit2, A
    }
return

DC_NewFileClose:
    Gui, Destroy
return

DC_NewFileOK:
    GuiControlGet, SrcFilePath, , Edit1
    GuiControlGet, NewFilename, , Edit2

    ClipSaved := ClipboardAll
    Clipboard :=
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 1
    DstPath := Clipboard
    Clipboard := ClipSaved
    ClipSaved := ""

    if (InStr(DstPath, "`r")) {
        DstPath := SubStr(DstPath, 1, InStr(DstPath, "`r") - 1)
    } else if (DstPath == "") {
        return
    }

    NewFilePath := DstPath . NewFilename
    if (FileExist(NewFilePath)) {
        MsgBox, 4, 新建文件, 新建文件已存在，是否覆盖？
        IfMsgBox No
            return
    }

    FileCopy, % SrcFilePath, % NewFilePath, 1

    ; 虽然不是完全匹配，基本也能用了
    DC_Run("cm_QuickSearch matchbeginning=on | text=" . NewFilename)

    Gui, Destroy
return

<DC_Toggle>:
    if (WinExist(DC)) {
        WinGet, Ac, MinMax, % DC
        if (Ac == -1) {
            WinActivate, % DC
        } else {
            if (!WinActive(DC)) {
                WinActivate, % DC
            } else {
                WinMinimize, % DC
            }
        }
    } else {
        Run, % DC_Path
        WinWait, % DC

        if (!WinActive(DC)) {
            WinActivate, % DC
        }
    }
return

<DC_MarkFile>:
    DC_Run("cm_EditComment")
    ; 不要在已有备注的文件使用
    Send, ^+{End}🖥{F2}
return

<DC_UnMarkFile>:
    DC_Run("cm_EditComment")
    ; 删除 DC_MarkFile 的文件标记，也可用于清空文件备注
    Send, ^+{End}{Del}{F2}
return

<DC_ToggleShowInfo>:
    Vim.GetWin(DC_Name).SetInfo(!Vim.GetWin(DC_Name).info)
return

<DC_CopyFileContent>:
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait, 1

    Fileread, Contents, % Clipboard
    Clipboard := Contents
return

<DC_CopyFilenamesOnly>:
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait, 1

    SplitPath, Clipboard, OutFileName, , , OutFilenameNoExt

    if (InStr(FileExist(Clipboard), "D")) {
        Clipboard := OutFileName
    } else if (InStr(Clipboard, ".")) {
        Clipboard := OutFilenameNoExt
    }
return

<DC_CreateFileShortcut>:
    ClipSaved := ClipboardAll
    Clipboard := ""
    DC_Run("cm_CopyFullNamesToClip")
    ClipWait

    FilePath := Clipboard
    Clipboard := ClipSaved
    ClipSaved := ""

    OutVar := FileExist(FilePath)
    if (InStr(OutVar, "D")) {
        FileCreateShortcut, % FilePath, % FilePath . ".lnk"
    } else if (OutVar != "") {
        FileCreateShortcut, % FilePath, % RegExReplace(FilePath, "\.[^.]*$", ".lnk")
    }
return

<DC_Focus>:
    IfWinExist, % DC
        Winactivate, % DC
    else {
        Run, % DC_Path
        WinWait, % DC
        IfWinNotActive, % DC
            WinActivate, % DC
    }
return

<DC_MapKeys>:
	Vim.Mode("normal", DC_Name)
    Vim.Map("<S-Enter>", "<DC_SelectedCurrentDir>", DC_Name)
    Vim.Map("<Esc>", "<DC_ReturnToCaller>", DC_Name)
return

<DC_UnMapKeys>:
	Vim.Mode("normal", DC_Name)
    Vim.Map("<S-Enter>", "<Default>", DC_Name)
    Vim.Map("<Esc>", "<Default>", DC_Name)
return

; 返回调用者
<DC_ReturnToCaller>:
    gosub <DC_UnMapKeys>

    WinActivate, ahk_id %DC_CallerId%

    DC_CallerId := 0
return

; 非 TC 窗口按下后激活 TC 窗口
; TC 窗口按下后复制当前选中文件返回原窗口后粘贴
<DC_OpenDCDialog>:
    WinGetClass, name, A

    ; 在 DC 按下快捷键时，激活调用窗体并执行粘贴操作
    if (name == DC_Class) {
        if (DC_CallerId != 0) {
            gosub <DC_Selected>
            DC_CallerId := 0
		}
    } else {
        DC_CallerId := WinExist("A")
        if (DC_CallerId == 0) {
            return
		}

        gosub <DC_Focus>
        gosub <DC_MapKeys>
    }
return

<DC_Selected>:
    gosub <DC_UnMapKeys>

    Clipboard := ""
    ; 不知道什么原因，必须加一个 MsgBox 功能才正常
    MsgBox, , , 处理中, 0.3

    DC_Run("cm_CopyCurrentPathToClip")

    ClipWait, 1
    Pwd := Clipboard

    Clipboard := ""
    DC_Run("cm_CopyNamesToClip")
    ClipWait, 1

    WinActivate, ahk_id %DC_CallerId%
    WinWait, ahk_id %DC_CallerId%
    DC_CallerId := 0

    if (!InStr(Clipboard, "`n")) {
        Clipboard := Pwd . Clipboard
        Send, {Home}
        Send, ^v
        Send, {Enter}

        return
    }

    ; 多选

    Files := ""
    Loop, parse, Clipboard, `n, `r
        Files .= """" . A_LoopField  . """ "

    ; 第一步：跳转到当前路径
    Clipboard := Pwd
    Send, ^a
    Send, ^v
    Send, {Enter}
    sleep, 100

    ; 第二步：提交文件名
    Clipboard := Files
    Send, ^v
    Send, {Enter}
return

<DC_SelectedCurrentDir>:
    gosub <DC_UnMapKeys>

    if (DC_CallerId == 0) {
        return
    }

    Clipboard := ""
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait

    ; 添加默认路径不带反斜杠，添加之

    Clipboard .= "\"

    WinActivate, ahk_id %DC_CallerId%
    WinWait, ahk_id %DC_CallerId%
    DC_CallerId := 0

    Send, {Home}
    Send, ^v
    Send, {Enter}
return

<DC_FlatViewSel>:
    DC_Run("cm_FlatViewSel")
return


Code style

Code style

foobar2000:
    global foobar2000_class := "{97E27FAA-C0B3-4b8e-A693-ED7881E99FC1}"

    ; insert模式
    vim.mode("insert", foobar2000_class)
    vim.map("<esc>", "<Normal_Mode_foobar2000>", foobar2000_class)

    ; normal模式
    vim.mode("normal", foobar2000_class)

    vim.map("i", "<Insert_Mode_foobar2000>", foobar2000_class)

    vim.map("0", "<0>", foobar2000_class)
    vim.map("1", "<1>", foobar2000_class)
    vim.map("2", "<2>", foobar2000_class)
    vim.map("3", "<3>", foobar2000_class)
    vim.map("4", "<4>", foobar2000_class)
    vim.map("5", "<5>", foobar2000_class)
    vim.map("6", "<6>", foobar2000_class)
    vim.map("7", "<7>", foobar2000_class)
    vim.map("8", "<8>", foobar2000_class)
    vim.map("9", "<9>", foobar2000_class)

    vim.map("j", "<down>", foobar2000_class)
    vim.map("k", "<up>", foobar2000_class)
    vim.map("l", "<enter>", foobar2000_class)
    vim.map("gg", "<home>", foobar2000_class)
    vim.map("G", "<end>", foobar2000_class)
    vim.map("<ctrl>f", "<pgdn>", foobar2000_class)
    vim.map("<ctrl>b", "<pgup>", foobar2000_class)
    vim.map("/", "<foobar2000_search>", foobar2000_class)
    vim.map("t", "<foobar2000_tree>", foobar2000_class)
    vim.map("m", "<foobar2000_list>", foobar2000_class)
    vim.map("n", "<Media_Next>", foobar2000_class)
    vim.map("p", "<Media_Prev>", foobar2000_class)
    vim.map("s", "<Media_Stop>", foobar2000_class)

    vim.map("gn", "<NextTab>", foobar2000_class)
    vim.map("gp", "<PrevTab>", foobar2000_class)

    vim.Comment("<Normal_Mode_foobar2000>", "进入normal模式")
    vim.Comment("<Insert_Mode_foobar2000>", "进入insert模式")
    vim.Comment("<foobar2000_search>", "打开搜索窗口")
    vim.Comment("<foobar2000_tree>", "定位到目录窗口")
    vim.Comment("<foobar2000_list>", "定位到播放列表")
return

<Normal_Mode_foobar2000>:
    global foobar2000_class
    vim.mode("normal", foobar2000_class)
return

<Insert_Mode_foobar2000>:
    global foobar2000_class
    vim.mode("insert", foobar2000_class)
return

<foobar2000_search>:
    send ^f
return

<foobar2000_tree>:
    ControlFocus, SysTreeView321
return

<foobar2000_list>:
    ControlFocus, {4B94B650-C2D8-40de-A0AD-E8FADF62D56C}1
return

foobar2000:
    global foobar2000_class:="{97E27FAA-C0B3-4b8e-A693-ED7881E99FC1}"

    ; insert模式
    vim.mode("insert", foobar2000_class)
    vim.map("<esc>", "<Normal_Mode_foobar2000>", foobar2000_class)

    ; normal模式
    vim.mode("normal", foobar2000_class)

    vim.map("i", "<Insert_Mode_foobar2000>", foobar2000_class)

    vim.map("0", "<0>", foobar2000_class)
    vim.map("1", "<1>", foobar2000_class)
    vim.map("2", "<2>", foobar2000_class)
    vim.map("3", "<3>", foobar2000_class)
    vim.map("4", "<4>", foobar2000_class)
    vim.map("5", "<5>", foobar2000_class)
    vim.map("6", "<6>", foobar2000_class)
    vim.map("7", "<7>", foobar2000_class)
    vim.map("8", "<8>", foobar2000_class)
    vim.map("9", "<9>", foobar2000_class)

    vim.map("j", "<down>", foobar2000_class)
    vim.map("k", "<up>", foobar2000_class)
    vim.map("l", "<enter>", foobar2000_class)
    vim.map("gg", "<home>", foobar2000_class)
    vim.map("G", "<end>", foobar2000_class)
    vim.map("<ctrl>f", "<pgdn>", foobar2000_class)
    vim.map("<ctrl>b", "<pgup>", foobar2000_class)
    vim.map("/", "<foobar2000_search>", foobar2000_class)
    vim.map("t", "<foobar2000_tree>", foobar2000_class)
    vim.map("m", "<foobar2000_list>", foobar2000_class)
    vim.map("n", "<Media_Next>", foobar2000_class)
    vim.map("p", "<Media_Prev>", foobar2000_class)
    vim.map("s", "<Media_Stop>", foobar2000_class)

    vim.map("gn", "<NextTab>", foobar2000_class)
    vim.map("gp", "<PrevTab>", foobar2000_class)

    vim.Comment("<Normal_Mode_foobar2000>", "进入normal模式")
    vim.Comment("<Insert_Mode_foobar2000>", "进入insert模式")
    vim.Comment("<foobar2000_search>", "打开搜索窗口")
    vim.Comment("<foobar2000_tree>", "定位到目录窗口")
    vim.Comment("<foobar2000_list>", "定位到播放列表")
return

<Normal_Mode_foobar2000>:
    global foobar2000_class
    vim.mode("normal", foobar2000_class)
return

<Insert_Mode_foobar2000>:
    global foobar2000_class
    vim.mode("insert", foobar2000_class)
return

<foobar2000_search>:
    send ^f
return

<foobar2000_tree>:
    ControlFocus, SysTreeView321
return

<foobar2000_list>:
    ControlFocus, {4B94B650-C2D8-40de-A0AD-E8FADF62D56C}1
return


Update work_default.ahk

Update work_default.ahk

; Autohotkey configuration file
; AHK Version v.1.1.30.01
; Franklin Chou (franklin.chou@nelsonmullins.com)
; 22 Mar. 2020
; Tested to work on Lenovo X1 Yoga, Gen. 4

#SingleInstance Force
#Persistent

GLOBAL_DEBUG_MODE := 0
Return

CapsLock::Ctrl
LCtrl::return
;LCtrl::CapsLock

; DEBUG TOOLS -----------------------------------------------------------------

#c::
  If(GLOBAL_DEBUG_MODE > 0) {
    WinGetTitle, title, A
    MsgBox %GLOBAL_DEBUG_MODE% ;%title%
  }
Return

f12::
  If(GLOBAL_DEBUG_MODE > 0) {
    Reload
  }
Return

#'::
If(GLOBAL_DEBUG_MODE > 0) {
  WinGet windows, List
  Loop %windows% {
    id := windows%A_Index%
    WinGetTitle wt, ahk_id %id%
    r .= wt . "`n"
  }
  MsgBox %r%
}
Return

; TIMEKEEPER ------------------------------------------------------------------

; Shift focus to the timekeeper app
#!e::
  timekeeper_app := WinExist("ahk_class WindowsForms10.Window.8.app.0.262fb3d")
  ;MsgBox %timekeeper_app%
  If(timekeeper_app > 0) {
    WinActivate, ahk_id %timekeeper_app%
  }
Return

; Start the timer on the selected item in the daily view
#IfWinActive ahk_class WindowsForms10.Window.8.app.0.262fb3d
  >+s::
    WinGetActiveTitle, active_title
    match_result := RegExMatch(active_title, "^Entries for")
    drop_down := 100
    If(match_result > 0) {
      WinMove, 100, 100
      MouseMove, 100, 280
      Send {RButton}
      Sleep, 100 ; need to sleep to allow the submenu to come up
      MouseMove, 170, 300 + drop_down
      Send {LButton}
    }
Return

; WORD ------------------------------------------------------------------------
#IfWinActive ahk_class OpusApp
   PrintScreen::AppsKey

; SYMBOL KEYS -----------------------------------------------------------------
>+s::send §

; Autohotkey configuration file
; AHK Version v.1.1.30.01
; Franklin Chou (franklin.chou@nelsonmullins.com)
; 22 Mar. 2020
; Tested to work on Lenovo X1 Yoga, Gen. 4

#SingleInstance Force
#Persistent

CapsLock::Ctrl
LCtrl::return
;LCtrl::CapsLock

; WORD ------------------------------------------------------------------------
#IfWinActive ahk_class OpusApp
  PrintScreen::AppsKey


Changes autohotkey script to show tray icon.  It was more annoying and confusing to have it hidden.

; Uncomment if you don't want this script appearing in your system tray
; #NoTrayIcon
#SingleInstance Force
#Persistent
MsgNum := DllCall("RegisterWindowMessage", Str, "VIRTUALDESKTOPGRIDSWITCHER_COMMAND")

exeName := "VirtualDesktopGridSwitcher.exe"

; Launch VirtualDesktopGridManager if it's not already running.
DetectHiddenWindows, On
If !WinExist("ahk_exe " . exeName) {
    Run "../VirtualDesktopGridSwitcher.exe"
}

; All commands
GO_UP := 1
GO_LEFT := 2
GO_RIGHT := 3
GO_DOWN := 4
MOVE_UP := 5
MOVE_LEFT := 6
MOVE_RIGHT := 7
MOVE_DOWN := 8
TOGGLE_ALWAYS_ON_TOP := 9
TOGGLE_STICKY := 10
return

; Return an HWND that will receive our commands.
GetTargetHwnd() {
    global exeName
    DetectHiddenWindows, On
    WinGet, a, List, ahk_exe %exeName%
    Loop, %a% {
        id := a%A_Index%
        WinGetClass, cls, ahk_id %id%
        ; Skip the "GDI+" window
        If(RegExMatch(cls, "^GDI") = 0) {
            return id
        }
    }
}

; Send a command to VirtualDesktopGridSwitcher
SendCommand(cmd) {
    ; All variables are global unless declared to be local
    global
    local id
    id := GetTargetHwnd()
    PostMessage, %MsgNum%, %cmd%, 0, , ahk_id %id%
}

;;;;;;;
; Hotkeys.  Customize these to your liking.

^#Left::SendCommand(GO_LEFT)
^#Right::SendCommand(GO_RIGHT)
^#Down::SendCommand(GO_DOWN)
^#Up::SendCommand(GO_UP)
#!Left::SendCommand(MOVE_LEFT)
#!Right::SendCommand(MOVE_RIGHT)
#!Down::SendCommand(MOVE_DOWN)
#!Up::SendCommand(MOVE_UP)
^#A::SendCommand(TOGGLE_ALWAYS_ON_TOP)
^#S::SendCommand(TOGGLE_STICKY)


fuck yeah

fuck yeah

; Autohotkey configuration file
; AHK Version v.1.1.32.00
; Franklin Chou (franklin.chou@nelsonmullins.com)
; 22 Mar. 2020
; Tested to work on Lenovo X1 Yoga, Gen. 4

#SingleInstance Force
#Persistent

GLOBAL_DEBUG_MODE := 1
Return

CapsLock::Ctrl
LCtrl::Return
;LCtrl::CapsLock

; DEBUG TOOLS -----------------------------------------------------------------

#c::
  If(GLOBAL_DEBUG_MODE > 0) {
    ; WinGetTitle, title, A
    WinGetClass, title, A
    MsgBox %title%
  }
Return

f12::
  If(GLOBAL_DEBUG_MODE > 0) {
    Reload
  }
Return

; SYSTEM ----------------------------------------------------------------------

; Access different windows of the same group
!`::
  WinGet, process_name, ProcessName, A ; get the active window's process name
  process_windows := GetWindowsOfProcess(process_name)

  n_process_windows := process_windows.Length()

  index := 1 ; AHK arrays are 1 indexed

  While(GetKeyState("Alt", "P")) {
    If (GetKeyState("``", "P")) {
      If (index < n_process_windows) {
        index := index + 1
        ; MsgBox %index% of %n_process_windows%
      } Else {
        index := 1
      }
      active_id := process_windows[index]
      WinActivate, ahk_id %active_id%
    }
  }

  KeyWait, Alt
  index := ""
Return

; Get the window ids of all the processes under that process name
GetWindowsOfProcess(process_name) {
  ids := Array()
  WinGet, window_ids, List ; get the IDs for all running windows
  Loop %window_ids% {
    id := window_ids%A_Index%
    WinGetTitle, title, ahk_id %id%
    WinGet, a_process_name, ProcessName, ahk_id %id%
    ; only include windows with visible title
    If (title && a_process_name = process_name) {
      ids.Push(id)
    }
  }
  Return, ids
}

; TIMEKEEPER ------------------------------------------------------------------

; Shift focus to the timekeeper app
#!e::
  timekeeper_app := WinExist("ahk_class WindowsForms10.Window.8.app.0.262fb3d")
  ;MsgBox %timekeeper_app%
  If(timekeeper_app > 0) {
    WinActivate, ahk_id %timekeeper_app%
  } Else {
    Run, DTE.exe, C:\Program Files (x86)\DTEAxiom
  }
Return

; Start the timer on the selected item in the daily view
#IfWinActive ahk_class WindowsForms10.Window.8.app.0.262fb3d
  >+s::
    WinGetActiveTitle, active_title
    match_result := RegExMatch(active_title, "^Entries for")
    ; each item in the dropdown is approximately 25 pixels
    ; so item 4 (Start Timer) is 100 pixels down from the context menu
    drop_down := 100
    If(match_result > 0) {
      WinMove, 100, 100
      MouseMove, 100, 280
      Send {RButton}
      Sleep, 10 ; need to sleep to allow submenu time to come up
      MouseMove, 170, 300 + drop_down
      Send {LButton}
    }
Return

; MSOFFICE --------------------------------------------------------------------

; Let the print screen key open the application options key (for spell check)
; Word and Outlook
#If WinActive("ahk_class OpusApp") || WinActive("ahk_class rctrl_renwnd32")
  PrintScreen::AppsKey
Return

; This ridiculous keymapping is care of Lenovo
; which maps F12 to some bloatware keyboard manager utility
#If WinActive("ahk_class OpusApp") || WinActive("ahk_class XLMAIN")
  F12::
    Send {F12}
Return

; WORD ONLY -------------------------------------------------------------------

; Cycle through types of markup
#If WinActive("ahk_class OpusApp")
  >+m::
    Send !r
    Sleep, 10
    Send td
    Send {Down}
    Send {Enter}
Return

; Autohotkey configuration file
; AHK Version v.1.1.32.00
; Franklin Chou (franklin.chou@nelsonmullins.com)
; 22 Mar. 2020
; Tested to work on Lenovo X1 Yoga, Gen. 4

#SingleInstance Force
#Persistent

GLOBAL_DEBUG_MODE := 1
Return

CapsLock::Ctrl
LCtrl::Return
;LCtrl::CapsLock

; DEBUG TOOLS -----------------------------------------------------------------

#c::
  If(GLOBAL_DEBUG_MODE > 0) {
    ; WinGetTitle, title, A
    WinGetClass, title, A
    MsgBox %title%
  }
Return

f12::
  If(GLOBAL_DEBUG_MODE > 0) {
    Reload
  }
Return

; SYSTEM ----------------------------------------------------------------------

; Access different windows of the same group
!`::
  WinGet, process_name, ProcessName, A ; get the active window's process name
  process_windows := GetWindowsOfProcess(process_name)

  n_process_windows := process_windows.Length()
  ; MsgBox, %process_name% -> %n_process_windows%

  index := 1 ; AHK arrays are 1 indexed

  While(GetKeyState("Alt", "P")) {
    If (GetKeyState("``", "P")) {
      If (index < n_process_windows) {
        index := index + 1
        ; MsgBox %index% of %n_process_windows%
      } Else {
        index := 1
      }

      active_id := process_windows[index]
      WinActivate, ahk_id %active_id%
    }
  }

  KeyWait, Alt
  WinActivate, ahk_id %active_id%
  index := ""
Return

; Get the window ids of all the processes under that process name
GetWindowsOfProcess(process_name) {
  ids := Array()
  WinGet, window_ids, List ; get the IDs for all running windows
  Loop %window_ids% {
    id := window_ids%A_Index%
    WinGetTitle, title, ahk_id %id%
    WinGet, a_process_name, ProcessName, ahk_id %id%
    ; only include windows with visible title
    If (title && a_process_name = process_name) {
      ids.Push(id)
    }
  }
  Return, ids
}

; TIMEKEEPER ------------------------------------------------------------------

; Shift focus to the timekeeper app
#!e::
  timekeeper_app := WinExist("ahk_class WindowsForms10.Window.8.app.0.262fb3d")
  ;MsgBox %timekeeper_app%
  If(timekeeper_app > 0) {
    WinActivate, ahk_id %timekeeper_app%
  } Else {
    Run, DTE.exe, C:\Program Files (x86)\DTEAxiom
  }
Return

; Start the timer on the selected item in the daily view
#IfWinActive ahk_class WindowsForms10.Window.8.app.0.262fb3d
  >+s::
    WinGetActiveTitle, active_title
    match_result := RegExMatch(active_title, "^Entries for")
    ; each item in the dropdown is approximately 25 pixels
    ; so item 4 (Start Timer) is 100 pixels down from the context menu
    drop_down := 100
    If(match_result > 0) {
      WinMove, 100, 100
      MouseMove, 100, 280
      Send {RButton}
      Sleep, 10 ; need to sleep to allow submenu time to come up
      MouseMove, 170, 300 + drop_down
      Send {LButton}
    }
Return

; MSOFFICE --------------------------------------------------------------------

; Let the print screen key open the application options key (for spell check)
; Word and Outlook
#If WinActive("ahk_class OpusApp") || WinActive("ahk_class rctrl_renwnd32")
  PrintScreen::AppsKey
Return

; This ridiculous keymapping is care of Lenovo
; which maps F12 to some bloatware keyboard manager utility
#If WinActive("ahk_class OpusApp") || WinActive("ahk_class XLMAIN")
  F12::
    Send {F12}
Return

; WORD ONLY -------------------------------------------------------------------

; Cycle through types of markup
#If WinActive("ahk_class OpusApp")
  >+m::
    Send !r
    Sleep, 10
    Send td
    Send {Down}
    Send {Enter}
Return


minor test case fix

minor test case fix

; truth values:
; ==========================================================
Assert(""    ? false : true, "Empty string is true")
Assert(0     ? false : true, "0 is true")
Assert(0.0   ? false : true, "0.0 is true")
Assert(false ? false : true, "false is true")
Assert(null  ? false : true, "null is true")
Assert(a     ? false : true, "Uninitialized var is not false")

Assert("a", "Non-empty string is false")
Assert(1, "1 is false")
Assert(true, "true is false")
Assert(!false, "!false is false")
; ==========================================================

Assert(0x2 "" == "2", "Hex-Int to string conversion failed")

five() {
	return(5)
}

Assert(five() "" == "5", "Return value failed")
Assert(5 ** 2 == 25.0, "Power failed")

cond() {
	if (true) {
		return(true)
	}
}
Assert(cond(), "function return in if failed")

c := 5
c += 8.2
Assert(c == 13.2, "+= failed")

; just testing if the expression isn't too long
b := 5
b .= ": " 5 + 8.2 " = " c " = " . 13.2 " != " 1 * 1 - 13.2 + 5.8 " + 4e-2 == " 0.001 * (0 + 1) * 10 ** 0 " += c"

var := ""
DriveGet(var, "List", "")
Assert(var != "", "'DriveGet List' failed")

Assert(A_YYYY "" == 2013 "", "The year has changed since 2013 :)")

Assert(A_WorkingDir != "", "A_WorkingDir is empty")

WD := A_WorkingDir
Assert(WD == A_WorkingDir, "Failed to set var to builtin var")

A_WorkingDir := A_WorkingDir . "/Tests"
Assert(A_WorkingDir == WD . "/Tests", "Failed to set A_WorkingDir")

Assert((5 < 3) ? false : true, "< failed")
Assert((5 < 3) "" == "0", "Bools as strings")

Assert((5 > 3) * 4 == 4, "Bool as int failed")

obj := { "a" : 4, 4 : 5, 5 : "a" }
Assert(obj != null, "Object literal failed")
Assert(obj.a "" == 4 "", "Object literal incorrect")

Assert(obj.b == null, "Retrieval of undefined object member failed")

obj.a += 5
Assert(obj.a "" == 9 "", "+= on obj member failed")

obj.a := "a"
Assert(obj.a == "a", "obj member assignment failed")

arr := [2, 4, 9]
Assert(arr != null, "Array literal failed")

; just testing for errors on empty literals
obj := {}
arr := []

a := 0
b := "b"
c := "c"
d := "d"
e := "e"
f := "f"
g := "g"

if (g) {
	Assert(g, "Assertion in if-Block failed")
}

; just a comment - divider

if (false) {
	throw "False is true"
} else {
	Assert(g, "Assertion in else-Block failed")
}

; todo: fix parsing so it works without parentheses
result := (a ? b ? c : d : e ? f : g)
Assert(result == "f", "Chained ternary failed")

a := b .= c
Assert(b == "bc", "chained concat-assign failed")
Assert(a == b, "chained assignment failed")

if (true) {
	return()
}
Assert(false, "conditional return in auto-execute failed")

Assert(cond, msg) {
	if (cond) {
		FileAppend("`tAssert (" cond ") : '" msg "'`n", "*")
	} else {
		throw(msg "")
	}
}

; truth values:
; ==========================================================
Assert(""    ? false : true, "Empty string is true")
Assert(0     ? false : true, "0 is true")
Assert(0.0   ? false : true, "0.0 is true")
Assert(false ? false : true, "false is true")
Assert(null  ? false : true, "null is true")
Assert(a     ? false : true, "Uninitialized var is not false")

Assert("a", "Non-empty string is false")
Assert(1, "1 is false")
Assert(true, "true is false")
Assert(!false, "!false is false")
; ==========================================================

Assert(0x2 "" == "2", "Hex-Int to string conversion failed")

five() {
	return(5)
}

Assert(five() "" == "5", "Return value failed")
Assert(5 ** 2 == 25.0, "Power failed")

cond() {
	if (true) {
		return(true)
	}
}
Assert(cond(), "function return in if failed")

c := 5
c += 8.2
Assert(c == 13.2, "+= failed")

; just testing if the expression isn't too long
b := 5
b .= ": " 5 + 8.2 " = " c " = " . 13.2 " != " 1 * 1 - 13.2 + 5.8 " + 4e-2 == " 0.001 * (0 + 1) * 10 ** 0 " += c"

var := ""
DriveGet(var, "List", "")
Assert(var != "", "'DriveGet List' failed")

Assert(A_YYYY "" == 2013 "", "The year has changed since 2013 :)")

Assert(A_WorkingDir != "", "A_WorkingDir is empty")

WD := A_WorkingDir
Assert(WD == A_WorkingDir, "Failed to set var to builtin var")

A_WorkingDir := A_WorkingDir . "/Tests"
Assert(A_WorkingDir == WD . "/Tests", "Failed to set A_WorkingDir")

Assert((5 < 3) ? false : true, "< failed")
Assert((5 < 3) "" == "0", "Bools as strings")

Assert((5 > 3) * 4 == 4, "Bool as int failed")

obj := { "a" : 4, 4 : 5, 5 : "a" }
Assert(obj != null, "Object literal failed")
Assert(obj.a "" == 4 "", "Object literal incorrect")

Assert(obj.b == null, "Retrieval of undefined object member failed")

obj.a += 5
Assert(obj.a "" == 9 "", "+= on obj member failed")

obj.a := "a"
Assert(obj.a == "a", "obj member assignment failed")

; just testing for errors on empty literals
obj := {}
arr := []

arr := [2, 4, 9]
Assert(arr != null, "Array literal failed")

a := 0
b := "b"
c := "c"
d := "d"
e := "e"
f := "f"
g := "g"

if (g) {
	Assert(g, "Assertion in if-Block failed")
}

; just a comment - divider

if (false) {
	throw "False is true"
} else {
	Assert(g, "Assertion in else-Block failed")
}

; todo: fix parsing so it works without parentheses
result := (a ? b ? c : d : e ? f : g)
Assert(result == "f", "Chained ternary failed")

a := b .= c
Assert(b == "bc", "chained concat-assign failed")
Assert(a == b, "chained assignment failed")

if (true) {
	return()
}
Assert(false, "conditional return in auto-execute failed")

Assert(cond, msg) {
	if (cond) {
		FileAppend("`tAssert (" cond ") : '" msg "'`n", "*")
	} else {
		throw(msg "")
	}
}


Updated AHK sample script

Updated AHK sample script

;	Samle AHK script to launch SnK (windowsless) with Ctrl+Alt+Backspace
Menu, Tray, Tip, SnK: Ctrl+Alt+BS

;	SnK first try to search for and kill fullscreen app that has highest cpu load
;	If no such app is found it will next try with not responding (hung) app and DirectX app
;	In the end, if everything else fails, it will just kill any process that has highest CPU load
;		/sec switch will prevent accidentially launching several SnKs in quick succession
;		/bpp will make a beep signaling that hotkey was triggered and SnK launched
;		+v enables message box pop up at the end of exection showing results
;	Place SnKh.exe in the same folder as this script for it to find executable
;	Script can be automatically started at Windows startup using Task Scheduler: https://technet.microsoft.com/en-us/library/cc766428.aspx
;	It is recommended to grant scheduled AHK script Admin rights by checking "Run with highest privileges" checkbox
;	This way SnK launched by the script will also have Admin rights
;	For other possible hotkey combinations and options check out official AHK docs: https://autohotkey.com/docs/Hotkeys.htm
$^!BS::Run SnKh.exe /sec /bpp +v /fsc /inr /d3d /cpu

;	Hotkey below is variation of previous hotkey
;	It allows to launch SnK with different commands depending on whether it was long or short hotkey press
;	To enable it - comment previous hotkey, uncomment lines below and assign SnKh calls proper commands
;	If you want to use other modifier keys for hotkey, edit KeyWait commands accordingly
;$^!BS::
;  KeyWait, Ctrl
;  KeyWait, Alt
;  if (A_TimeSinceThisHotkey > 3000)
;    Run SnKh.exe +v /prn="OnLongPress" /prn
;  else
;    Run SnKh.exe +v /prn="OnShortPress" /prn
;Return

;	Samle AHK script to launch SnK (windowsless) with Ctrl+Alt+Backspace
;	SnK first try to search for and kill fullscreen app that has highest cpu load
;	If no such app is found it will next try with DirectX app
;	In the end, if everything else fails, it will just kill any process that has highest CPU load
;		/sec switch will prevent accidentially launching several SnKs in quick succession
;		/bpp will make a beep signaling that hotkey was triggered and SnK launched
;		+v enables message box pop up at the end of exection showing results
;	Place SnKh.exe in the same folder as this script for it to find executable
;	Script can be automatically started at Windows startup using Task Scheduler: https://technet.microsoft.com/en-us/library/cc766428.aspx
;	It is recommended to grant scheduled AHK script Admin rights by checking "Run with highest privileges" checkbox
;	This way SnK launched by the script will also have Admin rights
;	For other possible hotkey combinations and options check out official AHK docs: https://autohotkey.com/docs/Hotkeys.htm
$^!BS::Run SnKh.exe /sec /bpp +v /fsc /d3d /cpu

;	Hotkey below is variation of previous hotkey
;	It allows to launch SnK with different commands depending on whether it was long or short hotkey press
;	To enable it - comment previous hotkey, uncomment lines below and assign SnKh calls proper commands
;	If you want to use other modifier keys for hotkey, edit KeyWait commands accordingly
;$^!BS::
;  KeyWait, Ctrl
;  KeyWait, Alt
;  if (A_TimeSinceThisHotkey > 3000)
;    Run SnKh.exe +v /prn="OnLongPress" /prn
;  else
;    Run SnKh.exe +v /prn="OnShortPress" /prn
;Return


Add shortcut to adjust volume with mouse scrolling