Auto select normal mode in vc_keymap

Auto select normal mode in vc_keymap

VimConfig:
    vim.SetPlugin("VimConfig", "Array", "0.1", "VimDesktop的配置界面")
    vim.SetAction("<vc_plugin>", "打开VimDesktop配置界面")
    vim.SetAction("<vc_keymap>", "打开VimDesktop配置界面")
return

/*
<vc_config>:
    menu, vimconfig_menu, add
    menu, vimconfig_menu, deleteall
    menu, vimconfig_menu, add, &Exit, <vc_keymap>
    GUI, vimconfig:Destroy
    GUI, vimconfig:Default
    GUI, vimconfig:Menu, vimconfig_menu
    GUI, vimconfig:Add, StatusBar
    GUI, vimconfig:Show, w700 h500
return

<vc_keymap2>:
{
    GUI, vimconfig_keymap:Destroy
    GUI, vimconfig_keymap:Default
    GUI, vimconfig_keymap:Font, s10, Microsoft YaHei
    GUI, vimconfig_keymap:Add, Text, x10 y13, 热键(&K)
    GUI, vimconfig_keymap:Add, Edit, x70 y10 w240 r1
    GUI, vimconfig_keymap:Add, Button, x320 y8 w30 h30, &?
    GUI, vimconfig_keymap:Add, Text, x10 y48, 动作(&L)
    GUI, vimconfig_keymap:Add, Edit, x70 y45 w240 r1
    GUI, vimconfig_keymap:Add, Button, x320 y43 w30 h30 g<vc_plugin>, &!
    ;GUI, vimconfig_keymap:Add, Button, x575 y350 w60 h65, 保存(&S)
    GUI, vimconfig_keymap:show
    return
}
*/

<vc_plugin>:
{
    plist := ""
    GUI, vimconfig_plugin:Destroy
    GUI, vimconfig_plugin:Default
    GUI, vimconfig_plugin:Font, s10, Microsoft YaHei
    GUI, vimconfig_plugin:Add, ListView, x10 y10 w150 h400 grid altsubmit gvimconfig_LoadActions, 插件
    for plugin, obj in vim.pluginlist
        LV_Add("", plugin)
    GUI, vimconfig_plugin:Add, ListView, x170 y10 w500 h400 grid altsubmit, 序号|动作|描述
    LV_ModifyCol(1, "center")
    LV_ModifyCol(2, "left 200")
    LV_ModifyCol(3, "left 400")
    GUI, vimconfig_plugin:Show
    return
}

vimconfig_LoadActions:
{
    If A_GuiEvent = Normal
    {
        GUI, vimconfig_plugin:ListView, sysListview321
        LV_GetText(plugin, A_EventInfo)
        GUI, vimconfig_plugin:Default
        GUI, vimconfig_plugin:ListView, sysListview322
        idx := 1
        LV_Delete()
        for action, type in vim.ActionFromPlugin
        {
            If type = %plugin%
            {
                Desc := vim.GetAction(action)
                LV_Add("", idx, action, Desc.Comment)
                idx++
            }
        }
    }
    return
}

<vc_keymap>:
{
    menu, vimconfig_keymap_menu, add
    ;menu, vimconfig_keymap_menu, deleteall
    menu, vimconfig_keymap_menu, add, &Exit, vimconfig_keymap_exit

    GUI, vimconfig_keymap:Destroy
    GUI, vimconfig_keymap:Default
    GUI, vimconfig_keymap:Font, s10, Microsoft YaHei

    GUI, vimconfig_keymap:Add, GroupBox, x10 y10 w200 h270, 窗口(&Q)
    GUI, vimconfig_keymap:Add, ListBox, x20 y36 w180 R12 center gvimconfig_keymap_loadmodelist

    GUI, vimconfig_keymap:Add, GroupBox, x10 y290  w200 h140, 模式(&M)
    GUI, vimconfig_keymap:Add, ListBox, x20 y316  w180 R5 center gvimconfig_keymap_loadhotkey

    GUI, vimconfig_keymap:Add, GroupBox, x225 y10 w420 h420, 热键定义(&V)
    GUI, vimconfig_keymap:Add, Listview, x235 y36 w630 h380 grid, 热键|动作|描述
/*
    GUI, vimconfig_keymap:Add, Text, x235 y309, 过滤(&F)
    GUI, vimconfig_keymap:Add, Edit, x290 y307 w160 r1

    GUI, vimconfig_keymap:Add, Button, x465 y305 w80, 添加(&A)
    GUI, vimconfig_keymap:Add, Button, x555 y305 w80, 删除(&D)

    GUI, vimconfig_keymap:Add, Text, x235 y353, 热键(&K)
    GUI, vimconfig_keymap:Add, Edit, x290 y350 w240 r1
    GUI, vimconfig_keymap:Add, Text, x235 y390, 动作(&L)
    GUI, vimconfig_keymap:Add, Edit, x290 y387 w240 r1

    GUI, vimconfig_keymap:Add, Button, x535 y350 w30 h30 ;gvimconfig_keymap_exit, &?
    GUI, vimconfig_keymap:Add, Button, x535 y385 w30 h30 g<vc_plugin>, &>
    GUI, vimconfig_keymap:Add, Button, x575 y350 w60 h65 ;, 保存(&S)

    GUI, vimconfig_keymap:Add, Statusbar
    GUI, vimconfig_keymap:Menu, vimconfig_keymap_menu
*/

    LV_ModifyCol(1, "left 100")
    LV_ModifyCol(2, "left 250")
    LV_ModifyCol(3, "left 250")

    vimconfig_keymap_loadwinlist()
    vimconfig_keymap_loadhotkey(vimconfig_keymap_loadmodelist(thiswin))

    GUI, vimconfig_keymap:show
    return
}

vimconfig_keymap_exit:
{
    GUI, vimconfig_keymap:Destroy
    return
}

vimconfig_keymap_loadwinlist()
{
    global vim
    list := "|全局"
    GUI, vimconfig_keymap:Default
    for win, obj in vim.winlist {
        if vim.ExcludeWinList[win]{
            continue
        }
        list .= "|" win
    }
    GuiControl, , ListBox1, %list%
}
vimconfig_keymap_loadmodelist:
    vimconfig_keymap_loadmodelist()
    GUI, vimconfig_keymap:Default
    LV_delete()
    GuiControl, Choose, ListBox2, |normal
return

vimconfig_keymap_loadmodelist(win="")
{
    global vim
    GUI, vimconfig_keymap:Default
    If not strlen(win)
        ControlGet, win, Choice, , ListBox1
    If win = 全局
        winObj := vim.GetWin()
    Else
        winObj := vim.GetWin(win)
    for mode, obj in winobj.modeList
        mlist .= "|" mode
    GuiControl, , ListBox2, %mlist%
    return win
}

vimconfig_keymap_loadhotkey:
    GUI, vimconfig_keymap:Default
    ControlGet, win, Choice, , ListBox1
    win := RegExMatch(win, "^全局$") ? "" : win
    ControlGet, mode, Choice, , ListBox2
    vimconfig_keymap_loadhotkey(win, mode)
return

vimconfig_keymap_loadhotkey(win, mode="")
{
    global vim
    If strlen(mode)
    {
        winObj  := vim.GetWin(win)
        modeobj := winObj.modeList[mode]
    }
    Else
        modeobj := vim.GetMode(win)
    GUI, vimconfig_keymap:Default
    LV_delete()
    for key, i in modeobj.keymapList
        LV_Add("", Key, i, vim.GetAction(i).comment)
}

VimConfig:
    vim.SetPlugin("VimConfig", "Array", "0.1", "VimDesktop的配置界面")
    vim.SetAction("<vc_plugin>", "打开VimDesktop配置界面")
    vim.SetAction("<vc_keymap>", "打开VimDesktop配置界面")
return

/*
<vc_config>:
    menu, vimconfig_menu, add
    menu, vimconfig_menu, deleteall
    menu, vimconfig_menu, add, &Exit, <vc_keymap>
    GUI, vimconfig:Destroy
    GUI, vimconfig:Default
    GUI, vimconfig:Menu, vimconfig_menu
    GUI, vimconfig:Add, StatusBar
    GUI, vimconfig:Show, w700 h500
return

<vc_keymap2>:
{
    GUI, vimconfig_keymap:Destroy
    GUI, vimconfig_keymap:Default
    GUI, vimconfig_keymap:Font, s10, Microsoft YaHei
    GUI, vimconfig_keymap:Add, Text, x10 y13, 热键(&K)
    GUI, vimconfig_keymap:Add, Edit, x70 y10 w240 r1
    GUI, vimconfig_keymap:Add, Button, x320 y8 w30 h30, &?
    GUI, vimconfig_keymap:Add, Text, x10 y48, 动作(&L)
    GUI, vimconfig_keymap:Add, Edit, x70 y45 w240 r1
    GUI, vimconfig_keymap:Add, Button, x320 y43 w30 h30 g<vc_plugin>, &!
    ;GUI, vimconfig_keymap:Add, Button, x575 y350 w60 h65, 保存(&S)
    GUI, vimconfig_keymap:show
    return
}
*/

<vc_plugin>:
{
    plist := ""
    GUI, vimconfig_plugin:Destroy
    GUI, vimconfig_plugin:Default
    GUI, vimconfig_plugin:Font, s10, Microsoft YaHei
    GUI, vimconfig_plugin:Add, ListView, x10 y10 w150 h400 grid altsubmit gvimconfig_LoadActions, 插件
    for plugin, obj in vim.pluginlist
        LV_Add("", plugin)
    GUI, vimconfig_plugin:Add, ListView, x170 y10 w500 h400 grid altsubmit, 序号|动作|描述
    LV_ModifyCol(1, "center")
    LV_ModifyCol(2, "left 200")
    LV_ModifyCol(3, "left 400")
    GUI, vimconfig_plugin:Show
    return
}

vimconfig_LoadActions:
{
    If A_GuiEvent = Normal
    {
        GUI, vimconfig_plugin:ListView, sysListview321
        LV_GetText(plugin, A_EventInfo)
        GUI, vimconfig_plugin:Default
        GUI, vimconfig_plugin:ListView, sysListview322
        idx := 1
        LV_Delete()
        for action, type in vim.ActionFromPlugin
        {
            If type = %plugin%
            {
                Desc := vim.GetAction(action)
                LV_Add("", idx, action, Desc.Comment)
                idx++
            }
        }
    }
    return
}

<vc_keymap>:
{
    menu, vimconfig_keymap_menu, add
    ;menu, vimconfig_keymap_menu, deleteall
    menu, vimconfig_keymap_menu, add, &Exit, vimconfig_keymap_exit

    GUI, vimconfig_keymap:Destroy
    GUI, vimconfig_keymap:Default
    GUI, vimconfig_keymap:Font, s10, Microsoft YaHei

    GUI, vimconfig_keymap:Add, GroupBox, x10 y10 w200 h270, 窗口(&Q)
    GUI, vimconfig_keymap:Add, ListBox, x20 y36 w180 R12 center gvimconfig_keymap_loadmodelist

    GUI, vimconfig_keymap:Add, GroupBox, x10 y290  w200 h140, 模式(&M)
    GUI, vimconfig_keymap:Add, ListBox, x20 y316  w180 R5 center gvimconfig_keymap_loadhotkey

    GUI, vimconfig_keymap:Add, GroupBox, x225 y10 w420 h420, 热键定义(&V)
    GUI, vimconfig_keymap:Add, Listview, x235 y36 w630 h380 grid, 热键|动作|描述
/*
    GUI, vimconfig_keymap:Add, Text, x235 y309, 过滤(&F)
    GUI, vimconfig_keymap:Add, Edit, x290 y307 w160 r1

    GUI, vimconfig_keymap:Add, Button, x465 y305 w80, 添加(&A)
    GUI, vimconfig_keymap:Add, Button, x555 y305 w80, 删除(&D)

    GUI, vimconfig_keymap:Add, Text, x235 y353, 热键(&K)
    GUI, vimconfig_keymap:Add, Edit, x290 y350 w240 r1
    GUI, vimconfig_keymap:Add, Text, x235 y390, 动作(&L)
    GUI, vimconfig_keymap:Add, Edit, x290 y387 w240 r1

    GUI, vimconfig_keymap:Add, Button, x535 y350 w30 h30 ;gvimconfig_keymap_exit, &?
    GUI, vimconfig_keymap:Add, Button, x535 y385 w30 h30 g<vc_plugin>, &>
    GUI, vimconfig_keymap:Add, Button, x575 y350 w60 h65 ;, 保存(&S)

    GUI, vimconfig_keymap:Add, Statusbar
    GUI, vimconfig_keymap:Menu, vimconfig_keymap_menu
*/

    LV_ModifyCol(1, "left 100")
    LV_ModifyCol(2, "left 250")
    LV_ModifyCol(3, "left 250")

    vimconfig_keymap_loadwinlist()
    vimconfig_keymap_loadhotkey(vimconfig_keymap_loadmodelist(thiswin))

    GUI, vimconfig_keymap:show
    return
}

