DC 插件：修复 <DC_NextParallelDir>

DC 插件：修复 <DC_NextParallelDir>

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

    ---

    DC 的优势

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

    ---

    TODO

    整理代码
*/

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_ColumnsView(columnset) {
    if (columnset == "") {
        DC_Run("cm_ColumnsView")
    } else {
        DC_Run("cm_ColumnsView columnset=" columnset)
    }
}

<DC_RenameFull>:
    Send, {f2}^a
return

<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_Show_50_50>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=50")
return

<DC_Show_100_0>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=100")
return

<DC_Show_0_100>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=0")
return

<DC_HorizontalFilePanels>:
    DC_Run("cm_HorizontalFilePanels mode=legacy")
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_MakeDir>:
    DC_Run("cm_MakeDir")
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, 新建文件
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

    ; TODO
    ; 好像无法实现定位到新创建的文件

    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_SortByName>:
    DC_Run("cm_SortByName")
return

<DC_SortByExt>:
    DC_Run("cm_SortByExt")
return

<DC_SortBySize>:
    DC_Run("cm_SortBySize")
return

<DC_SortByDate>:
    DC_Run("cm_SortByDate")
return

<DC_SortByAttr>:
    DC_Run("cm_SortByAttr")
return

<DC_ReverseOrder>:
    DC_Run("cm_ReverseOrder")
return

<DC_FocusSwap>:
    DC_Run("cm_FocusSwap")
    ; side=left/right
return

<DC_CopyCurrentPathToClip>:
    DC_Run("cm_CopyCurrentPathToClip")
return

<DC_OpenExplorer>:
    DC_Run(".")
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_ShowMainMenu>:
    DC_Run("cm_ShowMainMenu")
return

<DC_ShowButtonMenu>:
    DC_Run("cm_ShowButtonMenu")
return

<DC_OperationsViewer>:
    DC_Run("cm_OperationsViewer")
return

<DC_TreeView>:
    DC_Run("cm_TreeView")
return

<DC_FocusTreeView>:
    DC_Run("cm_FocusTreeView")
return

<DC_BriefView>:
    DC_Run("cm_BriefView")
return

<DC_ColumnsView1>:
    DC_ColumnsView("mine")
return

<DC_ColumnsView2>:
    DC_ColumnsView("test")
return

<DC_ThumbnailsView>:
    DC_Run("cm_ThumbnailsView")
    Gosub, <DC_ThumbnailsSwitchKey>
return

<DC_ThumbnailsSwitchKey>:
    InThumbsView := !InThumbsView

    if (InThumbsView) {
        vim.Map("l", "<right>", DC_Name)
    } else {
        vim.Map("l", "<enter>", DC_Name)
    }
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_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%"
    }
}

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

    ---

    DC 的优势

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

    ---

    TODO

    整理代码
*/

DoubleCommander:
    global DC := "ahk_class DClass"
    global DC_Dir := "c:\mine\app\doublecmd"
    ; 用于记录文件打开对话框所属窗体
    global DC_CallerId := 0

    DC_Name := "DoubleCommander"

    vim.SetWin(DC_Name, "DClass", "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, 2

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

    return PanelInfo
}

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

DC_ColumnsView(columnset) {
    if (columnset == "") {
        DC_Run("cm_ColumnsView")
    } else {
        DC_Run("cm_ColumnsView columnset=" columnset)
    }
}

<DC_RenameFull>:
    Send, {f2}^a
return

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

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

    Run, % DC_Dir . "\doublecmd.exe --no-splash"

    WinWaitActive, % DC

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

<DC_Show_50_50>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=50")
return

<DC_Show_100_0>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=100")
return

<DC_Show_0_100>:
    DC_Run("cm_PanelsSplitterPerPos splitpct=0")
return

<DC_HorizontalFilePanels>:
    DC_Run("cm_HorizontalFilePanels mode=legacy")
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_MakeDir>:
    DC_Run("cm_MakeDir")
return

<DC_PreviousParallelDir>:
    SleepTime := 10

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

    OldPwd := Clipboard

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

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

        Clipboard := ClipSaved
        ClipSaved := ""

        return
    }

    DC_Run("cm_ChangeDirToParent")
    Sleep, % SleepTime

    Send, {up}
    Sleep, % SleepTime

    Send, {right}

    Clipboard := ClipSaved
    ClipSaved := ""
return