vimconfig_keymap_exit:
{
    GUI, vimconfig_keymap:Destroy
    return
}

vimconfig_keymap_loadwinlist()
{
    global vim
    list := "|全局"
    GUI, vimconfig_keymap:Default
    for win, obj in vim.winlist {
        if vim.ExcludeWinList[win]{
            continue
        }
        list .= "|" win
    }
    GuiControl, , ListBox1, %list%
}
vimconfig_keymap_loadmodelist:
    vimconfig_keymap_loadmodelist()
    GUI, vimconfig_keymap:Default
    LV_delete()
return

vimconfig_keymap_loadmodelist(win="")
{
    global vim
    GUI, vimconfig_keymap:Default
    If not strlen(win)
        ControlGet, win, Choice, , ListBox1
    If win = 全局
        winObj := vim.GetWin()
    Else
        winObj := vim.GetWin(win)
    for mode, obj in winobj.modeList
        mlist .= "|" mode
    GuiControl, , ListBox2, %mlist%
    return win
}

vimconfig_keymap_loadhotkey:
    GUI, vimconfig_keymap:Default
    ControlGet, win, Choice, , ListBox1
    win := RegExMatch(win, "^全局$") ? "" : win
    ControlGet, mode, Choice, , ListBox2
    vimconfig_keymap_loadhotkey(win, mode)
return

vimconfig_keymap_loadhotkey(win, mode="")
{
    global vim
    If strlen(mode)
    {
        winObj  := vim.GetWin(win)
        modeobj := winObj.modeList[mode]
    }
    Else
        modeobj := vim.GetMode(win)
    GUI, vimconfig_keymap:Default
    LV_delete()
    for key, i in modeobj.keymapList
        LV_Add("", Key, i, vim.GetAction(i).comment)
}


Code style

Code style

VimConfig:
    vim.SetPlugin("VimConfig", "Array", "0.1", "VimDesktop的配置界面")
    vim.SetAction("<vc_plugin>", "打开VimDesktop配置界面")
    vim.SetAction("<vc_keymap>", "打开VimDesktop配置界面")
return

/*
<vc_config>:
    menu, vimconfig_menu, add
    menu, vimconfig_menu, deleteall
    menu, vimconfig_menu, add, &Exit, <vc_keymap>
    GUI, vimconfig:Destroy
    GUI, vimconfig:Default
    GUI, vimconfig:Menu, vimconfig_menu
    GUI, vimconfig:Add, StatusBar
    GUI, vimconfig:Show, w700 h500
return

<vc_keymap2>:
{
    GUI, vimconfig_keymap:Destroy
    GUI, vimconfig_keymap:Default
    GUI, vimconfig_keymap:Font, s10, Microsoft YaHei
    GUI, vimconfig_keymap:Add, Text, x10 y13, 热键(&K)
    GUI, vimconfig_keymap:Add, Edit, x70 y10 w240 r1
    GUI, vimconfig_keymap:Add, Button, x320 y8 w30 h30, &?
    GUI, vimconfig_keymap:Add, Text, x10 y48, 动作(&L)
    GUI, vimconfig_keymap:Add, Edit, x70 y45 w240 r1
    GUI, vimconfig_keymap:Add, Button, x320 y43 w30 h30 g<vc_plugin>, &!
    ;GUI, vimconfig_keymap:Add, Button, x575 y350 w60 h65, 保存(&S)
    GUI, vimconfig_keymap:show
    return
}
*/

<vc_plugin>:
{
    plist := ""
    GUI, vimconfig_plugin:Destroy
    GUI, vimconfig_plugin:Default
    GUI, vimconfig_plugin:Font, s10, Microsoft YaHei
    GUI, vimconfig_plugin:Add, ListView, x10 y10 w150 h400 grid altsubmit gvimconfig_LoadActions, 插件
    for plugin, obj in vim.pluginlist
        LV_Add("", plugin)
    GUI, vimconfig_plugin:Add, ListView, x170 y10 w500 h400 grid altsubmit, 序号|动作|描述
    LV_ModifyCol(1, "center")
    LV_ModifyCol(2, "left 200")
    LV_ModifyCol(3, "left 400")
    GUI, vimconfig_plugin:Show
    return
}

vimconfig_LoadActions:
{
    If A_GuiEvent = Normal
    {
        GUI, vimconfig_plugin:ListView, sysListview321
        LV_GetText(plugin, A_EventInfo)
        GUI, vimconfig_plugin:Default
        GUI, vimconfig_plugin:ListView, sysListview322
        idx := 1
        LV_Delete()
        for action, type in vim.ActionFromPlugin
        {
            If type = %plugin%
            {
                Desc := vim.GetAction(action)
                LV_Add("", idx, action, Desc.Comment)
                idx++
            }
        }
    }
    return
}

<vc_keymap>:
{
    menu, vimconfig_keymap_menu, add
    ;menu, vimconfig_keymap_menu, deleteall
    menu, vimconfig_keymap_menu, add, &Exit, vimconfig_keymap_exit

    GUI, vimconfig_keymap:Destroy
    GUI, vimconfig_keymap:Default
    GUI, vimconfig_keymap:Font, s10, Microsoft YaHei

    GUI, vimconfig_keymap:Add, GroupBox, x10 y10 w200 h270, 窗口(&Q)
    GUI, vimconfig_keymap:Add, ListBox, x20 y36 w180 R12 center gvimconfig_keymap_loadmodelist

    GUI, vimconfig_keymap:Add, GroupBox, x10 y290  w200 h140, 模式(&M)
    GUI, vimconfig_keymap:Add, ListBox, x20 y316  w180 R5 center gvimconfig_keymap_loadhotkey

    GUI, vimconfig_keymap:Add, GroupBox, x225 y10 w420 h420, 热键定义(&V)
    GUI, vimconfig_keymap:Add, Listview, x235 y36 w630 h380 grid, 热键|动作|描述
/*
    GUI, vimconfig_keymap:Add, Text, x235 y309, 过滤(&F)
    GUI, vimconfig_keymap:Add, Edit, x290 y307 w160 r1

    GUI, vimconfig_keymap:Add, Button, x465 y305 w80, 添加(&A)
    GUI, vimconfig_keymap:Add, Button, x555 y305 w80, 删除(&D)

    GUI, vimconfig_keymap:Add, Text, x235 y353, 热键(&K)
    GUI, vimconfig_keymap:Add, Edit, x290 y350 w240 r1
    GUI, vimconfig_keymap:Add, Text, x235 y390, 动作(&L)
    GUI, vimconfig_keymap:Add, Edit, x290 y387 w240 r1

    GUI, vimconfig_keymap:Add, Button, x535 y350 w30 h30 ;gvimconfig_keymap_exit, &?
    GUI, vimconfig_keymap:Add, Button, x535 y385 w30 h30 g<vc_plugin>, &>
    GUI, vimconfig_keymap:Add, Button, x575 y350 w60 h65 ;, 保存(&S)

    GUI, vimconfig_keymap:Add, Statusbar
    GUI, vimconfig_keymap:Menu, vimconfig_keymap_menu
*/

    LV_ModifyCol(1, "left 100")
    LV_ModifyCol(2, "left 250")
    LV_ModifyCol(3, "left 250")

    vimconfig_keymap_loadwinlist()
    vimconfig_keymap_loadhotkey(vimconfig_keymap_loadmodelist(thiswin))

    GUI, vimconfig_keymap:show
    return
}

vimconfig_keymap_exit:
{
    GUI, vimconfig_keymap:Destroy
    return
}

vimconfig_keymap_loadwinlist()
{
    global vim
    list := "|全局"
    GUI, vimconfig_keymap:Default
    for win, obj in vim.winlist {
        if vim.ExcludeWinList[win]{
            continue
        }
        list .= "|" win
    }
    GuiControl, , ListBox1, %list%
}
vimconfig_keymap_loadmodelist:
    vimconfig_keymap_loadmodelist()
    GUI, vimconfig_keymap:Default
    LV_delete()
    GuiControl, Choose, ListBox2, |normal
return

vimconfig_keymap_loadmodelist(win = "")
{
    global vim
    GUI, vimconfig_keymap:Default
    If not strlen(win)
        ControlGet, win, Choice, , ListBox1
    If win = 全局
        winObj := vim.GetWin()
    Else
        winObj := vim.GetWin(win)
    for mode, obj in winobj.modeList
        mlist .= "|" mode
    GuiControl, , ListBox2, %mlist%
    return win
}

vimconfig_keymap_loadhotkey:
    GUI, vimconfig_keymap:Default
    ControlGet, win, Choice, , ListBox1
    win := RegExMatch(win, "^全局$") ? "" : win
    ControlGet, mode, Choice, , ListBox2
    vimconfig_keymap_loadhotkey(win, mode)
return

vimconfig_keymap_loadhotkey(win, mode = "")
{
    global vim
    If strlen(mode)
    {
        winObj  := vim.GetWin(win)
        modeobj := winObj.modeList[mode]
    }
    Else
        modeobj := vim.GetMode(win)
    GUI, vimconfig_keymap:Default
    LV_delete()
    for key, i in modeobj.keymapList
        LV_Add("", Key, i, vim.GetAction(i).comment)
}

VimConfig:
    vim.SetPlugin("VimConfig", "Array", "0.1", "VimDesktop的配置界面")
    vim.SetAction("<vc_plugin>", "打开VimDesktop配置界面")
    vim.SetAction("<vc_keymap>", "打开VimDesktop配置界面")
return

/*
<vc_config>:
    menu, vimconfig_menu, add
    menu, vimconfig_menu, deleteall
    menu, vimconfig_menu, add, &Exit, <vc_keymap>
    GUI, vimconfig:Destroy
    GUI, vimconfig:Default
    GUI, vimconfig:Menu, vimconfig_menu
    GUI, vimconfig:Add, StatusBar
    GUI, vimconfig:Show, w700 h500
return

<vc_keymap2>:
{
    GUI, vimconfig_keymap:Destroy
    GUI, vimconfig_keymap:Default
    GUI, vimconfig_keymap:Font, s10, Microsoft YaHei
    GUI, vimconfig_keymap:Add, Text, x10 y13, 热键(&K)
    GUI, vimconfig_keymap:Add, Edit, x70 y10 w240 r1
    GUI, vimconfig_keymap:Add, Button, x320 y8 w30 h30, &?
    GUI, vimconfig_keymap:Add, Text, x10 y48, 动作(&L)
    GUI, vimconfig_keymap:Add, Edit, x70 y45 w240 r1
    GUI, vimconfig_keymap:Add, Button, x320 y43 w30 h30 g<vc_plugin>, &!
    ;GUI, vimconfig_keymap:Add, Button, x575 y350 w60 h65, 保存(&S)
    GUI, vimconfig_keymap:show
    return
}
*/

<vc_plugin>:
{
    plist := ""
    GUI, vimconfig_plugin:Destroy
    GUI, vimconfig_plugin:Default
    GUI, vimconfig_plugin:Font, s10, Microsoft YaHei
    GUI, vimconfig_plugin:Add, ListView, x10 y10 w150 h400 grid altsubmit gvimconfig_LoadActions, 插件
    for plugin, obj in vim.pluginlist
        LV_Add("", plugin)
    GUI, vimconfig_plugin:Add, ListView, x170 y10 w500 h400 grid altsubmit, 序号|动作|描述
    LV_ModifyCol(1, "center")
    LV_ModifyCol(2, "left 200")
    LV_ModifyCol(3, "left 400")
    GUI, vimconfig_plugin:Show
    return
}

vimconfig_LoadActions:
{
    If A_GuiEvent = Normal
    {
        GUI, vimconfig_plugin:ListView, sysListview321
        LV_GetText(plugin, A_EventInfo)
        GUI, vimconfig_plugin:Default
        GUI, vimconfig_plugin:ListView, sysListview322
        idx := 1
        LV_Delete()
        for action, type in vim.ActionFromPlugin
        {
            If type = %plugin%
            {
                Desc := vim.GetAction(action)
                LV_Add("", idx, action, Desc.Comment)
                idx++
            }
        }
    }
    return
}

<vc_keymap>:
{
    menu, vimconfig_keymap_menu, add
    ;menu, vimconfig_keymap_menu, deleteall
    menu, vimconfig_keymap_menu, add, &Exit, vimconfig_keymap_exit

    GUI, vimconfig_keymap:Destroy
    GUI, vimconfig_keymap:Default
    GUI, vimconfig_keymap:Font, s10, Microsoft YaHei

    GUI, vimconfig_keymap:Add, GroupBox, x10 y10 w200 h270, 窗口(&Q)
    GUI, vimconfig_keymap:Add, ListBox, x20 y36 w180 R12 center gvimconfig_keymap_loadmodelist

    GUI, vimconfig_keymap:Add, GroupBox, x10 y290  w200 h140, 模式(&M)
    GUI, vimconfig_keymap:Add, ListBox, x20 y316  w180 R5 center gvimconfig_keymap_loadhotkey

    GUI, vimconfig_keymap:Add, GroupBox, x225 y10 w420 h420, 热键定义(&V)
    GUI, vimconfig_keymap:Add, Listview, x235 y36 w630 h380 grid, 热键|动作|描述
/*
    GUI, vimconfig_keymap:Add, Text, x235 y309, 过滤(&F)
    GUI, vimconfig_keymap:Add, Edit, x290 y307 w160 r1

    GUI, vimconfig_keymap:Add, Button, x465 y305 w80, 添加(&A)
    GUI, vimconfig_keymap:Add, Button, x555 y305 w80, 删除(&D)

    GUI, vimconfig_keymap:Add, Text, x235 y353, 热键(&K)
    GUI, vimconfig_keymap:Add, Edit, x290 y350 w240 r1
    GUI, vimconfig_keymap:Add, Text, x235 y390, 动作(&L)
    GUI, vimconfig_keymap:Add, Edit, x290 y387 w240 r1

    GUI, vimconfig_keymap:Add, Button, x535 y350 w30 h30 ;gvimconfig_keymap_exit, &?
    GUI, vimconfig_keymap:Add, Button, x535 y385 w30 h30 g<vc_plugin>, &>
    GUI, vimconfig_keymap:Add, Button, x575 y350 w60 h65 ;, 保存(&S)

    GUI, vimconfig_keymap:Add, Statusbar
    GUI, vimconfig_keymap:Menu, vimconfig_keymap_menu
*/

    LV_ModifyCol(1, "left 100")
    LV_ModifyCol(2, "left 250")
    LV_ModifyCol(3, "left 250")

    vimconfig_keymap_loadwinlist()
    vimconfig_keymap_loadhotkey(vimconfig_keymap_loadmodelist(thiswin))

    GUI, vimconfig_keymap:show
    return
}

vimconfig_keymap_exit:
{
    GUI, vimconfig_keymap:Destroy
    return
}

vimconfig_keymap_loadwinlist()
{
    global vim
    list := "|全局"
    GUI, vimconfig_keymap:Default
    for win, obj in vim.winlist {
        if vim.ExcludeWinList[win]{
            continue
        }
        list .= "|" win
    }
    GuiControl, , ListBox1, %list%
}
vimconfig_keymap_loadmodelist:
    vimconfig_keymap_loadmodelist()
    GUI, vimconfig_keymap:Default
    LV_delete()
    GuiControl, Choose, ListBox2, |normal
return

vimconfig_keymap_loadmodelist(win="")
{
    global vim
    GUI, vimconfig_keymap:Default
    If not strlen(win)
        ControlGet, win, Choice, , ListBox1
    If win = 全局
        winObj := vim.GetWin()
    Else
        winObj := vim.GetWin(win)
    for mode, obj in winobj.modeList
        mlist .= "|" mode
    GuiControl, , ListBox2, %mlist%
    return win
}

vimconfig_keymap_loadhotkey:
    GUI, vimconfig_keymap:Default
    ControlGet, win, Choice, , ListBox1
    win := RegExMatch(win, "^全局$") ? "" : win
    ControlGet, mode, Choice, , ListBox2
    vimconfig_keymap_loadhotkey(win, mode)
return

vimconfig_keymap_loadhotkey(win, mode="")
{
    global vim
    If strlen(mode)
    {
        winObj  := vim.GetWin(win)
        modeobj := winObj.modeList[mode]
    }
    Else
        modeobj := vim.GetMode(win)
    GUI, vimconfig_keymap:Default
    LV_delete()
    for key, i in modeobj.keymapList
        LV_Add("", Key, i, vim.GetAction(i).comment)
}


More robust RunGame.ahk

More robust RunGame.ahk

; DEFAULT RUN SCRIPT

#Persistent
#MaxHotkeysPerInterval 200
#SingleInstance Force

debug := true

executable := "C:\WINNITRON_UserData\Playlists\official-winnitron\nidhogg\Nidhogg.exe"
forceQuitHoldTime := 3000
idleLimit := 30000
initialWait := 30000

start := SecondsToday()
WriteLog("START ---------------- " . A_Now)

; RUN THE GAME
Run, %executable%, , , process_pid
WriteLog("Launched " . executable . " with pid " . process_pid)

SetTimer, InitialWait, -%initialWait% ; negative period disables timer after first trigger
MouseMove 3000, 3000, 0

; This is the function that quits the game
KillApp()
{
	global process_pid

	WriteLog("Killing app with pid " . process_pid)
	WinKill, ahk_exe %executable%	; Tries to close using .exe
	WinKill, ahk_pid process_pid	; Tries to close using process id
	SetTitleMatchMode, 2
	WinKill, Nidhogg			; Tries to close hoping that part of the game name is in the title
	ExitApp
}

; Do this so we don't keep running through InitialWait and CloseOnIdle
Loop
{
}

InitialWait:
	WriteLog("Completed initial wait")
	SetTimer,  CloseOnIdle, % idleLimit+150
return

; This is the timer
CloseOnIdle:
	if (A_TimeIdle >= idleLimit)
	{
		WriteLog("Idle timeout!")
		KillApp()
		SetTimer,CloseOnIdle, Off
	}
	else
	{
		SetTimer,CloseOnIdle, % idleLimit-A_TimeIdle+150
	}
return

; Do this stuff when Esc is pressed
~Esc::
	WriteLog("ESC pressed")
	If escIsPressed
		return
	escIsPressed := true
	SetTimer, WaitForESCRelease, %forceQuitHoldTime%
return

; Do this stuff when Esc is UP
~Esc Up::
	SetTimer, WaitForESCRelease, Off
	escIsPressed := false
return

WaitForESCRelease:
	SetTimer, WaitForESCRelease, Off
	KillApp()
return

; DEBUGGING STUFF

; Number of seconds since midnight.
SecondsToday() {
	return A_Hour * 3600 + A_Min * 60 + A_Sec
}

WriteLog(message)
{
	global debug
	global start

	if (debug) {
		runningTimeSec := SecondsToday() - start
		debugLog := "ahk_output.txt"
		FileAppend,
		(
		%runningTimeSec%s %A_Tab% %message%

		), %debugLog%, UTF-8
	}
}

; KEYMAPS BELOW (NONE IN DEFAULT SCRIPT)

; DEFAULT RUN SCRIPT

#Persistent
#MaxHotkeysPerInterval 200

; RUN THE GAME
Run, C:\WINNITRON_UserData\Playlists\official-winnitron\nidhogg\Nidhogg.exe, , , process_pid
idleLimit:= 10000 ; three seconds
SetTimer, InitialWait, 30000
MouseMove 3000, 3000, 0

; This is the function that quits the app
KillApp()
{
	WinKill, ahk_exe C:\WINNITRON_UserData\Playlists\official-winnitron\nidhogg\Nidhogg.exe	; Tries to close using .exe
	WinKill, ahk_pid process_pid	; Tries to close using process id
	SetTitleMatchMode, 2
	WinKill, Nidhogg			; Tries to close hoping that part of the game name is in the title
	ExitApp
}

InitialWait:
	SetTimer,  CloseOnIdle, % idleLimit+150
return

; This is the timer
CloseOnIdle:
	if (A_TimeIdle>=idleLimit)
	{
		KillApp()
		SetTimer,CloseOnIdle, Off
	}
	else
	{
		SetTimer,CloseOnIdle, % idleLimit-A_TimeIdle+150
	}
return

; Do this stuff when Esc is pressed
~Esc::
	If escIsPressed
		return
	escIsPressed := true
	SetTimer, WaitForESCRelease, 3000		; 3 seconds
return

; Do this stuff when Esc is UP
~Esc Up::
	SetTimer, WaitForESCRelease, Off
	escIsPressed := false
return

WaitForESCRelease:
	SetTimer, WaitForESCRelease, Off
	KillApp()
return

; KEYMAPS BELOW (NONE IN DEFAULT SCRIPT)


update ahk

update ahk

^`::
IfWinActive, ahk_exe VirtualBox.exe
    Send !{Tab}
else
    WinActivate, ahk_exe VirtualBox.exe
return

^!c::
IfWinActive, ahk_exe chrome.exe
    Send !{Tab}
else
    WinActivate ahk_exe chrome.exe
return

^!f::
IfWinActive, ahk_exe firefox.exe
    Send !{Tab}
else
    WinActivate ahk_exe firefox.exe
return

^!u::
IfWinActive, ahk_exe Unity.exe
    Send !{Tab}
else
    WinActivate ahk_exe Unity.exe
return

^!a::
IfWinActive, ahk_exe atom.exe
    Send !{Tab}
else
    WinActivate ahk_exe atom.exe
return

^!v::
IfWinActive, ahk_exe gvim.exe
    Send !{Tab}
else
    WinActivate ahk_exe gvim.exe
return

^!s::
IfWinActive, ahk_exe WDExpress.exe
    Send !{Tab}
else
    WinActivate ahk_exe WDExpress.exe
return

^!i::
IfWinActive, ahk_exe idea.exe
    Send !{Tab}
else
    WinActivate ahk_exe idea.exe
return

^!t::
IfWinActive, ahk_exe Telegram.exe
    Send !{Tab}
else
    WinActivate ahk_exe Telegram.exe
return

^!h::
IfWinActive, ahk_exe zeal.exe
    Send !{Tab}
else
    WinActivate ahk_exe zeal.exe
return

^`::
IfWinActive, ahk_exe VirtualBox.exe
    Send !{Tab}
else
    WinActivate, ahk_exe VirtualBox.exe
return

^!c::
IfWinActive, ahk_exe chrome.exe
    Send !{Tab}
else
    WinActivate ahk_exe chrome.exe
return

^!f::
IfWinActive, ahk_exe firefox.exe
    Send !{Tab}
else
    WinActivate ahk_exe firefox.exe