<DC_NextParallelDir>:
    SleepTime := 10

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

    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

    Send, {down}
    Sleep, % SleepTime

    Send, {right}
    Sleep, % SleepTime

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

    if (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, 新建文件
return

DC_NewFileClose:
    Gui, Destroy
return

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

    ClipSaved := ClipboardAll
    Clipboard :=
    DC_Run("cm_CopyCurrentPathToClip")
    ClipWait, 2
    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

    ; TODO
    ; 好像无法实现定位到新创建的文件

    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_Dir . "\doublecmd.exe --no-splash"
        WinWait, % DC

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

<DC_SortByName>:
    DC_Run("cm_SortByName")
return

<DC_SortByExt>:
    DC_Run("cm_SortByExt")
return

<DC_SortBySize>:
    DC_Run("cm_SortBySize")
return

<DC_SortByDate>:
    DC_Run("cm_SortByDate")
return

<DC_SortByAttr>:
    DC_Run("cm_SortByAttr")
return

<DC_ReverseOrder>:
    DC_Run("cm_ReverseOrder")
return

<DC_FocusSwap>:
    DC_Run("cm_FocusSwap")
    ; side=left/right
return

<DC_CopyCurrentPathToClip>:
    DC_Run("cm_CopyCurrentPathToClip")
return

<DC_OpenExplorer>:
    DC_Run(".")
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_ShowMainMenu>:
    DC_Run("cm_ShowMainMenu")
return

<DC_ShowButtonMenu>:
    DC_Run("cm_ShowButtonMenu")
return

<DC_OperationsViewer>:
    DC_Run("cm_OperationsViewer")
return

<DC_TreeView>:
    DC_Run("cm_TreeView")
return

<DC_FocusTreeView>:
    DC_Run("cm_FocusTreeView")
return

<DC_BriefView>:
    DC_Run("cm_BriefView")
return

<DC_ColumnsView1>:
    DC_ColumnsView("mine")
return

<DC_ColumnsView2>:
    DC_ColumnsView("test")
return

<DC_ThumbnailsView>:
    DC_Run("cm_ThumbnailsView")
    Gosub, <DC_ThumbnailsSwitchKey>
return

<DC_ThumbnailsSwitchKey>:
    InThumbsView := !InThumbsView

    if (InThumbsView) {
        vim.Map("l", "<right>", DC_Name)
    } else {
        vim.Map("l", "<enter>", DC_Name)
    }
return

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

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

    Fileread, Contents, % Clipboard
    Clipboard := Contents
return

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

    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_Dir . "\doublecmd.exe --no-splash"
        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 == "DClass") {
        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, 2
    pwd := Clipboard

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

    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_OpenPath(Path, InNewTab := true, LeftOrRight := "") {
    LeftOfRight := DC_GetPanelInfo()[1]
    if (LeftOfRight == "right") {
        LeftOrRight := "-R"
    } else {
        LeftOrRight := "-L"
    }

    if (InNewTab) {
        Run, "%DC_Dir%\doublecmd.exe" --no-splash -T "%LeftOrRight%" "%Path%"
    } else {
        Run, "%DC_Dir%\doublecmd.exe" --no-splash "%LeftOrRight%" "%Path%"
    }
}


Add some hotkeys for Git Gui.

Add some hotkeys for Git Gui.

#InstallKeybdHook
#SingleInstance Force
SetTitleMatchMode, RegEx

; ahk_class PotPlayer

#SC01F::Send {Media_Play_Pause}

$+1::Send {!}
$+2::Send {@}
$+3::Send {#}
$+4::Send {$}
$+5::Send {`%}
$+6::Send {^}
;$+7::Send {&}
$+8::Send {*}

GetKeyboardLayout()
{
	HKL := DllCall("GetKeyboardLayout", "UInt", 0, "Ptr")
	Return HKL
}

GetKeyboardLayoutName()
{
	VarSetCapacity(Str, 1000)
	DllCall("GetKeyboardLayoutName", "Str", Str, "Int")
	Return Str
}

ActivateKeyboardLayout(HKL) ; This does not work.
{
	; For initialization, necessary to run only once.
	DllCall("Ole32.dll\OleInitialize", "Ptr", 0, "Int")
	DllCall("LoadKeyboardLayout", "Str", "00020409", "Int")

	T := DllCall("ActivateKeyboardLayout", "UInt", HKL, "UInt", 0x00000000, "PTR")
	If (!T)
	{
		MsgBox, Error
	}
}

Capslock::
	SetCapsLockState, Off
	If (Lang = 0)
	{
		PostMessage, 0x50, 0, 0xF0020409,, A
		Lang := 1
	}
	Else
	{
		PostMessage, 0x50, 0, 0xF03A0429,, A
		Lang := 0
	}
	Return

<^Capslock::
	SetCapsLockState, Off
	PostMessage, 0x50, 0, 0xF01A0409,, A
	Return

>^Capslock::
	SetCapsLockState, Off
	PostMessage, 0x50, 0, 0xF01B0409,, A
	Return

!Capslock::
	T := GetKeyboardLayout()
	H := Format("{1:X}", T)
	MsgBox, %T% %H%
	Return

Temp()
{
	;^1:: ; This line is commented out.
		T := GetKeyboardLayout()
		H := Format("{1:X}", T)
		MsgBox, %T% %H%
		Return

	;^2:: ; This line is commented out.
		;ActivateKeyboardLayout(0xF0020409)
		PostMessage, 0x50, 0, 0xF0020409,, A
		MsgBox, Done.
		Return
}

#IfWinActive, ^Git Gui ahk_class ^TkTopLevel$

^+t::
	Send !c
	Send {Down 3}
	Send {Enter}
	Return
^+i::
	Send !c
	Send {Down 4}
	Send {Enter}
#IfWinActive, ahk_class ^#32770$
	Send y
#IfWinActive, ^Git Gui ahk_class ^TkTopLevel$
	Return
^+u::
	Send !c
	Send {Down 5}
	Send {Enter}
	Return
^+j::
	Send !c
	Send {Down 6}
	Send {Enter}
	Return

#IfWinActive

#InstallKeybdHook
#SingleInstance Force

; ahk_class PotPlayer

#SC01F::Send {Media_Play_Pause}

$+1::Send {!}
$+2::Send {@}
$+3::Send {#}
$+4::Send {$}
$+5::Send {`%}
$+6::Send {^}
;$+7::Send {&}
$+8::Send {*}

GetKeyboardLayout()
{
	HKL := DllCall("GetKeyboardLayout", "UInt", 0, "Ptr")
	Return HKL
}

GetKeyboardLayoutName()
{
	VarSetCapacity(Str, 1000)
	DllCall("GetKeyboardLayoutName", "Str", Str, "Int")
	Return Str
}

ActivateKeyboardLayout(HKL) ; This does not work.
{
	; For initialization, necessary to run only once.
	DllCall("Ole32.dll\OleInitialize", "Ptr", 0, "Int")
	DllCall("LoadKeyboardLayout", "Str", "00020409", "Int")

	T := DllCall("ActivateKeyboardLayout", "UInt", HKL, "UInt", 0x00000000, "PTR")
	If (!T)
	{
		MsgBox, Error
	}
}

Capslock::
	SetCapsLockState, Off
	If (Lang = 0)
	{
		PostMessage, 0x50, 0, 0xF0020409,, A
		Lang := 1
	}
	Else
	{
		PostMessage, 0x50, 0, 0xF03A0429,, A
		Lang := 0
	}
	Return

<^Capslock::
	SetCapsLockState, Off
	PostMessage, 0x50, 0, 0xF01A0409,, A
	Return

>^Capslock::
	SetCapsLockState, Off
	PostMessage, 0x50, 0, 0xF01B0409,, A
	Return

!Capslock::
	T := GetKeyboardLayout()
	H := Format("{1:X}", T)
	MsgBox, %T% %H%
	Return

Temp()
{
	;^1:: ; This line is commented out.
		T := GetKeyboardLayout()
		H := Format("{1:X}", T)
		MsgBox, %T% %H%
		Return

	;^2:: ; This line is commented out.
		;ActivateKeyboardLayout(0xF0020409)
		PostMessage, 0x50, 0, 0xF0020409,, A
		MsgBox, Done.
		Return
}


Add AhkTest function

Add AhkTest function

global Arg

Functions:
    @("Help", "帮助信息")
    @("KeyHelp", "置顶的按键帮助信息")
    @("AhkRun", "使用 Ahk 的 Run() 运行 `; command", true)
    @("CmdRun", "使用 cmd 运行 : command", true)
    @("CmdRunOnly", "只使用 cmd 运行")
    @("WinRRun", "使用 win + r 运行", true)
    @("Dictionary", "有道词典在线翻译", true)
    @("RunAndDisplay", "使用 cmd 运行，并显示结果", true)
    @("ReindexFiles", "重新索引待搜索文件")
    @("Clip", "显示剪切板内容")
    @("Calc", "计算器")
    @("SearchOnBaidu", "使用 Baidu（百度）搜索剪切板或输入内容", true)
    @("SearchOnGoogle", "使用 Google（谷歌）搜索剪切板或输入内容", true)
    @("SearchOnBing", "使用 Bing（必应）搜索剪切板或输入内容", true)
    @("SearchOnTaobao", "使用 Taobao（淘宝）搜索剪切板或输入内容")
    @("SearchOnJingdong", "使用 JD（京东）搜索剪切板或输入内容")
    @("EditConfig", "编辑配置文件")
    @("ClearClipboardFormat", "清除剪切板中文字的格式")
    @("RunClipboard", "使用 ahk 的 Run 运行剪切板内容")
    @("EmptyRecycle", "清空回收站")
    @("Logoff", "注销 登出")
    @("RestartMachine", "重启")
    @("ShutdownMachine", "关机")
    @("SuspendMachine", "挂起 睡眠 待机")
    @("HibernateMachine", "休眠")
    @("TurnMonitorOff", "关闭显示器")
    @("T2S", "将剪切板或输入内容中的繁体转成简体")
    @("S2T", "将剪切板或输入内容中的简体转成繁体")
    @("ShowIp", "显示 IP")
    @("Calendar", "用浏览器打开万年历")
    @("CleanupRank", "清理命令权重中的无效命令")
    @("CurrencyRate", "汇率 使用示例： hl JPY EUR 2")
    @("CNY2USD", "汇率 人民币兑换美元")
    @("USD2CNY", "汇率 美元兑换人民币")
    @("ProcessList", "进程列表")
    @("UrlEncode", "URL 编码")
    @("DiskSpace", "查看磁盘空间")
    @("ArgTest", "参数测试：ArgTest arg1,arg2,...")
    @("AhkTest", "运行参数或者剪切板中的 AHK 代码")

    if (IsLabel("ReservedFunctions"))
    {
        GoSub, ReservedFunctions
    }
return

Help:
    DisplayResult(KeyHelpText() . GetAllFunctions())
return

KeyHelp:
    ToolTip, % KeyHelpText()
    SetTimer, RemoveToolTip, 5000
return

CmdRun:
    RunWithCmd(Arg)
return

CmdRunOnly:
    RunWithCmd(Arg, true)
return

AhkRun:
    Run, %Arg%
return

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

EditConfig:
    Run, % g_ConfFile
return

CNY2USD:
    DisplayResult("查询中，可能会比较慢或者查询失败，请稍后...")
    DisplayResult(QueryCurrencyRate("CNY", "USD", Arg))
return

USD2CNY:
    DisplayResult("查询中，可能会比较慢或者查询失败，请稍后...")
    DisplayResult(QueryCurrencyRate("USD", "CNY", Arg))
return

CurrencyRate:
    args := StrSplit(Arg, " ")
    if (args.Length() != 3)
    {
        DisplayResult("使用示例：`n    CurrencyRate USD CNY 2")
        return
    }

    DisplayResult("查询中，可能会比较慢或者查询失败，请稍后...")
    DisplayResult(QueryCurrencyRate(args[1], args[2], args[3]))
return

QueryCurrencyRate(fromCurrency, toCurrency, amount)
{
    headers := Object()
    headers["apikey"] := "c9098c96599be340bbd9551e2b061f63"

    jsonText := UrlDownloadToString("http://apis.baidu.com/apistore/currencyservice/currency?"
        . "fromCurrency=" fromCurrency "&toCurrency=" toCurrency "&amount=" amount, headers)
    parsed := JSON.Load(jsonText)

    if (parsed.errNum != 0 && parsed.errMsg != "success")
    {
        return "查询失败，错误信息：`n`n" jsonText
    }

    result := fromCurrency " 兑换 " toCurrency " 当前汇率：`n`n" parsed.retData.currency "`n`n`n"
    result .= amount " " fromCurrency " = " parsed.retData.convertedamount " " toCurrency "`n"

    return result
}

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

    for index, argument in args
    {
        result .= "第 " . index . " 个参数：" . 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 == "" ? clipboard : Arg

    url := "http://fanyi.youdao.com/openapi.do?keyfrom=YouDaoCV&key=659600698&"
            . "type=data&doctype=json&version=1.2&q=" UrlEncode(word)

    jsonText := StrReplace(UrlDownloadToString(url), "-phonetic", "_phonetic")

    if (jsonText == "no query")
    {
        DisplayResult("未查到结果")
        return
    }

    parsed := JSON.Load(jsonText)
    result := parsed.query

    if (parsed.basic.uk_phonetic != "" && parsed.basic.us_phonetic != "")
    {
        result .= " UK: [" parsed.basic.uk_phonetic "], US: [" parsed.basic.us_phonetic "]`n"
    }
    else if (parsed.basic.phonetic != "")
    {
        result .= " [" parsed.basic.phonetic "]`n"
    }
    else
    {
        result .= "`n"
    }

    if (parsed.basic.explains.Length() > 0)
    {
        result .= "`n"
        for index, explain in parsed.basic.explains
        {
            result .= "    * " explain "`n"
        }
    }

    if (parsed.web.Length() > 0)
    {
        result .= "`n----`n"

        for i, element in parsed.web
        {
            result .= "`n    * " element.key
            for j, value in element.value
            {
                if (j == 1)
                {
                    result .= "`n       "
                }
                else
                {
                    result .= "`; "
                }

                result .= value
            }
        }
    }

    DisplayResult(result)
    clipboard := result
return

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

T2S:
    text := Arg == "" ? clipboard : Arg
    clipboard := ""
    clipboard := Kanji_t2s(text)
    ClipWait
    DisplayResult(clipboard)
return

S2T:
    text := Arg == "" ? clipboard : Arg
    clipboard := ""
    clipboard := Kanji_s2t(text)
    ClipWait
    DisplayResult(clipboard)
return

ClearClipboardFormat:
    clipboard := clipboard
return

SearchOnBaidu:
    word := Arg == "" ? clipboard : Arg

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

SearchOnGoogle:
    word := UrlEncode(Arg == "" ? clipboard : Arg)

    Run, https://www.google.com.hk/#newwindow=1&safe=strict&q=%word%
return

SearchOnBing:
    word := Arg == "" ? clipboard : Arg

    Run, http://cn.bing.com/search?q=%word%
return

SearchOnTaobao:
    word := Arg == "" ? clipboard : Arg

    Run, https://s.taobao.com/search?q=%word%
return

SearchOnJingdong:
    word := Arg == "" ? clipboard : Arg

    Run, http://search.jd.com/Search?keyword=%word%&enc=utf-8
return

RunClipboard:
    Run, %clipboard%
return

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

RunAndDisplay:
    DisplayResult(RunAndGetOutput(Arg))
return

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

Logoff:
    MsgBox, 4, , 将要注销，是否执行？
    {
        Shutdown, 0
    }
return

ShutdownMachine:
    MsgBox, 4, , 将要关机，是否执行？
    IfMsgBox Yes
    {
        Shutdown, 1
    }
return

RestartMachine:
    MsgBox, 4, , 将要重启机器，是否执行？
    IfMsgBox Yes
    {
        Shutdown, 2
    }
return

HibernateMachine:
    MsgBox, 4, , 将要休眠，是否执行？
    IfMsgBox Yes
    {
        ; 参数 #1: 使用 1 代替 0 来进行休眠而不是挂起。
        ; 参数 #2: 使用 1 代替 0 来立即挂起而不询问每个应用程序以获得许可。
        ; 参数 #3: 使用 1 而不是 0 来禁止所有的唤醒事件。
        DllCall("PowrProf\SetSuspendState", "int", 1, "int", 0, "int", 0)
    }
return

SuspendMachine:
    MsgBox, 4, , 将要待机，是否执行？
    IfMsgBox Yes
    {
        DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)
    }
return

TurnMonitorOff:
    ; 关闭显示器:
    SendMessage, 0x112, 0xF170, 2,, Program Manager
    ; 0x112 is WM_SYSCOMMAND, 0xF170 is SC_MONITORPOWER.
    ; 对上面命令的注释: 使用 -1 代替 2 来打开显示器.
    ; 使用 1 代替 2 来激活显示器的节能模式.
return

EmptyRecycle:
    MsgBox, 4, , 将要清空回收站，是否执行？
    IfMsgBox Yes
    {
        FileRecycleEmpty,
    }
return

ProcessList:
    result := ""

    for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
        result .= "* | 进程 | " process.Name " | " process.CommandLine "`n"
    Sort, result

    DisplayResult(FilterResult(AlignText(result), Arg))
    TurnOnResultFilter()
return

UrlEncode:
    text := Arg == "" ? clipboard : Arg
    clipboard := UrlEncode(text)
    DisplayResult(clipboard)
return

DiskSpace:
    result := ""

    DriveGet, list, list
    Loop, Parse, list
    {
        drive := A_LoopField ":"
        DriveGet, label, label, %drive%
        DriveGet, cap, capacity, %drive%
        DrivespaceFree, free, %drive%
        SetFormat, float, 5.2
        percent := 100 * (cap - free) / cap
        SetFormat, float, 6.2
        cap /= 1024.0
        free /= 1024.0
        result = %result%* | %drive% | 总共: %cap% G  可用: %free% G | 已使用：%percent%`%  卷标: %label%`n
    }

	DisplayResult(AlignText(result))
return

AhkTest:
    text := Arg == "" ? clipboard : Arg
    FileDelete, %A_Temp%\RunZ.AhkTest.ahk
    FileAppend, %text%, %A_Temp%\RunZ.AhkTest.ahk
    Run, %A_Temp%\RunZ.AhkTest.ahk
return

global Arg

Functions:
    @("Help", "帮助信息")
    @("KeyHelp", "置顶的按键帮助信息")
    @("AhkRun", "使用 Ahk 的 Run() 运行 `; command", true)
    @("CmdRun", "使用 cmd 运行 : command", true)
    @("CmdRunOnly", "只使用 cmd 运行")
    @("WinRRun", "使用 win + r 运行", true)
    @("Dictionary", "有道词典在线翻译", true)
    @("RunAndDisplay", "使用 cmd 运行，并显示结果", true)
    @("ReindexFiles", "重新索引待搜索文件")
    @("Clip", "显示剪切板内容")
    @("Calc", "计算器")
    @("SearchOnBaidu", "使用 Baidu（百度）搜索剪切板或输入内容", true)
    @("SearchOnGoogle", "使用 Google（谷歌）搜索剪切板或输入内容", true)
    @("SearchOnBing", "使用 Bing（必应）搜索剪切板或输入内容", true)
    @("SearchOnTaobao", "使用 Taobao（淘宝）搜索剪切板或输入内容")
    @("SearchOnJingdong", "使用 JD（京东）搜索剪切板或输入内容")
    @("EditConfig", "编辑配置文件")
    @("ClearClipboardFormat", "清除剪切板中文字的格式")
    @("RunClipboard", "使用 ahk 的 Run 运行剪切板内容")
    @("EmptyRecycle", "清空回收站")
    @("Logoff", "注销 登出")
    @("RestartMachine", "重启")
    @("ShutdownMachine", "关机")
    @("SuspendMachine", "挂起 睡眠 待机")
    @("HibernateMachine", "休眠")
    @("TurnMonitorOff", "关闭显示器")
    @("T2S", "将剪切板或输入内容中的繁体转成简体")
    @("S2T", "将剪切板或输入内容中的简体转成繁体")
    @("ShowIp", "显示 IP")
    @("Calendar", "用浏览器打开万年历")
    @("CleanupRank", "清理命令权重中的无效命令")
    @("CurrencyRate", "汇率 使用示例： hl JPY EUR 2")
    @("CNY2USD", "汇率 人民币兑换美元")
    @("USD2CNY", "汇率 美元兑换人民币")
    @("ProcessList", "进程列表")
    @("UrlEncode", "URL 编码")
    @("DiskSpace", "查看磁盘空间")
    @("ArgTest", "参数测试：ArgTest arg1,arg2,...")

    if (IsLabel("ReservedFunctions"))
    {
        GoSub, ReservedFunctions
    }
return

Help:
    DisplayResult(KeyHelpText() . GetAllFunctions())
return

KeyHelp:
    ToolTip, % KeyHelpText()
    SetTimer, RemoveToolTip, 5000
return

CmdRun:
    RunWithCmd(Arg)
return

CmdRunOnly:
    RunWithCmd(Arg, true)
return

AhkRun:
    Run, %Arg%
return

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

EditConfig:
    Run, % g_ConfFile
return

CNY2USD:
    DisplayResult("查询中，可能会比较慢或者查询失败，请稍后...")
    DisplayResult(QueryCurrencyRate("CNY", "USD", Arg))
return

USD2CNY:
    DisplayResult("查询中，可能会比较慢或者查询失败，请稍后...")
    DisplayResult(QueryCurrencyRate("USD", "CNY", Arg))
return

CurrencyRate:
    args := StrSplit(Arg, " ")
    if (args.Length() != 3)
    {
        DisplayResult("使用示例：`n    CurrencyRate USD CNY 2")
        return
    }

    DisplayResult("查询中，可能会比较慢或者查询失败，请稍后...")
    DisplayResult(QueryCurrencyRate(args[1], args[2], args[3]))
return

QueryCurrencyRate(fromCurrency, toCurrency, amount)
{
    headers := Object()
    headers["apikey"] := "c9098c96599be340bbd9551e2b061f63"

    jsonText := UrlDownloadToString("http://apis.baidu.com/apistore/currencyservice/currency?"
        . "fromCurrency=" fromCurrency "&toCurrency=" toCurrency "&amount=" amount, headers)
    parsed := JSON.Load(jsonText)

    if (parsed.errNum != 0 && parsed.errMsg != "success")
    {
        return "查询失败，错误信息：`n`n" jsonText
    }

    result := fromCurrency " 兑换 " toCurrency " 当前汇率：`n`n" parsed.retData.currency "`n`n`n"
    result .= amount " " fromCurrency " = " parsed.retData.convertedamount " " toCurrency "`n"

    return result
}

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

    for index, argument in args
    {
        result .= "第 " . index . " 个参数：" . 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 == "" ? clipboard : Arg

    url := "http://fanyi.youdao.com/openapi.do?keyfrom=YouDaoCV&key=659600698&"
            . "type=data&doctype=json&version=1.2&q=" UrlEncode(word)

    jsonText := StrReplace(UrlDownloadToString(url), "-phonetic", "_phonetic")

    if (jsonText == "no query")
    {
        DisplayResult("未查到结果")
        return
    }

    parsed := JSON.Load(jsonText)
    result := parsed.query

    if (parsed.basic.uk_phonetic != "" && parsed.basic.us_phonetic != "")
    {
        result .= " UK: [" parsed.basic.uk_phonetic "], US: [" parsed.basic.us_phonetic "]`n"
    }
    else if (parsed.basic.phonetic != "")
    {
        result .= " [" parsed.basic.phonetic "]`n"
    }
    else
    {
        result .= "`n"
    }

    if (parsed.basic.explains.Length() > 0)
    {
        result .= "`n"
        for index, explain in parsed.basic.explains
        {
            result .= "    * " explain "`n"
        }
    }

    if (parsed.web.Length() > 0)
    {
        result .= "`n----`n"

        for i, element in parsed.web
        {
            result .= "`n    * " element.key
            for j, value in element.value
            {
                if (j == 1)
                {
                    result .= "`n       "
                }
                else
                {
                    result .= "`; "
                }

                result .= value
            }
        }
    }

    DisplayResult(result)
    clipboard := result
return

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

T2S:
    text := Arg == "" ? clipboard : Arg
    clipboard := ""
    clipboard := Kanji_t2s(text)
    ClipWait
    DisplayResult(clipboard)
return

S2T:
    text := Arg == "" ? clipboard : Arg
    clipboard := ""
    clipboard := Kanji_s2t(text)
    ClipWait
    DisplayResult(clipboard)
return

ClearClipboardFormat:
    clipboard := clipboard
return

SearchOnBaidu:
    word := Arg == "" ? clipboard : Arg

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

SearchOnGoogle:
    word := UrlEncode(Arg == "" ? clipboard : Arg)

    Run, https://www.google.com.hk/#newwindow=1&safe=strict&q=%word%
return

SearchOnBing:
    word := Arg == "" ? clipboard : Arg

    Run, http://cn.bing.com/search?q=%word%
return

SearchOnTaobao:
    word := Arg == "" ? clipboard : Arg

    Run, https://s.taobao.com/search?q=%word%
return

SearchOnJingdong:
    word := Arg == "" ? clipboard : Arg

    Run, http://search.jd.com/Search?keyword=%word%&enc=utf-8
return

RunClipboard:
    Run, %clipboard%
return

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

RunAndDisplay:
    DisplayResult(RunAndGetOutput(Arg))
return

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

Logoff:
    MsgBox, 4, , 将要注销，是否执行？
    {
        Shutdown, 0
    }
return

ShutdownMachine:
    MsgBox, 4, , 将要关机，是否执行？
    IfMsgBox Yes
    {
        Shutdown, 1
    }
return

RestartMachine:
    MsgBox, 4, , 将要重启机器，是否执行？
    IfMsgBox Yes
    {
        Shutdown, 2
    }
return

HibernateMachine:
    MsgBox, 4, , 将要休眠，是否执行？
    IfMsgBox Yes
    {
        ; 参数 #1: 使用 1 代替 0 来进行休眠而不是挂起。
        ; 参数 #2: 使用 1 代替 0 来立即挂起而不询问每个应用程序以获得许可。
        ; 参数 #3: 使用 1 而不是 0 来禁止所有的唤醒事件。
        DllCall("PowrProf\SetSuspendState", "int", 1, "int", 0, "int", 0)
    }
return

SuspendMachine:
    MsgBox, 4, , 将要待机，是否执行？
    IfMsgBox Yes
    {
        DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)
    }
return

TurnMonitorOff:
    ; 关闭显示器:
    SendMessage, 0x112, 0xF170, 2,, Program Manager
    ; 0x112 is WM_SYSCOMMAND, 0xF170 is SC_MONITORPOWER.
    ; 对上面命令的注释: 使用 -1 代替 2 来打开显示器.
    ; 使用 1 代替 2 来激活显示器的节能模式.
return

EmptyRecycle:
    MsgBox, 4, , 将要清空回收站，是否执行？
    IfMsgBox Yes
    {
        FileRecycleEmpty,
    }
return

ProcessList:
    result := ""

    for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
        result .= "* | 进程 | " process.Name " | " process.CommandLine "`n"
    Sort, result

    DisplayResult(FilterResult(AlignText(result), Arg))
    TurnOnResultFilter()
return

UrlEncode:
    text := Arg == "" ? clipboard : Arg
    clipboard := UrlEncode(text)
    DisplayResult(clipboard)
return

DiskSpace:
    result := ""

    DriveGet, list, list
    Loop, Parse, list
    {
        drive := A_LoopField ":"
        DriveGet, label, label, %drive%
        DriveGet, cap, capacity, %drive%
        DrivespaceFree, free, %drive%
        SetFormat, float, 5.2
        percent := 100 * (cap - free) / cap
        SetFormat, float, 6.2
        cap /= 1024.0
        free /= 1024.0
        result = %result%* | %drive% | 总共: %cap% G  可用: %free% G | 已使用：%percent%`%  卷标: %label%`n
    }

	DisplayResult(AlignText(result))
return


Update text

Update text

; RunZ:System
; 操作系统相关功能

System:
    @("Clip", "显示剪切板内容")
    @("ClearClipboardFormat", "清除剪切板中文字的格式")
    @("EmptyRecycle", "清空回收站")
    @("Logoff", "注销 登出")
    @("RestartMachine", "重启")
    @("ShutdownMachine", "关机")
    @("SuspendMachine", "挂起 睡眠 待机")
    @("HibernateMachine", "休眠")
    @("TurnMonitorOff", "关闭显示器")
    @("ListProcess", "列出进程 ps")
    @("DiskSpace", "查看磁盘空间 df")
    @("IncreaseVolume", "提高音量")
    @("DecreaseVolume", "降低音量")
    @("SystemState", "系统状态 top")
    @("KillProcess", "杀死进程")
    @("SendToClip", "发送到剪切板")
    @("ListWindow", "窗口列表")
    @("ActivateWindow", "激活窗口")
    @("ListRunningService", "列出运行的服务")
    @("ListAllService", "列出所有的服务")
    @("ShowService", "显示服务详情")
    @("ShowProcess", "显示进程详情")
return

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

ClearClipboardFormat:
    clipboard := clipboard
return

Logoff:
    MsgBox, 4, , 将要注销，是否执行？
    IfMsgBox Yes
    {
        Shutdown, 0
    }
return

ShutdownMachine:
    MsgBox, 4, , 将要关机，是否执行？
    IfMsgBox Yes
    {
        Shutdown, 1
    }
return

RestartMachine:
    MsgBox, 4, , 将要重启机器，是否执行？
    IfMsgBox Yes
    {
        Shutdown, 2
    }
return

HibernateMachine:
    MsgBox, 4, , 将要休眠，是否执行？
    IfMsgBox Yes
    {
        ; 参数 #1: 使用 1 代替 0 来进行休眠而不是挂起。
        ; 参数 #2: 使用 1 代替 0 来立即挂起而不询问每个应用程序以获得许可。
        ; 参数 #3: 使用 1 而不是 0 来禁止所有的唤醒事件。
        DllCall("PowrProf\SetSuspendState", "int", 1, "int", 0, "int", 0)
    }
return

SuspendMachine:
    MsgBox, 4, , 将要待机，是否执行？
    IfMsgBox Yes
    {
        DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)
    }
return

TurnMonitorOff:
    ; 关闭显示器:
    SendMessage, 0x112, 0xF170, 2,, Program Manager
    ; 0x112 is WM_SYSCOMMAND, 0xF170 is SC_MONITORPOWER.
    ; 对上面命令的注释: 使用 -1 代替 2 来打开显示器.
    ; 使用 1 代替 2 来激活显示器的节能模式.
return

EmptyRecycle:
    MsgBox, 4, , 将要清空回收站，是否执行？
    IfMsgBox Yes
    {
        FileRecycleEmpty,
    }
return

ListProcess:
    result := ""

    for process in ComObjGet("winmgmts:").ExecQuery("select * from Win32_Process")
    {
        result .= "* | 进程 | " process.Name " | " process.CommandLine "`n"
    }
    Sort, result

    SetCommandFilter("KillProcess|ShowProcess|CountNumber")
    DisplayResult(FilterResult(AlignText(result), Arg))
    TurnOnResultFilter()
return

DiskSpace:
    result := ""

    DriveGet, list, list
    Loop, Parse, list
    {
        drive := A_LoopField ":"
        DriveGet, label, label, %drive%
        DriveGet, cap, capacity, %drive%
        DrivespaceFree, free, %drive%
        SetFormat, float, 5.2
        percent := 100 * (cap - free) / cap
        SetFormat, float, 6.2
        cap /= 1024.0
        free /= 1024.0
        result = %result%* | %drive% | 总共: %cap% G  可用: %free% G | 已使用：%percent%`%  卷标: %label%`n
    }

    DisplayResult(AlignText(result))
return

IncreaseVolume:
    SoundSet, +5
return

DecreaseVolume:
    SoundSet, -5
return

SystemState:
    if (!SetExecInterval(1))
    {
        return
    }

    GMSEx := GlobalMemoryStatusEx()
    result := "* | 状态 | 运行时间 | " Round(A_TickCount / 1000 / 3600, 3) " 小时`n"
    result .= "* | 状态 | CPU 占用 | " CPULoad() "% `n"
    result .= "* | 状态 | 内存占用 | " Round(100 * (GMSEx[2] - GMSEx[3]) / GMSEx[2], 2) "% `n"
    result .= "* | 状态 | 进程总数 | " GetProcessCount() "`n"
    result .= "* | 状态 | 内存总量 | " Round(GMSEx[2] / 1024**2, 2) "MB `n"
    result .= "* | 状态 | 可用内存 | " Round(GMSEx[3] / 1024**2, 2) "MB `n"
    DisplayResult(AlignText(result))
return

KillProcess:
    args := StrSplit(Arg, " ")
    for index, argument in args
    {
        Process, Close, %argument%
    }

    DisplayResult("已尝试杀死 " Arg " 进程")
return

SendToClip:
    clipboard := Arg
    GoSub, Clip
return

ListWindow:
    result := ""

    WinGet, id, list, , , Program Manager
    Loop, %id%
    {
        thisId := id%A_Index%
        WinGetTitle, title, ahk_id %thisId%
        WinGet, name, ProcessName, ahk_id %thisId%
        if (title == "")
        {
            continue
        }
        result .= "* | 窗口 | " name " | " title "`n"
    }

    SetCommandFilter("ActivateWindow|KillProcess")
    DisplayResult(AlignText(result))
    TurnOnResultFilter()
return

ActivateWindow:
    DisplayResult()
    ClearInput()

    if (FullPipeArg != "")
    {
        Loop, Parse, FullPipeArg, `n, `r
        {
            if (A_LoopField == "")
            {
                return
            }
            splitedLine := StrSplit(A_LoopField, " | ")
            WinActivate, % Trim(splitedLine[4])
        }
    }
    else
    {
        for index, argument in StrSplit(Arg, " ")
        {
            WinActivate, ahk_exe %argument%
        }
    }
return

ListAllService:
    result :=
    for service in ComObjGet("winmgmts:").ExecQuery("select * from Win32_Service")
    {
        result .= "* | 服务 | " service.Name " | " service.DisplayName "`n"
    }
    Sort, result

    SetCommandFilter("CountNumber|ShowService")
    DisplayResult(FilterResult(AlignText(result), Arg))
    TurnOnResultFilter()
return

ListRunningService:
    result :=
    for service in ComObjGet("winmgmts:").ExecQuery("select * from Win32_Service")
    {
        if (service.Started != 0)
        {
            result .= "* | 服务 | " service.Name " | " service.DisplayName "`n"
        }
    }
    Sort, result

    SetCommandFilter("CountNumber|ShowService")
    DisplayResult(FilterResult(AlignText(result), Arg))
    TurnOnResultFilter()
return

ShowService:
    result :=
    ; 暂时只支持一个，选得多了查起来太慢
    for service in ComObjGet("winmgmts:")
        .ExecQuery("select * from Win32_Service where Name = '" StrSplit(Arg, " ")[1] "'")
    {
        ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa394418%28v=vs.85%29.aspx
        result .= "* | 服务 | 名称 | " service.Name "`n"
        result .= "* | 服务 | 描述 | " service.Description "`n"
        result .= "* | 服务 | 是否在运行 | " service.Started "`n"
        result .= "* | 服务 | 路径 | " service.PathName "`n"
        result .= "* | 服务 | 进程 ID | " service.ProcessId "`n"
        result .= "* | 服务 | 类型 | " service.ServiceType "`n"
        break
    }

    DisplayResult(AlignText(result))
return

ShowProcess:
    result :=
    ; 暂时只支持一个，选得多了查起来太慢
    for process in ComObjGet("winmgmts:")
        .ExecQuery("select * from Win32_Process where Name = '" StrSplit(Arg, " ")[1] "'")
    {
        ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa394372%28v=vs.85%29.aspx
        result .= "* | 服务 | 名称 | " process.Name "`n"
        result .= "* | 服务 | 描述 | " process.Description "`n"
        result .= "* | 服务 | 命令行 | " process.CommandLine "`n"
        result .= "* | 服务 | 启动时间 | " process.CreationDate "`n"
        result .= "* | 服务 | ID | " process.ProcessId "`n"
        break
    }

    DisplayResult(AlignText(result))
return

; RunZ:System
; 操作系统相关功能

System:
    @("Clip", "显示剪切板内容")
    @("ClearClipboardFormat", "清除剪切板中文字的格式")
    @("EmptyRecycle", "清空回收站")
    @("Logoff", "注销 登出")
    @("RestartMachine", "重启")
    @("ShutdownMachine", "关机")
    @("SuspendMachine", "挂起 睡眠 待机")
    @("HibernateMachine", "休眠")
    @("TurnMonitorOff", "关闭显示器")
    @("ListProcess", "列出进程 ps")
    @("DiskSpace", "查看磁盘空间 df")
    @("IncreaseVolume", "提高音量")
    @("DecreaseVolume", "降低音量")
    @("SystemState", "系统状态 top")
    @("KillProcess", "杀死进程")
    @("SendToClip", "发送到剪切板")
    @("ListWindow", "窗口列表")
    @("ActivateWindow", "激活窗口")
    @("ListRunningService", "列出运行的服务")
    @("ListAllService", "列出运行的服务")
    @("ShowService", "显示服务详情")
    @("ShowProcess", "显示进程详情")
return

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

ClearClipboardFormat:
    clipboard := clipboard
return

Logoff:
    MsgBox, 4, , 将要注销，是否执行？
    IfMsgBox Yes
    {
        Shutdown, 0
    }
return

ShutdownMachine:
    MsgBox, 4, , 将要关机，是否执行？
    IfMsgBox Yes
    {
        Shutdown, 1
    }
return

RestartMachine:
    MsgBox, 4, , 将要重启机器，是否执行？
    IfMsgBox Yes
    {
        Shutdown, 2
    }
return

HibernateMachine:
    MsgBox, 4, , 将要休眠，是否执行？
    IfMsgBox Yes
    {
        ; 参数 #1: 使用 1 代替 0 来进行休眠而不是挂起。
        ; 参数 #2: 使用 1 代替 0 来立即挂起而不询问每个应用程序以获得许可。
        ; 参数 #3: 使用 1 而不是 0 来禁止所有的唤醒事件。
        DllCall("PowrProf\SetSuspendState", "int", 1, "int", 0, "int", 0)
    }
return

SuspendMachine:
    MsgBox, 4, , 将要待机，是否执行？
    IfMsgBox Yes
    {
        DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)
    }