return

^!u::
IfWinActive, ahk_exe Unity.exe
    Send !{Tab}
else
    WinActivate ahk_exe Unity.exe
return

^!v::
IfWinActive, ahk_exe gvim.exe
    Send !{Tab}
else
    WinActivate ahk_exe gvim.exe
return

^!s::
IfWinActive, ahk_exe WDExpress.exe
    Send !{Tab}
else
    WinActivate ahk_exe WDExpress.exe
return

^!i::
IfWinActive, ahk_exe idea.exe
    Send !{Tab}
else
    WinActivate ahk_exe idea.exe
return

^!t::
IfWinActive, ahk_exe Telegram.exe
    Send !{Tab}
else
    WinActivate ahk_exe Telegram.exe
return

^!h::
IfWinActive, ahk_exe zeal.exe
    Send !{Tab}
else
    WinActivate ahk_exe zeal.exe
return


Code style

Code style

/*
API 函数列表：
vim.mode("模式", "ahk_class")  ; 设置运行的模式
vim.map("热键", "Label标签", "ahk_class")  ;映射热键
vim.settimeout("按键超时时间", "ahk_class")  ;设置按键超时时间
vim.listkey("ahk_class")  ;显示所有映射的热键体
vim.control("on/off", "ahk_class")  ;启用/禁用映射的热键
vim.comment("标签", "描述", "是否允许多次运行（0/1)")
内置Label:
<Repeat> 重复上一次动作
*/

#UseHook On
Setkeydelay, -1
return

; 此函数可以根据自己的喜好进行修改
ShowComment(more="") {
    if not ToShowComment
        return

    WinGetClass, win, A
    w := vim.Vaild(win)
    mode := w.GetMode()
    msg := mode.KeyTemp "`n=============================`n"
    ;GUIControl, , Edit1, %msg%

    if Strlen(more)
    {
        Loop, Parse, more, `n
        {
            key := Trim(A_LoopField)
            action := mode.KeyBody[key]
            ;comment := vim.CommentList[action]
            comment := GetCommentDest(action)
            if Strlen(comment)
                msg .= key "  >>  " comment "`n"
            else
                msg .= key "  >>  " action "`n"

        }
        Tooltip % msg
        ;GUI, VIMINFO:Show
    }
    else
        Tooltip
        ;GUI, VIMINFO:Show, Hide
}

; ====================
; ====================
; 内部脚本，请匆修改！
; ====================
; ====================

; 初始化 vimcore
Init() {
    OnMessage(0x05, "GuiSize")
    GoSub, vimnew
}

vimnew:
    Global vim := new vimcore
return

; 以下为class封装，请匆修改
Class vimcore {
    __New() {
       This.vimWindows := []
       This.vimGlobal  := new This.vimClass("")
       This.TimeOutClass := ""
       This.ExcludeList := []
       ;This.ExcludeList["AutoHotkey"] := True
       This.CommentList := []
       This.CommentType := []
       This.UseHotkey   := []
    }

    Vaild(win) {
        if Strlen(win) = 0
            Return This.vimGlobal
        w := This.vimWindows[win]
        if w.winVaild
            return w
        else
            return This.vimGlobal
    }

    mode(mode, win="") {
        if Strlen(win) = 0
            w := This.vimGlobal
        else
            w := This.vimWindows[win]
        if not w.winVaild
        {
            w := new This.vimClass(win)
            This.vimWindows[win] := w
        }
        w.SetMode(mode)
        ShowComment()
    }

    sMap(key, label, win=""){
        This.UseHotkey[key] := True
        this.Map(key, label, win)
    }

    Map(key, label, win="") {
        if not RegExMatch(Key, "[^\s]")
            return
        if Strlen(win) = 0
            w := This.vimGlobal
        else
            w := This.vimWindows[win]
        if not w.winVaild
        {
            w := new This.vimClass(win)
            This.vimWindows[win] := w
        }
        mode := w.GetMode()
        mode.SetHotkey(key, label)
    }

    Comment(action, desc, complex=1) {
        This.CommentList[action] := desc
        This.CommentType[action] := complex
    }

    do() {
        WinGetClass, win, A
        w := This.Vaild(win)
        m := w.GetMode()
        if This.ExcludeList[win] And not this.UseHotkey[m.GetThisHotkey()]
        {
            Send, % m.TransSendKey(A_ThisHotkey)
            return
        }
        if w.winVaild {
            mode := w.GetMode()
            if Mode.KeyList[A_ThisHotkey]
                mode.Try()
            else
            {
                w := This.vimGlobal
                mode := w.GetMode()
                mode.Try()
            }
        }
    }

    Filter(String) {

        WinGetClass, win, A

        if This.ExcludeList[win]
            return
        w := This.Vaild(win)

        if w.winVaild {
            mode := w.GetMode()
            mode.query(string)
        }
    }

    Exclude(win) {
        This.ExcludeList[win] := True
    }

    Include(win) {
        This.ExcludeList[win] := False
    }

    ListKey(win="", mode="") {
        w := This.Vaild(win)
        if strlen(mode) {
            m := w.winmode[mode]
            For k , l in m.KeyBody
                msg .= k "  " l "`n"
            return msg
        }
        else {
            For n , m  in w.winMode
            {
                msg .= "====`n" n "`n----`n"
                mode := m
                For k , l in m.KeyBody
                    msg .= k "  " l "`n"
            }
            return msg
        }
    }

    copy(win1, win2) {

        w2 := This.vimWindows[win2]

        if w2.winVaild
            return False

        w1 := This.Vaild(win1)
        w1.winName := win2
        For n , m in w1.WinMode
        {
            mode := m
            mode.win := win2
            w1.WinMode[n] := mode
            For k , l in m.KeyList
            {
                Hotkey, IfWinActive, ahk_class %win2%
                Hotkey, %k%, <HotkeyLabel>
            }
        }
        This.vimWindows[win2] := w1
        return True
    }

    CopyMode(win, mode, to) {
        w := This.Vaild(win)
        if strlen(mode) = 0
            return

        vim.mode(to, win)
        m := w.winmode[mode]
        For k , l in m.KeyBody
            vim.map(k, l, win)
    }

    Control(switch, win="") {
        w := This.Vaild(win)
        if switch = on
        {
            For n , m  in w.winMode
            {
                mode := m
                For k , l in m.KeyList
                {
                    Hotkey, %k%, on
                }
            }
        }
        if switch = off
        {
            For n , m  in w.winMode
            {
                mode := m
                For k , l in m.KeyList
                {
                    Hotkey, %k%, off
                }
            }
        }
    }

    test() {
        msgbox vim test
    }

    SetTimeOut(tick, win="") {
        w := This.Vaild(win)
        if not w.winVaild
        {
            w := new This.vimClass(win)
            This.vimWindows[win] := w
        }
        w.TimeOut := tick
    }

    TimeOut() {
        w := This.Vaild(This.TimeOutClass)
        mode := w.GetMode()
        mode.KeyTemp := ""
        ;GoSub, % mode.TimeOutAction
        mode.ExecSub(mode.TimeOutAction)
        ;    ShowComment()
        mode.TimeOutAction := ""
    }

    Repeat() {
        WinGetClass, win, A
        w := This.vimWindows[win]
        if not w.winVaild
            w := This.vimGlobal
        if w.winVaild {
            mode := w.GetMode()
            mode.KeyCount := w.winRepeatCount
            mode.ExecSub(w.winRepeat, Ture)
        }
    }

    GetWin() {
        WinGetClass, win, A
        Return This.Vaild(win)
    }

    GetCount() {
        w := This.GetWin()
        m := w.GetMode()
        Return m.KeyCount ? m.KeyCount : 1
    }

    Class vimClass {

        __New(win) {
            This.winName := win
            This.winVaild   := 1
            This.winControl := 0
            This.winTimeOut := 0
            THis.winMaxCount := 99
            This.winKeyList := []
            This.winMode    := []
            This.winThisMode := ""
            This.winRepeat   := ""
            This.winRepeatCount := 0
        }
        ;设置窗口类下的模式
        SetMode(md) {
            m := This.winMode[md]
            if Strlen(m.Mode) = 0 {
                This.winThisMode := md
                m := new This.Mode(md, This.winName)
                This.winMode[md] := m
            }
            else
                This.winThisMode := md
            return m
        }
        ;获取窗口类下的模式

        GetMode() {
            m := This.winMode[This.winThisMode]
            return m
        }

        Class Mode {
            __New(mode, win) {
                This.Mode := mode
                This.win  := win ;可变
                if Strlen(win)
                    This.CheckMode := win "_CheckMode"
                else
                    This.CheckMode := "CheckMode"
                This.KeyTemp   := ""
                This.KeyString := ""
                This.KeyCount := 0
                This.TimeOut := 0
                This.TimeOutTick   := 0
                This.TimeOutAction := ""
                This.KeyBody := []
                This.KeyList := []
                This.KeyMap  := []
            }

            test() {
                msgbox % This.Mode
            }

            Try(){
                checkMode := This.CheckMode
                settimer, <TimeOutLabel>, off
                Key := This.GetThisHotkey()
                if ( Not This.KeyList[A_ThisHotkey] ) or ( IsFunc(CheckMode) AND (%CheckMode%()) ) {
                    Send, % This.TransSendKey(A_ThisHotkey)
                    ShowComment()
                    return
                }
                _SaveKeyTemp := This.KeyTemp
                This.KeyTemp .= Key
                P := 1
                more := ""
                moreCount := 0
                Loop {
                    P := RegExMatch(This.KeyString, "i)\t" This.ToMatch(This.keyTemp) "[^\t]*", m, P)
                    if P {
                        ;msgbox % This.KeyString "`np=" p "`nm=" m
                        more .= m "`n"
                        P += Strlen(m)
                        moreCount++
                    }
                    else
                        Break
                }
                more := RTrim(more, "`n")
                if moreCount = 0
                {
                    This.KeyTemp := ""

                    action := This.KeyBody[_SaveKeyTemp]
                    if Strlen(action) {
                        This.ExecSub(Action)
                    }
                    else {
                        action := This.KeyBody[Key]
                        if Strlen(action) {
                            if InvalidMode
                                ShowComment()
                            else
                                This.ExecSub(Action)
                        }
                        else {
                            if RegExMatch(This.KeyString, "i)\t" This.ToMatch(key) "[^\t]*")
                            {
                                if InvalidMode
                                    ShowComment()
                                else
                                    This.Try()
                            }
                            else
                            {
                                Send, % This.TransSendKey(A_ThisHotkey)
                                ShowComment()
                            }
                            return
                        }
                    }
                }
                else if moreCount = 1
                {
                    Action := This.KeyBody[This.KeyTemp]
                    if Strlen(Action) {
                        This.ExecSub(Action)
                        This.KeyTemp := ""
                    }
                    else
                        ShowComment(more)
                }
                else
                {
                    TimeOut := 0 - GetTimeOutClass(This.win)
                    if Timeout And This.KeyBody[This.KeyTemp]{
                        This.TimeOutAction := This.KeyBody[This.KeyTemp]
                        This.TimeOutTick   := A_TickCount
                        SetTimeOutClass(This.win)
                        Settimer, <TimeOutLabel>, %TimeOut%
                    }
                    ErrorLevel := True
                    ShowComment(more)
                    return more
                }
            }

            ExecSub(action) {
                w := vim.vaild(This.win)
                if RegExMatch(Action, "(?<=^<)\d(?=>$)", cnt) {
                        This.KeyCount := This.KeyCount * 10 + cnt
                        MaxCount := w.winMaxCount
                        if This.KeyCount > MaxCount
                            This.KeyCount := MaxCount
                        Tooltip % This.KeyCount
                        return false
                }
                else {
                    ShowComment()
                    if This.KeyCount And GetCommentType(Action)
                        cnt := This.KeyCount
                    else
                        cnt := 1
                    ;cnt := This.KeyCount ? This.KeyCount : 1
                    if RegExMatch(action, "^<.*>$") {
                        if IsLabel(action) {
                            Loop, %cnt%
                                GoSub % Action
                        }
                        else {
                            Msgbox %Action%不存在，请检查脚本
                            Return
                        }
                    }
                    if RegExMatch(action, "^\(.*\)$") {
                        file := SubStr(action, 2, Strlen(action)-2)
                        Run, %File%, , UseErrorLevel, ExecID
                        if ErrorLevel
                        {
                            msgbox 运行%file%失败
                            return
                        }
                        else
                        {
                            WinWait, AHK_PID %ExecID%, , 1
                            WinActivate, AHK_PID %ExecID%
                        }
                    }
                    if RegExMatch(Action, "^\{.*\}$") {
                        Text := Substr(Action, 2, Strlen(Action)-2)
                        Loop, %cnt%
                            Send, %Text%
                    }

                    This.KeyCount := 0
                    if rpt
                        return
                    if not RegExMatch(action, "i)^<repeat>$") {
                        w.winRepeatCount := cnt
                        w.winRepeat := Action
                    }
                }
                EmptyMem()
            }

            SetHotkey(key, label) {
                ;msgbox % This.win
                if Strlen(This.win) > 0 {
                    class := This.win
                    Hotkey, IfWinActive, ahk_class %class%
                }
                else
                    Hotkey, IfWinActive

                mKey := ""
                Loop, Parse, Key
                {
                    if Asc(A_LoopField) >= 65 And Asc(A_LoopField) <= 90
                        mKey .= "<shift>" . Chr(Asc(A_LoopField)+32)
                    else
                        mKey .= A_LoopField
                }
                Hotkey_OK := True
                ;Idx := This.KeyList[0] ? This.KeyList[0] : 1
                cnt := 1
                _SaveList := []
                for, i, k in This.ResolveHotkey(mKey)
                {
                    Hotkey, %k%, <HotkeyLabel>, On, UseErrorLevel
                    if ErrorLevel
                    {
                        Msgbox 映射错误
                        Hotkey_OK := False
                        Break
                    }
                    ;if Not This.KeyList[k] {
                    ;    This.KeyList[idx] := k
                    ;    idx++
                    ;}
                    _SaveList[cnt] := k
                    cnt++
                    This.KeyList[k] := This.KeyList[k] ? This.KeyList[k] + 1 : 1
                }
                ;This.KeyList[0] := idx
                if Not Hotkey_OK {
                    For i , k IN _SaveList
                    {
                        This.KeyList[k] := This.KeyList[k] - 1
                        if This.KeyList[k] = 0 {
                            Hotkey, %k%, off
                        }
                    }
                }
                else {
                    This.KeyBody[mkey] := label
                    if not RegExMatch(This.KeyString, "\t" This.ToMatch(mKey) "[^\t]*")
                        This.KeyString .= A_Tab mKey A_Tab
                }
            }

            ResolveHotkey(KeyList)
            {
                Keys := []
                NewKeyList := []
                n := 1
                Loop
                {
                    Pos := RegExMatch(KeyList, "<[^<>]*>", A_Index)
                    if Pos
                    {
                        LoopKey := SubStr(KeyList, 1, Pos-1)
                        Loop, Parse, LoopKey
                        {
                            if Asc(A_LoopField) >= 65 And Asc(A_LoopField) <= 90
                            {
                                Keys[n] := "shift"
                                n++
                                Keys[n] := Chr(Asc(A_LoopField)+32)
                            }
                            else
                                Keys[n] := A_LoopField
                            n++
                        }
                        KeyList := SubStr(KeyList, Pos, Strlen(KeyList))
                        Pos := RegExMatch(KeyList, ">")
                        Keys[n] := SubStr(KeyList, 2, Pos-2)
                        KeyList := SubStr(KeyList, Pos+1, Strlen(KeyList))
                        n++
                    }
                    else
                    {
                        Loop, Parse, KeyList
                        {
                            if Asc(A_LoopField) >= 65 And Asc(A_LoopField) <= 90
                            {
                                Keys[n] := "shift"
                                n++
                                Keys[n] := Chr(Asc(A_LoopField)+32)
                            }
                            else
                                Keys[n] := A_LoopField
                            n++
                        }
                        Break
                    }
                }
                n := 1
                For, i, key in Keys
                {
                    if RegExMatch(key, "i)(l|r)?(ctrl|shift|win|alt)")
                    {
                        List .= Key " & "
                        Continue
                    }
                    else
                    {
                        List .= Key
                        NewKeyList[n] := List
                        List :=
                    }
                    n++
                }
                Return NewKeyList
            }

            GetThisHotkey(G_ThisHotkey="")
            {
                if Strlen(G_ThisHotkey) = 0
                    G_ThisHotkey := A_ThisHotkey
                GetKeyState, Var, CapsLock, T
                if Var = D
                {
                    if RegExMatch(ThisHotkey, "i)^(l|r)?shift\s&\s[a-z]$")
                        ThisHotkey := Substr(ThisHotkey, 0)
                    else if RegExMatch(G_ThisHotkey, "^[a-z]$")
                        ThisHotkey := "shift & " . G_ThisHotkey
                    else
                        ThisHotkey := A_ThisHotkey
                }
                else
                    ThisHotkey := G_ThisHotkey
                Loop
                {
                    if RegExMatch(ThisHotkey, "(?<!<)(((l|r)?(ctrl|control|alt|win|shift))|(f\d\d?)|esc|escape|space|tab|enter|bs|del|ins|home|end|pgup|pgdn|up|down|left|right|((?<=&\s)[<>]$))(?!>)", m) {
                        ThisHotkey := RegExReplace(ThisHotkey, This.ToMatch(m), "<" m ">")
                    }
                    else
                    {
                        ThisHotkey := RegExReplace(ThisHotkey, "\s&\s")
                        Break
                    }
                }
                ;msgbox % Thishotkey
                Return ThisHotKey
            }

            ; TransSendKey(hotkey) {{{2
            ; 在SendKey时，将hotkey转换为Send能支持的格式
            TransSendKey(hotkey)
            {
                Loop
                {
                    if RegExMatch(Hotkey, "i)^(f\d\d?)|esc|escpa|space|tab|enter|bs|del|ins|home|end|pgup|pgdn|up|down|left|right|!|#|\+|\^|\{|\}$")
                    {
                        Hotkey := "{" . Hotkey . "}"
                        Break
                    }
                    if StrLen(hotkey) > 1 AND Not RegExMatch(Hotkey, "^\+.$")
                    {
                        Hotkey := "{" . hotkey . "}"
                        if RegExMatch(hotkey, "i)(shift|lshift|rshift)(\s\&\s)?.+$")
                            Hotkey := "+" . RegExReplace(hotkey, "i)(shift|lshift|rshift)(\s\&\s)?")
                        if RegExMatch(hotkey, "i)(ctrl|lctrl|rctrl|control|lcontrol|rcontrol)(\s\&\s)?.+$")
                            Hotkey := "^" . RegExReplace(hotkey, "i)(ctrl|lctrl|rctrl|control|lcontrol|rcontrol)(\s\&\s)?")
                        if RegExMatch(hotkey, "i)(lwin|rwin)(\s\&\s)?.+$")
                            Hotkey := "#" . RegExReplace(hotkey, "i)(lwin|rwin)(\s\&\s)?")
                        if RegExMatch(hotkey, "i)(alt|lalt|ralt)(\s\&\s)?.+$")
                            Hotkey := "!" . RegExReplace(hotkey, "i)(alt|lalt|ralt)(\s\&\s)?")A
                    }
                    if RegExMatch(Hotkey, "^\+.$")
                    {
                        Hotkey := SubStr(Hotkey, 1, 1) . "{" . SubStr(Hotkey, 2) . "}"
                    }
                    GetKeyState, Var, CapsLock, T
                    if Var = D
                    {
                        if RegExMatch(Hotkey, "^\+\{[a-z]\}$")
                        {
                            Hotkey := SubStr(Hotkey, 2)
                            Break
                        }
                        if RegExMatch(Hotkey, "^[a-z]$")
                        {
                            Hotkey := "+{" . Hotkey . "}"
                            Break
                        }
                        if RegExMatch(Hotkey, "^\{[a-z]\}$")
                        {
                            Hotkey := "+" . Hotkey
                            Break
                        }
                    }
                    Break
                }
                Return hotkey
            }

            ToMatch(Key)
            {
                Key := RegExReplace(Key, "\+|\?|\.|\*|\{|\}|\(|\)|\||\^|\$|\[|\]|\\", "\$0")
                Return RegExReplace(Key, "\s", "\s")
            }

        }
    }

}

SetTimeOutClass(win) {
    vim.TimeOutClass := win
}
GetTimeOutClass(win) {
    w := vim.Vaild(win)
    return w.TimeOut
}
GetCommentDest(action) {
    Return vim.CommentList[action]
}
GetCommentType(action) {
    Type := vim.CommentType[action]
    if Strlen(Type)
        return Type
    else
        return true
}
EmptyMem(PID="AHK Rocks")
{
    pid:=(pid="AHK Rocks") ? DllCall("GetCurrentProcessId") : pid
    h:=DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "Int", pid)
    DllCall("SetProcessWorkingSetSize", "UInt", h, "Int", -1, "Int", -1)
    DllCall("CloseHandle", "Int", h)
}
<TimeOutLabel>:
    vim.TimeOut()
return

<HotkeyLabel>:
    vim.Do()
return

<Repeat>:
    vim.Repeat()
return

/*
API 函数列表：
vim.mode("模式","ahk_class")  ; 设置运行的模式
vim.map("热键","Label标签","ahk_class")  ;映射热键
vim.settimeout("按键超时时间","ahk_class")  ;设置按键超时时间
vim.listkey("ahk_class")  ;显示所有映射的热键体
vim.control("on/off","ahk_class")  ;启用/禁用映射的热键
vim.comment("标签","描述","是否允许多次运行（0/1)")
内置Label:
<Repeat> 重复上一次动作
*/
#UseHook On
Setkeydelay,-1
return

; 此函数可以根据自己的喜好进行修改
ShowComment(more="") {
    if not ToShowComment
	return
    WinGetClass,win,A
    w := vim.Vaild(win)
    mode := w.GetMode()
    msg := mode.KeyTemp "`n=============================`n"
;	GUIControl,,Edit1,%msg%

    If Strlen(more)
    {
        Loop,Parse,more,`n
        {
            key := Trim(A_LoopField)
            action := mode.KeyBody[key]
            ;comment := vim.CommentList[action]
            comment := GetCommentDest(action)
            If Strlen(comment)
                msg .= key "  >>  " comment "`n"
            Else
                msg .= key "  >>  " action "`n"

        }
        Tooltip % msg
		;GUI,VIMINFO:Show
    }
    Else
        Tooltip
		;GUI,VIMINFO:Show,Hide
}

; ====================
; ====================
; 内部脚本，请匆修改！
; ====================
; ====================

; 初始化 vimcore
Init() {
	OnMessage(0x05,"GuiSize")
    GoSub,vimnew
}

vimnew:
    Global vim := new vimcore
return

; 以下为class封装，请匆修改
Class vimcore {
    __New() {
       This.vimWindows := []
       This.vimGlobal  := new This.vimClass("")
       This.TimeOutClass := ""
	   This.ExcludeList := []
	   ;This.ExcludeList["AutoHotkey"] := True
       This.CommentList := []
       This.CommentType := []
	   This.UseHotkey   := []
    }

    Vaild(win) {
        if Strlen(win) = 0
            Return This.vimGlobal
        w := This.vimWindows[win]
        if w.winVaild
            return w
        Else
            return This.vimGlobal
    }

    mode(mode,win="") {
        if Strlen(win) = 0
            w := This.vimGlobal
        Else
            w := This.vimWindows[win]
        If not w.winVaild
        {
            w := new This.vimClass(win)
            This.vimWindows[win] := w
        }
        w.SetMode(mode)
        ShowComment()
    }

	sMap(key,label,win=""){
		This.UseHotkey[key] := True
    	this.Map(key,label,win)
	}
    Map(key,label,win="") {
		If not RegExMatch(Key,"[^\s]")
			return
        if Strlen(win) = 0
            w := This.vimGlobal
        Else
            w := This.vimWindows[win]
        If not w.winVaild
        {
            w := new This.vimClass(win)
            This.vimWindows[win] := w
        }
        mode := w.GetMode()
        mode.SetHotkey(key,label)
    }

    Comment(action,desc,complex=1) {
        This.CommentList[action] := desc
        This.CommentType[action] := complex
    }

    do() {
        WinGetClass,win,A
        w := This.Vaild(win)
		m := w.GetMode()
		If This.ExcludeList[win] And not this.UseHotkey[m.GetThisHotkey()]
		{
			Send,% m.TransSendKey(A_ThisHotkey)
			return
		}
        If w.winVaild {
            mode := w.GetMode()
			If Mode.KeyList[A_ThisHotkey]
            	mode.Try()
			Else
			{
				w := This.vimGlobal
				mode := w.GetMode()
				mode.Try()
			}
        }
    }

	Filter(String) {

        WinGetClass,win,A

		If This.ExcludeList[win]
			return
        w := This.Vaild(win)

        If w.winVaild {
            mode := w.GetMode()
			mode.query(string)
        }
    }

	Exclude(win) {
		This.ExcludeList[win] := True
	}

	Include(win) {
		This.ExcludeList[win] := False
	}

    ListKey(win="",mode="") {
        w := This.Vaild(win)
        If strlen(mode) {
            m := w.winmode[mode]
            For k , l in m.KeyBody
                msg .= k "  " l "`n"
            return msg
        }
        Else {
            For n , m  in w.winMode
            {
                msg .= "====`n" n "`n----`n"
                mode := m
                For k , l in m.KeyBody
                    msg .= k "  " l "`n"
            }
            return msg
        }
    }

	copy(win1,win2) {

        w2 := This.vimWindows[win2]

        If w2.winVaild
            return False

		w1 := This.Vaild(win1)
		w1.winName := win2
		For n , m in w1.WinMode
		{
			mode := m
			mode.win := win2
			w1.WinMode[n] := mode
			For k , l in m.KeyList
            {
				Hotkey,IfWinActive,ahk_class %win2%
                Hotkey,%k%,<HotkeyLabel>
            }
		}
		This.vimWindows[win2] := w1
        return True
	}

	CopyMode(win,mode,to) {
		w := This.Vaild(win)
		If strlen(mode) = 0
			return

		vim.mode(to,win)
		m := w.winmode[mode]
		For k , l in m.KeyBody
			vim.map(k,l,win)
	}

    Control(switch,win="") {
        w := This.Vaild(win)
        If switch = on
        {
            For n , m  in w.winMode
            {
                mode := m
                For k , l in m.KeyList
                {
                    Hotkey,%k%,on
                }
            }
        }
        If switch = off
        {
            For n , m  in w.winMode
            {
                mode := m
                For k , l in m.KeyList
                {
                    Hotkey,%k%,off
                }
            }
        }
    }

    test() {
        msgbox vim test
    }

    SetTimeOut(tick,win="") {
        w := This.Vaild(win)
        If not w.winVaild
        {
            w := new This.vimClass(win)
            This.vimWindows[win] := w
        }
        w.TimeOut := tick
    }

    TimeOut() {
        w := This.Vaild(This.TimeOutClass)
        mode := w.GetMode()
        mode.KeyTemp := ""
        ;GoSub,% mode.TimeOutAction
        mode.ExecSub(mode.TimeOutAction)
        ;    ShowComment()
        mode.TimeOutAction := ""
    }

    Repeat() {
        WinGetClass,win,A
        w := This.vimWindows[win]
        If not w.winVaild
            w := This.vimGlobal
        If w.winVaild {
            mode := w.GetMode()
            mode.KeyCount := w.winRepeatCount
            mode.ExecSub(w.winRepeat,Ture)
        }
    }

    GetWin() {
        WinGetClass,win,A
        Return This.Vaild(win)
    }

	GetCount() {
		w := This.GetWin()
		m := w.GetMode()
		Return m.KeyCount ? m.KeyCount : 1
	}

    Class vimClass {

        __New(win) {
            This.winName := win
            This.winVaild   := 1
            This.winControl := 0
            This.winTimeOut := 0
            THis.winMaxCount := 99
            This.winKeyList := []
            This.winMode    := []
            This.winThisMode := ""
            This.winRepeat   := ""
            This.winRepeatCount := 0
        }
        ;设置窗口类下的模式
        SetMode(md) {
            m := This.winMode[md]
            If Strlen(m.Mode) = 0 {
                This.winThisMode := md
                m := new This.Mode(md,This.winName)
                This.winMode[md] := m
            }
            Else
                This.winThisMode := md
            return m
        }
        ;获取窗口类下的模式

        GetMode() {
            m := This.winMode[This.winThisMode]
            return m
        }

        Class Mode {
            __New(mode,win) {
                This.Mode := mode
                This.win  := win ;可变
                If Strlen(win)
                    This.CheckMode := win "_CheckMode"
                Else
                    This.CheckMode := "CheckMode"
                This.KeyTemp   := ""
                This.KeyString := ""
                This.KeyCount := 0
                This.TimeOut := 0
                This.TimeOutTick   := 0
                This.TimeOutAction := ""
                This.KeyBody := []
                This.KeyList := []
                This.KeyMap  := []
            }

            test() {
                msgbox % This.Mode
            }

            Try(){
				checkMode := This.CheckMode
                settimer,<TimeOutLabel>,off
                Key := This.GetThisHotkey()
                If ( Not This.KeyList[A_ThisHotkey] ) or ( IsFunc(CheckMode) AND (%CheckMode%()) ) {
                    Send,% This.TransSendKey(A_ThisHotkey)
                    ShowComment()
					return
				}
                _SaveKeyTemp := This.KeyTemp
                This.KeyTemp .= Key
                P := 1
                more := ""
                moreCount := 0
                Loop {
                    P := RegExMatch(This.KeyString,"i)\t" This.ToMatch(This.keyTemp) "[^\t]*",m,P)
                    If P {
                        ;msgbox % This.KeyString "`np=" p "`nm=" m
                        more .= m "`n"
                        P += Strlen(m)
                        moreCount++
                    }
                    Else
                        Break
                }
                more := RTrim(more,"`n")
                If moreCount = 0
                {
                	This.KeyTemp := ""

                    action := This.KeyBody[_SaveKeyTemp]
                    If Strlen(action) {
                        This.ExecSub(Action)
                    }
                    Else {
                        action := This.KeyBody[Key]
                        If Strlen(action) {
							If InvalidMode
                            	ShowComment()
							Else
                            	This.ExecSub(Action)
						}
                        Else {
							If RegExMatch(This.KeyString,"i)\t" This.ToMatch(key) "[^\t]*")
							{
								If InvalidMode
                            		ShowComment()
								Else
                        			This.Try()
							}
							Else
							{
                            	Send,% This.TransSendKey(A_ThisHotkey)
                            	ShowComment()
							}
							return
                        }
                    }
                }
                Else If moreCount = 1
                {
                    Action := This.KeyBody[This.KeyTemp]
                    If Strlen(Action) {
                        This.ExecSub(Action)
                        This.KeyTemp := ""
                    }
                    Else
                        ShowComment(more)
                }
                Else
                {
                    TimeOut := 0 - GetTimeOutClass(This.win)
                    If Timeout And This.KeyBody[This.KeyTemp]{
                        This.TimeOutAction := This.KeyBody[This.KeyTemp]
                        This.TimeOutTick   := A_TickCount
                        SetTimeOutClass(This.win)
                        Settimer,<TimeOutLabel>,%TimeOut%
                    }
                    ErrorLevel := True
                    ShowComment(more)
                    return more
                }
            }

            ExecSub(action) {
                w := vim.vaild(This.win)
                If RegExMatch(Action,"(?<=^<)\d(?=>$)",cnt) {
                        This.KeyCount := This.KeyCount * 10 + cnt
                        MaxCount := w.winMaxCount
                        If This.KeyCount > MaxCount
                            This.KeyCount := MaxCount
                        Tooltip % This.KeyCount
                        return false
                }
                Else {
                    ShowComment()
                    If This.KeyCount And GetCommentType(Action)
                        cnt := This.KeyCount
                    Else
                        cnt := 1
                    ;cnt := This.KeyCount ? This.KeyCount : 1
                    If RegExMatch(action,"^<.*>$") {
                        If IsLabel(action) {
                            Loop,%cnt%
                                GoSub % Action
                        }
                        Else {
                            Msgbox %Action%不存在，请检查脚本
                            Return
                        }
                    }
                    If RegExMatch(action,"^\(.*\)$") {
						file := SubStr(action,2,Strlen(action)-2)
                        Run,%File%,,UseErrorLevel,ExecID
                        If ErrorLevel
                        {
                            msgbox 运行%file%失败
                            return
                        }
                        Else
                        {
                            WinWait,AHK_PID %ExecID%,,1
                            WinActivate,AHK_PID %ExecID%
                        }
                    }
                    If RegExMatch(Action,"^\{.*\}$") {
                        Text := Substr(Action,2,Strlen(Action)-2)
                        Loop,%cnt%
                            Send,%Text%
                    }

                    This.KeyCount := 0
                    If rpt
                        return
                    If not RegExMatch(action,"i)^<repeat>$") {
                        w.winRepeatCount := cnt
                        w.winRepeat := Action
                    }
                }
				EmptyMem()
            }

            SetHotkey(key,label) {
                ;msgbox % This.win
                If Strlen(This.win) > 0 {
                    class := This.win
                    Hotkey,IfWinActive,ahk_class %class%
                }
                Else
                    Hotkey,IfWinActive

                mKey := ""
                Loop,Parse,Key
                {
                    If Asc(A_LoopField) >= 65 And Asc(A_LoopField) <= 90
                        mKey .= "<shift>" . Chr(Asc(A_LoopField)+32)
                    Else
                        mKey .= A_LoopField
                }
                Hotkey_OK := True
                ;Idx := This.KeyList[0] ? This.KeyList[0] : 1
                cnt := 1
                _SaveList := []
                for,i,k in This.ResolveHotkey(mKey)
                {
                    Hotkey,%k%,<HotkeyLabel>,On,UseErrorLevel
                    If ErrorLevel
                    {
                        Msgbox 映射错误
                        Hotkey_OK := False
                        Break
                    }
                    ;If Not This.KeyList[k] {
                    ;    This.KeyList[idx] := k
                    ;    idx++
                    ;}
                    _SaveList[cnt] := k
                    cnt++
                    This.KeyList[k] := This.KeyList[k] ? This.KeyList[k] + 1 : 1
                }
                ;This.KeyList[0] := idx
                If Not Hotkey_OK {
                    For i , k IN _SaveList
                    {
                        This.KeyList[k] := This.KeyList[k] - 1
                        If This.KeyList[k] = 0 {
                            Hotkey,%k%,off
                        }
                    }
                }
                Else {
                    This.KeyBody[mkey] := label
                    If not RegExMatch(This.KeyString,"\t" This.ToMatch(mKey) "[^\t]*")
                        This.KeyString .= A_Tab mKey A_Tab
                }
            }

            ResolveHotkey(KeyList)
            {
                Keys := []
                NewKeyList := []
                n := 1
                Loop
                {
                    Pos := RegExMatch(KeyList,"<[^<>]*>",A_Index)
                    If Pos
                    {
                        LoopKey := SubStr(KeyList,1,Pos-1)
                        Loop,Parse,LoopKey
                        {
                            If Asc(A_LoopField) >= 65 And Asc(A_LoopField) <= 90
                            {
                                Keys[n] := "shift"
                                n++
                                Keys[n] := Chr(Asc(A_LoopField)+32)
                            }
                            Else
                                Keys[n] := A_LoopField
                            n++
                        }
                        KeyList := SubStr(KeyList,Pos,Strlen(KeyList))
                        Pos := RegExMatch(KeyList,">")
                        Keys[n] := SubStr(KeyList,2,Pos-2)
                        KeyList := SubStr(KeyList,Pos+1,Strlen(KeyList))
                        n++
                    }
                    Else
                    {
                        Loop,Parse,KeyList
                        {
                            If Asc(A_LoopField) >= 65 And Asc(A_LoopField) <= 90
                            {
                                Keys[n] := "shift"
                                n++
                                Keys[n] := Chr(Asc(A_LoopField)+32)
                            }
                            Else
                                Keys[n] := A_LoopField
                            n++
                        }
                        Break
                    }
                }
                n := 1
                For,i,key in Keys
                {
                    If RegExMatch(key,"i)(l|r)?(ctrl|shift|win|alt)")
                    {
                        List .= Key " & "
                        Continue
                    }
                    Else
                    {
                        List .= Key
                        NewKeyList[n] := List
                        List :=
                    }
                    n++
                }
                Return NewKeyList
            }

            GetThisHotkey(G_ThisHotkey="")
            {
                If Strlen(G_ThisHotkey) = 0
                    G_ThisHotkey := A_ThisHotkey
                GetKeyState,Var,CapsLock,T
                If Var = D
                {
                    If RegExMatch(ThisHotkey,"i)^(l|r)?shift\s&\s[a-z]$")
                        ThisHotkey := Substr(ThisHotkey,0)
                    Else If RegExMatch(G_ThisHotkey,"^[a-z]$")
                        ThisHotkey := "shift & " . G_ThisHotkey
					Else
						ThisHotkey := A_ThisHotkey
                }
                Else
                    ThisHotkey := G_ThisHotkey
                Loop
                {
                    If RegExMatch(ThisHotkey,"(?<!<)(((l|r)?(ctrl|control|alt|win|shift))|(f\d\d?)|esc|escape|space|tab|enter|bs|del|ins|home|end|pgup|pgdn|up|down|left|right|((?<=&\s)[<>]$))(?!>)",m) {
                        ThisHotkey := RegExReplace(ThisHotkey,This.ToMatch(m),"<" m ">")
                    }
                    Else
                    {
                        ThisHotkey := RegExReplace(ThisHotkey,"\s&\s")
                        Break
                    }
                }
                ;msgbox % Thishotkey
                Return ThisHotKey
            }

            ; TransSendKey(hotkey) {{{2
            ; 在SendKey时，将hotkey转换为Send能支持的格式
            TransSendKey(hotkey)
            {
                Loop
                {
                    If RegExMatch(Hotkey,"i)^(f\d\d?)|esc|escpa|space|tab|enter|bs|del|ins|home|end|pgup|pgdn|up|down|left|right|!|#|\+|\^|\{|\}$")
                    {
                        Hotkey := "{" . Hotkey . "}"
                        Break
                    }
                    If StrLen(hotkey) > 1 AND Not RegExMatch(Hotkey,"^\+.$")
                    {
                        Hotkey := "{" . hotkey . "}"
                        If RegExMatch(hotkey,"i)(shift|lshift|rshift)(\s\&\s)?.+$")
                            Hotkey := "+" . RegExReplace(hotkey,"i)(shift|lshift|rshift)(\s\&\s)?")
                        If RegExMatch(hotkey,"i)(ctrl|lctrl|rctrl|control|lcontrol|rcontrol)(\s\&\s)?.+$")
                            Hotkey := "^" . RegExReplace(hotkey,"i)(ctrl|lctrl|rctrl|control|lcontrol|rcontrol)(\s\&\s)?")
                        If RegExMatch(hotkey,"i)(lwin|rwin)(\s\&\s)?.+$")
                            Hotkey := "#" . RegExReplace(hotkey,"i)(lwin|rwin)(\s\&\s)?")
                        If RegExMatch(hotkey,"i)(alt|lalt|ralt)(\s\&\s)?.+$")
                            Hotkey := "!" . RegExReplace(hotkey,"i)(alt|lalt|ralt)(\s\&\s)?")A
                    }
                    If RegExMatch(Hotkey,"^\+.$")
                    {
                        Hotkey := SubStr(Hotkey,1,1) . "{" . SubStr(Hotkey,2) . "}"
                    }
                    GetKeyState,Var,CapsLock,T
                    If Var = D
                    {
                        If RegExMatch(Hotkey,"^\+\{[a-z]\}$")
                        {
                            Hotkey := SubStr(Hotkey,2)
                            Break
                        }
                        If RegExMatch(Hotkey,"^[a-z]$")
                        {
                            Hotkey := "+{" . Hotkey . "}"
                            Break
                        }
                        If RegExMatch(Hotkey,"^\{[a-z]\}$")
                        {
                            Hotkey := "+" . Hotkey
                            Break
                        }
                    }
                    Break
                }
                Return hotkey
            }

            ToMatch(Key)
            {
                Key := RegExReplace(Key,"\+|\?|\.|\*|\{|\}|\(|\)|\||\^|\$|\[|\]|\\","\$0")
                Return RegExReplace(Key,"\s","\s")
            }

        }
    }

}

SetTimeOutClass(win) {
    vim.TimeOutClass := win
}
GetTimeOutClass(win) {
    w := vim.Vaild(win)
    return w.TimeOut
}
GetCommentDest(action) {
    Return vim.CommentList[action]
}
GetCommentType(action) {
    Type := vim.CommentType[action]
    If Strlen(Type)
        return Type
    Else
        return true
}
EmptyMem(PID="AHK Rocks")
{
    pid:=(pid="AHK Rocks") ? DllCall("GetCurrentProcessId") : pid
    h:=DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", 0, "Int", pid)
    DllCall("SetProcessWorkingSetSize", "UInt", h, "Int", -1, "Int", -1)
    DllCall("CloseHandle", "Int", h)
}
<TimeOutLabel>:
    vim.TimeOut()
return

<HotkeyLabel>:
    vim.Do()
return

<Repeat>:
    vim.Repeat()
return


Launches exe with the correct working directory; fixes #11

; Uncomment the next line if you don't want this script appearing in your system tray
;#NoTrayIcon
#SingleInstance Force
#Persistent
Initialize()
return

;;;;;;;;;;;
; Desktop names.  Will appear in the overlay while you switch desktops.
DesktopNames() {
    global
    desktopName := Object()
    ; Example: desktopName[4] := "Work Documents"
    desktopName[0] := ""
    desktopName[1] := ""
    desktopName[2] := ""
    desktopName[3] := ""
    desktopName[4] := ""
    desktopName[5] := ""
    desktopName[6] := ""
    desktopName[7] := ""
    desktopName[8] := ""
}

Options() {
    global
    overlayEnabled := 1 ; 1 = enabled, 0 = disabled
    hideOverlayDelay := 1000 ; milliseconds for overlay to remain visible before auto-hiding
}

;;;;;;;
; 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)
^#F1::SendCommand(GO_TO, 0)
^#F2::SendCommand(GO_TO, 1)
^#F3::SendCommand(GO_TO, 2)
^#F4::SendCommand(GO_TO, 3)
^#F5::SendCommand(GO_TO, 4)
^#F6::SendCommand(GO_TO, 5)
^#F7::SendCommand(GO_TO, 6)
^#F8::SendCommand(GO_TO, 7)
^#F9::SendCommand(GO_TO, 8)
^#F10::SendCommand(GO_TO, 9)
^#F11::SendCommand(GO_TO, 10)
^#F12::SendCommand(GO_TO, 11)
#!F1::SendCommand(MOVE_TO, 0)
#!F2::SendCommand(MOVE_TO, 1)
#!F3::SendCommand(MOVE_TO, 2)
#!F4::SendCommand(MOVE_TO, 3)
#!F5::SendCommand(MOVE_TO, 4)
#!F6::SendCommand(MOVE_TO, 5)
#!F7::SendCommand(MOVE_TO, 6)
#!F8::SendCommand(MOVE_TO, 7)
#!F9::SendCommand(MOVE_TO, 8)
#!F10::SendCommand(MOVE_TO, 9)
#!F11::SendCommand(MOVE_TO, 10)
#!F12::SendCommand(MOVE_TO, 11)
^#A::ToggleAlwaysOnTop()
^#S::SendCommand(TOGGLE_STICKY)
^#D::SendCommand(DEBUG_SHOW_CURRENT_WINDOW_HWND)
#If overlayVisible
; When either Ctrl or Win is released, the overlay is hidden.
~*Ctrl Up::HideOverlay()
~*LWin Up::HideOverlay()
#If

; Called once when the script is launched.
Initialize() {
    global
    CommandConstants()
    DesktopNames()
    Options()

    MsgNum := DllCall("RegisterWindowMessage", Str, "VIRTUALDESKTOPGRIDSWITCHER_COMMAND")

    exeName := "VirtualDesktopGridSwitcher.exe"
    ; Use this when running via Visual Studio's debugger
    ;exeName := "VirtualDesktopGridSwitcher.vshost.exe"

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

    ; Run function when this script is exited
    OnExit("OnExitFn")

    overlayVisible := 0

    ; Register listener to receive messages from .exe
    OnMessage(MsgNum, "ReceiveMessage")
    myHwnd := HexToDec(A_ScriptHwnd)
    SendCommand(SET_HWND_MESSAGE_TARGET, myHwnd)
}

CommandConstants() {
    global
    ; 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_STICKY := 10
    DEBUG_SHOW_CURRENT_WINDOW_HWND := 11
    SET_HWND_MESSAGE_TARGET := 12
    SWITCHED_DESKTOP := 13
    QUIT := 14
    GO_TO := 15
    MOVE_TO := 16
}

; 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, value := 0) {
    ; All variables are global unless declared to be local
    global
    local id
    id := GetTargetHwnd()
    PostMessage, % MsgNum, % cmd, % value, , ahk_id %id%
}

; Called when VirtualDesktopGridSwitcher sends us a message
ReceiveMessage(command, value, msg, hwnd) {
    ; All variables are global unless declared to be local
    global
    local num
    if (command == SWITCHED_DESKTOP) {
        num := value + 1
        ShowOverlay("Desktop " + num, desktopName[value], "../Icons/" . num . ".ico")
    } else {
        MsgBox, % command, % value
    }
}

HexToDec(hex) {
    result := hex + 0
    ; result .= ""
    return result
}

ShowOverlay(title, message, icon := "") {
    global overlayVisible, overlayEnabled, hideOverlayDelay
    if(!overlayEnabled) {
        return
    }
    overlayVisible := 1
    SysGet, primary, MonitorPrimary
    SysGet, monitor, Monitor, % primary
    width := 200
    height := 120
    padding := 100
    x := monitorLeft + ((monitorRight - monitorLeft) / 2) - (width / 2)
    y := monitorBottom - height - padding
    iconSize := 64
    textColor := "303030"
    windowColor := "FFFFFF"
    SplashImage, % icon, B1 X%x% Y%y% W%width% H%height% ZH%iconSize% ZW%iconSize% CW%windowColor% CT%textColor%, % message, % title, ,
    SetTimer, HideOverlay, % -hideOverlayDelay
}

HideOverlay() {
    global overlayVisible
    overlayVisible := 0
    SplashImage, Off
}

ToggleAlwaysOnTop(hwnd := "") {
    if(hwnd == "") {
        hwnd := WinExist("A")
    }
    WinSet, AlwaysOnTop, Toggle, ahk_id %hwnd%
    ;WinGet, ExStyle, ExStyle, ahk_id %hwnd%
    ;if(ExStyle & 0x8) {
    ;    message := "Always on Top Enabled"
    ;} else {
    ;    message := "Always on Top Disabled"
    ;}
    ;TrayTip, , %message%, 1, 0x10
}

OnExitFn(reason, exitCode) {
    global
    ; Kill the Exe.  Expectation is that this .ahk script will manage the exe's
    ; lifetime, both starting and stopping it.
    If(reason != "Reload" && reason != "Single") {
        SendCommand(QUIT)
    }
}

; Uncomment the next line if you don't want this script appearing in your system tray
;#NoTrayIcon
#SingleInstance Force
#Persistent
Initialize()
return

;;;;;;;;;;;
; Desktop names.  Will appear in the overlay while you switch desktops.
DesktopNames() {
    global
    desktopName := Object()
    ; Example: desktopName[4] := "Work Documents"
    desktopName[0] := ""
    desktopName[1] := ""
    desktopName[2] := ""
    desktopName[3] := ""
    desktopName[4] := ""
    desktopName[5] := ""
    desktopName[6] := ""
    desktopName[7] := ""
    desktopName[8] := ""
}

Options() {
    global
    overlayEnabled := 1 ; 1 = enabled, 0 = disabled
    hideOverlayDelay := 1000 ; milliseconds for overlay to remain visible before auto-hiding
}

;;;;;;;
; 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)
^#F1::SendCommand(GO_TO, 0)
^#F2::SendCommand(GO_TO, 1)
^#F3::SendCommand(GO_TO, 2)
^#F4::SendCommand(GO_TO, 3)
^#F5::SendCommand(GO_TO, 4)
^#F6::SendCommand(GO_TO, 5)
^#F7::SendCommand(GO_TO, 6)
^#F8::SendCommand(GO_TO, 7)
^#F9::SendCommand(GO_TO, 8)
^#F10::SendCommand(GO_TO, 9)
^#F11::SendCommand(GO_TO, 10)
^#F12::SendCommand(GO_TO, 11)
#!F1::SendCommand(MOVE_TO, 0)
#!F2::SendCommand(MOVE_TO, 1)
#!F3::SendCommand(MOVE_TO, 2)
#!F4::SendCommand(MOVE_TO, 3)
#!F5::SendCommand(MOVE_TO, 4)
#!F6::SendCommand(MOVE_TO, 5)
#!F7::SendCommand(MOVE_TO, 6)
#!F8::SendCommand(MOVE_TO, 7)
#!F9::SendCommand(MOVE_TO, 8)
#!F10::SendCommand(MOVE_TO, 9)
#!F11::SendCommand(MOVE_TO, 10)
#!F12::SendCommand(MOVE_TO, 11)
^#A::ToggleAlwaysOnTop()
^#S::SendCommand(TOGGLE_STICKY)
^#D::SendCommand(DEBUG_SHOW_CURRENT_WINDOW_HWND)
#If overlayVisible
; When either Ctrl or Win is released, the overlay is hidden.
~*Ctrl Up::HideOverlay()
~*LWin Up::HideOverlay()
#If

; Called once when the script is launched.
Initialize() {
    global
    CommandConstants()
    DesktopNames()
    Options()

    MsgNum := DllCall("RegisterWindowMessage", Str, "VIRTUALDESKTOPGRIDSWITCHER_COMMAND")

    exeName := "VirtualDesktopGridSwitcher.exe"
    ; Use this when running via Visual Studio's debugger
    ;exeName := "VirtualDesktopGridSwitcher.vshost.exe"

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

    ; Run function when this script is exited
    OnExit("OnExitFn")

    overlayVisible := 0

    ; Register listener to receive messages from .exe
    OnMessage(MsgNum, "ReceiveMessage")
    myHwnd := HexToDec(A_ScriptHwnd)
    SendCommand(SET_HWND_MESSAGE_TARGET, myHwnd)
}

CommandConstants() {
    global
    ; 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_STICKY := 10
    DEBUG_SHOW_CURRENT_WINDOW_HWND := 11
    SET_HWND_MESSAGE_TARGET := 12
    SWITCHED_DESKTOP := 13
    QUIT := 14
    GO_TO := 15
    MOVE_TO := 16
}

; 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, value := 0) {
    ; All variables are global unless declared to be local
    global
    local id
    id := GetTargetHwnd()
    PostMessage, % MsgNum, % cmd, % value, , ahk_id %id%
}