return

TurnMonitorOff:
    ; 关闭显示器:
    SendMessage, 0x112, 0xF170, 2,, Program Manager
    ; 0x112 is WM_SYSCOMMAND, 0xF170 is SC_MONITORPOWER.
    ; 对上面命令的注释: 使用 -1 代替 2 来打开显示器.
    ; 使用 1 代替 2 来激活显示器的节能模式.
return

EmptyRecycle:
    MsgBox, 4, , 将要清空回收站，是否执行？
    IfMsgBox Yes
    {
        FileRecycleEmpty,
    }
return

ListProcess:
    result := ""

    for process in ComObjGet("winmgmts:").ExecQuery("select * from Win32_Process")
    {
        result .= "* | 进程 | " process.Name " | " process.CommandLine "`n"
    }
    Sort, result

    SetCommandFilter("KillProcess|ShowProcess|CountNumber")
    DisplayResult(FilterResult(AlignText(result), Arg))
    TurnOnResultFilter()
return

DiskSpace:
    result := ""

    DriveGet, list, list
    Loop, Parse, list
    {
        drive := A_LoopField ":"
        DriveGet, label, label, %drive%
        DriveGet, cap, capacity, %drive%
        DrivespaceFree, free, %drive%
        SetFormat, float, 5.2
        percent := 100 * (cap - free) / cap
        SetFormat, float, 6.2
        cap /= 1024.0
        free /= 1024.0
        result = %result%* | %drive% | 总共: %cap% G  可用: %free% G | 已使用：%percent%`%  卷标: %label%`n
    }

    DisplayResult(AlignText(result))
return

IncreaseVolume:
    SoundSet, +5
return

DecreaseVolume:
    SoundSet, -5
return

SystemState:
    if (!SetExecInterval(1))
    {
        return
    }

    GMSEx := GlobalMemoryStatusEx()
    result := "* | 状态 | 运行时间 | " Round(A_TickCount / 1000 / 3600, 3) " 小时`n"
    result .= "* | 状态 | CPU 占用 | " CPULoad() "% `n"
    result .= "* | 状态 | 内存占用 | " Round(100 * (GMSEx[2] - GMSEx[3]) / GMSEx[2], 2) "% `n"
    result .= "* | 状态 | 进程总数 | " GetProcessCount() "`n"
    result .= "* | 状态 | 内存总量 | " Round(GMSEx[2] / 1024**2, 2) "MB `n"
    result .= "* | 状态 | 可用内存 | " Round(GMSEx[3] / 1024**2, 2) "MB `n"
    DisplayResult(AlignText(result))
return

KillProcess:
    args := StrSplit(Arg, " ")
    for index, argument in args
    {
        Process, Close, %argument%
    }

    DisplayResult("已尝试杀死 " Arg " 进程")
return

SendToClip:
    clipboard := Arg
    GoSub, Clip
return

ListWindow:
    result := ""

    WinGet, id, list, , , Program Manager
    Loop, %id%
    {
        thisId := id%A_Index%
        WinGetTitle, title, ahk_id %thisId%
        WinGet, name, ProcessName, ahk_id %thisId%
        if (title == "")
        {
            continue
        }
        result .= "* | 窗口 | " name " | " title "`n"
    }

    SetCommandFilter("ActivateWindow|KillProcess")
    DisplayResult(AlignText(result))
    TurnOnResultFilter()