; Called when VirtualDesktopGridSwitcher sends us a message
ReceiveMessage(command, value, msg, hwnd) {
    ; All variables are global unless declared to be local
    global
    local num
    if (command == SWITCHED_DESKTOP) {
        num := value + 1
        ShowOverlay("Desktop " + num, desktopName[value], "../Icons/" . num . ".ico")
    } else {
        MsgBox, % command, % value
    }
}

HexToDec(hex) {
    result := hex + 0
    ; result .= ""
    return result
}

ShowOverlay(title, message, icon := "") {
    global overlayVisible, overlayEnabled, hideOverlayDelay
    if(!overlayEnabled) {
        return
    }
    overlayVisible := 1
    SysGet, primary, MonitorPrimary
    SysGet, monitor, Monitor, % primary
    width := 200
    height := 120
    padding := 100
    x := monitorLeft + ((monitorRight - monitorLeft) / 2) - (width / 2)
    y := monitorBottom - height - padding
    iconSize := 64
    textColor := "303030"
    windowColor := "FFFFFF"
    SplashImage, % icon, B1 X%x% Y%y% W%width% H%height% ZH%iconSize% ZW%iconSize% CW%windowColor% CT%textColor%, % message, % title, ,
    SetTimer, HideOverlay, % -hideOverlayDelay
}