return

ActivateWindow:
    DisplayResult()
    ClearInput()

    if (FullPipeArg != "")
    {
        Loop, Parse, FullPipeArg, `n, `r
        {
            if (A_LoopField == "")
            {
                return
            }
            splitedLine := StrSplit(A_LoopField, " | ")
            WinActivate, % Trim(splitedLine[4])
        }
    }
    else
    {
        for index, argument in StrSplit(Arg, " ")
        {
            WinActivate, ahk_exe %argument%
        }
    }
return

ListAllService:
    result :=
    for service in ComObjGet("winmgmts:").ExecQuery("select * from Win32_Service")
    {
        result .= "* | 服务 | " service.Name " | " service.DisplayName "`n"
    }
    Sort, result

    SetCommandFilter("CountNumber|ShowService")
    DisplayResult(FilterResult(AlignText(result), Arg))
    TurnOnResultFilter()
return

ListRunningService:
    result :=
    for service in ComObjGet("winmgmts:").ExecQuery("select * from Win32_Service")
    {
        if (service.Started != 0)
        {
            result .= "* | 服务 | " service.Name " | " service.DisplayName "`n"
        }
    }
    Sort, result

    SetCommandFilter("CountNumber|ShowService")
    DisplayResult(FilterResult(AlignText(result), Arg))
    TurnOnResultFilter()
return

ShowService:
    result :=
    ; 暂时只支持一个，选得多了查起来太慢
    for service in ComObjGet("winmgmts:")
        .ExecQuery("select * from Win32_Service where Name = '" StrSplit(Arg, " ")[1] "'")
    {
        ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa394418%28v=vs.85%29.aspx
        result .= "* | 服务 | 名称 | " service.Name "`n"
        result .= "* | 服务 | 描述 | " service.Description "`n"
        result .= "* | 服务 | 是否在运行 | " service.Started "`n"
        result .= "* | 服务 | 路径 | " service.PathName "`n"
        result .= "* | 服务 | 进程 ID | " service.ProcessId "`n"
        result .= "* | 服务 | 类型 | " service.ServiceType "`n"
        break
    }

    DisplayResult(AlignText(result))
return

ShowProcess:
    result :=
    ; 暂时只支持一个，选得多了查起来太慢
    for process in ComObjGet("winmgmts:")
        .ExecQuery("select * from Win32_Process where Name = '" StrSplit(Arg, " ")[1] "'")
    {
        ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa394372%28v=vs.85%29.aspx
        result .= "* | 服务 | 名称 | " process.Name "`n"
        result .= "* | 服务 | 描述 | " process.Description "`n"
        result .= "* | 服务 | 命令行 | " process.CommandLine "`n"
        result .= "* | 服务 | 启动时间 | " process.CreationDate "`n"
        result .= "* | 服务 | ID | " process.ProcessId "`n"
        break
    }

    DisplayResult(AlignText(result))
return


More minor fixes

More minor fixes

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#SingleInstance force
;#NoTrayIcon
SendMode Input

Menu, Tray, Icon, assets/keyboard.ico, 1, 1
Menu, Tray, Tip, Emoji Keyboard
Menu, Tray, Add, &Show, Toggle
Menu, Tray, Add
Menu, Tray, Add, Emoji &Keyboard by Gilles Waeber, Credits
Menu, Tray, Add
Menu, Tray, Add, E&xit, Exit
Menu, Tray, Default, &Show
Menu, Tray, NoStandard

#Include assets\JSON_ToObj.ahk
#Include assets\Webapp.ahk
__Webapp_AppStart:
;<< Header End >>

;             not focusable
Gui __Webapp_:+E0x08000000 +AlwaysOnTop -MaximizeBox -MinimizeBox ; +E0x40000 +ToolWindow ;  -Caption
OnMessage(0x112, "WM_SYSCOMMAND")

WM_SYSCOMMAND(wParam)
{
	global vVisible
    if (wParam = 0xF060 and vVisible) ; SC_CLOSE hide instead of closing
    {
        Hide()
        return 0
    }
}

;Variable containing the current state
vVisible := false

;Get our HTML DOM object
iWebCtrl := getDOM()

;Change App name on run-time
setAppName("Emoji Keyboard")

; Our custom protocol's url event handler
app_call(args) {

	;MsgBox %args%
	param := SubStr(args, 6)
	if SubStr(args, 1, 5) = "send/"
		Send(param)
}

; function to run when page is loaded
app_page(NewURL) {
}

Gui __Webapp_:Hide
Return

~LAlt::	; <-- OPEN with double left alt key
	global vVisible
	if (A_PriorHotkey <> "~LAlt" or A_TimeSincePriorHotkey > 400) {
		if(vVisible){
			vVisible := false
			Hide()
			KeyWait, LAlt
			Send, {LAlt}
		}
		return
	}
	KeyWait, LAlt
	Show()
Return

; Functions to be called from the html/js source
Exit() {
	ExitApp
}

clipSaved =
bClipSaved := False

Credits(){
	Run, http://www.gilleswaeber.ch
}
Reload() {
	Reload
}
Run(t) {
	Run, %t%
}
Send(t) {
	global clipSaved, bClipSaved
	if(not bClipSaved){
		clipSaved := ClipboardAll
		bClipSaved := True
	}
	Clipboard := t
	Sleep, 10
	Send, ^v
	SetTimer, RestoreClipboard, 200
}
RestoreClipboard() {
	global clipSaved, bClipSaved
	SetTimer, RestoreClipboard, Off
	Clipboard := clipSaved
	clipSaved =
	bClipSaved := False
}
Show(){
	global vVisible
	vVisible := true
	Gui __Webapp_:Show
	Sleep, 10
	Send, !{Esc}
}
Hide(){
	global vVisible
	vVisible := false
	Gui __Webapp_:Hide
}
Toggle(){
	global vVisible
	if(vVisible){
		Hide()
	}
	else{
		Show()
	}
}
Ready(){
	global j
	getDOM().document.ahk.setKeymap(j.keymap)
}

#If vVisible
; Corresponding keys                    	;	US	CH
SC001::getDOM().document.ahk.input(1)   	;	ESC	ESC
SC03B::getDOM().document.ahk.input(59)   	;	F1	F1
SC03C::getDOM().document.ahk.input(60)   	;	F2	F2
SC03D::getDOM().document.ahk.input(61)   	;	F3	F3
SC03E::getDOM().document.ahk.input(62)   	;	F4	F4
SC03F::getDOM().document.ahk.input(63)   	;	F5	F5
SC040::getDOM().document.ahk.input(64)   	;	F6	F6
SC041::getDOM().document.ahk.input(65)   	;	F7	F7
SC042::getDOM().document.ahk.input(66)   	;	F8	F8
SC043::getDOM().document.ahk.input(67)   	;	F9	F9
SC044::getDOM().document.ahk.input(68)   	;	F10	F10
SC057::getDOM().document.ahk.input(87)   	;	F11	F11
SC058::getDOM().document.ahk.input(88)   	;	F12	F12
SC029::getDOM().document.ahk.input(41)   	;	`	§
SC002::getDOM().document.ahk.input(2)    	;	1	1
SC003::getDOM().document.ahk.input(3)   	;	2	2
SC004::getDOM().document.ahk.input(4)   	;	3	3
SC005::getDOM().document.ahk.input(5)   	;	4	4
SC006::getDOM().document.ahk.input(6)   	;	5	5
SC007::getDOM().document.ahk.input(7)   	;	6	6
SC008::getDOM().document.ahk.input(8)   	;	7	7
SC009::getDOM().document.ahk.input(9)   	;	8	8
SC00A::getDOM().document.ahk.input(10)   	;	9	9
SC00B::getDOM().document.ahk.input(11)   	;	0	0
SC00C::getDOM().document.ahk.input(12)   	;	-	'
SC00D::getDOM().document.ahk.input(13)   	;	=	^
SC010::getDOM().document.ahk.input(16)   	;	q	q
SC011::getDOM().document.ahk.input(17)   	;	w	w
SC012::getDOM().document.ahk.input(18)   	;	e	e
SC013::getDOM().document.ahk.input(19)   	;	r	r
SC014::getDOM().document.ahk.input(20)   	;	t	t
SC015::getDOM().document.ahk.input(21)   	;	y	z
SC016::getDOM().document.ahk.input(22)   	;	u	u
SC017::getDOM().document.ahk.input(23)   	;	i	i
SC018::getDOM().document.ahk.input(24)   	;	o	o
SC019::getDOM().document.ahk.input(25)   	;	p	p
SC01A::getDOM().document.ahk.input(26)   	;	[	è
SC01B::getDOM().document.ahk.input(27)   	;	]	¨
SC01E::getDOM().document.ahk.input(30)   	;	a	a
SC01F::getDOM().document.ahk.input(31)   	;	s	s
SC020::getDOM().document.ahk.input(32)   	;	d	d
SC021::getDOM().document.ahk.input(33)   	;	f	f
SC022::getDOM().document.ahk.input(34)   	;	g	g
SC023::getDOM().document.ahk.input(35)   	;	h	h
SC024::getDOM().document.ahk.input(36)   	;	j	j
SC025::getDOM().document.ahk.input(37)   	;	k	k
SC026::getDOM().document.ahk.input(38)   	;	l	l
SC027::getDOM().document.ahk.input(39)   	;	;	é
SC028::getDOM().document.ahk.input(40)   	;	'	à
SC02B::getDOM().document.ahk.input(43)   	;	\	$
SC056::getDOM().document.ahk.input(86)   	;	\	<
SC02C::getDOM().document.ahk.input(44)   	;	z	y
SC02D::getDOM().document.ahk.input(45)   	;	x	x
SC02E::getDOM().document.ahk.input(46)   	;	c	c
SC02F::getDOM().document.ahk.input(47)   	;	v	v
SC030::getDOM().document.ahk.input(48)   	;	b	b
SC031::getDOM().document.ahk.input(49)   	;	n	n
SC032::getDOM().document.ahk.input(50)   	;	m	m
SC033::getDOM().document.ahk.input(51)   	;	,	,
SC034::getDOM().document.ahk.input(52)   	;	.	.
SC035::getDOM().document.ahk.input(53)   	;	/	-
+SC029::getDOM().document.ahk.input(41)   	;	`	§
+SC002::getDOM().document.ahk.input(2,1)	;	1	1
+SC003::getDOM().document.ahk.input(3,1)	;	2	2
+SC004::getDOM().document.ahk.input(4,1)	;	3	3
+SC005::getDOM().document.ahk.input(5,1)	;	4	4
+SC006::getDOM().document.ahk.input(6,1)	;	5	5
+SC007::getDOM().document.ahk.input(7,1)	;	6	6
+SC008::getDOM().document.ahk.input(8,1)	;	7	7
+SC009::getDOM().document.ahk.input(9,1)	;	8	8
+SC00A::getDOM().document.ahk.input(10,1)	;	9	9
+SC00B::getDOM().document.ahk.input(11,1)	;	0	0
+SC00C::getDOM().document.ahk.input(12,1)	;	-	'
+SC00D::getDOM().document.ahk.input(13,1)	;	=	^
+SC010::getDOM().document.ahk.input(16,1)	;	q	q
+SC011::getDOM().document.ahk.input(17,1)	;	w	w
+SC012::getDOM().document.ahk.input(18,1)	;	e	e
+SC013::getDOM().document.ahk.input(19,1)	;	r	r
+SC014::getDOM().document.ahk.input(20,1)	;	t	t
+SC015::getDOM().document.ahk.input(21,1)	;	y	z
+SC016::getDOM().document.ahk.input(22,1)	;	u	u
+SC017::getDOM().document.ahk.input(23,1)	;	i	i
+SC018::getDOM().document.ahk.input(24,1)	;	o	o
+SC019::getDOM().document.ahk.input(25,1)	;	p	p
+SC01A::getDOM().document.ahk.input(26,1)	;	[	è
+SC01B::getDOM().document.ahk.input(27,1)	;	]	¨
+SC01E::getDOM().document.ahk.input(30,1)	;	a	a
+SC01F::getDOM().document.ahk.input(31,1)	;	s	s
+SC020::getDOM().document.ahk.input(32,1)	;	d	d
+SC021::getDOM().document.ahk.input(33,1)	;	f	f
+SC022::getDOM().document.ahk.input(34,1)	;	g	g
+SC023::getDOM().document.ahk.input(35,1)	;	h	h
+SC024::getDOM().document.ahk.input(36,1)	;	j	j
+SC025::getDOM().document.ahk.input(37,1)	;	k	k
+SC026::getDOM().document.ahk.input(38,1)	;	l	l
+SC027::getDOM().document.ahk.input(39,1)	;	;	é
+SC028::getDOM().document.ahk.input(40,1)	;	'	à
+SC02B::getDOM().document.ahk.input(43,1)	;	\	$
+SC056::getDOM().document.ahk.input(86,1)	;	\	<
+SC02C::getDOM().document.ahk.input(44,1)	;	z	y
+SC02D::getDOM().document.ahk.input(45,1)	;	x	x
+SC02E::getDOM().document.ahk.input(46,1)	;	c	c
+SC02F::getDOM().document.ahk.input(47,1)	;	v	v
+SC030::getDOM().document.ahk.input(48,1)	;	b	b
+SC031::getDOM().document.ahk.input(49,1)	;	n	n
+SC032::getDOM().document.ahk.input(50,1)	;	m	m
+SC033::getDOM().document.ahk.input(51,1)	;	,	,
+SC034::getDOM().document.ahk.input(52,1)	;	.	.
+SC035::getDOM().document.ahk.input(53,1)	;	/	-
#If

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#SingleInstance force
;#NoTrayIcon
SendMode Input