HideOverlay() {
    global overlayVisible
    overlayVisible := 0
    SplashImage, Off
}

ToggleAlwaysOnTop(hwnd := "") {
    if(hwnd == "") {
        hwnd := WinExist("A")
    }
    WinSet, AlwaysOnTop, Toggle, ahk_id %hwnd%
    ;WinGet, ExStyle, ExStyle, ahk_id %hwnd%
    ;if(ExStyle & 0x8) {
    ;    message := "Always on Top Enabled"
    ;} else {
    ;    message := "Always on Top Disabled"
    ;}
    ;TrayTip, , %message%, 1, 0x10
}

OnExitFn(reason, exitCode) {
    global
    ; Kill the Exe.  Expectation is that this .ahk script will manage the exe's
    ; lifetime, both starting and stopping it.
    If(reason != "Reload" && reason != "Single") {
        SendCommand(QUIT)
    }
}


Added MSOffice specific commands.

Added MSOffice specific commands.

; Autohotkey configuration file
; AHK Version v1.1.22.06
; Franklin Chou (franklin.chou@yahoo.com)
; 20 Nov. 2015

;------------------------------------------------------------------------------
; GLOSSARY OF COMMONLY USED KEY MODIFIERS
;
; # Windows key
; ! Alt key
; ^ Control key
; + Shift key
; < Use the Left key of a pair
; > Use the Right key of a pair
;------------------------------------------------------------------------------