Menu, Tray, Icon, assets/keyboard.ico, 1, 1
Menu, Tray, Tip, Emoji Keyboard
Menu, Tray, Add, &Show, Toggle
Menu, Tray, Add
Menu, Tray, Add, Emoji &Keyboard by Gilles Waeber, Credits
Menu, Tray, Add
Menu, Tray, Add, E&xit, Exit
Menu, Tray, Default, &Show
Menu, Tray, NoStandard

#Include assets\JSON_ToObj.ahk
#Include assets\Webapp.ahk
__Webapp_AppStart:
;<< Header End >>

;             not focusable
Gui __Webapp_:+E0x08000000 +AlwaysOnTop -MaximizeBox -MinimizeBox ; +E0x40000 +ToolWindow ;  -Caption
OnMessage(0x112, "WM_SYSCOMMAND")

WM_SYSCOMMAND(wParam)
{
	global vVisible
    if (wParam = 0xF060 and vVisible) ; SC_CLOSE hide instead of closing
    {
        Hide()
        return 0
    }
}

;Variable containing the current state
vVisible := false

;Get our HTML DOM object
iWebCtrl := getDOM()

;Change App name on run-time
setAppName("Emoji Keyboard")

; Our custom protocol's url event handler
app_call(args) {

	;MsgBox %args%
	param := SubStr(args, 6)
	if SubStr(args, 1, 5) = "send/"
		Send(param)
}

; function to run when page is loaded
app_page(NewURL) {
}

Gui __Webapp_:Hide

~LAlt::	; <-- OPEN with double left alt key
	global vVisible
	if (A_PriorHotkey <> "~LAlt" or A_TimeSincePriorHotkey > 400) {
		if(vVisible){
			vVisible := false
			Hide()
			KeyWait, LAlt
			Send, {LAlt}
		}
		return
	}
	KeyWait, LAlt
	Show()
Return

; Functions to be called from the html/js source
Exit() {
	ExitApp
}

clipSaved =
bClipSaved := False

Credits(){
	Run, http://www.gilleswaeber.ch
}
Reload() {
	Reload
}
Run(t) {
	Run, %t%
}
Send(t) {
	global clipSaved, bClipSaved
	if(not bClipSaved){
		clipSaved := ClipboardAll
		bClipSaved := True
	}
	Clipboard := t
	Sleep, 10
	Send, ^v
	SetTimer, RestoreClipboard, 200
}
RestoreClipboard() {
	global clipSaved, bClipSaved
	SetTimer, RestoreClipboard, Off
	Clipboard := clipSaved
	clipSaved =
	bClipSaved := False
}
Show(){
	global vVisible
	vVisible := true
	Gui __Webapp_:Show
	Sleep, 10
	Send, !{Esc}
}
Hide(){
	global vVisible
	vVisible := false
	Gui __Webapp_:Hide
}
Toggle(){
	global vVisible
	if(vVisible){
		Hide()
	}
	else{
		Show()
	}
}
Ready(){
	global j
	getDOM().document.ahk.setKeymap(j.keymap)
}

#If vVisible
; Corresponding keys                    	;	US	CH
SC001::getDOM().document.ahk.input(1)   	;	ESC	ESC
SC03B::getDOM().document.ahk.input(59)   	;	F1	F1
SC03C::getDOM().document.ahk.input(60)   	;	F2	F2
SC03D::getDOM().document.ahk.input(61)   	;	F3	F3
SC03E::getDOM().document.ahk.input(62)   	;	F4	F4
SC03F::getDOM().document.ahk.input(63)   	;	F5	F5
SC040::getDOM().document.ahk.input(64)   	;	F6	F6
SC041::getDOM().document.ahk.input(65)   	;	F7	F7
SC042::getDOM().document.ahk.input(66)   	;	F8	F8
SC043::getDOM().document.ahk.input(67)   	;	F9	F9
SC044::getDOM().document.ahk.input(68)   	;	F10	F10
SC057::getDOM().document.ahk.input(87)   	;	F11	F11
SC058::getDOM().document.ahk.input(88)   	;	F12	F12
SC029::getDOM().document.ahk.input(41)   	;	`	§
SC002::getDOM().document.ahk.input(2)    	;	1	1
SC003::getDOM().document.ahk.input(3)   	;	2	2
SC004::getDOM().document.ahk.input(4)   	;	3	3
SC005::getDOM().document.ahk.input(5)   	;	4	4
SC006::getDOM().document.ahk.input(6)   	;	5	5
SC007::getDOM().document.ahk.input(7)   	;	6	6
SC008::getDOM().document.ahk.input(8)   	;	7	7
SC009::getDOM().document.ahk.input(9)   	;	8	8
SC00A::getDOM().document.ahk.input(10)   	;	9	9
SC00B::getDOM().document.ahk.input(11)   	;	0	0
SC00C::getDOM().document.ahk.input(12)   	;	-	'
SC00D::getDOM().document.ahk.input(13)   	;	=	^
SC010::getDOM().document.ahk.input(16)   	;	q	q
SC011::getDOM().document.ahk.input(17)   	;	w	w
SC012::getDOM().document.ahk.input(18)   	;	e	e
SC013::getDOM().document.ahk.input(19)   	;	r	r
SC014::getDOM().document.ahk.input(20)   	;	t	t
SC015::getDOM().document.ahk.input(21)   	;	y	z
SC016::getDOM().document.ahk.input(22)   	;	u	u
SC017::getDOM().document.ahk.input(23)   	;	i	i
SC018::getDOM().document.ahk.input(24)   	;	o	o
SC019::getDOM().document.ahk.input(25)   	;	p	p
SC01A::getDOM().document.ahk.input(26)   	;	[	è
SC01B::getDOM().document.ahk.input(27)   	;	]	¨
SC01E::getDOM().document.ahk.input(30)   	;	a	a
SC01F::getDOM().document.ahk.input(31)   	;	s	s
SC020::getDOM().document.ahk.input(32)   	;	d	d
SC021::getDOM().document.ahk.input(33)   	;	f	f
SC022::getDOM().document.ahk.input(34)   	;	g	g
SC023::getDOM().document.ahk.input(35)   	;	h	h
SC024::getDOM().document.ahk.input(36)   	;	j	j
SC025::getDOM().document.ahk.input(37)   	;	k	k
SC026::getDOM().document.ahk.input(38)   	;	l	l
SC027::getDOM().document.ahk.input(39)   	;	;	é
SC028::getDOM().document.ahk.input(40)   	;	'	à
SC02B::getDOM().document.ahk.input(43)   	;	\	$
SC056::getDOM().document.ahk.input(86)   	;	\	<
SC02C::getDOM().document.ahk.input(44)   	;	z	y
SC02D::getDOM().document.ahk.input(45)   	;	x	x
SC02E::getDOM().document.ahk.input(46)   	;	c	c
SC02F::getDOM().document.ahk.input(47)   	;	v	v
SC030::getDOM().document.ahk.input(48)   	;	b	b
SC031::getDOM().document.ahk.input(49)   	;	n	n
SC032::getDOM().document.ahk.input(50)   	;	m	m
SC033::getDOM().document.ahk.input(51)   	;	,	,
SC034::getDOM().document.ahk.input(52)   	;	.	.
SC035::getDOM().document.ahk.input(53)   	;	/	-
+SC029::getDOM().document.ahk.input(41)   	;	`	§
+SC002::getDOM().document.ahk.input(2,1)	;	1	1
+SC003::getDOM().document.ahk.input(3,1)	;	2	2
+SC004::getDOM().document.ahk.input(4,1)	;	3	3
+SC005::getDOM().document.ahk.input(5,1)	;	4	4
+SC006::getDOM().document.ahk.input(6,1)	;	5	5
+SC007::getDOM().document.ahk.input(7,1)	;	6	6
+SC008::getDOM().document.ahk.input(8,1)	;	7	7
+SC009::getDOM().document.ahk.input(9,1)	;	8	8
+SC00A::getDOM().document.ahk.input(10,1)	;	9	9
+SC00B::getDOM().document.ahk.input(11,1)	;	0	0
+SC00C::getDOM().document.ahk.input(12,1)	;	-	'
+SC00D::getDOM().document.ahk.input(13,1)	;	=	^
+SC010::getDOM().document.ahk.input(16,1)	;	q	q
+SC011::getDOM().document.ahk.input(17,1)	;	w	w
+SC012::getDOM().document.ahk.input(18,1)	;	e	e
+SC013::getDOM().document.ahk.input(19,1)	;	r	r
+SC014::getDOM().document.ahk.input(20,1)	;	t	t
+SC015::getDOM().document.ahk.input(21,1)	;	y	z
+SC016::getDOM().document.ahk.input(22,1)	;	u	u
+SC017::getDOM().document.ahk.input(23,1)	;	i	i
+SC018::getDOM().document.ahk.input(24,1)	;	o	o
+SC019::getDOM().document.ahk.input(25,1)	;	p	p
+SC01A::getDOM().document.ahk.input(26,1)	;	[	è
+SC01B::getDOM().document.ahk.input(27,1)	;	]	¨
+SC01E::getDOM().document.ahk.input(30,1)	;	a	a
+SC01F::getDOM().document.ahk.input(31,1)	;	s	s
+SC020::getDOM().document.ahk.input(32,1)	;	d	d
+SC021::getDOM().document.ahk.input(33,1)	;	f	f
+SC022::getDOM().document.ahk.input(34,1)	;	g	g
+SC023::getDOM().document.ahk.input(35,1)	;	h	h
+SC024::getDOM().document.ahk.input(36,1)	;	j	j
+SC025::getDOM().document.ahk.input(37,1)	;	k	k
+SC026::getDOM().document.ahk.input(38,1)	;	l	l
+SC027::getDOM().document.ahk.input(39,1)	;	;	é
+SC028::getDOM().document.ahk.input(40,1)	;	'	à
+SC02B::getDOM().document.ahk.input(43,1)	;	\	$
+SC056::getDOM().document.ahk.input(86,1)	;	\	<
+SC02C::getDOM().document.ahk.input(44,1)	;	z	y
+SC02D::getDOM().document.ahk.input(45,1)	;	x	x
+SC02E::getDOM().document.ahk.input(46,1)	;	c	c
+SC02F::getDOM().document.ahk.input(47,1)	;	v	v
+SC030::getDOM().document.ahk.input(48,1)	;	b	b
+SC031::getDOM().document.ahk.input(49,1)	;	n	n
+SC032::getDOM().document.ahk.input(50,1)	;	m	m
+SC033::getDOM().document.ahk.input(51,1)	;	,	,
+SC034::getDOM().document.ahk.input(52,1)	;	.	.
+SC035::getDOM().document.ahk.input(53,1)	;	/	-
#If


Update bindings

Update bindings

#InstallKeybdHook
#UseHook

is_terminal()
{
  ifWinActive,ahk_exe WindowsTerminal.exe
    return 1
  return 0
}

is_vscode()
{
  ifWinActive,ahk_exe Code.exe
    return 0
  return 1
}

SetKeyDelay 0

; Mac-style commands (Win + {key})

; cursor
^a::
  if is_terminal()
    send %A_ThisHotKey%
  else
    send {HOME}
  return

<#a::
  send ^a
  return

^b::
  if is_terminal()
    send %A_ThisHotKey%
  else
    send {Left}
  return

<#b::
  if is_vscode()
    send %A_ThisHotKey%
  else
    send ^b
  return

<#c::
  send ^c
  return

<#d::
  send ^d
  return

; cursor
^d::
  if is_terminal()
    send %A_ThisHotKey%
  else
    send {DEL}
  return

; cursor
^e::
  if is_terminal()
    send %A_ThisHotKey%
  else
    send {END}
  return

; cursor
^f::
  if is_terminal()
    send %A_ThisHotKey%
  else
    send {Right}
  return

^+f::
  if is_terminal()
    send %A_ThisHotKey%
  else
    send ^f
  return

; win+d -> win+m
<#m::
  send #d
  return

<#f::
  send ^f
  return

<#j::
  if is_vscode()
    send %A_ThisHotKey%
  else
    send ^j
  return

<#n::
  if is_vscode()
    send %A_ThisHotKey%
  else
    send ^n
  return

<^n::
  ; vim: c-{p,n}
  if is_terminal()
    send ^n
  else
    send #n
  return

^p::
  ; vim: c-{p,n}
  if is_terminal()
    send %A_ThisHotKey%
  else
    send {Up}
  return

<#r::
  send ^r
  return

<^r::
  ; vim: redo
  if is_terminal()
    ; FIXME (himkt): %A_ThisHotKey%
    send ^r
  else
    send #r
  return

<#s::
  send ^s
  return

<#t::
  send ^t
  return

<#v::
  send ^+v
  return

<^+v::
  send #v
  return

<#w::
  send ^w
  return

<#x::
  send ^x
  return

<^x::
  if is_terminal()
    ; FIXME (himkt): %A_ThisHotKey%
    send ^x
  else
    send #x
  return

<#+z::
  send ^Z
  return

<#z::
  send ^z
  return

<#/::
  send ^/
  return

<#Space::
  send ^{Space}
  return

<#Left::
  send ^{Left}
  return

<#+Left::
  send ^+{Left}
  return

<^Left::
  send #{Left}
  return

<#Right::
  send ^{Right}
  return

<#+Right::
  send ^+{Right}
  return

<^Right::
  send #{Right}
  return

<#Up::
  send ^{Up}
  return

<^Up::
  send #{Up}
  return

<#Down::
  send ^{Down}
  return

<^Down::
  send #{Down}
  return

<#Backspace::
  send ^{BS}
  return

<#Enter::
  send ^{Enter}
  return

#InstallKeybdHook
#UseHook

is_not_terminal()
{
  ifWinActive,ahk_exe WindowsTerminal.exe
    return 1
  return 0
}

is_vscode()
{
  ifWinActive,ahk_exe Code.exe
    return 0
  return 1
}

SetKeyDelay 0

; Cursor

^a::
  if is_not_terminal()
    send %A_ThisHotKey%
  else
    send {HOME}
  return

^d::
  if is_not_terminal()
    send %A_ThisHotKey%
  else
    send {DEL}
  return

^e::
  if is_not_terminal()
    send %A_ThisHotKey%
  else
    send {END}
  return

^p::
  if is_not_terminal()
    send %A_ThisHotKey%
  else
    send {Up}
  return

^n::
  if is_not_terminal()
    send %A_ThisHotKey%
  else
    send {Down}
  return

^f::
  if is_not_terminal()
    send %A_ThisHotKey%
  else
    send {Right}
  return

^+f::
  if is_not_terminal()
    send %A_ThisHotKey%
  else
    send ^f
  return

^b::
  if is_not_terminal()
    send %A_ThisHotKey%
  else
    send {Left}
  return

; Mac-style commands (Win + {key})

<#a::
  send ^a
  return

<#b::
  if is_vscode()
    send %A_ThisHotKey%
  else
    send ^b
  return

<#c::
  send ^c
  return

<#d::
  send ^d
  return

; win+d -> win+m
<#m::
  send #d
  return

<#f::
  send ^f
  return

<#j::
  if is_vscode()
    send %A_ThisHotKey%
  else
    send ^j
  return

<#n::
  if is_vscode()
    send %A_ThisHotKey%
  else
    send ^n
  return

<^n::
  send #n
  return

<#r::
  send ^r
  return

<^r::
  send #r
  return

<#s::
  send ^s
  return

<#t::
  send ^t
  return

<#v::
  send ^+v
  return

<^+v::
  send #v
  return

<#w::
  send ^w
  return

<#x::
  send ^x
  return

<^x::
  send #x
  return

<#+z::
  send ^Z
  return

<#z::
  send ^z
  return

<#/::
  send ^/
  return

<#Space::
  send ^{Space}
  return

<#Left::
  send ^{Left}
  return

<#+Left::
  send ^+{Left}
  return

<^Left::
  send #{Left}
  return

<#Right::
  send ^{Right}
  return

<#+Right::
  send ^+{Right}
  return

<^Right::
  send #{Right}
  return

<#Up::
  send ^{Up}
  return

<^Up::
  send #{Up}
  return

<#Down::
  send ^{Down}
  return

<^Down::
  send #{Down}
  return

<#Backspace::
  send ^{BS}
  return

<#Enter::
  send ^{Enter}
  return