#SingleInstance force

PrintScreen::AppsKey

; Print screen reassigned to Windows Key + PrintScreen
#PrintScreen::PrintScreen

;------------------------------------------------------------------------------
; COMMONLY USED SYMBOL KEYS

>+P::send
>+S::send
;------------------------------------------------------------------------------

#IfWinActive,, Microsoft Word
  PgUp::Home
  PgDn::End
  <!Up:: Send {PgUp}
  <!Down:: Send {PgDn}
#IfWinActive

; no-commit
FireFox := "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"
Word	:= "C:\Program Files\Microsoft Office\Office15\WINWORD.EXE"
; no-commit-end

#^R::Reload
#B::Run, "FireFox"
#W::Run, "Word"

; Autohotkey configuration file
; AHK Version v1.1.22.06
; Franklin Chou (franklin.chou@yahoo.com)
; 20 Nov. 2015

;------------------------------------------------------------------------------
; # Windows key
; ! Alt key
; ^ Control key
; + Shift key
; < Use the Left key of a pair
; > Use the Right key of a pair
;------------------------------------------------------------------------------

#SingleInstance force

PrintScreen::AppsKey

; Print screen reassigned to Windows Key + PrintScreen
#PrintScreen::PrintScreen

; Right shift and S, insert section symbol
>+S::send

#IfWinActive,, Microsoft Word
  PgUp::Home
  PgDn::End
  <!Up:: Send {PgUp}
  <!Down:: Send {PgDn}
#IfWinActive

; 3 lines omitted

#^R::Reload
#B::Run, "FireFox"
#W::Run, "Word"


Remove support for cbwin

Remove support for cbwin

#NoTrayIcon
#NoEnv

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

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

; Prepare mintty_base and wslbridge_base {{{1
icon_option = -i "%A_ScriptFullPath%"
if (icon != "" && FileExist(icon)) {
    icon_option = -i "%icon%"
}

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

mintty_base = "%A_ScriptDir%\bin\mintty" --wsl --rootfs=// --configdir "%A_ScriptDir%\etc" %icon_option%
wslbridge_base = -e /bin/wslbridge %distro_option% -e SHELL="%shell%" -e LANG

; Run as run-wsl-file or any editor {{{1
SplitPath, A_ScriptName, , , , exe_name
if (exe_name == "run-wsl-file") {
    arg = %1%

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

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

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

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

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

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

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

    Run, %mintty_base% %mintty_options% -t "%filepath%" %wslbridge_base% -t "%exe_name%" %options% %filename%
    ExitApp
}

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

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

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

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

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

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

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

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

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

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

if (user_command != "") {
    if (change_directory != "") {
        wslbridge_options = %wslbridge_options% -C "%change_directory%"
    }

    Run, %mintty_base% %mintty_options% -t "%user_command%" %wslbridge_base% %wslbridge_options% -t %shell% -c "%user_command%"
    ExitApp
}

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

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

; Build command line {{{1
cmd =
opts = %wslbridge_options% -t

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

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

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

if (cmd != "") {
    Run, %mintty_base% %mintty_options% -t "%title%" %wslbridge_base% %opts% %cmd%
}

; Activate window {{{1
Loop, 5 {
    WinActivate, %title%
    if (WinActive(title)) {
        break
    }

    Sleep, 50
}

if (keep_wsl_running) {
    Process, Exist, sleep

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

#NoTrayIcon
#NoEnv

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

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

; Prepare mintty_base and wslbridge_base {{{1
icon_option = -i "%A_ScriptFullPath%"
if (icon != "" && FileExist(icon)) {
    icon_option = -i "%icon%"
}

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

mintty_base = "%A_ScriptDir%\bin\mintty" --wsl --rootfs=// --configdir "%A_ScriptDir%\etc" %icon_option%
wslbridge_base = -e /bin/wslbridge %distro_option% -e SHELL="%shell%" -e LANG

; Run as run-wsl-file or any editor {{{1
SplitPath, A_ScriptName, , , , exe_name
if (exe_name == "run-wsl-file") {
    arg = %1%

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

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

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

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

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

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

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

    Run, %mintty_base% %mintty_options% -t "%filepath%" %wslbridge_base% -t "%exe_name%" %options% %filename%
    ExitApp
}

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

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

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

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

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

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

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

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

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

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

if (user_command != "") {
    if (change_directory != "") {
        wslbridge_options = %wslbridge_options% -C "%change_directory%"
    }

    Run, %mintty_base% %mintty_options% -t "%user_command%" %wslbridge_base% %wslbridge_options% -t %shell% -c "%user_command%"
    ExitApp
}

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

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

; Build command line {{{1
cmd =
opts = %wslbridge_options% -t

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

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

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

if (cmd != "") {
    Run, %mintty_base% %mintty_options% -t "%title%" %wslbridge_base% %opts% %cmd%
}

; Activate window {{{1
Loop, 5 {
    WinActivate, %title%
    if (WinActive(title)) {
        break
    }

    Sleep, 50
}

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

    if (ErrorLevel == 0) {
        Run, "%A_ScriptDir%\bin\outbash" --outbash-session -c 'exec sleep 10000000d', , Hide
    }
} else if (keep_wsl_running) {
    Process, Exist, sleep

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