├── .gitignore ├── Conf ├── README.txt ├── RunZ.ini.help.txt ├── Skins │ ├── Default.ini │ └── New.ini └── UserFunctionsAuto.txt.template ├── Core ├── Common.ahk ├── ControlPanelFunctions.txt └── RunZCmdTool.ahk ├── LICENSE ├── Lib ├── EasyIni.ahk ├── Eval.ahk ├── Gdip.ahk ├── JSON.ahk ├── Kanji │ └── Kanji.txt ├── Logger.ahk ├── TCMatch.ahk └── TCMatch │ └── tcmatch.ini ├── Plugins ├── Core.ahk ├── Demo.ahk ├── Kanji.ahk ├── Misc.ahk ├── QRCode.ahk └── System.ahk ├── README.md ├── RunZ.ahk ├── RunZ.ico ├── VERSION └── build /.gitignore: -------------------------------------------------------------------------------- 1 | #################### 2 | # Windows 3 | #################### 4 | # Windows image file caches 5 | Thumbs.db 6 | ehthumbs.db 7 | 8 | # Folder config file 9 | Desktop.ini 10 | 11 | # Recycle Bin used on file shares 12 | $RECYCLE.BIN/ 13 | 14 | # Windows Installer files 15 | *.cab 16 | *.msi 17 | *.msm 18 | *.msp 19 | 20 | #################### 21 | # vim 22 | #################### 23 | [._]*.s[a-w][a-z] 24 | [._]s[a-w][a-z] 25 | *.un~ 26 | Session.vim 27 | .netrwhist 28 | *~ 29 | *.exe 30 | Private 31 | SearchFileList.txt 32 | RunZ.ini 33 | .RunZ.ini.bak 34 | UserFunctions.ahk 35 | Doc 36 | RunZ.auto.ini 37 | Reserved 38 | SendToRunZ.js 39 | SendToRunZ.lnk 40 | *.jpg 41 | UserFunctionsAuto.txt 42 | UserFunctionsAuto.txt.bak 43 | UserFileList.txt 44 | tcmatch.dll 45 | tcmatch64.dll 46 | tcmatch.tbl 47 | Plugins.ahk 48 | -------------------------------------------------------------------------------- /Conf/README.txt: -------------------------------------------------------------------------------- 1 | 此目录文件说明: 2 | 3 | RunZ.ini.help.txt 4 | 主配置 RunZ.ini 的帮助文件,当 RunZ.ini 不存在时,它会被复制成 RunZ.ini。 5 | 6 | RunZ.ini 7 | 主配置文件,配置需要手动修改,程序不会自动写入。 8 | 9 | UserFunctions.ahk.help.txt 10 | 用户函数帮助文件,不生效,仅供参考。手动将其复制为 UserFunctions.ahk 可生效。 11 | 12 | UserFunctions.ahk 13 | 用户函数文件,该文件需要手动修改,程序不会自动写入,修改前请仔细阅读文件中的说明。 14 | 15 | UserFunctionsAuto.txt.template 16 | 发送到菜单写入的配置模版,请不要修改此文件。 17 | 如果打开了发送到菜单功能,并且无 UserFunctionsAuto.txt 文件,改文件会被复制为 UserFunctionsAuto.txt。 18 | 19 | UserFunctionsAuto.txt 20 | 发送到菜单写入的配置,也可以手动修改,修改前请仔细阅读文件中的说明。 21 | 22 | UserFunctionsAuto.txt.bak 23 | UserFunctionsAuto.txt 的上一次备份,如果发现最新版本有问题请手动恢复。 24 | 25 | Skins 26 | 皮肤目录,皮肤名为该目录下 ini 文件的文件名(不含 .ini)。 27 | 28 | SearchFileList.txt 29 | 搜索到的文件列表,不要手动修改此文件,会被覆盖。 30 | 31 | UserFileList.txt 32 | 用户自己添加的待搜索文件列表,也是简单模式“发送到”菜单使用的文件列表。 33 | -------------------------------------------------------------------------------- /Conf/RunZ.ini.help.txt: -------------------------------------------------------------------------------- 1 | [Config] 2 | CreateSendToLnk=1 3 | ; 是否创建“发送到”菜单,1 创建,0 删除 4 | CreateStartupLnk=0 5 | ; 是否开机自启动 6 | SearchFileDir=A_ProgramsCommon | A_StartMenu 7 | ; 搜索的目录,可以使用 全路径 或 ahk 以 A_ 开头的变量,必须以 " | " 分隔 8 | ; 路径可包含空格,无需加引号 9 | SearchFileType=*.lnk | *.exe 10 | ; 搜索的文件类型,必须以 " | " 分隔 11 | SearchFileExclude=卸载 12 | ; 排除的文件,正则表达式 13 | SearchFullPath=0 14 | ; 搜索完整路径,否则只搜文件名 15 | ShowFileExt=0 16 | ; 在界面显示文件扩展名 17 | TCMatchPath=Lib\TCMatch\tcmatch.dll 18 | ; tcmatch.dll 地址,如果没有则使用 InStr 匹配 19 | SaveInputText=0 20 | ; 退出时保存编辑框内容 21 | KeepInputText=1 22 | ; 窗口隐藏时不清空编辑框内容 23 | RunOnce=0 24 | ; 运行一次命令就退出,对展示信息的命令无效 25 | TCPath=c:\totalcmd\totalcmd.exe 26 | ; TotalCommander 路径,如果为空则使用资源管理器打开 27 | RunInBackground=1 28 | ; 在后台运行 29 | RunIfOnlyOne=0 30 | ; 如果结果中只有一个则直接运行 31 | LoadControlPanelFunctions=1 32 | ; 加载控制面板中的功能 33 | ExitIfInactivate=0 34 | ; 窗口失去焦点后窗口关闭,启用后窗口置顶显示功能失效 35 | WindowAlwaysOnTop=0 36 | ; 窗口置顶显示 37 | SaveHistory=1 38 | ; 记录历史 39 | HistorySize=15 40 | ; 记录历史的数量 41 | AutoRank=1 42 | ; 自动根据使用频率调节顺序,因为效率问题,结果不能实时体现,重启或 ctrl + r 后更新 43 | ClickToRun=1 44 | ; 是否单击执行鼠标处命令,0 则只定位到该处 45 | SwitchToEngIME=0 46 | ; 每次激活窗口自动切换到英文输入法 47 | ChangeCommandOnMouseMove=0 48 | ; 当鼠标移动时,定位到鼠标所在命令,会消耗一些 CPU,并且造成文字闪烁 49 | ClearInputWithEsc=0 50 | ; 输入 Esc 时,如果输入框有内容则清空,无内容才关闭窗口 51 | Editor= 52 | ; 用来打开配置文件的编辑器,默认为资源管理器关联的编辑器,可以右键->属性->打开方式修改 53 | SendToMenuSimpleMode=1 54 | ; 使用简单模式的发送到菜单 55 | SendToMenuReadLnkFile=1 56 | ; 如果使用发送到菜单发送的文件是 .lnk 的快捷方式,从文件读取路径后添加目标文件 57 | DebugMode=0 58 | ; 开启调试模式,可以看到更多错误信息 59 | 60 | [Gui] 61 | ; Skin=New 62 | ; 指定皮肤名,如果为空则使用此 [Gui] 中的配置,否则 [Gui] 其他字段失效 63 | HideTitle=1 64 | ; 隐藏标题栏 65 | ShowTrayIcon=1 66 | ; 是否显示托盘图标 67 | ShowCurrentCommand=1 68 | ; 在下方详情框显示当前命令 69 | DisplayRows=15 70 | ; 在列表中显示的行数,请不要在显示区域下方留空隙,否则鼠标定位会有偏差 71 | DisplayCol3MaxLength=30 72 | ; 在列表中第三列的宽度 73 | DisplayCol4MaxLength=36 74 | ; 在列表中第四列的宽度 75 | HideCol2=0 76 | ; 隐藏第二列,即显示 文件、功能 的一列 77 | ; 如果隐藏,第二列的空间会分给第三列 78 | HideCol4IfEmpty=1 79 | ; 当第四列内容为空时,隐藏第四列,展开第三列 80 | FontName=宋体 81 | ; 字体名称 82 | ; 如果想更换,需要使用等宽字体,可以用 Inziu Iosevka Slab SC,在 http://pan.baidu.com/s/1i5Ndii5 83 | ; 可下载,其中也包含一张截图。下载后安装,然后 FontName=Inziu Iosevka Slab SC 即可 84 | ; 但需要合理修改 FontSize DisplayRows DisplayCol3MaxLength DisplayCol4MaxLength 等字段,以免折行 85 | FontSize=12 86 | ; 字体大小 87 | FontColor=000000 88 | ; 字体颜色 89 | WidgetWidth=650 90 | ; 输入框和输出框宽度 91 | EditHeight=24 92 | ; 输入框和详情框高度 93 | DisplayAreaHeight=246 94 | ; 输出框高度 95 | FirstChar=a 96 | ; 列表第一行的首字母或数字 97 | EditColor=f0f0f0 98 | ; 输入框颜色 99 | BackgroundColor=f0f0f0 100 | ; 背景色,包括边框、输出框和详情框颜色 101 | BackgroundPicture=Background1.jpg 102 | ; 背景图片,需要放在 Conf\Skins 目录内,背景图片只能在边框部分显示 103 | ; 如果使用图片后有闪屏现象, 先将图片大小调整为解决窗口大小,提高加载速度 104 | ; 如果闪屏依然明显,请将图片上文本框的位置挖空填充为和文本背景相似的颜色,或者修改成 png 的透明色 105 | BorderSize=15 106 | ; 边框宽度 107 | ShowInputBoxOnlyIfEmpty=0 108 | ; 当输入框为空时只显示输入框 109 | RoundCorner=0 110 | ; 如果不为 0,使用圆形边角,数字代表程度,大于 10 才比较明显,可以修改后试验效果 111 | 112 | [Command] 113 | 114 | 115 | 116 | ; 这里的 command 优先显示 117 | ; 118 | ; 文件类型(直接使用 AHK 的 Run() 运行): 119 | ; file | 文件路径 | 注释 120 | ; 如: 121 | ; file | notepad | 记事本 122 | ; 注释里可以包含要搜索的字符串,也可以没有: 123 | ; file | c:\mine\mine.exe 124 | ; 125 | ; url 类型: 126 | ; url | www.baidu.com | 百度 127 | ; 可包括 http://,也可不包含 128 | ; 129 | ; cmd 类型,在 cmd.exe 运行命令,运行后会自动暂停: 130 | ; 如: 131 | ; cmd | ipconfig | 查看 IP 地址 132 | 133 | [Hotkey] 134 | 135 | 136 | 137 | ; 映射 RunZ 自身使用的按键: 138 | ; key=label 139 | ; 等同于 140 | ; Hotkey, key, label 141 | ; 如(可使用 Test 测试): 142 | ; f1=Test 143 | ; 具体功能请直接在代码里搜 Hotkey 对应的标签 144 | ; key=Default 可取消代码中的按键映射 145 | ; 注意优先级比默认的 Alt + 字母数字 系列按键高,如无特殊原因不要修改 Alt 的映射 146 | 147 | [GlobalHotkey] 148 | #j=ToggleWindow 149 | !space=ToggleWindow 150 | 151 | 152 | 153 | ; 语法和 [Hotkey] 一样,但作用范围是全局的 154 | 155 | [Plugins] 156 | Core=1 157 | ; 核心功能,禁用需谨慎 158 | System=1 159 | ; 操作系统相关功能 160 | Misc=1 161 | ; 实用工具集合 162 | QRCode=1 163 | ; 生成二维码 164 | Kanji=0 165 | ; 简体繁体转换 166 | Demo=0 167 | ; 插件示例 168 | 169 | 170 | 171 | ; 插件名=1 启用插件 172 | ; 插件名=0 禁用插件 173 | ; 这里没有的插件,默认是启用的 174 | 175 | [FallbackCommand] 176 | function | AhkRun | 使用 Ahk 的 Run() 运行 ; command 177 | function | CmdRun | 使用 cmd 运行 : command 178 | function | WinRRun | 使用 win + r 运行 179 | function | RunAndDisplay | 使用 cmd 运行,并显示结果 180 | function | SearchOnBaidu | 使用 百度 搜索剪切板或输入内容 181 | function | SearchOnGoogle | 使用 谷歌 搜索剪切板或输入内容 182 | function | SearchOnBing | 使用 必应 搜索剪切板或输入内容 183 | 184 | 185 | 186 | ; 回退命令指当搜索不到结果时显示哪些命令,按顺序排列,第一个为回车使用的 187 | -------------------------------------------------------------------------------- /Conf/Skins/Default.ini: -------------------------------------------------------------------------------- 1 | ; 注释以 RunZ.ini.help.txt 里的为准,这里可能更新不及时。 2 | 3 | [Gui] 4 | HideTitle=1 5 | ; 隐藏标题栏 6 | ShowTrayIcon=1 7 | ; 是否显示托盘图标 8 | ShowCurrentCommand=1 9 | ; 在下方详情框显示当前命令 10 | DisplayRows=15 11 | ; 在列表中显示的行数,请不要在显示区域下方留空隙,否则鼠标定位会有偏差 12 | DisplayCol3MaxLength=25 13 | ; 在列表中第三列的宽度 14 | DisplayCol4MaxLength=35 15 | ; 在列表中第四列的宽度 16 | HideCol4IfEmpty=1 17 | ; 当第四列内容为空时,隐藏第四列,展开第三列 18 | FontName=宋体 19 | ; 字体名称 20 | FontSize=12 21 | ; 字体大小 22 | FontColor=000000 23 | ; 字体颜色 24 | WidgetWidth=600 25 | ; 输入框和输出框宽度 26 | EditHeight=24 27 | ; 输入框和详情框高度 28 | DisplayAreaHeight=246 29 | ; 输出框高度 30 | FirstChar=a 31 | ; 列表第一行的首字母或数字 32 | EditColor=f0f0f0 33 | ; 输入框颜色 34 | BackgroundColor=f0f0f0 35 | ; 背景色,包括边框、输出框和详情框颜色 36 | BackgroundPicture=Background.jpg 37 | ; 背景图片,需要放在 Conf\Skins 目录内,背景图片只能在边框部分显示 38 | ; 如果使用图片后有闪屏现象, 先将图片大小调整为解决窗口大小,提高加载速度 39 | ; 如果闪屏依然明显,请将图片上文本框的位置挖空填充为和文本背景相似的颜色,或者修改成 png 的透明色 40 | BorderSize=15 41 | ; 边框宽度 42 | -------------------------------------------------------------------------------- /Conf/Skins/New.ini: -------------------------------------------------------------------------------- 1 | ; 注释以 RunZ.ini.help.txt 里的为准,这里可能更新不及时。 2 | 3 | [Gui] 4 | HideTitle=1 5 | ; 隐藏标题栏 6 | ShowTrayIcon=1 7 | ; 是否显示托盘图标 8 | ShowCurrentCommand=1 9 | ; 在下方详情框显示当前命令 10 | DisplayRows=15 11 | ; 在列表中显示的行数,请不要在显示区域下方留空隙,否则鼠标定位会有偏差 12 | DisplayCol3MaxLength=25 13 | ; 在列表中第三列的宽度 14 | DisplayCol4MaxLength=35 15 | ; 在列表中第四列的宽度 16 | HideCol4IfEmpty=1 17 | ; 当第四列内容为空时,隐藏第四列,展开第三列 18 | FontName=宋体 19 | ; 字体名称 20 | FontSize=12 21 | ; 字体大小 22 | FontColor=f0f0f0 23 | ; 字体颜色 24 | WidgetWidth=600 25 | ; 输入框和输出框宽度 26 | EditHeight=24 27 | ; 输入框和详情框高度 28 | DisplayAreaHeight=246 29 | ; 输出框高度 30 | FirstChar=a 31 | ; 列表第一行的首字母或数字 32 | EditColor=191919 33 | ; 输入框颜色 34 | BackgroundColor=191919 35 | ; 背景色,包括边框、输出框和详情框颜色 36 | BackgroundPicture=Background2.jpg 37 | ; 背景图片,需要放在 Conf\Skins 目录内,背景图片只能在边框部分显示 38 | ; 如果使用图片后有闪屏现象, 先将图片大小调整为解决窗口大小,提高加载速度 39 | ; 如果闪屏依然明显,请将图片上文本框的位置挖空填充为和文本背景相似的颜色,或者修改成 png 的透明色 40 | BorderSize=15 41 | ; 边框宽度 42 | -------------------------------------------------------------------------------- /Conf/UserFunctionsAuto.txt.template: -------------------------------------------------------------------------------- 1 | ; 此文件(AHK 代码)由发送到菜单或命令行工具写入,也可手动修改 2 | ; 一定不要添加重复标签,否则程序会启动异常,必须再手动修改或删除该文件来恢复 3 | 4 | global Arg 5 | 6 | UserFunctionsAuto: 7 | ; 第一个参数为标签名 8 | ; 第二个为搜索项(内容随意) 9 | ; 第三个参数为 true 时,当搜索无结果也会显示,默认为 false 10 | ; 第四个参数为绑定的全局热键,默认无 11 | ; 比如: 12 | ; @("UserTest1", "用户测试(ut1)", false, "#p") 13 | ; 请不要修改包含 -*-*-*-*-*- 的行(包括前边的空格),否则发送到菜单功能会异常 14 | 15 | ; 以下内容为自动添加,手动添加请在此行上方添加 16 | ; -*-*-*-*-*- 17 | return 18 | 19 | ; 以下内容为自动添加 20 | ; -*-*-*-*-*- 21 | 22 | ; 以下内容为手动添加,可自由编辑 23 | -------------------------------------------------------------------------------- /Core/Common.ahk: -------------------------------------------------------------------------------- 1 | ; http://ahk8.com/archive/index.php/thread-1927.html 2 | UnicodeDecode(text) 3 | { 4 | while pos := RegExMatch(text, "\\u\w{4}") 5 | { 6 | tmp := UrlEncodeEscape(SubStr(text, pos + 2, 4)) 7 | text := RegExReplace(text, "\\u\w{4}", tmp, "", 1) 8 | } 9 | return text 10 | } 11 | 12 | ; http://ahk8.com/archive/index.php/thread-1927.html 13 | UrlEncodeEscape(text) 14 | { 15 | text := "0x" . text 16 | VarSetCapacity(LE, 2, "UShort") 17 | NumPut(text, LE) 18 | return StrGet(&LE, 2) 19 | } 20 | 21 | ; https://autohotkey.com/board/topic/113942-solved-get-cpu-usage-in/ 22 | CPULoad() 23 | { 24 | static PIT, PKT, PUT 25 | if (Pit = "") 26 | { 27 | return 0, DllCall("GetSystemTimes", "Int64P", PIT, "Int64P", PKT, "Int64P", PUT) 28 | } 29 | DllCall("GetSystemTimes", "Int64P", CIT, "Int64P", CKT, "Int64P", CUT) 30 | IdleTime := PIT - CIT, KernelTime := PKT - CKT, UserTime := PUT - CUT 31 | SystemTime := KernelTime + UserTime 32 | return ((SystemTime - IdleTime) * 100) // SystemTime, PIT := CIT, PKT := CKT, PUT := CUT 33 | } 34 | 35 | ; https://autohotkey.com/board/topic/113942-solved-get-cpu-usage-in/ 36 | GlobalMemoryStatusEx() 37 | { 38 | static MEMORYSTATUSEX, init := VarSetCapacity(MEMORYSTATUSEX, 64, 0) && NumPut(64, MEMORYSTATUSEX, "UInt") 39 | if (DllCall("Kernel32.dll\GlobalMemoryStatusEx", "Ptr", &MEMORYSTATUSEX)) 40 | { 41 | return { 2 : NumGet(MEMORYSTATUSEX, 8, "UInt64") 42 | , 3 : NumGet(MEMORYSTATUSEX, 16, "UInt64") 43 | , 4 : NumGet(MEMORYSTATUSEX, 24, "UInt64") 44 | , 5 : NumGet(MEMORYSTATUSEX, 32, "UInt64") } 45 | } 46 | } 47 | 48 | ; https://autohotkey.com/board/topic/113942-solved-get-cpu-usage-in/ 49 | GetProcessCount() 50 | { 51 | proc := "" 52 | for process in ComObjGet("winmgmts:\\.\root\CIMV2").ExecQuery("SELECT * FROM Win32_Process") 53 | { 54 | proc++ 55 | } 56 | return proc 57 | } 58 | 59 | SwitchIME(dwLayout) 60 | { 61 | HKL := DllCall("LoadKeyboardLayout", Str, dwLayout, UInt, 1) 62 | ControlGetFocus, ctl, A 63 | SendMessage, 0x50, 0, HKL, %ctl%, A 64 | } 65 | 66 | SwitchToEngIME() 67 | { 68 | ; 下方代码可只保留一个 69 | SwitchIME(0x04090409) ; 英语(美国) 美式键盘 70 | SwitchIME(0x08040804) ; 中文(中国) 简体中文-美式键盘 71 | } 72 | 73 | ; 0:英文 1:中文 74 | GetInputState(WinTitle = "A") 75 | { 76 | ControlGet, hwnd, HWND, , , %WinTitle% 77 | if (A_Cursor = "IBeam") 78 | return 1 79 | if (WinActive(WinTitle)) 80 | { 81 | ptrSize := !A_PtrSize ? 4 : A_PtrSize 82 | VarSetCapacity(stGTI, cbSize := 4 + 4 + (PtrSize * 6) + 16, 0) 83 | NumPut(cbSize, stGTI, 0, "UInt") ; DWORD cbSize; 84 | hwnd := DllCall("GetGUIThreadInfo", Uint, 0, Uint, &stGTI) 85 | ? NumGet(stGTI, 8 + PtrSize, "UInt") : hwnd 86 | } 87 | return DllCall("SendMessage" 88 | , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint, hwnd) 89 | , UInt, 0x0283 ;Message : WM_IME_CONTROL 90 | , Int, 0x0005 ;wParam : IMC_GETOPENSTATUS 91 | , Int, 0) ;lParam : 0 92 | } 93 | 94 | ; 根据字节取子字符串,如果多删了一个字节,补一个空格 95 | SubStrByByte(text, length) 96 | { 97 | textForCalc := RegExReplace(text, "[^\x00-\xff]", "`t`t") 98 | textLength := 0 99 | realRealLength := 0 100 | 101 | Loop, Parse, textForCalc 102 | { 103 | if (A_LoopField != "`t") 104 | { 105 | textLength++ 106 | textRealLength++ 107 | } 108 | else 109 | { 110 | textLength += 0.5 111 | textRealLength++ 112 | } 113 | 114 | if (textRealLength >= length) 115 | { 116 | break 117 | } 118 | } 119 | 120 | result := SubStr(text, 1, round(textLength - 0.5)) 121 | 122 | ; 删掉一个汉字,补一个空格 123 | if (round(textLength - 0.5) != round(textLength)) 124 | result .= " " 125 | 126 | return result 127 | } 128 | 129 | ; 修改自万年书妖的 Candy 里的 SksSub_UrlEncode 函数,用于转换编码。感谢! 130 | UrlEncode(url, enc = "UTF-8") 131 | { 132 | enc := Trim(enc) 133 | If enc= 134 | return url 135 | formatInteger := A_FormatInteger 136 | SetFormat, IntegerFast, H 137 | VarSetCapacity(buff, StrPut(url, enc)) 138 | Loop % StrPut(url, &buff, enc) - 1 139 | { 140 | byte := NumGet(buff, A_Index-1, "UChar") 141 | encoded .= byte > 127 or byte < 33 ? "%" SubStr(byte, 3) : Chr(byte) 142 | } 143 | SetFormat, IntegerFast, %formatInteger% 144 | return encoded 145 | } 146 | 147 | UrlDownloadToString(url, headers := "") 148 | { 149 | static whr := ComObjCreate("WinHttp.WinHttpRequest.5.1") 150 | whr.Open("GET", url, true) 151 | 152 | if (headers != "") 153 | { 154 | for key, value in headers 155 | { 156 | whr.SetRequestHeader(key, value) 157 | } 158 | } 159 | 160 | whr.Send() 161 | whr.WaitForResponse() 162 | return whr.ResponseText 163 | } 164 | -------------------------------------------------------------------------------- /Core/ControlPanelFunctions.txt: -------------------------------------------------------------------------------- 1 | file | control | 控制面板 2 | file | control sysdm.cpl | 系统属性 3 | file | control Access.cpl | 辅助功能选项 4 | file | control Appwiz.cpl | 添加删除程序 删除软件 程序和功能 5 | file | control Desk.cpl | 显示 6 | file | control Fax.cpl | 传真向导 7 | file | control Hdwwiz.cpl | 添加删除硬件 8 | file | control Intl.cpl | 区域语言选项 9 | file | control Joy.cpl | 游戏控制器 10 | file | control Liccpa.cpl | 许可 11 | file | control Main.cpl | 鼠标属性 12 | file | control Mmsys.cpl | 声音和音频设备 13 | file | control Modem.cpl | 电话和调制解调器选项 14 | file | control Ncpa.cpl | 网络连接 15 | file | control Netcpl.cpl | 网络和拨号连接 16 | file | control Nwc.cpl | Netware客户端连接 17 | file | control Odbccp32.cpl | ODBC数据源 18 | file | control Powercfg.cpl | 电源管理 电源选项 19 | file | control Sticpl.cpl | 扫描仪和照相机 20 | file | control Sysdm.cpl | 系统 21 | file | control Telephon.cpl | 拨号规则和调制解调器 22 | file | control Timedate.cpl | 日期和时间 23 | file | control admintools | 管理工具 24 | file | control desktop | 显示属性 25 | file | control firewall.cpl | 防火墙配置 26 | file | control folders | 文件夹选项 27 | file | control fonts | 字体 28 | file | control inetcpl.cpl,,4 | Internet 属性 29 | file | control printers | 打印机和传真 30 | file | control sysdm.cpl | 高级系统配置 31 | file | control userpasswords | 用户账户 32 | file | control schedtasks | 计划任务 33 | file | rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0 | 桌面图标 34 | file | rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,1 | 屏幕保护 35 | file | rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,2 | 外观和个性化 36 | file | rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,3 | 系统设置 37 | file | rundll32.exe shell32.dll,Control_RunDLL main.cpl @1 | 键盘属性 38 | file | rundll32.exe shell32.dll,Options_RunDLL 1 | 任务栏和开始菜单 39 | file | rundll32.exe sysdm.cpl,EditEnvironmentVariables | 环境变量 40 | file | devmgmt.msc | 设备管理器 41 | file | eventvwr.msc | 事件查看器 42 | file | compmgmt.msc | 计算机管理 43 | file | taskmgr.exe | 任务管理器 44 | file | calc.exe | 计算器 calc.exe 45 | file | mspaint.exe | 画图 46 | file | cmd.exe | 命令提示符 DOS(cmd.exe) 47 | file | C:\Program Files\Internet Explorer\iexplore.exe | IE浏览器 48 | file | regedit.exe | 注册表 49 | file | write.exe | 写字板 50 | file | cleanmgr.exe | 磁盘清理 51 | file | gpedit.msc | 组策略 52 | file | comexp.msc | 组件服务 53 | file | diskmgmt.msc | 磁盘管理 54 | file | dxdiag.exe | DirectX 诊断工具 55 | file | WF.msc | 防火墙 56 | file | lusrmgr.msc | 本地用户和组 57 | file | msconfig.exe | 系统配置工具 58 | file | perfmon.exe /res | 资源监视器 59 | file | perfmon.exe | 性能监视器 60 | file | winver.exe | 关于 Windows 61 | file | services.msc | 服务 62 | file | netplwiz | 用户帐户 63 | file | SndVol.exe | 音量合成器 64 | -------------------------------------------------------------------------------- /Core/RunZCmdTool.ahk: -------------------------------------------------------------------------------- 1 | #NoEnv 2 | #NoTrayIcon 3 | SendMode Input 4 | SetWorkingDir %A_ScriptDir% 5 | 6 | FileEncoding, utf-8 7 | 8 | ; 如果该文件报错,说明 UserFunctionsAuto.txt 文件里有重复标签,需要手动修改或删除 9 | 10 | global g_ConfFile := A_ScriptDir . "\..\Conf\RunZ.ini" 11 | global g_Conf := class_EasyINI(g_ConfFile) 12 | global g_UserFunctionsAutoFileName := A_ScriptDir "\..\Conf\UserFunctionsAuto.txt" 13 | global g_UserFileList := A_ScriptDir "\..\Conf\UserFileList.txt" 14 | global g_FileContent 15 | 16 | allLabels := Object() 17 | index := 1 18 | 19 | Loop, %0% 20 | { 21 | inputFileName := %A_Index% 22 | SplitPath, inputFileName, fileName, fileDir, fileExt, fileNameNoExt 23 | 24 | if (fileNameNoExt == "") 25 | { 26 | continue 27 | } 28 | 29 | if (fileExt == "ahk") 30 | { 31 | FileReadLine, firstLine, %inputFileName%, 1 32 | if (InStr(firstLine, " RunZ:")) 33 | { 34 | pluginName := StrSplit(firstLine, "; RunZ:")[2] 35 | if (FileExist(A_ScriptDir "\..\Plugins\" pluginName ".ahk")) 36 | { 37 | ToolTip, %pluginName% 插件已存在 38 | sleep 1500 39 | ExitApp 40 | } 41 | FileMove, %inputFileName%, %A_ScriptDir%\..\Plugins\%pluginName%.ahk 42 | FileAppend, #include *i `%A_ScriptDir`%\Plugins\%pluginName%.ahk`n 43 | , %A_ScriptDir%\..\Core\Plugins.ahk 44 | ToolTip, %pluginName% 插件安装成功,请手动重启 RunZ 以生效 45 | sleep 1500 46 | ExitApp 47 | } 48 | } 49 | 50 | labelName := SafeLabel(fileNameNoExt) 51 | fileExt := SafeFilename(fileExt) 52 | fileDir := SafeFilename(fileDir) 53 | fileName := SafeFilename(fileName) 54 | filePath := fileDir "\" fileName 55 | fileDesc := "" 56 | 57 | if (fileExt == "lnk" && g_Conf.Config.SendToMenuReadLnkFile) 58 | { 59 | FileGetShortcut, %filePath%, filePath, fileDir, targetArg, fileDesc 60 | 61 | if (fileDesc = filePath) 62 | { 63 | fileDesc := "" 64 | } 65 | 66 | filePath .= " " targetArg 67 | 68 | if (!g_Conf.Config.SendToMenuSimpleMode) 69 | { 70 | filePath := SafeFilename(filePath) 71 | } 72 | } 73 | 74 | if (g_Conf.Config.SendToMenuSimpleMode) 75 | { 76 | FileAppend, file | %filePath% | %fileDesc%`r`n, %g_UserFileList% 77 | 78 | continue 79 | } 80 | 81 | if (!FileExist(g_UserFunctionsAutoFileName)) 82 | { 83 | FileCopy, %g_UserFunctionsAutoFileName%.template, %g_UserFunctionsAutoFileName% 84 | } 85 | 86 | FileRead, g_FileContent, %g_UserFunctionsAutoFileName% 87 | 88 | 89 | uniqueLabelName := labelName 90 | 91 | ; 如果和已有标签重名,添加时间 92 | if (IsLabel(uniqueLabelName) || allLabels.HasKey(uniqueLabelName)) 93 | { 94 | uniqueLabelName .= "_" A_Now "_" index 95 | index++ 96 | } 97 | 98 | AddFile(uniqueLabelName, labelName, filePath, fileDir) 99 | allLabels[uniqueLabelName] := true 100 | } 101 | 102 | if (g_Conf.Config.SendToMenuSimpleMode) 103 | { 104 | ToolTip, 文件添加完毕,3 秒内生效 105 | sleep 1500 106 | ExitApp 107 | } 108 | 109 | FileMove, %g_UserFunctionsAutoFileName%, %g_UserFunctionsAutoFileName%.bak, 1 110 | FileAppend, %g_FileContent%, %g_UserFunctionsAutoFileName%, utf-8 111 | 112 | ; 打开文件来编辑 113 | if (g_Conf.Config.Editor != "") 114 | { 115 | Run, % g_Conf.Config.Editor " """ g_UserFunctionsAutoFileName """" 116 | } 117 | else 118 | { 119 | Run, %g_UserFunctionsAutoFileName% 120 | } 121 | 122 | 123 | return 124 | 125 | ; 添加一个需要运行的文件 126 | AddFile(name, comment, path, dir) 127 | { 128 | addFunctionsText = @("%name%", "%comment%") 129 | addLabelsText = %name%:`r`n `; 用法: Run, "文件名" "参数..", 工作目录, Max|Min|Hide`r`n 130 | addLabelsText = %addLabelsText% Run, "%path%", "%dir%"`r`nreturn`r`n 131 | 132 | g_FileContent := StrReplace(g_FileContent 133 | , " `; -*-*-*-*-*-", " `; -*-*-*-*-*-`r`n " addFunctionsText) 134 | g_FileContent := StrReplace(g_FileContent 135 | , "`r`n`; -*-*-*-*-*-", "`r`n`; -*-*-*-*-*-`r`n" addLabelsText) 136 | } 137 | 138 | SafeLabel(label) 139 | { 140 | StringReplace, label, label, ", _, All 141 | return RegExReplace(label, "[ `%```t',]", "_") 142 | } 143 | 144 | SafeFilename(label) 145 | { 146 | StringReplace, label, label, ", `"`", All 147 | StringReplace, label, label, ``, ````, All 148 | StringReplace, label, label, `%, ```%, All 149 | StringReplace, label, label, `,, ```,, All 150 | return label 151 | } 152 | 153 | ; 伪 @ 函数,用于避免运行出错 154 | @(a = "", b = "", c = "", d = "", e = "", f = "") 155 | { 156 | } 157 | 158 | #include %A_ScriptDir%\..\Lib\EasyIni.ahk 159 | ; 用于判断是否有重复标签 160 | #include *i %A_ScriptDir%\..\Conf\UserFunctionsAuto.txt 161 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Gore Liu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Lib/EasyIni.ahk: -------------------------------------------------------------------------------- 1 | ; http://ahkscript.org/boards/viewtopic.php?f=6&t=5522&hilit=lib+ini 2 | ; Author : Verdlin 3 | class_EasyIni(sFile="", sLoadFromStr="") 4 | { 5 | return new EasyIni(sFile, sLoadFromStr) 6 | } 7 | 8 | class EasyIni 9 | { 10 | __New(sFile="", sLoadFromStr="") ; Loads ths file into memory. 11 | { 12 | this := this.CreateIniObj("EasyIni_ReservedFor_m_sFile", sFile 13 | , "EasyIni_ReservedFor_TopComments", Object()) ; Top comments can be stored in linear array because order will simply be numeric 14 | 15 | if (sFile == A_Blank && sLoadFromStr == A_Blank) 16 | return this 17 | 18 | ; Append ".ini" if it is not already there. 19 | if (SubStr(sFile, StrLen(sFile)-3, 4) != ".ini") 20 | this.EasyIni_ReservedFor_m_sFile := sFile := (sFile . ".ini") 21 | 22 | sIni := sLoadFromStr 23 | if (sIni == A_Blank) 24 | FileRead, sIni, %sFile% 25 | 26 | /* 27 | Current design (not fully implemented): 28 | --------------------------------------------------------------------------------------------------------------------------------------------------- 29 | Comments at the top of the section apply to the file as a whole. They are keyed off an internal section called "EasyIni_ReservedFor_TopComments." 30 | Comments above section headers apply to the the last key of the previous section. 31 | If a comment appears between two keys, then it will apply to the key above it -- this is consistent with the solution for comments above section headers. 32 | Newlines will be stored in similar fashion to comments. 33 | --------------------------------------------------------------------------------------------------------------------------------------------------- 34 | 35 | --------------------------------------------------------------------------------------------------------------------------------------------------- 36 | If full-support for comments needs to be added, then the design below should supersede the design above. 37 | By saying, "Full-support" I mean a way to directly access these comments based upon sections and keys. 38 | --------------------------------------------------------------------------------------------------------------------------------------------------- 39 | 40 | --------------------------------------------------------------------------------------------------------------------------------------------------- 41 | Comments at the top of the section apply to the file as a whole. They are keyed off an internal section called "EasyIni_ReservedFor_TopComments." 42 | Comments above section headers apply to the section header. If people dislike this, I may instead chose to make the comments apply to the last key of the previous section if there a newline in-between the comment in question and the next section. I may come up with some decent solution as I experiment 43 | If a comment appears between two keys, then it will apply to the key below it -- this is consistent with the solution for comments above section headers. 44 | Newlines will be stored in similar fashion to comments. 45 | --------------------------------------------------------------------------------------------------------------------------------------------------- 46 | */ 47 | 48 | Loop, Parse, sIni, `n, `r 49 | { 50 | sTrimmedLine := Trim(A_LoopField) 51 | 52 | ; Comments or newlines within the ini 53 | if (SubStr(sTrimmedLine, 1, 1) == ";" || sTrimmedLine == A_Blank) ; A_Blank would be a newline 54 | { 55 | ; Chr(14) is just the magical char to indicate that this line should only be a newline "`n" 56 | LoopField := A_LoopField == A_Blank ? Chr(14) : A_LoopField 57 | 58 | if (sCurSec == A_Blank) 59 | this.EasyIni_ReservedFor_TopComments.Insert(A_Index, LoopField) ; not using sTrimmedLine so as to keep comment formatting 60 | else 61 | { 62 | if (sPrevKeyForThisSec == A_Blank) ; This happens when there is a comment in the section before the first key, if any 63 | sPrevKeyForThisSec := "SectionComment" 64 | 65 | if (IsObject(this[sCurSec].EasyIni_ReservedFor_Comments)) 66 | { 67 | if (this[sCurSec].EasyIni_ReservedFor_Comments.HasKey(sPrevKeyForThisSec)) 68 | this[sCurSec].EasyIni_ReservedFor_Comments[sPrevKeyForThisSec] .= "`n" LoopField 69 | else this[sCurSec].EasyIni_ReservedFor_Comments.Insert(sPrevKeyForThisSec, LoopField) 70 | } 71 | else 72 | { 73 | if (IsObject(this[sCurSec])) 74 | this[sCurSec].EasyIni_ReservedFor_Comments := {(sPrevKeyForThisSec):LoopField} 75 | else this[sCurSec, "EasyIni_ReservedFor_Comments"] := {(sPrevKeyForThisSec):LoopField} 76 | } 77 | } 78 | continue 79 | } 80 | 81 | ; [Section] 82 | if (SubStr(sTrimmedLine, 1, 1) = "[" && InStr(sTrimmedLine, "]")) ; need to be sure that this isn't just a key starting with "[" 83 | { 84 | if (sCurSec != A_Blank && !this.HasKey(sCurSec)) 85 | this[sCurSec] := EasyIni_CreateBaseObj() 86 | sCurSec := SubStr(sTrimmedLine, 2, InStr(sTrimmedLine, "]", false, 0) - 2) ; 0 search right to left. We want to trim the *last* occurence of "]" 87 | sPrevKeyForThisSec := "" 88 | continue 89 | } 90 | 91 | ; key=val 92 | iPosOfEquals := InStr(sTrimmedLine, "=") 93 | if (iPosOfEquals) 94 | { 95 | sPrevKeyForThisSec := SubStr(sTrimmedLine, 1, iPosOfEquals - 1) ; so it's not the previous key yet...but it will be on next iteration :P 96 | val := SubStr(sTrimmedLine, iPosOfEquals + 1) 97 | StringReplace, val, val , `%A_ScriptDir`%, %A_ScriptDir%, All 98 | StringReplace, val, val , `%A_WorkingDir`%, %A_ScriptDir%, All 99 | this[sCurSec, sPrevKeyForThisSec] := val 100 | } 101 | else ; at this point, we know it isn't a comment, or newline, it isn't a section, and it isn't a conventional key-val pair. Treat this line as a key with no val 102 | { 103 | sPrevKeyForThisSec := sTrimmedLine 104 | this[sCurSec, sPrevKeyForThisSec] := "" 105 | } 106 | } 107 | ; if there is a section with no keys and it is at the bottom of the file, then we missed it 108 | if (sCurSec != A_Blank && !this.HasKey(sCurSec)) 109 | this[sCurSec] := EasyIni_CreateBaseObj() 110 | 111 | return this 112 | } 113 | 114 | CreateIniObj(parms*) 115 | { 116 | ; Define prototype object for ini arrays: 117 | static base := {__Set: "EasyIni_Set", _NewEnum: "EasyIni_NewEnum", Remove: "EasyIni_Remove", Insert: "EasyIni_Insert", InsertBefore: "EasyIni_InsertBefore", AddSection: "EasyIni.AddSection", RenameSection: "EasyIni.RenameSection", DeleteSection: "EasyIni.DeleteSection", GetSections: "EasyIni.GetSections", FindSecs: "EasyIni.FindSecs", AddKey: "EasyIni.AddKey", RenameKey: "EasyIni.RenameKey", DeleteKey: "EasyIni.DeleteKey", GetKeys: "EasyIni.GetKeys", FindKeys: "EasyIni.FindKeys", GetVals: "EasyIni.GetVals", FindVals: "EasyIni.FindVals", HasVal: "EasyIni.HasVal", Copy: "EasyIni.Copy", Merge: "EasyIni.Merge", GetFileName: "EasyIni.GetFileName", GetOnlyIniFileName:"EasyIni.GetOnlyIniFileName", IsEmpty:"EasyIni.IsEmpty", Reload: "EasyIni.Reload", GetIsSaved: "EasyIni.GetIsSaved", Save: "EasyIni.Save", ToVar: "EasyIni.ToVar", GetValue: "EasyIni.GetValue"} 118 | ; Create and return new object: 119 | return Object("_keys", Object(), "base", base, parms*) 120 | } 121 | 122 | AddSection(sec, key="", val="", ByRef rsError="") 123 | { 124 | if (this.HasKey(sec)) 125 | { 126 | rsError := "Error! Cannot add new section [" sec "], because it already exists." 127 | return false 128 | } 129 | 130 | if (key == A_Blank) 131 | this[sec] := EasyIni_CreateBaseObj() 132 | else this[sec, key] := val 133 | 134 | return true 135 | } 136 | 137 | RenameSection(sOldSec, sNewSec, ByRef rsError="") 138 | { 139 | if (!this.HasKey(sOldSec)) 140 | { 141 | rsError := "Error! Could not rename section [" sOldSec "], because it does not exist." 142 | return false 143 | } 144 | 145 | aKeyValsCopy := this[sOldSec] 146 | this.DeleteSection(sOldSec) 147 | this[sNewSec] := aKeyValsCopy 148 | return true 149 | } 150 | 151 | DeleteSection(sec) 152 | { 153 | this.Remove(sec) 154 | return 155 | } 156 | 157 | GetSections(sDelim="`n", sSort="") 158 | { 159 | for sec in this 160 | secs .= (A_Index == 1 ? sec : sDelim sec) 161 | 162 | if (sSort) 163 | Sort, secs, D%sDelim% %sSort% 164 | 165 | return secs 166 | } 167 | 168 | FindSecs(sExp, iMaxSecs="") 169 | { 170 | aSecs := [] 171 | for sec in this 172 | { 173 | if (RegExMatch(sec, sExp)) 174 | { 175 | aSecs.Insert(sec) 176 | if (iMaxSecs&& aSecs.MaxIndex() == iMaxSecs) 177 | return aSecs 178 | } 179 | } 180 | return aSecs 181 | } 182 | 183 | AddKey(sec, key, val="", ByRef rsError="") 184 | { 185 | if (this.HasKey(sec)) 186 | { 187 | if (this[sec].HasKey(key)) 188 | { 189 | rsError := "Error! Could not add key, " key " because there is a key in the same section:`nSection: " sec "`nKey: " key 190 | return false 191 | } 192 | } 193 | else 194 | { 195 | rsError := "Error! Could not add key, " key " because Section, " sec " does not exist." 196 | return false 197 | } 198 | this[sec, key] := val 199 | return true 200 | } 201 | 202 | RenameKey(sec, OldKey, NewKey, ByRef rsError="") 203 | { 204 | if (!this[sec].HasKey(OldKey)) 205 | { 206 | rsError := "Error! The specified key " OldKey " could not be modified because it does not exist." 207 | return false 208 | } 209 | 210 | ValCopy := this[sec][OldKey] 211 | this.DeleteKey(sec, OldKey) 212 | this.AddKey(sec, NewKey) 213 | this[sec][NewKey] := ValCopy 214 | return true 215 | } 216 | 217 | DeleteKey(sec, key) 218 | { 219 | this[sec].Remove(key) 220 | return 221 | } 222 | 223 | GetKeys(sec, sDelim="`n", sSort="") 224 | { 225 | for key in this[sec] 226 | keys .= A_Index == 1 ? key : sDelim key 227 | 228 | if (sSort) 229 | Sort, keys, D%sDelim% %sSort% 230 | 231 | return keys 232 | } 233 | 234 | FindKeys(sec, sExp, iMaxKeys="") 235 | { 236 | aKeys := [] 237 | for key in this[sec] 238 | { 239 | if (RegExMatch(key, sExp)) 240 | { 241 | aKeys.Insert(key) 242 | if (iMaxKeys && aKeys.MaxIndex() == iMaxKeys) 243 | return aKeys 244 | } 245 | } 246 | return aKeys 247 | } 248 | 249 | ; Non-regex, exact match on key 250 | ; returns key(s) and their assocationed section(s) 251 | FindExactKeys(key, iMaxKeys="") 252 | { 253 | aKeys := {} 254 | for sec, aData in this 255 | { 256 | if (aData.HasKey(key)) 257 | { 258 | aKeys.Insert(sec, key) 259 | if (iMaxKeys && aKeys.MaxIndex() == iMaxKeys) 260 | return aKeys 261 | } 262 | } 263 | return aKeys 264 | } 265 | 266 | GetVals(sec, sDelim="`n", sSort="") 267 | { 268 | for key, val in this[sec] 269 | vals .= A_Index == 1 ? val : sDelim val 270 | 271 | if (sSort) 272 | Sort, vals, D%sDelim% %sSort% 273 | 274 | return vals 275 | } 276 | 277 | GetValue(sec, key) 278 | { 279 | return this[sec, key] 280 | } 281 | 282 | FindVals(sec, sExp, iMaxVals="") 283 | { 284 | aVals := [] 285 | for key, val in this[sec] 286 | { 287 | if (RegExMatch(val, sExp)) 288 | { 289 | aVals.Insert(val) 290 | if (iMaxVals && aVals.MaxIndex() == iMaxVals) 291 | break 292 | } 293 | } 294 | return aVals 295 | } 296 | 297 | HasVal(sec, FindVal) 298 | { 299 | for k, val in this[sec] 300 | if (FindVal = val) 301 | return true 302 | return false 303 | } 304 | 305 | ; SourceIni: May be EasyIni object or simply a path to an ini file. 306 | ; bCopyFileName = true: Allow copying of data without copying the file name. 307 | Copy(SourceIni, bCopyFileName = true) 308 | { 309 | ; Get ini as string. 310 | if (IsObject(SourceIni)) 311 | sIniString := SourceIni.ToVar() 312 | else FileRead, sIniString, %SourceIni% 313 | 314 | ; Effectively make this function static by allowing calls via EasyIni.Copy. 315 | if (IsObject(this)) 316 | { 317 | if (bCopyFileName) 318 | sOldFileName := this.GetFileName() 319 | this := A_Blank ; avoid any copy constructor issues. 320 | 321 | ; ObjClone doesn't work consistently. It's likely a problem with the meta-function overrides, 322 | ; but this is a nice, quick hack. 323 | this := class_EasyIni(SourceIni.GetFileName(), sIniString) 324 | 325 | ; Restore file name. 326 | this.EasyIni_ReservedFor_m_sFile := sOldFileName 327 | } 328 | else 329 | return class_EasyIni(bCopyFileName ? SourceIni.GetFileName() : "", sIniString) 330 | 331 | return this 332 | } 333 | 334 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 335 | /* 336 | Author: Verdlin 337 | STILL UNDER CONSTRUCTION. Need to handle comments, and then this will be complete. 338 | Function: Merge 339 | Purpose: Merge two EasyIni objects. 340 | Parameters 341 | vOtherIni: Other EasyIni object to merge with this. 342 | bRemoveNonMatching: If true, removes sections and keys that do not exist in both inis. 343 | bOverwriteMatching: If true, any key that exists in both objects will use the val from vOtherIni. 344 | vExceptionsIni: class_Easy ini object full of exceptions keys for secs. Any matching key will remain unchanged. 345 | */ 346 | Merge(vOtherIni, bRemoveNonMatching = false, bOverwriteMatching = false, vExceptionsIni = "") 347 | { 348 | ; TODO: Perhaps just save one ini, read it back in, and then perform merging? I think this would help with formatting. 349 | ; [Sections] 350 | for sec, aKeysAndVals in vOtherIni 351 | { 352 | if (!this.HasKey(sec)) 353 | if (bRemoveNonMatching) 354 | this.DeleteSection(sec) 355 | else this.AddSection(sec) 356 | 357 | ; key=val 358 | for key, val in aKeysAndVals 359 | { 360 | bMakeException := vExceptionsIni[sec].HasKey(key) 361 | 362 | if (this[sec].HasKey(key)) 363 | { 364 | if (bOverwriteMatching && !bMakeException) 365 | this[sec, key] := val 366 | } 367 | else 368 | { 369 | if (bRemoveNonMatching && !bMakeException) 370 | this.DeleteKey(sec, key) 371 | else if (!bRemoveNonMatching) 372 | this.AddKey(sec, key, val) 373 | } 374 | } 375 | } 376 | return 377 | } 378 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 379 | 380 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 381 | /* 382 | Author: Verdlin 383 | Function: GetFileName 384 | Purpose: Wrapper to return the extremely long named member var, EasyIni_ReservedFor_m_sFile 385 | Parameters 386 | None 387 | */ 388 | GetFileName() 389 | { 390 | return this.EasyIni_ReservedFor_m_sFile 391 | } 392 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 393 | 394 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 395 | /* 396 | Author: Verdlin 397 | Function: GetFileName 398 | Purpose: Wrapper to return just the .ini name without the path. 399 | Parameters 400 | None 401 | */ 402 | GetOnlyIniFileName() 403 | { 404 | return SubStr(this.EasyIni_ReservedFor_m_sFile, InStr(this.EasyIni_ReservedFor_m_sFile,"\", false, -1)+1) 405 | } 406 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 407 | 408 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 409 | /* 410 | Author: Verdlin 411 | Function: IsEmpty 412 | Purpose: To indicate whether or not this ini has data 413 | Parameters 414 | None 415 | */ 416 | IsEmpty() 417 | { 418 | return (this.GetSections() == A_Blank ; No sections. 419 | && !this.EasyIni_ReservedFor_TopComments.HasKey(1)) ; and no comments. 420 | } 421 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 422 | 423 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 424 | /* 425 | Author: Verdlin 426 | Function: Reload 427 | Purpose: Reloads object from ini file. This is necessary when other routines may be modifying the same ini file. 428 | Parameters 429 | None 430 | */ 431 | Reload() 432 | { 433 | if (FileExist(this.GetFileName())) 434 | this := class_EasyIni(this.GetFileName()) ; else nothing to reload. 435 | return this 436 | } 437 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 438 | 439 | ; TODO: Add option to store load and save times in comment at bottom of ini? 440 | Save(sSaveAs="", bWarnIfExist=false) 441 | { 442 | if (sSaveAs == A_Blank) 443 | sFile := this.GetFileName() 444 | else 445 | { 446 | sFile := sSaveAs 447 | 448 | ; Append ".ini" if it is not already there. 449 | if (SubStr(sFile, StrLen(sFile)-3, 4) != ".ini") 450 | sFile .= ".ini" 451 | 452 | if (bWarnIfExist && FileExist(sFile)) 453 | { 454 | MsgBox, 4,, The file "%sFile%" already exists.`n`nAre you sure that you want to overwrite it? 455 | IfMsgBox, No 456 | return false 457 | } 458 | } 459 | 460 | ; Formatting is preserved in ini object. 461 | ; FileDelete, %sFile% 462 | FileMove, %sFile%, %sFile%.EasyIni.bak 463 | 464 | bIsFirstLine := true 465 | for k, v in this.EasyIni_ReservedFor_TopComments 466 | { 467 | FileAppend, % (A_Index == 1 ? "" : "`n") (v == Chr(14) ? "" : v), %sFile% 468 | bIsFirstLine := false 469 | } 470 | 471 | for section, aKeysAndVals in this 472 | { 473 | FileAppend, % (bIsFirstLine ? "[" : "`n[") section "]", %sFile% 474 | bIsFirstLine := false 475 | 476 | bEmptySection := true 477 | for key, val in aKeysAndVals 478 | { 479 | bEmptySection := false 480 | FileAppend, `n%key%=%val%, %sFile% 481 | 482 | ; Add the comment(s) for this key 483 | sComments := this[section].EasyIni_ReservedFor_Comments[key] 484 | Loop, Parse, sComments, `n 485 | FileAppend, % "`n" (A_LoopField == Chr(14) ? "" : A_LoopField), %sFile% 486 | } 487 | if (bEmptySection) 488 | { 489 | ; An empy section may contain comments... 490 | sComments := this[section].EasyIni_ReservedFor_Comments["SectionComment"] 491 | Loop, Parse, sComments, `n 492 | FileAppend, % "`n" (A_LoopField == Chr(14) ? "" : A_LoopField), %sFile% 493 | } 494 | } 495 | 496 | FileDelete, %sFile%.EasyIni.bak 497 | return true 498 | } 499 | 500 | ToVar() 501 | { 502 | sTmpFile := "$$$EasyIni_Temp.ini" 503 | this.Save(sTmpFile, !A_IsCompiled) 504 | FileRead, sIniAsVar, %sTmpFile% 505 | FileDelete, %sTmpFile% 506 | return sIniAsVar 507 | } 508 | } 509 | 510 | ; For all of the EasyIni_* functions below, much credit is due to Lexikos and Rbrtryn for their work with ordered arrays 511 | ; See http://www.autohotkey.com/board/topic/61792-ahk-l-for-loop-in-order-of-key-value-pair-creation/?p=389662 for Lexikos's initial work with ordered arrays 512 | ; See http://www.autohotkey.com/board/topic/94043-ordered-array/#entry592333 for Rbrtryn's OrderedArray lib 513 | EasyIni_CreateBaseObj(parms*) 514 | { 515 | ; Define prototype object for ordered arrays: 516 | static base := {__Set: "EasyIni_Set", _NewEnum: "EasyIni_NewEnum", Remove: "EasyIni_Remove", Insert: "EasyIni_Insert", InsertBefore: "EasyIni_InsertBefore"} 517 | ; Create and return new base object: 518 | return Object("_keys", Object(), "base", base, parms*) 519 | } 520 | 521 | EasyIni_Set(obj, parms*) 522 | { 523 | ; If this function is called, the key must not already exist. 524 | ; Sub-class array if necessary then add this new key to the key list, if it doesn't begin with "EasyIni_ReservedFor_" 525 | if parms.maxindex() > 2 526 | ObjInsert(obj, parms[1], EasyIni_CreateBaseObj()) 527 | 528 | ; Skip over member variables 529 | if (SubStr(parms[1], 1, 20) <> "EasyIni_ReservedFor_") 530 | ObjInsert(obj._keys, parms[1]) 531 | ; Since we don't return a value, the default behaviour takes effect. 532 | ; That is, a new key-value pair is created and stored in the object. 533 | } 534 | 535 | EasyIni_NewEnum(obj) 536 | { 537 | ; Define prototype object for custom enumerator: 538 | static base := Object("Next", "EasyIni_EnumNext") 539 | ; Return an enumerator wrapping our _keys array's enumerator: 540 | return Object("obj", obj, "enum", obj._keys._NewEnum(), "base", base) 541 | } 542 | 543 | EasyIni_EnumNext(e, ByRef k, ByRef v="") 544 | { 545 | ; If Enum.Next() returns a "true" value, it has stored a key and 546 | ; value in the provided variables. In this case, "i" receives the 547 | ; current index in the _keys array and "k" receives the value at 548 | ; that index, which is a key in the original object: 549 | if r := e.enum.Next(i,k) 550 | ; We want it to appear as though the user is simply enumerating 551 | ; the key-value pairs of the original object, so store the value 552 | ; associated with this key in the second output variable: 553 | v := e.obj[k] 554 | return r 555 | } 556 | 557 | EasyIni_Remove(obj, parms*) 558 | { 559 | r := ObjRemove(obj, parms*) ; Remove keys from main object 560 | Removed := [] 561 | for k, v in obj._keys ; Get each index key pair 562 | if not ObjHasKey(obj, v) ; if key is not in main object 563 | Removed.Insert(k) ; Store that keys index to be removed later 564 | for k, v in Removed ; For each key to be removed 565 | ObjRemove(obj._keys, v, "") ; remove that key from key list 566 | 567 | return r 568 | } 569 | 570 | EasyIni_Insert(obj, parms*) 571 | { 572 | r := ObjInsert(obj, parms*) ; Insert keys into main object 573 | enum := ObjNewEnum(obj) ; Can't use for-loop because it would invoke EasyIni_NewEnum 574 | while enum[k] { ; For each key in main object 575 | for i, kv in obj._keys ; Search for key in obj._keys 576 | if (k = "_keys" || k = kv || SubStr(k, 1, 20) = "EasyIni_ReservedFor_" || SubStr(kv, 1, 20) = "EasyIni_ReservedFor_") ; If found... 577 | continue 2 ; Get next key in main object 578 | ObjInsert(obj._keys, k) ; Else insert key into obj._keys 579 | } 580 | 581 | return r 582 | } 583 | 584 | EasyIni_InsertBefore(obj, key, parms*) 585 | { 586 | OldKeys := obj._keys ; Save key list 587 | obj._keys := [] ; Clear key list 588 | for idx, k in OldKeys { ; Put the keys before key 589 | if (k = key) ; back into key list 590 | break 591 | obj._keys.Insert(k) 592 | } 593 | 594 | r := ObjInsert(obj, parms*) ; Insert keys into main object 595 | enum := ObjNewEnum(obj) ; Can't use for-loop because it would invoke EasyIni_NewEnum 596 | while enum[k] { ; For each key in main object 597 | for i, kv in OldKeys ; Search for key in OldKeys 598 | if (k = "_keys" || k = kv) ; If found... 599 | continue 2 ; Get next key in main object 600 | ObjInsert(obj._keys, k) ; Else insert key into obj._keys 601 | } 602 | 603 | for i, k in OldKeys { ; Put the keys after key 604 | if (i < idx) ; back into key list 605 | continue 606 | obj._keys.Insert(k) 607 | } 608 | 609 | return r 610 | } 611 | -------------------------------------------------------------------------------- /Lib/Eval.ahk: -------------------------------------------------------------------------------- 1 | ; https://autohotkey.com/board/topic/15675-monster-evaluate-math-expressions-in-strings/ 2 | ; 3 | ; MONSTER Version 1.2 to EVALUATE ARITHMETIC EXPRESSIONS in strings (needs AHK 1.0.48+) 4 | ; Containing HEX, Signed Binary ('11 = -1, '011 = 3), scientific numbers (1.2e+5) 5 | ; Assignments :=, preceding an expression. E.g: a:=1; b:=2; a+b 6 | ; User defined functions: f(x) := expr; 7 | ; AHK Functions Abs|Ceil|Exp|Floor|Log|Ln|Round|Sqrt|Sin|Cos|Tan|ASin|ACos|ATan 8 | ; Predefined functions: SGN|Fib|Fac (sign, Fibonacci numbers, Factorials) 9 | ; '(',')'; Variables; Predefined operators GCD,MIN,MAX,Choose (2-parameter functions) 10 | ; Predefined constants: e, pi, inch, foot, mile, ounce, pint, gallon, oz, lb; 11 | ; Logic operators: !, ||, &&; ternary operator: (_?_:_); 12 | ; Relations: =,<>; <,>,<=,>= 13 | ; Binary operators: ~; |, ^, &, <<, >> 14 | ; Arithmetic operators: +, -; *, /, \ (or % = mod); ** (or @ = power) 15 | ; Output FORMAT: $x,$h: Hex; $b{W}: W-bit binary; 16 | ; ${k}: k-digit fixpoint, ${k}e,${k}g: k-digit scientific (Default $6g) 17 | 18 | #SingleInstance Force 19 | #NoEnv 20 | SetBatchLines -1 21 | Process Priority,,High 22 | 23 | xe := 2.718281828459045, xpi := 3.141592653589793 ; referenced as "e", "pi" 24 | xinch := 2.54, xfoot := 30.48, xmile := 1.609344 ; [cm], [cm], [Km] 25 | xounce := 0.02841, xpint := 0.5682, xgallon := 4.54609 ; liters 26 | xoz := 28.35, xlb := 453.59237 ; gramms 27 | 28 | /* -test cases 29 | MsgBox % Eval("1e1") ; 10 30 | MsgBox % Eval("0x1E") ; 30 31 | MsgBox % Eval("ToBin(35)") ; 100011 32 | MsgBox % Eval("$b 35") ; 0100011 33 | MsgBox % Eval("'10010") ; -14 34 | MsgBox % Eval("2>3 ? 9 : 7") ; 7 35 | MsgBox % Eval("$2E 1e3 -50.0e+0 + 100.e-1") ; 9.60E+002 36 | MsgBox % Eval("fact(x) := x < 2 ? 1 : x*fact(x-1); fact(5)") ; 120 37 | MsgBox % Eval("f(ab):=sqrt(ab)/ab; y:=f(2); ff(y):=y*(y-1)/2/x; x := 2; y+ff(3)/f(16)") ; 6.70711 38 | MsgBox % Eval("x := qq:1; x := 5*x; y := x+1") ; 6 [if y empty, x := 1...] 39 | MsgBox % Eval("x:=-!0; x<0 ? 2*x : sqrt(x)") ; -2 40 | MsgBox % Eval("tan(atan(atan(tan(1))))-exp(sqrt(1))") ; -1.71828 41 | MsgBox % Eval("---2+++9 + ~-2 --1 -2*-3") ; 15 42 | MsgBox % Eval("x1:=1; f1:=sin(x1)/x1; y:=2; f2:=sin(y)/y; f1/f2") ; 1.85082 43 | MsgBox % Eval("Round(fac(10)/fac(5)**2) - (10 choose 5) + Fib(8)") ; 21 44 | MsgBox % Eval("1 min-1 min-2 min 2") ; -2 45 | MsgBox % Eval("(-1>>1<=9 && 3>2)<<2>>1") ; 2 46 | MsgBox % Eval("(1 = 1) + (2<>3 || 2 < 1) + (9>=-1 && 3>2)") ; 3 47 | MsgBox % Eval("$b6 -21/3") ; 111001 48 | MsgBox % Eval("$b ('1001 << 5) | '01000") ; 100101000 49 | MsgBox % Eval("$0 194*lb/1000") ; 88 [Kg] 50 | MsgBox % Eval("$x ~0xfffffff0 & 7 | 0x100 << 2") ; 0x407 51 | MsgBox % Eval("- 1 * (+pi -((3%5))) +pi+ 1-2 + e-ROUND(abs(sqrt(floor(2)))**2)-e+pi $9") ; 3.141592654 52 | MsgBox % Eval("(20+4 GCD abs(2**4)) + (9 GCD (6 CHOOSE 2))") ; 11 53 | t := A_TickCount 54 | Loop 1000 55 | r := Eval("x:=" A_Index/1000 ";atan(x)-exp(sqrt(x))") ; simulated plot 56 | t := A_TickCount - t 57 | MsgBox Result = %r%`nTime = %t% ; -1.93288: ~400 ms [on Inspiron 9300] 58 | */ 59 | 60 | ^#-:: ; Replace selection or `expression with result 61 | ^#=:: ; Append result to selection or `expression 62 | ClipBoard = 63 | SendInput ^c ; copy selection 64 | ClipWait 0.5 65 | If (ErrorLevel) { 66 | SendInput +{HOME}^c ; copy, keep selection to overwrite (^x for some apps) 67 | ClipWait 1 68 | IfEqual ErrorLevel,1, Return 69 | If RegExMatch(ClipBoard, "(.*)(``)(.*)", y) 70 | SendInput % "{RAW}" y1 . (A_ThisHotKey="^#=" ? y3 . " = " : "") . Eval(y3) 71 | } Else 72 | SendInput % "{RAW}" . (A_ThisHotKey="^#=" ? ClipBoard . " = " : "") . Eval(ClipBoard) 73 | Return 74 | 75 | Eval(x) { ; non-recursive PRE/POST PROCESSING: I/O forms, numbers, ops, ";" 76 | Local FORM, FormF, FormI, i, W, y, y1, y2, y3, y4 77 | FormI := A_FormatInteger, FormF := A_FormatFloat 78 | 79 | SetFormat Integer, D ; decimal intermediate results! 80 | RegExMatch(x, "\$(b|h|x|)(\d*[eEgG]?)", y) 81 | FORM := y1, W := y2 ; HeX, Bin, .{digits} output format 82 | SetFormat FLOAT, 0.16e ; Full intermediate float precision 83 | StringReplace x, x, %y% ; remove $.. 84 | Loop 85 | If RegExMatch(x, "i)(.*)(0x[a-f\d]*)(.*)", y) 86 | x := y1 . y2+0 . y3 ; convert hex numbers to decimal 87 | Else Break 88 | Loop 89 | If RegExMatch(x, "(.*)'([01]*)(.*)", y) 90 | x := y1 . FromBin(y2) . y3 ; convert binary numbers to decimal: sign = first bit 91 | Else Break 92 | x := RegExReplace(x,"(^|[^.\d])(\d+)(e|E)","$1$2.$3") ; add missing '.' before E (1e3 -> 1.e3) 93 | ; literal scientific numbers between ‘ and ’ chars 94 | x := RegExReplace(x,"(\d*\.\d*|\d)([eE][+-]?\d+)","‘$1$2’") 95 | 96 | StringReplace x, x,`%, \, All ; % -> \ (= MOD) 97 | StringReplace x, x, **,@, All ; ** -> @ for easier process 98 | StringReplace x, x, +, ±, All ; ± is addition 99 | x := RegExReplace(x,"(‘[^’]*)±","$1+") ; ...not inside literal numbers 100 | StringReplace x, x, -, ¬, All ; ¬ is subtraction 101 | x := RegExReplace(x,"(‘[^’]*)¬","$1-") ; ...not inside literal numbers 102 | 103 | Loop Parse, x, `; 104 | y := Eval1(A_LoopField) ; work on pre-processed sub expressions 105 | ; return result of last sub-expression (numeric) 106 | If FORM = b ; convert output to binary 107 | y := W ? ToBinW(Round(y),W) : ToBin(Round(y)) 108 | Else If (FORM="h" or FORM="x") { 109 | SetFormat Integer, Hex ; convert output to hex 110 | y := Round(y) + 0 111 | } 112 | Else { 113 | W := W="" ? "0.6g" : "0." . W ; Set output form, Default = 6 decimal places 114 | SetFormat FLOAT, %W% 115 | y += 0.0 116 | } 117 | SetFormat Integer, %FormI% ; restore original formats 118 | SetFormat FLOAT, %FormF% 119 | Return y 120 | } 121 | 122 | Eval1(x) { ; recursive PREPROCESSING of :=, vars, (..) [decimal, no ";"] 123 | Local i, y, y1, y2, y3 124 | ; save function definition: f(x) := expr 125 | If RegExMatch(x, "(\S*?)\((.*?)\)\s*:=\s*(.*)", y) { 126 | f%y1%__X := y2, f%y1%__F := y3 127 | Return 128 | } 129 | ; execute leftmost ":=" operator of a := b := ... 130 | If RegExMatch(x, "(\S*?)\s*:=\s*(.*)", y) { 131 | y := "x" . y1 ; user vars internally start with x to avoid name conflicts 132 | Return %y% := Eval1(y2) 133 | } 134 | ; here: no variable to the left of last ":=" 135 | x := RegExReplace(x,"([\)’.\w]\s+|[\)’])([a-z_A-Z]+)","$1«$2»") ; op -> «op» 136 | 137 | x := RegExReplace(x,"\s+") ; remove spaces, tabs, newlines 138 | 139 | x := RegExReplace(x,"([a-z_A-Z]\w*)\(","'$1'(") ; func( -> 'func'( to avoid atan|tan conflicts 140 | 141 | x := RegExReplace(x,"([a-z_A-Z]\w*)([^\w'»’]|$)","%x$1%$2") ; VAR -> %xVAR% 142 | x := RegExReplace(x,"(‘[^’]*)%x[eE]%","$1e") ; in numbers %xe% -> e 143 | x := RegExReplace(x,"‘|’") ; no more need for number markers 144 | Transform x, Deref, %x% ; dereference all right-hand-side %var%-s 145 | 146 | Loop { ; find last innermost (..) 147 | If RegExMatch(x, "(.*)\(([^\(\)]*)\)(.*)", y) 148 | x := y1 . Eval@(y2) . y3 ; replace (x) with value of x 149 | Else Break 150 | } 151 | Return Eval@(x) 152 | } 153 | 154 | Eval@(x) { ; EVALUATE PRE-PROCESSED EXPRESSIONS [decimal, NO space, vars, (..), ";", ":="] 155 | Local i, y, y1, y2, y3, y4 156 | 157 | If x is number ; no more operators left 158 | Return x 159 | ; execute rightmost ?,: operator 160 | RegExMatch(x, "(.*)(\?|:)(.*)", y) 161 | IfEqual y2,?, Return Eval@(y1) ? Eval@(y3) : "" 162 | IfEqual y2,:, Return ((y := Eval@(y1)) = "" ? Eval@(y3) : y) 163 | 164 | StringGetPos i, x, ||, R ; execute rightmost || operator 165 | IfGreaterOrEqual i,0, Return Eval@(SubStr(x,1,i)) || Eval@(SubStr(x,3+i)) 166 | StringGetPos i, x, &&, R ; execute rightmost && operator 167 | IfGreaterOrEqual i,0, Return Eval@(SubStr(x,1,i)) && Eval@(SubStr(x,3+i)) 168 | ; execute rightmost =, <> operator 169 | RegExMatch(x, "(.*)(?])(\<\>|=)(.*)", y) 170 | IfEqual y2,=, Return Eval@(y1) = Eval@(y3) 171 | IfEqual y2,<>, Return Eval@(y1) <> Eval@(y3) 172 | ; execute rightmost <,>,<=,>= operator 173 | RegExMatch(x, "(.*)(?])(\<=?|\>=?)(?![\<\>])(.*)", y) 174 | IfEqual y2,<, Return Eval@(y1) < Eval@(y3) 175 | IfEqual y2,>, Return Eval@(y1) > Eval@(y3) 176 | IfEqual y2,<=, Return Eval@(y1) <= Eval@(y3) 177 | IfEqual y2,>=, Return Eval@(y1) >= Eval@(y3) 178 | ; execute rightmost user operator (low precedence) 179 | RegExMatch(x, "i)(.*)«(.*?)»(.*)", y) 180 | If IsFunc(y2) 181 | Return %y2%(Eval@(y1),Eval@(y3)) ; predefined relational ops 182 | 183 | StringGetPos i, x, |, R ; execute rightmost | operator 184 | IfGreaterOrEqual i,0, Return Eval@(SubStr(x,1,i)) | Eval@(SubStr(x,2+i)) 185 | StringGetPos i, x, ^, R ; execute rightmost ^ operator 186 | IfGreaterOrEqual i,0, Return Eval@(SubStr(x,1,i)) ^ Eval@(SubStr(x,2+i)) 187 | StringGetPos i, x, &, R ; execute rightmost & operator 188 | IfGreaterOrEqual i,0, Return Eval@(SubStr(x,1,i)) & Eval@(SubStr(x,2+i)) 189 | ; execute rightmost <<, >> operator 190 | RegExMatch(x, "(.*)(\<\<|\>\>)(.*)", y) 191 | IfEqual y2,<<, Return Eval@(y1) << Eval@(y3) 192 | IfEqual y2,>>, Return Eval@(y1) >> Eval@(y3) 193 | ; execute rightmost +- (not unary) operator 194 | RegExMatch(x, "(.*[^!\~±¬\@\*/\\])(±|¬)(.*)", y) ; lower precedence ops already handled 195 | IfEqual y2,±, Return Eval@(y1) + Eval@(y3) 196 | IfEqual y2,¬, Return Eval@(y1) - Eval@(y3) 197 | ; execute rightmost */% operator 198 | RegExMatch(x, "(.*)(\*|/|\\)(.*)", y) 199 | IfEqual y2,*, Return Eval@(y1) * Eval@(y3) 200 | IfEqual y2,/, Return Eval@(y1) / Eval@(y3) 201 | IfEqual y2,\, Return Mod(Eval@(y1),Eval@(y3)) 202 | ; execute rightmost power 203 | StringGetPos i, x, @, R 204 | IfGreaterOrEqual i,0, Return Eval@(SubStr(x,1,i)) ** Eval@(SubStr(x,2+i)) 205 | ; execute rightmost function, unary operator 206 | If !RegExMatch(x,"(.*)(!|±|¬|~|'(.*)')(.*)", y) 207 | Return x ; no more function (y1 <> "" only at multiple unaries: --+-) 208 | IfEqual y2,!,Return Eval@(y1 . !y4) ; unary ! 209 | IfEqual y2,±,Return Eval@(y1 . y4) ; unary + 210 | IfEqual y2,¬,Return Eval@(y1 . -y4) ; unary - (they behave like functions) 211 | IfEqual y2,~,Return Eval@(y1 . ~y4) ; unary ~ 212 | If IsFunc(y3) 213 | Return Eval@(y1 . %y3%(y4)) ; built-in and predefined functions(y4) 214 | Return Eval@(y1 . Eval1(RegExReplace(f%y3%__F, f%y3%__X, y4))) ; LAST: user defined functions 215 | } 216 | 217 | ToBin(n) { ; Binary representation of n. 1st bit is SIGN: -8 -> 1000, -1 -> 1, 0 -> 0, 8 -> 01000 218 | if (n == "") 219 | { 220 | return 0 221 | } 222 | Return n=0||n=-1 ? -n : ToBin(n>>1) . n&1 223 | } 224 | ToBinW(n,W=8) { ; LS W-bits of Binary representation of n 225 | Loop %W% ; Recursive (slower): Return W=1 ? n&1 : ToBinW(n>>1,W-1) . n&1 226 | b := n&1 . b, n >>= 1 227 | Return b 228 | } 229 | FromBin(bits) { ; Number converted from the binary "bits" string, 1st bit is SIGN 230 | n = 0 231 | Loop Parse, bits 232 | n += n + A_LoopField 233 | Return n - (SubStr(bits,1,1)<0)-(x<0) 238 | } 239 | 240 | MIN(a,b) { 241 | Return a0 || n&1 ? b : -b 261 | } 262 | fac(n) { ; n! 263 | Return n<2 ? 1 : n*fac(n-1) 264 | } 265 | -------------------------------------------------------------------------------- /Lib/JSON.ahk: -------------------------------------------------------------------------------- 1 | /** 2 | * Lib: JSON.ahk 3 | * JSON lib for AutoHotkey. 4 | * Version: 5 | * v2.1.2 [updated 04/07/2016 (MM/DD/YYYY)] 6 | * License: 7 | * WTFPL [http://wtfpl.net/] 8 | * Requirements: 9 | * Latest version of AutoHotkey (v1.1+ or v2.0-a+) 10 | * Installation: 11 | * Use #Include JSON.ahk or copy into a function library folder and then 12 | * use #Include 13 | * Links: 14 | * GitHub: - https://github.com/cocobelgica/AutoHotkey-JSON 15 | * Forum Topic - http://goo.gl/r0zI8t 16 | * Email: - cocobelgica gmail com 17 | */ 18 | 19 | 20 | /** 21 | * Class: JSON 22 | * The JSON object contains methods for parsing JSON and converting values 23 | * to JSON. Callable - NO; Instantiable - YES; Subclassable - YES; 24 | * Nestable(via #Include) - NO. 25 | * Methods: 26 | * Load() - see relevant documentation before method definition header 27 | * Dump() - see relevant documentation before method definition header 28 | */ 29 | class JSON 30 | { 31 | /** 32 | * Method: Load 33 | * Parses a JSON string into an AHK value 34 | * Syntax: 35 | * value := JSON.Load( text [, reviver ] ) 36 | * Parameter(s): 37 | * value [retval] - parsed value 38 | * text [in, opt] - JSON formatted string 39 | * reviver [in, opt] - function object, similar to JavaScript's 40 | * JSON.parse() 'reviver' parameter 41 | */ 42 | class Load extends JSON.Functor 43 | { 44 | Call(self, text, reviver:="") 45 | { 46 | this.rev := IsObject(reviver) ? reviver : false 47 | ; Object keys(and array indices) are temporarily stored in arrays so that 48 | ; we can enumerate them in the order they appear in the document/text instead 49 | ; of alphabetically. Skip if no reviver function is specified. 50 | this.keys := this.rev ? {} : false 51 | 52 | static q := Chr(34) 53 | , json_value := q . "{[01234567890-tfn" 54 | , json_value_or_array_closing := q . "{[]01234567890-tfn" 55 | , object_key_or_object_closing := q . "}" 56 | 57 | key := "" 58 | is_key := false 59 | root := {} 60 | stack := [root] 61 | next := json_value 62 | pos := 0 63 | 64 | while ((ch := SubStr(text, ++pos, 1)) != "") { 65 | if InStr(" `t`r`n", ch) 66 | continue 67 | if !InStr(next, ch, 1) 68 | this.ParseError(next, text, pos) 69 | 70 | holder := stack[1] 71 | is_array := holder.IsArray 72 | 73 | if InStr(",:", ch) { 74 | next := (is_key := !is_array && ch == ",") ? q : json_value 75 | 76 | } else if InStr("}]", ch) { 77 | ObjRemoveAt(stack, 1) 78 | next := stack[1]==root ? "" : stack[1].IsArray ? ",]" : ",}" 79 | 80 | } else { 81 | if InStr("{[", ch) { 82 | ; Check if Array() is overridden and if its return value has 83 | ; the 'IsArray' property. If so, Array() will be called normally, 84 | ; otherwise, use a custom base object for arrays 85 | static json_array := Func("Array").IsBuiltIn || ![].IsArray ? {IsArray: true} : 0 86 | 87 | ; sacrifice readability for minor(actually negligible) performance gain 88 | (ch == "{") 89 | ? ( is_key := true 90 | , value := {} 91 | , next := object_key_or_object_closing ) 92 | ; ch == "[" 93 | : ( value := json_array ? new json_array : [] 94 | , next := json_value_or_array_closing ) 95 | 96 | ObjInsertAt(stack, 1, value) 97 | 98 | if (this.keys) 99 | this.keys[value] := [] 100 | 101 | } else { 102 | if (ch == q) { 103 | i := pos 104 | while (i := InStr(text, q,, i+1)) { 105 | value := StrReplace(SubStr(text, pos+1, i-pos-1), "\\", "\u005c") 106 | 107 | static ss_end := A_AhkVersion<"2" ? 0 : -1 108 | if (SubStr(value, ss_end) != "\") 109 | break 110 | } 111 | 112 | if (!i) 113 | this.ParseError("'", text, pos) 114 | 115 | value := StrReplace(value, "\/", "/") 116 | , value := StrReplace(value, "\" . q, q) 117 | , value := StrReplace(value, "\b", "`b") 118 | , value := StrReplace(value, "\f", "`f") 119 | , value := StrReplace(value, "\n", "`n") 120 | , value := StrReplace(value, "\r", "`r") 121 | , value := StrReplace(value, "\t", "`t") 122 | 123 | pos := i ; update pos 124 | 125 | i := 0 126 | while (i := InStr(value, "\",, i+1)) { 127 | if !(SubStr(value, i+1, 1) == "u") 128 | this.ParseError("\", text, pos - StrLen(SubStr(value, i+1))) 129 | 130 | uffff := Abs("0x" . SubStr(value, i+2, 4)) 131 | if (A_IsUnicode || uffff < 0x100) 132 | value := SubStr(value, 1, i-1) . Chr(uffff) . SubStr(value, i+6) 133 | } 134 | 135 | if (is_key) { 136 | key := value, next := ":" 137 | continue 138 | } 139 | 140 | } else { 141 | value := SubStr(text, pos, i := RegExMatch(text, "[\]\},\s]|$",, pos)-pos) 142 | 143 | static number := "number", integer :="integer" 144 | if value is %number% 145 | { 146 | if value is %integer% 147 | value += 0 148 | } 149 | else if (value == "true" || value == "false") 150 | value := %value% + 0 151 | else if (value == "null") 152 | value := "" 153 | else 154 | ; we can do more here to pinpoint the actual culprit 155 | ; but that's just too much extra work. 156 | this.ParseError(next, text, pos, i) 157 | 158 | pos += i-1 159 | } 160 | 161 | next := holder==root ? "" : is_array ? ",]" : ",}" 162 | } ; If InStr("{[", ch) { ... } else 163 | 164 | is_array? key := ObjPush(holder, value) : holder[key] := value 165 | 166 | if (this.keys && this.keys.HasKey(holder)) 167 | this.keys[holder].Push(key) 168 | } 169 | 170 | } ; while ( ... ) 171 | 172 | return this.rev ? this.Walk(root, "") : root[""] 173 | } 174 | 175 | ParseError(expect, text, pos, len:=1) 176 | { 177 | static q := Chr(34) 178 | 179 | line := StrSplit(SubStr(text, 1, pos), "`n", "`r").Length() 180 | col := pos - InStr(text, "`n",, -(StrLen(text)-pos+1)) 181 | msg := Format("{1}`n`nLine:`t{2}`nCol:`t{3}`nChar:`t{4}" 182 | , (expect == "") ? "Extra data" 183 | : (expect == "'") ? "Unterminated string starting at" 184 | : (expect == "\") ? "Invalid \escape" 185 | : (expect == ":") ? "Expecting ':' delimiter" 186 | : (expect == q) ? "Expecting object key enclosed in double quotes" 187 | : (expect == q . "}") ? "Expecting object key enclosed in double quotes or object closing '}'" 188 | : (expect == ",}") ? "Expecting ',' delimiter or object closing '}'" 189 | : (expect == ",]") ? "Expecting ',' delimiter or array closing ']'" 190 | : InStr(expect, "]") ? "Expecting JSON value or array closing ']'" 191 | : "Expecting JSON value(string, number, true, false, null, object or array)" 192 | , line, col, pos) 193 | 194 | static offset := A_AhkVersion<"2" ? -3 : -4 195 | throw Exception(msg, offset, SubStr(text, pos, len)) 196 | } 197 | 198 | Walk(holder, key) 199 | { 200 | value := holder[key] 201 | if IsObject(value) { 202 | for i, k in this.keys[value] { 203 | ; check if ObjHasKey(value, k) ?? 204 | v := this.Walk.Call(this, value, k) ; bypass __Call 205 | if (v != JSON.Undefined) 206 | value[k] := v 207 | else 208 | ObjDelete(value, k) 209 | } 210 | } 211 | 212 | return this.rev.Call(holder, key, value) 213 | } 214 | } 215 | 216 | /** 217 | * Method: Dump 218 | * Converts an AHK value into a JSON string 219 | * Syntax: 220 | * str := JSON.Dump( value [, replacer, space ] ) 221 | * Parameter(s): 222 | * str [retval] - JSON representation of an AHK value 223 | * value [in] - any value(object, string, number) 224 | * replacer [in, opt] - function object, similar to JavaScript's 225 | * JSON.stringify() 'replacer' parameter 226 | * space [in, opt] - similar to JavaScript's JSON.stringify() 227 | * 'space' parameter 228 | */ 229 | class Dump extends JSON.Functor 230 | { 231 | Call(self, value, replacer:="", space:="") 232 | { 233 | this.rep := IsObject(replacer) ? replacer : "" 234 | 235 | this.gap := "" 236 | if (space) { 237 | static integer := "integer" 238 | if space is %integer% 239 | Loop, % ((n := Abs(space))>10 ? 10 : n) 240 | this.gap .= " " 241 | else 242 | this.gap := SubStr(space, 1, 10) 243 | 244 | this.indent := "`n" 245 | } 246 | 247 | return this.Str({"": value}, "") 248 | } 249 | 250 | Str(holder, key) 251 | { 252 | value := holder[key] 253 | 254 | if (this.rep) 255 | value := this.rep.Call(holder, key, ObjHasKey(holder, key) ? value : JSON.Undefined) 256 | 257 | if IsObject(value) { 258 | ; Check object type, skip serialization for other object types such as 259 | ; ComObject, Func, BoundFunc, FileObject, RegExMatchObject, Property, etc. 260 | static type := A_AhkVersion<"2" ? "" : Func("Type") 261 | if (type ? type.Call(value) == "Object" : ObjGetCapacity(value) != "") { 262 | if (this.gap) { 263 | stepback := this.indent 264 | this.indent .= this.gap 265 | } 266 | 267 | is_array := value.IsArray 268 | ; Array() is not overridden, rollback to old method of 269 | ; identifying array-like objects. Due to the use of a for-loop 270 | ; sparse arrays such as '[1,,3]' are detected as objects({}). 271 | if (!is_array) { 272 | for i in value 273 | is_array := i == A_Index 274 | until !is_array 275 | } 276 | 277 | str := "" 278 | if (is_array) { 279 | Loop, % value.Length() { 280 | if (this.gap) 281 | str .= this.indent 282 | 283 | v := this.Str(value, A_Index) 284 | str .= (v != "") ? v . "," : "null," 285 | } 286 | } else { 287 | colon := this.gap ? ": " : ":" 288 | for k in value { 289 | v := this.Str(value, k) 290 | if (v != "") { 291 | if (this.gap) 292 | str .= this.indent 293 | 294 | str .= this.Quote(k) . colon . v . "," 295 | } 296 | } 297 | } 298 | 299 | if (str != "") { 300 | str := RTrim(str, ",") 301 | if (this.gap) 302 | str .= stepback 303 | } 304 | 305 | if (this.gap) 306 | this.indent := stepback 307 | 308 | return is_array ? "[" . str . "]" : "{" . str . "}" 309 | } 310 | 311 | } else ; is_number ? value : "value" 312 | return ObjGetCapacity([value], 1)=="" ? value : this.Quote(value) 313 | } 314 | 315 | Quote(string) 316 | { 317 | static q := Chr(34) 318 | 319 | if (string != "") { 320 | string := StrReplace(string, "\", "\\") 321 | ; , string := StrReplace(string, "/", "\/") ; optional in ECMAScript 322 | , string := StrReplace(string, q, "\" . q) 323 | , string := StrReplace(string, "`b", "\b") 324 | , string := StrReplace(string, "`f", "\f") 325 | , string := StrReplace(string, "`n", "\n") 326 | , string := StrReplace(string, "`r", "\r") 327 | , string := StrReplace(string, "`t", "\t") 328 | 329 | static rx_escapable := A_AhkVersion<"2" ? "O)[^\x20-\x7e]" : "[^\x20-\x7e]" 330 | while RegExMatch(string, rx_escapable, m) 331 | string := StrReplace(string, m.Value, Format("\u{1:04x}", Ord(m.Value))) 332 | } 333 | 334 | return q . string . q 335 | } 336 | } 337 | 338 | /** 339 | * Property: Undefined 340 | * Proxy for 'undefined' type 341 | * Syntax: 342 | * undefined := JSON.Undefined 343 | * Remarks: 344 | * For use with reviver and replacer functions since AutoHotkey does not 345 | * have an 'undefined' type. Returning blank("") or 0 won't work since these 346 | * can't be distnguished from actual JSON values. This leaves us with objects. 347 | * Replacer() - the caller may return a non-serializable AHK objects such as 348 | * ComObject, Func, BoundFunc, FileObject, RegExMatchObject, and Property to 349 | * mimic the behavior of returning 'undefined' in JavaScript but for the sake 350 | * of code readability and convenience, it's better to do 'return JSON.Undefined'. 351 | * Internally, the property returns a ComObject with the variant type of VT_EMPTY. 352 | */ 353 | Undefined[] 354 | { 355 | get { 356 | static empty := {}, vt_empty := ComObject(0, &empty, 1) 357 | return vt_empty 358 | } 359 | } 360 | 361 | class Functor 362 | { 363 | __Call(method, args*) 364 | { 365 | ; When casting to Call(), use a new instance of the "function object" 366 | ; so as to avoid directly storing the properties(used across sub-methods) 367 | ; into the "function object" itself. 368 | if IsObject(method) 369 | return (new this).Call(method, args*) 370 | else if (method == "") 371 | return (new this).Call(args*) 372 | } 373 | } 374 | } -------------------------------------------------------------------------------- /Lib/Kanji/Kanji.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goreliu/runz/27453eb51f96ad22b8c0e5e4e6adc140eb4f1488/Lib/Kanji/Kanji.txt -------------------------------------------------------------------------------- /Lib/Logger.ahk: -------------------------------------------------------------------------------- 1 | ; log := new Logger("test.log") 2 | ; log.Debug("test") 3 | 4 | class Logger 5 | { 6 | __New(filename) 7 | { 8 | this.filename := filename 9 | } 10 | 11 | Debug(msg) 12 | { 13 | FileAppend, % A_Now . " " . msg . "`n", % this.filename 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Lib/TCMatch.ahk: -------------------------------------------------------------------------------- 1 | global g_TCMatchModule 2 | 3 | TCMatchOn(dllPath = "") 4 | { 5 | static TCMatchDllPath 6 | if (g_TCMatchModule != "") 7 | { 8 | return g_TCMatchModule 9 | } 10 | 11 | if (dllPath == "" && TCMatchDllPath == "") 12 | { 13 | return 0 14 | } 15 | else if (dllPath != "") 16 | { 17 | if (!FileExist(dllPath)) 18 | { 19 | return 0 20 | } 21 | else 22 | { 23 | TCMatchDllPath := dllPath 24 | } 25 | } 26 | 27 | g_TCMatchModule := DllCall("LoadLibrary", "Str", TCMatchDllPath, "Ptr") 28 | return g_TCMatchModule 29 | } 30 | 31 | TCMatchOff() 32 | { 33 | DllCall("FreeLibrary", "Ptr", g_TCMatchModule) 34 | g_TCMatchModule := "" 35 | } 36 | 37 | TCMatch(aHaystack, aNeedle) 38 | { 39 | if (A_PtrSize == 8) 40 | { 41 | return DllCall("TCMatch64\MatchFileW", "WStr", aNeedle, "WStr", aHaystack) 42 | } 43 | 44 | return DllCall("TCMatch\MatchFileW", "WStr", aNeedle, "WStr", aHaystack) 45 | } 46 | -------------------------------------------------------------------------------- /Lib/TCMatch/tcmatch.ini: -------------------------------------------------------------------------------- 1 | [general] 2 | simple_search_activate_char= 3 | regex_search_activate_char=? 4 | leven_search_activate_char=< 5 | srch_activate_char=* 6 | preset_activate_char=> 7 | simple_search_match_beginning_activate_char=^ 8 | and_separator_char=& 9 | or_separator_char=| 10 | wdx_separator_char=/ 11 | negate_char=! 12 | case_sensitive=0 13 | allow_empty_result=1 14 | filter_files_and_folders=3 15 | match_beginning=0 16 | use_pinyin=1 17 | use_korean=0 18 | [gui] 19 | override_search=1 20 | invert_result=0 21 | [wdx] 22 | debug_output=0 23 | wdx_cache=1000 24 | -------------------------------------------------------------------------------- /Plugins/Core.ahk: -------------------------------------------------------------------------------- 1 | ; RunZ:Core 2 | ; 核心功能 3 | 4 | Core: 5 | @("Help", "帮助信息") 6 | @("KeyHelp", "置顶的按键帮助信息") 7 | @("AhkRun", "使用 Ahk 的 Run() 运行 `; command") 8 | @("CmdRun", "使用 cmd 运行 : command") 9 | @("CmdRunOnly", "只使用 cmd 运行") 10 | @("WinRRun", "使用 win + r 运行") 11 | @("RunAndDisplay", "使用 cmd 运行,并显示结果") 12 | @("ReindexFiles", "重新索引待搜索文件") 13 | @("EditConfig", "编辑配置文件") 14 | @("RunClipboard", "使用 ahk 的 Run 运行剪切板内容") 15 | @("CleanupRank", "清理命令权重中的无效命令") 16 | @("ShowArg", "显示参数:ShowArg arg1 arg2 ...") 17 | @("AhkTest", "运行参数或者剪切板中的 AHK 代码") 18 | @("InstallPlugin", "安装插件") 19 | @("RemovePlugin", "卸载插件") 20 | @("ListPlugin", "列出插件") 21 | @("CleanupPlugin", "清理插件") 22 | @("CountNumber", "计算数量 wc") 23 | @("Open", "打开") 24 | return 25 | 26 | CmdRun: 27 | RunWithCmd(Arg) 28 | return 29 | 30 | CmdRunOnly: 31 | RunWithCmd(Arg, true) 32 | return 33 | 34 | AhkRun: 35 | if (!g_Conf.Config.DebugMode) 36 | { 37 | try 38 | { 39 | Run, %Arg% 40 | } 41 | catch e 42 | { 43 | MsgBox, 运行命令 %Arg% 失败`n设置配置文件中 DebugMode 为 1 可查看错误详情 44 | } 45 | } 46 | else 47 | { 48 | Run, %Arg% 49 | } 50 | return 51 | 52 | ShowArg: 53 | args := StrSplit(Arg, " ") 54 | result := "共有 " . args.Length() . " 个参数。`n`n" 55 | 56 | for index, argument in args 57 | { 58 | result .= "第 " . index . " 个参数:" . argument . "`n" 59 | } 60 | 61 | DisplayResult(result) 62 | return 63 | 64 | RunClipboard: 65 | Run, %clipboard% 66 | return 67 | 68 | RunAndDisplay: 69 | DisplayResult(RunAndGetOutput(Arg)) 70 | return 71 | 72 | WinRRun: 73 | Send, #r 74 | Sleep, 100 75 | Send, %Arg% 76 | Send, {enter} 77 | return 78 | 79 | AhkTest: 80 | text := Arg == "" ? clipboard : Arg 81 | FileDelete, %A_Temp%\RunZ.AhkTest.ahk 82 | FileAppend, %text%, %A_Temp%\RunZ.AhkTest.ahk 83 | Run, %A_Temp%\RunZ.AhkTest.ahk 84 | return 85 | 86 | InstallPlugin: 87 | pluginPath := Arg 88 | 89 | if (InStr(pluginPath, "http") == 1) 90 | { 91 | DisplayResult("下载中,请稍后...") 92 | UrlDownloadToFile, %pluginPath%, %A_Temp%\RunZ.Plugin.txt 93 | pluginPath := A_Temp "\RunZ.Plugin.txt" 94 | } 95 | 96 | if (FileExist(pluginPath)) 97 | { 98 | FileReadLine, firstLine, %pluginPath%, 1 99 | if (!InStr(firstLine, "; RunZ:")) 100 | { 101 | DisplayResult(pluginPath " 并不是有效的 RunZ 插件") 102 | return 103 | } 104 | 105 | pluginName := StrSplit(firstLine, "; RunZ:")[2] 106 | if (FileExist(A_ScriptDir "\Plugins\" pluginName ".ahk")) 107 | { 108 | DisplayResult("该插件已存在") 109 | return 110 | } 111 | 112 | FileMove, %pluginPath%, %A_ScriptDir%\Plugins\%pluginName%.ahk 113 | FileAppend, #include *i `%A_ScriptDir`%\Plugins\%pluginName%.ahk`n 114 | , %A_ScriptDir%\Core\Plugins.ahk 115 | 116 | DisplayResult(pluginName " 插件安装成功,RunZ 将重启并启用该插件") 117 | Sleep, 1000 118 | GoSub, RestartRunZ 119 | } 120 | else 121 | { 122 | DisplayResult(pluginPath " 文件不存在") 123 | } 124 | return 125 | 126 | RemovePlugin: 127 | pluginName := Arg 128 | if (!FileExist(A_ScriptDir "\Plugins\" pluginName ".ahk")) 129 | { 130 | DisplayResult("未安装该插件") 131 | return 132 | } 133 | 134 | FileRead, currentPlugins, %A_ScriptDir%\Core\Plugins.ahk 135 | StringReplace, currentPlugins, currentPlugins 136 | , #include *i `%A_ScriptDir`%\Plugins\%pluginName%.ahk`r`n 137 | FileDelete, %A_ScriptDir%\Core\Plugins.ahk 138 | FileAppend, %currentPlugins%, %A_ScriptDir%\Core\Plugins.ahk 139 | FileDelete, %A_ScriptDir%\Plugins\%pluginName%.ahk 140 | 141 | DisplayResult(pluginName " 插件删除成功,RunZ 将重启以生效") 142 | Sleep, 1000 143 | GoSub, RestartRunZ 144 | return 145 | 146 | ListPlugin: 147 | result := "" 148 | Loop, Files, %A_ScriptDir%\Plugins\*.ahk 149 | { 150 | pluginName := StrReplace(A_LoopFileName, ".ahk") 151 | FileReadLine, secondLine, %A_LoopFileLongPath%, 2 152 | if (g_Conf.GetValue("Plugins", pluginName) == 0) 153 | { 154 | result .= "* | 插件 | " pluginName " | 已禁用 描述:" SubStr(secondLine, 3) "`n" 155 | } 156 | else 157 | { 158 | result .= "* | 插件 | " pluginName " | 已启用 描述:" SubStr(secondLine, 3) "`n" 159 | } 160 | } 161 | 162 | DisplayResult(AlignText(result)) 163 | TurnOnResultFilter() 164 | SetCommandFilter("RemovePlugin") 165 | return 166 | 167 | CleanupPlugin: 168 | result := "" 169 | FileRead, currentPlugins, %A_ScriptDir%\Core\Plugins.ahk 170 | Loop, Parse, currentPlugins, `n, `r 171 | { 172 | SplitPath, A_LoopField , , , , pluginName, 173 | if (g_Conf.GetValue("Plugins", pluginName) == 0) 174 | { 175 | result .= pluginName " 插件已被清理,下次运行 RunZ 将不再引入`n" 176 | StringReplace, currentPlugins, currentPlugins 177 | , #include *i `%A_ScriptDir`%\Plugins\%pluginName%.ahk`r`n 178 | } 179 | } 180 | 181 | if (result != "") 182 | { 183 | DisplayResult(result) 184 | FileDelete, %A_ScriptDir%\Core\Plugins.ahk 185 | FileAppend, %currentPlugins%, %A_ScriptDir%\Core\Plugins.ahk 186 | } 187 | else 188 | { 189 | DisplayResult("无可清理插件") 190 | } 191 | return 192 | 193 | CountNumber: 194 | result := "* | 数量 | " StrSplit(Arg, " ").Length() " | 以空格为分隔符`n" 195 | if (SubStr(FullPipeArg, 0, -1) = "`n") 196 | { 197 | result .= "* | 数量 | " StrSplit(FullPipeArg, "`n").Length() - 1 " | 以换行为分隔符`n" 198 | } 199 | else 200 | { 201 | result .= "* | 数量 | " StrSplit(FullPipeArg, "`n").Length() " | 以换行为分隔符`n" 202 | } 203 | 204 | DisplayResult(AlignText(result)) 205 | return 206 | 207 | Open: 208 | Run, % StrSplit(FullPipeArg, "`r")[1] 209 | return 210 | -------------------------------------------------------------------------------- /Plugins/Demo.ahk: -------------------------------------------------------------------------------- 1 | ; RunZ:Demo 2 | ; 插件示例 3 | ; 4 | ; 第一行为固定格式 ; RunZ:插件名 5 | ; 插件名需要和文件名一致 6 | ; 第二行为固定格式 ; 插件描述 7 | ; 插件需要使用 UTF-8 BOM 编码 8 | ; 9 | ; 该插件默认不启用,在配置文件可启用该插件 10 | 11 | ; 该标签名要和首行的插件名一致 12 | Demo: 13 | ; 第一个参数为标签名 14 | ; 第二个为搜索项,即该功能的表述,内容随意 15 | ; 第三个参数为 true 时,当搜索无结果也会显示,默认为 false 16 | ; 第四个参数为绑定的全局热键,默认无 17 | @("Demo1", "插件实例1") 18 | @("Demo2", "插件实例2") 19 | @("Demo3", "插件实例3") 20 | return 21 | 22 | 23 | ; 和 @ 函数的第一个参数对应 24 | Demo1: 25 | ; 在指定目录启动软件 26 | Run, notepad, c: 27 | return 28 | 29 | Demo2: 30 | ; DisplayResult(text) 内置函数用来在列表框展示文本 31 | DisplayResult("我是插件") 32 | return 33 | 34 | Demo3: 35 | ; Arg 为用户输入的参数 36 | DisplayResult("我的参数:" Arg) 37 | return 38 | -------------------------------------------------------------------------------- /Plugins/Kanji.ahk: -------------------------------------------------------------------------------- 1 | ; RunZ:Kanji 2 | ; 简体繁体互相转换 3 | 4 | Kanji: 5 | @("T2S", "将剪切板或输入内容中的繁体转成简体") 6 | @("S2T", "将剪切板或输入内容中的简体转成繁体") 7 | return 8 | 9 | T2S: 10 | text := Arg == "" ? clipboard : Arg 11 | clipboard := "" 12 | clipboard := Kanji_t2s(text) 13 | ClipWait 14 | DisplayResult(clipboard) 15 | return 16 | 17 | S2T: 18 | text := Arg == "" ? clipboard : Arg 19 | clipboard := "" 20 | clipboard := Kanji_s2t(text) 21 | ClipWait 22 | DisplayResult(clipboard) 23 | return 24 | 25 | Kanji_s2t(text) 26 | { 27 | return Kanji(text, 1) 28 | } 29 | 30 | Kanji_t2s(text) 31 | { 32 | return Kanji(text) 33 | } 34 | 35 | ; https://autohotkey.com/boards/viewtopic.php?t=9133 36 | Kanji(s, r := "") 37 | { 38 | ; r = 1-简繁 ""-繁简 39 | static f := __Kanji() 40 | n := r ? f.1 : f.2 41 | Loop, Parse, s 42 | b .= n[A_Loopfield] ? n[A_Loopfield] : A_Loopfield 43 | Return b 44 | } 45 | 46 | __Kanji() 47 | { 48 | FileRead, s, % A_ScriptDir "\lib\Kanji\Kanji.txt" 49 | f := [], h := [], s := Trim(s) 50 | Loop, Parse, s, % A_Space 51 | f[a := SubStr(A_Loopfield, 1, 1)] := b := SubStr(A_Loopfield, 2), h[b] := a 52 | return [f, h] 53 | } 54 | -------------------------------------------------------------------------------- /Plugins/Misc.ahk: -------------------------------------------------------------------------------- 1 | ; RunZ:Misc 2 | ; 实用工具集合 3 | 4 | Misc: 5 | @("Dictionary", "有道词典在线翻译") 6 | @("Calc", "计算器") 7 | @("SearchOnBaidu", "使用 百度 搜索剪切板或输入内容") 8 | @("SearchOnGoogle", "使用 谷歌 搜索剪切板或输入内容") 9 | @("SearchOnBing", "使用 必应 搜索剪切板或输入内容") 10 | @("SearchOnTaobao", "使用 淘宝 搜索剪切板或输入内容") 11 | @("SearchOnJD", "使用 京东 搜索剪切板或输入内容") 12 | @("ShowIp", "显示 IP") 13 | @("Calendar", "用浏览器打开万年历") 14 | ; @("CurrencyRate", "汇率 使用示例: hl JPY EUR 2") 15 | ; @("CNY2USD", "汇率 人民币兑换美元") 16 | ; k@("USD2CNY", "汇率 美元兑换人民币") 17 | @("UrlEncode", "URL 编码") 18 | return 19 | 20 | /* 21 | CNY2USD: 22 | DisplayResult("查询中,可能会比较慢或者查询失败,请稍后...") 23 | DisplayResult(QueryCurrencyRate("CNY", "USD", Arg)) 24 | return 25 | 26 | USD2CNY: 27 | DisplayResult("查询中,可能会比较慢或者查询失败,请稍后...") 28 | DisplayResult(QueryCurrencyRate("USD", "CNY", Arg)) 29 | return 30 | 31 | CurrencyRate: 32 | args := StrSplit(Arg, " ") 33 | if (args.Length() != 3) 34 | { 35 | DisplayResult("使用示例:`n CurrencyRate USD CNY 2") 36 | return 37 | } 38 | 39 | DisplayResult("查询中,可能会比较慢或者查询失败,请稍后...") 40 | DisplayResult(QueryCurrencyRate(args[1], args[2], args[3])) 41 | return 42 | 43 | QueryCurrencyRate(fromCurrency, toCurrency, amount) 44 | { 45 | headers := Object() 46 | headers["apikey"] := "c9098c96599be340bbd9551e2b061f63" 47 | 48 | jsonText := UrlDownloadToString("http://apis.baidu.com/apistore/currencyservice/currency?" 49 | . "fromCurrency=" fromCurrency "&toCurrency=" toCurrency "&amount=" amount, headers) 50 | parsed := JSON.Load(jsonText) 51 | 52 | if (parsed.errNum != 0 && parsed.errMsg != "success") 53 | { 54 | return "查询失败,错误信息:`n`n" jsonText 55 | } 56 | 57 | result := fromCurrency " 兑换 " toCurrency " 当前汇率:`n`n" parsed.retData.currency "`n`n`n" 58 | result .= amount " " fromCurrency " = " parsed.retData.convertedamount " " toCurrency "`n" 59 | 60 | return result 61 | } 62 | */ 63 | 64 | ShowIp: 65 | DisplayResult(A_IPAddress1 66 | . "`r`n" . A_IPAddress2 67 | . "`r`n" . A_IPAddress3 68 | . "`r`n" . A_IPAddress4) 69 | return 70 | 71 | /* 72 | Dictionary: 73 | word := Arg == "" ? clipboard : Arg 74 | 75 | EncodeDecodeURI(str, encode := true, component := true) { 76 | static Doc, JS 77 | if !Doc { 78 | Doc := ComObjCreate("htmlfile") 79 | Doc.write("") 80 | JS := Doc.parentWindow 81 | ( Doc.documentMode < 9 && JS.execScript() ) 82 | } 83 | Return JS[ (encode ? "en" : "de") . "codeURI" . (component ? "Component" : "") ](str) 84 | } 85 | 86 | BingFanyi(word){ 87 | url := "https://cn.bing.com/dict/search?q=" . EncodeDecodeURI(word) 88 | 89 | httpRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1") 90 | httpRequest.Open("GET", url) 91 | httpRequest.Send() 92 | 93 | responseBody := httpRequest.ResponseText 94 | 95 | ; return BingExtract(SubStr(responseBody, 1, 2000)) 96 | 97 | html := ComObjCreate("HTMLFile") 98 | html.write(responseBody) 99 | 100 | div := html.getElementsByTagName("div") 101 | 102 | ;翻译 103 | result .= div[14].innerText 104 | return result 105 | } 106 | 107 | YouDaoFanyi(word){ 108 | url := "https://www.youdao.com/result?lang=en&word=" . EncodeDecodeURI(word) 109 | httpRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1") 110 | httpRequest.Open("GET", url) 111 | httpRequest.Send() 112 | 113 | HtmlText := httpRequest.ResponseText 114 | 115 | html := ComObjCreate("HTMLFile") 116 | html.write(SubStr(HtmlText, 30000)) 117 | 118 | ul := html.getElementsByTagName("ul") 119 | span := html.getElementsByTagName("span") 120 | 121 | result := "" 122 | ;音标 123 | result .= span[17].innerText . " " . span[18].innerText . " " . span[19].innerText . " " . span[20].innerText . "`n" 124 | ;翻译 125 | result .= ul[5].innerText . "`n" 126 | ;语法 127 | ; result .= html.getElementsByTagName("ul")[6].innerText . " " 128 | ; network 129 | result .= ul[8].innerText . "`n" 130 | ; phrase 131 | result .= ul[9].innerText . "`n" 132 | result .= ul[11].innerText . "`n" 133 | result .= ul[13].innerText . "`n" 134 | return result 135 | } 136 | 137 | ; result := BingFanyi(word) 138 | result := YouDaoFanyi(word) 139 | DisplayResult(result) 140 | clipboard := result 141 | return 142 | */ 143 | 144 | Calendar: 145 | Run % "http://www.baidu.com/baidu?wd=%CD%F2%C4%EA%C0%FA" 146 | return 147 | 148 | SearchOnBaidu: 149 | word := Arg == "" ? clipboard : Arg 150 | 151 | Run, https://www.baidu.com/s?wd=%word% 152 | return 153 | 154 | SearchOnGoogle: 155 | word := UrlEncode(Arg == "" ? clipboard : Arg) 156 | 157 | Run, https://www.google.com.hk/#newwindow=1&safe=strict&q=%word% 158 | return 159 | 160 | SearchOnBing: 161 | word := Arg == "" ? clipboard : Arg 162 | 163 | Run, http://cn.bing.com/search?q=%word% 164 | return 165 | 166 | SearchOnTaobao: 167 | word := Arg == "" ? clipboard : Arg 168 | 169 | Run, https://s.taobao.com/search?q=%word% 170 | return 171 | 172 | SearchOnJD: 173 | word := Arg == "" ? clipboard : Arg 174 | 175 | Run, http://search.jd.com/Search?keyword=%word%&enc=utf-8 176 | return 177 | 178 | Calc: 179 | result := Eval(Arg) 180 | DisplayResult(result) 181 | clipboard := result 182 | TurnOnRealtimeExec() 183 | return 184 | 185 | UrlEncode: 186 | text := Arg == "" ? clipboard : Arg 187 | clipboard := UrlEncode(text) 188 | DisplayResult(clipboard) 189 | return 190 | 191 | 192 | #include %A_ScriptDir%\Lib\Eval.ahk 193 | #include %A_ScriptDir%\Lib\JSON.ahk 194 | -------------------------------------------------------------------------------- /Plugins/QRCode.ahk: -------------------------------------------------------------------------------- 1 | ; RunZ:QRCode 2 | ; 生成二维码 3 | 4 | QRCode: 5 | if (!FileExist(A_ScriptDir "\Lib\Reserved\quricol" A_PtrSize * 8 ".dll")) 6 | { 7 | return 8 | } 9 | 10 | @("GenerateQR", "生成二维码") 11 | return 12 | 13 | GenerateQR: 14 | word := Arg == "" ? clipboard : Arg 15 | if (word == "") 16 | { 17 | DisplayResult(AlignText("* | 错误 | 剪切板内无文本数据")) 18 | return 19 | } 20 | 21 | DisplayResult(AlignText("* | 内容 | 二维码内容长度 | " StrLen(word) "`n" 22 | . "* | 内容 | 二维码内容 | 见下方`n`n" word)) 23 | 24 | QRfile := GenerateQR(SubStr(word, 1, 1000)) 25 | 26 | /* 27 | 少占用 300 - 400 K 内存,先不引入 Gdip.ahk 28 | GdipToken := Gdip_Startup() 29 | 30 | bitmap := Gdip_CreateBitmapFromFile(QRfile) 31 | imageWidth := Gdip_GetImageWidth(bitmap) 32 | Gdip_DisposeImage(bitmap) 33 | Gdip_Shutdown(GdipToken) 34 | 35 | windowWidth := imageWidth 36 | 37 | if (windowWidth >= 300) 38 | { 39 | windowWidth := 300 40 | } 41 | */ 42 | 43 | windowWidth := 300 44 | 45 | Gui, QR:Destroy 46 | Gui, QR:Add, Picture, x0 y0 w%windowWidth% h-1 gQRSaveAs, % file := QRfile 47 | Gui, QR:Show, % "w" windowWidth " h" windowWidth 48 | return 49 | 50 | QRSaveAs: 51 | Fileselectfile, selectedFile, s16, 二维码.png, 另存为, PNG图片(*.png) 52 | if (selectedFile == "") 53 | { 54 | return 55 | } 56 | 57 | if (!RegExMatch(selectedFile,"i)\.png")) 58 | { 59 | selectedFile .= ".png" 60 | } 61 | 62 | FileMove, %file%, %selectedFile%, 1 63 | GUI, QR:Destroy 64 | return 65 | 66 | QrGuiEscape: 67 | QrGuiClose: 68 | FileDelete, %file% 69 | GUI, QR:Destroy 70 | return 71 | 72 | GenerateQR(string, file = "") 73 | { 74 | if (file == "") 75 | { 76 | file := A_Temp "\RunZ.QR.png" 77 | } 78 | 79 | hModule := DllCall(A_ScriptDir "\Lib\Reserved\quricol" A_PtrSize * 8 ".dll\GeneratePNG" 80 | , "str", file, "str", string, "int", 4, "int", 12, "int", 0) 81 | DllCall("FreeLibrary", "Ptr", hModule) 82 | return file 83 | } 84 | 85 | ;#include %A_ScriptDir%\Lib\Gdip.ahk 86 | -------------------------------------------------------------------------------- /Plugins/System.ahk: -------------------------------------------------------------------------------- 1 | ; RunZ:System 2 | ; 操作系统相关功能 3 | 4 | System: 5 | @("Clip", "显示剪切板内容") 6 | @("ClearClipboardFormat", "清除剪切板中文字的格式") 7 | @("EmptyRecycle", "清空回收站") 8 | @("Logoff", "注销 登出") 9 | @("RestartMachine", "重启") 10 | @("ShutdownMachine", "关机") 11 | @("SuspendMachine", "挂起 睡眠 待机") 12 | @("HibernateMachine", "休眠") 13 | @("TurnMonitorOff", "关闭显示器") 14 | @("ListProcess", "列出进程 ps") 15 | @("DiskSpace", "查看磁盘空间 df") 16 | @("IncreaseVolume", "提高音量") 17 | @("DecreaseVolume", "降低音量") 18 | @("SystemState", "系统状态 top") 19 | @("KillProcess", "杀死进程") 20 | @("SendToClip", "发送到剪切板") 21 | @("ListWindow", "窗口列表") 22 | @("ActivateWindow", "激活窗口") 23 | @("ListRunningService", "列出运行的服务") 24 | @("ListAllService", "列出所有的服务") 25 | @("ShowService", "显示服务详情") 26 | @("ShowProcess", "显示进程详情") 27 | return 28 | 29 | Clip: 30 | GoSub, ActivateRunZ 31 | DisplayResult("剪切板内容长度 " . StrLen(clipboard) . " :`n`n" . clipboard) 32 | return 33 | 34 | ClearClipboardFormat: 35 | clipboard := clipboard 36 | return 37 | 38 | Logoff: 39 | MsgBox, 4, , 将要注销,是否执行? 40 | IfMsgBox Yes 41 | { 42 | Shutdown, 0 43 | } 44 | return 45 | 46 | ShutdownMachine: 47 | MsgBox, 4, , 将要关机,是否执行? 48 | IfMsgBox Yes 49 | { 50 | Shutdown, 1 51 | } 52 | return 53 | 54 | RestartMachine: 55 | MsgBox, 4, , 将要重启机器,是否执行? 56 | IfMsgBox Yes 57 | { 58 | Shutdown, 2 59 | } 60 | return 61 | 62 | HibernateMachine: 63 | MsgBox, 4, , 将要休眠,是否执行? 64 | IfMsgBox Yes 65 | { 66 | ; 参数 #1: 使用 1 代替 0 来进行休眠而不是挂起。 67 | ; 参数 #2: 使用 1 代替 0 来立即挂起而不询问每个应用程序以获得许可。 68 | ; 参数 #3: 使用 1 而不是 0 来禁止所有的唤醒事件。 69 | DllCall("PowrProf\SetSuspendState", "int", 1, "int", 0, "int", 0) 70 | } 71 | return 72 | 73 | SuspendMachine: 74 | MsgBox, 4, , 将要待机,是否执行? 75 | IfMsgBox Yes 76 | { 77 | DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0) 78 | } 79 | return 80 | 81 | TurnMonitorOff: 82 | ; 关闭显示器: 83 | Sleep, 200 84 | SendMessage, 0x112, 0xF170, 2, , Program Manager 85 | ; 0x112 is WM_SYSCOMMAND, 0xF170 is SC_MONITORPOWER. 86 | ; 对上面命令的注释: 使用 -1 代替 2 来打开显示器. 87 | ; 使用 1 代替 2 来激活显示器的节能模式. 88 | return 89 | 90 | EmptyRecycle: 91 | Items := ComObjCreate("Shell.Application").Namespace(10).Items() 92 | Text := "回收站中共有 " . Items.Count() . " 项 (取消可以管理回收站文件):`n`n" 93 | 94 | Lines := 0 95 | For F in Items { 96 | if (Lines >= 30) { 97 | Text .= "……`n" 98 | break 99 | } 100 | 101 | Lines += 1 102 | 103 | Text .= F.Name . " (" . (F.IsFolder == 0 ? F.Size . " 字节)" : "目录)") . "`n" 104 | } 105 | 106 | if (Lines == 0) { 107 | MsgBox, , , 回收站是空的,将自动关闭, 0.5 108 | return 109 | } 110 | 111 | MsgBox, 3, , % Text . "`n将要清空回收站,是否执行?" 112 | 113 | IfMsgBox Yes 114 | { 115 | FileRecycleEmpty 116 | return 117 | } 118 | 119 | IfMsgBox Cancel 120 | { 121 | Run, explorer.exe ::{645ff040-5081-101b-9f08-00aa002f954e} 122 | } 123 | return 124 | 125 | ListProcess: 126 | result := "" 127 | 128 | for process in ComObjGet("winmgmts:").ExecQuery("select * from Win32_Process") 129 | { 130 | result .= "* | 进程 | " process.Name " | " process.CommandLine "`n" 131 | } 132 | Sort, result 133 | 134 | SetCommandFilter("KillProcess|ShowProcess|CountNumber") 135 | DisplayResult(FilterResult(AlignText(result), Arg)) 136 | TurnOnResultFilter() 137 | return 138 | 139 | DiskSpace: 140 | result := "" 141 | 142 | DriveGet, list, list 143 | Loop, Parse, list 144 | { 145 | drive := A_LoopField ":" 146 | DriveGet, label, label, %drive% 147 | DriveGet, cap, capacity, %drive% 148 | DriveSpaceFree, free, %drive% 149 | used := cap - free 150 | ;SetFormat, float, 5.2 151 | ;percent := 100 * (cap - free) / cap 152 | SetFormat, float, 7.2 153 | cap /= 1024.0 154 | free /= 1024.0 155 | used /= 1024.0 156 | result = %result%* | %drive% | 总共: %cap% G 可用: %free% G | 已用:%used% 卷标: %label%`n 157 | } 158 | 159 | DisplayResult(AlignText(result)) 160 | return 161 | 162 | IncreaseVolume: 163 | SoundSet, +5 164 | return 165 | 166 | DecreaseVolume: 167 | SoundSet, -5 168 | return 169 | 170 | SystemState: 171 | if (!SetExecInterval(1)) 172 | { 173 | return 174 | } 175 | 176 | GMSEx := GlobalMemoryStatusEx() 177 | result := "* | 状态 | 运行时间 | " Round(A_TickCount / 1000 / 3600, 3) " 小时`n" 178 | result .= "* | 状态 | CPU 占用 | " CPULoad() "% `n" 179 | result .= "* | 状态 | 内存占用 | " Round(100 * (GMSEx[2] - GMSEx[3]) / GMSEx[2], 2) "% `n" 180 | result .= "* | 状态 | 进程总数 | " GetProcessCount() "`n" 181 | result .= "* | 状态 | 内存总量 | " Round(GMSEx[2] / 1024**2, 2) "MB `n" 182 | result .= "* | 状态 | 可用内存 | " Round(GMSEx[3] / 1024**2, 2) "MB `n" 183 | DisplayResult(AlignText(result)) 184 | return 185 | 186 | KillProcess: 187 | args := StrSplit(Arg, " ") 188 | for index, argument in args 189 | { 190 | Process, Close, %argument% 191 | } 192 | 193 | DisplayResult("已尝试杀死 " Arg " 进程") 194 | return 195 | 196 | SendToClip: 197 | clipboard := Arg 198 | GoSub, Clip 199 | return 200 | 201 | ListWindow: 202 | result := "" 203 | 204 | WinGet, id, list, , , Program Manager 205 | Loop, %id% 206 | { 207 | thisId := id%A_Index% 208 | WinGetTitle, title, ahk_id %thisId% 209 | WinGet, name, ProcessName, ahk_id %thisId% 210 | if (title == "") 211 | { 212 | continue 213 | } 214 | result .= "* | 窗口 | " name " | " title "`n" 215 | } 216 | 217 | SetCommandFilter("ActivateWindow|KillProcess") 218 | DisplayResult(AlignText(result)) 219 | TurnOnResultFilter() 220 | return 221 | 222 | ActivateWindow: 223 | DisplayResult() 224 | ClearInput() 225 | 226 | if (FullPipeArg != "") 227 | { 228 | Loop, Parse, FullPipeArg, `n, `r 229 | { 230 | if (A_LoopField == "") 231 | { 232 | return 233 | } 234 | splitedLine := StrSplit(A_LoopField, " | ") 235 | WinActivate, % Trim(splitedLine[4]) 236 | } 237 | } 238 | else 239 | { 240 | for index, argument in StrSplit(Arg, " ") 241 | { 242 | WinActivate, ahk_exe %argument% 243 | } 244 | } 245 | return 246 | 247 | ListAllService: 248 | result := 249 | for service in ComObjGet("winmgmts:").ExecQuery("select * from Win32_Service") 250 | { 251 | result .= "* | 服务 | " service.Name " | " service.DisplayName "`n" 252 | } 253 | Sort, result 254 | 255 | SetCommandFilter("CountNumber|ShowService") 256 | DisplayResult(FilterResult(AlignText(result), Arg)) 257 | TurnOnResultFilter() 258 | return 259 | 260 | ListRunningService: 261 | result := 262 | for service in ComObjGet("winmgmts:").ExecQuery("select * from Win32_Service") 263 | { 264 | if (service.Started != 0) 265 | { 266 | result .= "* | 服务 | " service.Name " | " service.DisplayName "`n" 267 | } 268 | } 269 | Sort, result 270 | 271 | SetCommandFilter("CountNumber|ShowService") 272 | DisplayResult(FilterResult(AlignText(result), Arg)) 273 | TurnOnResultFilter() 274 | return 275 | 276 | ShowService: 277 | result := 278 | ; 暂时只支持一个,选得多了查起来太慢 279 | for service in ComObjGet("winmgmts:") 280 | .ExecQuery("select * from Win32_Service where Name = '" StrSplit(Arg, " ")[1] "'") 281 | { 282 | ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa394418%28v=vs.85%29.aspx 283 | result .= "* | 服务 | 名称 | " service.Name "`n" 284 | result .= "* | 服务 | 描述 | " service.Description "`n" 285 | result .= "* | 服务 | 是否在运行 | " service.Started "`n" 286 | result .= "* | 服务 | 路径 | " service.PathName "`n" 287 | result .= "* | 服务 | 进程 ID | " service.ProcessId "`n" 288 | result .= "* | 服务 | 类型 | " service.ServiceType "`n" 289 | break 290 | } 291 | 292 | DisplayResult(AlignText(result)) 293 | return 294 | 295 | ShowProcess: 296 | result := 297 | ; 暂时只支持一个,选得多了查起来太慢 298 | for process in ComObjGet("winmgmts:") 299 | .ExecQuery("select * from Win32_Process where Name = '" StrSplit(Arg, " ")[1] "'") 300 | { 301 | ; https://msdn.microsoft.com/en-us/library/windows/desktop/aa394372%28v=vs.85%29.aspx 302 | result .= "* | 服务 | 名称 | " process.Name "`n" 303 | result .= "* | 服务 | 描述 | " process.Description "`n" 304 | result .= "* | 服务 | 命令行 | " process.CommandLine "`n" 305 | result .= "* | 服务 | 启动时间 | " process.CreationDate "`n" 306 | result .= "* | 服务 | ID | " process.ProcessId "`n" 307 | break 308 | } 309 | 310 | DisplayResult(AlignText(result)) 311 | return 312 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## RunZ 2 | 3 | 专业的快速启动工具。 4 | 5 | #### 链接 6 | 7 | [详细介绍](https://github.com/goreliu/runz/wiki) 8 | 9 | [下载地址](https://github.com/goreliu/runz/releases) 10 | 11 | [用户手册](https://github.com/goreliu/runz/wiki/用户手册) 12 | 13 | [常见问题](https://github.com/goreliu/runz/wiki/常见问题) 14 | 15 | [问题反馈](https://github.com/goreliu/runz/wiki/问题反馈) 16 | 17 | [更新历史](https://github.com/goreliu/runz/wiki/更新历史) 18 | 19 | #### 截图 20 | 21 | ![主界面](https://raw.githubusercontent.com/wiki/goreliu/runz/Images/main.png) 22 | -------------------------------------------------------------------------------- /RunZ.ahk: -------------------------------------------------------------------------------- 1 | #NoEnv 2 | #SingleInstance, Force 3 | #NoTrayIcon 4 | #MaxHotkeysPerInterval 200 5 | 6 | FileEncoding, utf-8 7 | SendMode Input 8 | SetWorkingDir %A_ScriptDir% 9 | 10 | ; 自动生成的待搜索文件列表 11 | global g_SearchFileList := A_ScriptDir . "\Conf\SearchFileList.txt" 12 | ; 用户配置的待搜索文件列表 13 | global g_UserFileList := A_ScriptDir . "\Conf\UserFileList.txt" 14 | ; 配置文件 15 | global g_ConfFile := A_ScriptDir . "\Conf\RunZ.ini" 16 | ; 自动写入的配置文件 17 | global g_AutoConfFile := A_ScriptDir . "\Conf\RunZ.auto.ini" 18 | 19 | if !FileExist(g_ConfFile) 20 | { 21 | FileCopy, %g_ConfFile%.help.txt, %g_ConfFile% 22 | } 23 | 24 | if (FileExist(g_AutoConfFile ".EasyIni.bak")) 25 | { 26 | MsgBox, % "发现上次写入配置的备份文件:`n" 27 | . g_AutoConfFile . ".EasyIni.bak" 28 | . "`n确定则将其恢复,否则请手动检查文件内容再继续" 29 | FileMove, % g_AutoConfFile ".EasyIni.bak", % g_AutoConfFile 30 | } 31 | else if (!FileExist(g_AutoConfFile)) 32 | { 33 | FileAppend, % "; 此文件由 RunZ 自动写入,如需手动修改请先关闭 RunZ !`n`n" 34 | . "[Auto]`n[Rank]`n[History]" , % g_AutoConfFile 35 | } 36 | 37 | global g_Conf := class_EasyIni(g_ConfFile) 38 | global g_AutoConf := class_EasyIni(g_AutoConfFile) 39 | 40 | if (g_Conf.Gui.Skin != "") 41 | { 42 | global g_SkinConf := class_EasyIni(A_ScriptDir "\Conf\Skins\" g_Conf.Gui.Skin ".ini").Gui 43 | } 44 | else 45 | { 46 | global g_SkinConf := g_Conf.Gui 47 | } 48 | 49 | ; 当前输入命令的参数,数组,为了方便没有添加 g_ 前缀 50 | global Arg 51 | ; 用来调用管道的完整参数(所有列),供有必要的插件使用 52 | global FullPipeArg 53 | ; 不能是 RunZ.ahk 的子串,否则按键绑定会有问题 54 | global g_WindowName := "RunZ " 55 | ; 所有命令 56 | global g_Commands 57 | ; 当搜索无结果时使用的命令 58 | global g_FallbackCommands 59 | ; 编辑框当前内容 60 | global g_CurrentInput 61 | ; 当前匹配到的第一条命令 62 | global g_CurrentCommand 63 | ; 当前匹配到的所有命令 64 | global g_CurrentCommandList 65 | ; 是否启用 TCMatch 66 | global g_EnableTCMatch = TCMatchOn(g_Conf.Config.TCMatchPath) 67 | ; 列表第一列的首字母或数字 68 | global g_FirstChar := Asc(g_SkinConf.FirstChar) 69 | ; 在列表中显示的行数 70 | global g_DisplayRows := g_SkinConf.DisplayRows 71 | ; 命令使用了显示框 72 | global g_UseDisplay 73 | ; 历史命令 74 | global g_HistoryCommands 75 | ; 运行命令时临时设置,避免因为自身退出无法运行需要提权的软件 76 | global g_DisableAutoExit 77 | ; 当前的命令在搜索结果的行数 78 | global g_CurrentLine 79 | ; 使用备用的命令 80 | global g_UseFallbackCommands 81 | ; 对命令结果进行实时搜索 82 | global g_UseResultFilter 83 | ; 当参数改变后实时重新执行命令 84 | global g_UseRealtimeExec 85 | ; 排除的命令 86 | global g_ExcludedCommands 87 | ; 间隔运行命令的间隔时间 88 | global g_ExecInterval 89 | ; 上次间隔运行的功能标签 90 | global g_LastExecLabel 91 | ; 用来调用管道的参数(结果第三列) 92 | global g_PipeArg 93 | ; 用来补全命令用的 94 | global g_CommandFilter 95 | ; 插件列表 96 | global g_Plugins := Object() 97 | 98 | global g_InputArea := "Edit1" 99 | global g_DisplayArea := "Edit3" 100 | global g_CommandArea := "Edit4" 101 | 102 | FileRead, currentPlugins, %A_ScriptDir%\Core\Plugins.ahk 103 | needRestart := false 104 | 105 | Loop, Files, %A_ScriptDir%\Plugins\*.ahk 106 | { 107 | FileReadLine, firstLine, %A_LoopFileLongPath%, 1 108 | pluginName := StrSplit(firstLine, ":")[2] 109 | if (!(g_Conf.GetValue("Plugins", pluginName) == 0)) 110 | { 111 | if (RegExMatch(currentPlugins, "m)" pluginName ".ahk$")) 112 | { 113 | g_Plugins.Push(pluginName) 114 | } 115 | else 116 | { 117 | FileAppend, #include *i `%A_ScriptDir`%\Plugins\%pluginName%.ahk`n 118 | , %A_ScriptDir%\Core\Plugins.ahk 119 | needRestart := true 120 | } 121 | } 122 | } 123 | 124 | if (needRestart) 125 | { 126 | Reload 127 | } 128 | 129 | if (g_SkinConf.ShowTrayIcon) 130 | { 131 | Menu, Tray, Icon 132 | Menu, Tray, NoStandard 133 | if (g_Conf.Config.RunInBackground) 134 | { 135 | Menu, Tray, Add, 显示 &S, ActivateRunZ 136 | Menu, Tray, Default, 显示 &S 137 | Menu, Tray, Click, 1 138 | } 139 | Menu, Tray, Add, 配置 &C, EditConfig 140 | Menu, Tray, Add, 帮助 &H, KeyHelp 141 | Menu, Tray, Add, 142 | Menu, Tray, Add, 重启 &R, RestartRunZ 143 | Menu, Tray, Add, 退出 &X, ExitRunZ 144 | } 145 | 146 | Menu, Tray, Icon, %A_ScriptDir%\RunZ.ico 147 | 148 | if (FileExist(g_SearchFileList)) 149 | { 150 | LoadFiles() 151 | } 152 | else 153 | { 154 | GoSub, ReindexFiles 155 | } 156 | 157 | Gui, Color, % g_SkinConf.BackgroundColor, % g_SkinConf.EditColor 158 | 159 | if (FileExist(A_ScriptDir "\Conf\Skins\" g_SkinConf.BackgroundPicture)) 160 | { 161 | Gui, Add, Picture, x0 y0, % A_ScriptDir "\Conf\Skins\" g_SkinConf.BackgroundPicture 162 | } 163 | 164 | border := 10 165 | if (g_SkinConf.BorderSize >= 0) 166 | { 167 | border := g_SkinConf.BorderSize 168 | } 169 | windowHeight := border * 3 + g_SkinConf.EditHeight + g_SkinConf.DisplayAreaHeight 170 | 171 | Gui, Font, % "C" g_SkinConf.FontColor " S" g_SkinConf.FontSize, % g_SkinConf.FontName 172 | Gui, Add, Edit, % "x" border " y" border " gProcessInputCommand -WantReturn" 173 | . " w" g_SkinConf.WidgetWidth " h" g_SkinConf.EditHeight, 174 | Gui, Add, Edit, y+0 w0 h0 ReadOnly -WantReturn 175 | Gui, Add, Button, y+0 w0 h0 Default gRunCurrentCommand 176 | Gui, Add, Edit, % "y+" border " -VScroll ReadOnly -WantReturn" 177 | . " w" g_SkinConf.WidgetWidth " h" g_SkinConf.DisplayAreaHeight 178 | , % AlignText(SearchCommand("", true)) 179 | 180 | if (g_SkinConf.ShowCurrentCommand) 181 | { 182 | Gui, Add, Edit, % "y+" border " ReadOnly" 183 | . " w" g_SkinConf.WidgetWidth " h" g_SkinConf.EditHeight, 184 | windowHeight += border + g_SkinConf.EditHeight 185 | } 186 | 187 | if (g_SkinConf.ShowInputBoxOnlyIfEmpty) 188 | { 189 | windowHeight := border * 2 + g_SkinConf.EditHeight 190 | SysGet, screenHeight, 79 191 | windowY := "y" (screenHeight - border * 2 - g_SkinConf.EditHeight - g_SkinConf.DisplayAreaHeight) / 2 192 | } 193 | 194 | if (g_SkinConf.HideTitle) 195 | { 196 | Gui -Caption 197 | } 198 | 199 | cmdlineArg = %1% 200 | if (cmdlineArg == "--hide") 201 | { 202 | hideWindow := " Hide" 203 | } 204 | 205 | Gui, Show, % windowY " w" border * 2 + g_SkinConf.WidgetWidth 206 | . " h" windowHeight hideWindow, % g_WindowName 207 | 208 | if (g_SkinConf.RoundCorner > 0) 209 | { 210 | WinSet, Region, % "0-0 w" border * 2 + g_SkinConf.WidgetWidth " h" windowHeight 211 | . " r" g_SkinConf.RoundCorner "-" g_SkinConf.RoundCorner, % g_WindowName 212 | } 213 | 214 | if (g_Conf.Config.SwitchToEngIME) 215 | { 216 | SwitchToEngIME() 217 | } 218 | 219 | if (g_Conf.Config.WindowAlwaysOnTop) 220 | { 221 | WinSet, AlwaysOnTop, On, A 222 | } 223 | 224 | if (g_Conf.Config.ExitIfInactivate) 225 | { 226 | OnMessage(0x06, "WM_ACTIVATE") 227 | } 228 | 229 | OnMessage(0x0200, "WM_MOUSEMOVE") 230 | 231 | Hotkey, IfWinActive, % g_WindowName 232 | 233 | Hotkey, Esc, EscFunction 234 | Hotkey, !F4, ExitRunZ 235 | 236 | Hotkey, Tab, TabFunction 237 | Hotkey, F1, Help 238 | Hotkey, +F1, KeyHelp 239 | Hotkey, F2, EditConfig 240 | Hotkey, F3, EditAutoConfig 241 | Hotkey, ^q, RestartRunZ 242 | Hotkey, ^l, ClearInput 243 | Hotkey, ^d, OpenCurrentFileDir 244 | Hotkey, ^x, DeleteCurrentFile 245 | Hotkey, ^s, ShowCurrentFile 246 | Hotkey, ^r, ReindexFiles 247 | Hotkey, ^h, DisplayHistoryCommands 248 | Hotkey, ^n, IncreaseRank 249 | Hotkey, ^=, IncreaseRank 250 | Hotkey, ^p, DecreaseRank 251 | Hotkey, ^-, DecreaseRank 252 | Hotkey, ^f, NextPage 253 | Hotkey, ^b, PrevPage 254 | Hotkey, ^i, HomeKey 255 | Hotkey, ^o, EndKey 256 | Hotkey, ^j, NextCommand 257 | Hotkey, ^k, PrevCommand 258 | Hotkey, Down, NextCommand 259 | Hotkey, Up, PrevCommand 260 | Hotkey, ~LButton, ClickFunction 261 | Hotkey, RButton, OpenContextMenu 262 | Hotkey, AppsKey, OpenContextMenu 263 | Hotkey, ^Enter, SaveResultAsArg 264 | 265 | ; 剩余按键 Ctrl + e g m t w 266 | 267 | Loop, % g_DisplayRows 268 | { 269 | key := Chr(g_FirstChar + A_Index - 1) 270 | ; lalt + 271 | Hotkey, !%key%, RunSelectedCommand 272 | ; tab + 273 | Hotkey, ~%key%, RunSelectedCommand 274 | ; shift + 275 | Hotkey, ~+%key%, GotoCommand 276 | } 277 | 278 | for key, label in g_Conf.Hotkey 279 | { 280 | if (label != "Default") 281 | { 282 | Hotkey, %key%, %label% 283 | } 284 | else 285 | { 286 | Hotkey, %key%, Off 287 | } 288 | } 289 | 290 | Hotkey, IfWinActive 291 | 292 | for key, label in g_Conf.GlobalHotkey 293 | { 294 | if (label != "Default") 295 | { 296 | Hotkey, %key%, %label% 297 | } 298 | else 299 | { 300 | Hotkey, %key%, Off 301 | } 302 | } 303 | 304 | if (g_Conf.Config.SaveInputText && g_AutoConf.Auto.InputText != "") 305 | { 306 | Send, % g_AutoConf.Auto.InputText 307 | } 308 | 309 | if (g_Conf.Config.SaveHistory) 310 | { 311 | g_HistoryCommands := Object() 312 | LoadHistoryCommands() 313 | } 314 | 315 | UpdateSendTo(g_Conf.Config.CreateSendToLnk, false) 316 | UpdateStartupLnk(g_Conf.Config.CreateStartupLnk, false) 317 | 318 | SetTimer, WatchUserFileList, 3000 319 | return 320 | 321 | Default: 322 | return 323 | 324 | RestartRunZ: 325 | SaveAutoConf() 326 | Reload 327 | return 328 | 329 | Test: 330 | MsgBox, 测试 331 | return 332 | 333 | HomeKey: 334 | Send, {home} 335 | return 336 | 337 | EndKey: 338 | Send, {End} 339 | return 340 | 341 | NextPage: 342 | if (!g_UseDisplay) 343 | { 344 | return 345 | } 346 | 347 | ControlFocus, %g_DisplayArea% 348 | Send, {pgdn} 349 | ControlFocus, %g_InputArea% 350 | return 351 | 352 | PrevPage: 353 | if (!g_UseDisplay) 354 | { 355 | return 356 | } 357 | 358 | ControlFocus, %g_DisplayArea% 359 | Send, {pgup} 360 | ControlFocus, %g_InputArea% 361 | return 362 | 363 | ActivateRunZ: 364 | Gui, Show, , % g_WindowName 365 | 366 | if (g_Conf.Config.SwitchToEngIME) 367 | { 368 | SwitchToEngIME() 369 | } 370 | 371 | Loop, 5 372 | { 373 | Sleep, 50 374 | 375 | if (WinActive(g_WindowName)) 376 | { 377 | ControlFocus, %g_InputArea% 378 | Send, ^a 379 | break 380 | } 381 | 382 | Gui, Show, , % g_WindowName 383 | } 384 | return 385 | 386 | ToggleWindow: 387 | if (WinActive(g_WindowName)) 388 | { 389 | if (!g_Conf.Config.KeepInputText) 390 | { 391 | ControlSetText, %g_InputArea%, , %g_WindowName% 392 | } 393 | 394 | Gui, Hide 395 | } 396 | else 397 | { 398 | GoSub, ActivateRunZ 399 | } 400 | return 401 | 402 | getMouseCurrentLine() 403 | { 404 | MouseGetPos, , mouseY, , classnn, 405 | if (classnn != g_DisplayArea) 406 | { 407 | return -1 408 | } 409 | 410 | ControlGetPos, , y, , h, %g_DisplayArea% 411 | lineHeight := h / g_DisplayRows 412 | index := Ceil((mouseY - y) / lineHeight) 413 | return index 414 | } 415 | 416 | ClickFunction: 417 | if (g_UseDisplay) 418 | { 419 | return 420 | } 421 | 422 | index := getMouseCurrentLine() 423 | if (index < 0) 424 | { 425 | return 426 | } 427 | 428 | if (g_CurrentCommandList[index] != "") 429 | { 430 | ChangeCommand(index - 1, true) 431 | } 432 | 433 | ControlFocus, %g_InputArea% 434 | Send, {end} 435 | 436 | if (g_Conf.Config.ClickToRun) 437 | { 438 | RunCommand(g_CurrentCommand) 439 | } 440 | return 441 | 442 | OpenContextMenu: 443 | if (!g_UseDisplay) 444 | { 445 | currentCommandText := "" 446 | if (!g_CurrentLine > 0) 447 | { 448 | currentCommandText .= Chr(g_FirstChar) 449 | } 450 | else 451 | { 452 | currentCommandText .= Chr(g_FirstChar + g_CurrentLine - 1) 453 | } 454 | Menu, ContextMenu, Add, %currentCommandText%> 运行 &Z, RunCurrentCommand 455 | Menu, ContextMenu, Add 456 | } 457 | 458 | Menu, ContextMenu, Add, 编辑配置 &E, EditConfig 459 | Menu, ContextMenu, Add, 重建索引 &S, ReindexFiles 460 | Menu, ContextMenu, Add, 显示历史 &H, DisplayHistoryCommands 461 | Menu, ContextMenu, Add, 更新路径 &C, ChangePath 462 | Menu, ContextMenu, Add 463 | Menu, ContextMenu, Add, 显示帮助 &A, Help 464 | Menu, ContextMenu, Add, 重新启动 &R, RestartRunZ 465 | Menu, ContextMenu, Add, 退出程序 &X, ExitRunZ 466 | Menu, ContextMenu, Show 467 | Menu, ContextMenu, DeleteAll 468 | return 469 | 470 | TabFunction: 471 | ControlGetFocus, ctrl, 472 | if (ctrl == g_InputArea) 473 | { 474 | ; 定位到一个隐藏编辑框 475 | ControlFocus, Edit2 476 | } 477 | else 478 | { 479 | ControlFocus, %g_InputArea% 480 | } 481 | return 482 | 483 | EscFunction: 484 | ToolTip 485 | if (g_Conf.Config.ClearInputWithEsc && g_CurrentInput != "") 486 | { 487 | GoSub, ClearInput 488 | } 489 | else 490 | { 491 | if (!g_Conf.Config.KeepInputText) 492 | { 493 | ControlSetText, %g_InputArea%, , %g_WindowName% 494 | } 495 | GoSub, HideOrExit 496 | } 497 | return 498 | 499 | HideOrExit: 500 | ; 如果是后台运行模式,只关闭窗口,不退出程序 501 | if (g_Conf.Config.RunInBackground) 502 | { 503 | Gui, Hide 504 | } 505 | else 506 | { 507 | GoSub, ExitRunZ 508 | } 509 | return 510 | 511 | NextCommand: 512 | if (g_UseDisplay) 513 | { 514 | ControlFocus, %g_DisplayArea% 515 | Send {down} 516 | return 517 | } 518 | ChangeCommand(1) 519 | return 520 | 521 | PrevCommand: 522 | if (g_UseDisplay) 523 | { 524 | ControlFocus, %g_DisplayArea% 525 | Send {up} 526 | return 527 | } 528 | ChangeCommand(-1) 529 | return 530 | 531 | GotoCommand: 532 | ControlGetFocus, ctrl, 533 | if (ctrl == g_InputArea) 534 | { 535 | return 536 | } 537 | 538 | index := Asc(SubStr(A_ThisHotkey, 0, 1)) - g_FirstChar + 1 539 | 540 | if (g_CurrentCommandList[index] != "") 541 | { 542 | ChangeCommand(index - 1, true) 543 | } 544 | return 545 | 546 | ChangeCommand(step, resetCurrentLine = false) 547 | { 548 | ControlGetText, g_CurrentInput, %g_InputArea% 549 | 550 | if (resetCurrentLine 551 | || (SubStr(g_CurrentInput, 1, 1) != "@" && SubStr(g_CurrentInput, 1, 2) != "|@")) 552 | { 553 | g_CurrentLine := 1 554 | } 555 | 556 | row := g_CurrentCommandList.Length() 557 | if (row > g_DisplayRows) 558 | { 559 | row := g_DisplayRows 560 | } 561 | 562 | g_CurrentLine := Mod(g_CurrentLine + step, row) 563 | if (g_CurrentLine == 0) 564 | { 565 | g_CurrentLine := row 566 | } 567 | 568 | ; 重置当前命令 569 | g_CurrentCommand := g_CurrentCommandList[g_CurrentLine] 570 | 571 | ; 修改输入框内容 572 | currentChar := Chr(g_FirstChar + g_CurrentLine - 1) 573 | if (SubStr(g_CurrentInput, 1, 1) == "|") 574 | { 575 | newInput := "|@" currentChar " " 576 | } 577 | else 578 | { 579 | newInput := "@" currentChar " " 580 | } 581 | 582 | if (g_UseFallbackCommands) 583 | { 584 | if (SubStr(g_CurrentInput, 1, 1) == "@") 585 | { 586 | newInput .= SubStr(g_CurrentInput, 4) 587 | } 588 | else 589 | { 590 | newInput .= g_CurrentInput 591 | } 592 | } 593 | 594 | ControlGetText, result, %g_DisplayArea% 595 | result := StrReplace(result, ">| ", " | ") 596 | if (currentChar == Chr(g_FirstChar)) 597 | { 598 | result := currentChar ">" SubStr(result, 3) 599 | } 600 | else 601 | { 602 | result := StrReplace(result, "`r`n" currentChar " | ", "`r`n" currentChar ">| ") 603 | } 604 | 605 | DisplaySearchResult(result) 606 | 607 | ControlSetText, %g_InputArea%, %newInput%, %g_WindowName% 608 | Send, {end} 609 | } 610 | 611 | GuiClose() 612 | { 613 | if (!g_Conf.Config.RunInBackground) 614 | { 615 | GoSub, ExitRunZ 616 | } 617 | } 618 | 619 | SaveAutoConf() 620 | { 621 | if (g_Conf.Config.SaveInputText) 622 | { 623 | g_AutoConf.DeleteKey("Auto", "InputText") 624 | g_AutoConf.AddKey("Auto", "InputText", g_CurrentInput) 625 | } 626 | 627 | if (g_Conf.Config.SaveHistory) 628 | { 629 | g_AutoConf.DeleteSection("History") 630 | g_AutoConf.AddSection("History") 631 | 632 | for index, element in g_HistoryCommands 633 | { 634 | if (element != "") 635 | { 636 | g_AutoConf.AddKey("History", index, element) 637 | } 638 | } 639 | } 640 | 641 | Loop 642 | { 643 | g_AutoConf.Save() 644 | 645 | if (!FileExist(g_AutoConfFile)) 646 | { 647 | MsgBox, 配置文件 %g_AutoConfFile% 写入后丢失,请检查磁盘并点确定来重试 648 | } 649 | else 650 | { 651 | break 652 | } 653 | } 654 | } 655 | 656 | ExitRunZ: 657 | SaveAutoConf() 658 | ExitApp 659 | return 660 | 661 | GenerateSearchFileList() 662 | { 663 | FileDelete, %g_SearchFileList% 664 | 665 | searchFileType := g_Conf.Config.SearchFileType 666 | 667 | for dirIndex, dir in StrSplit(g_Conf.Config.SearchFileDir, " | ") 668 | { 669 | if (InStr(dir, "A_") == 1) 670 | { 671 | searchPath := %dir% 672 | } 673 | else 674 | { 675 | searchPath := dir 676 | } 677 | 678 | for extIndex, ext in StrSplit(searchFileType, " | ") 679 | { 680 | Loop, Files, %searchPath%\%ext%, R 681 | { 682 | if (g_Conf.Config.SearchFileExclude != "" 683 | && RegExMatch(A_LoopFileLongPath, g_Conf.Config.SearchFileExclude)) 684 | { 685 | continue 686 | } 687 | FileAppend, file | %A_LoopFileLongPath%`n, %g_SearchFileList%, 688 | } 689 | } 690 | } 691 | } 692 | 693 | ReindexFiles: 694 | if (WinActive(g_WindowName)) 695 | { 696 | ToolTip, 正在重建索引,请稍后... 697 | } 698 | 699 | GenerateSearchFileList() 700 | 701 | GoSub, CleanupRank 702 | 703 | if (WinActive(g_WindowName)) 704 | { 705 | ToolTip, 重建索引完毕 706 | SetTimer, RemoveToolTip, 800 707 | } 708 | return 709 | 710 | EditConfig: 711 | if (g_Conf.Config.Editor != "") 712 | { 713 | Run, % g_Conf.Config.Editor " """ g_ConfFile """" 714 | } 715 | else 716 | { 717 | Run, % g_ConfFile 718 | } 719 | return 720 | 721 | EditAutoConfig: 722 | if (g_Conf.Config.Editor != "") 723 | { 724 | Run, % g_Conf.Config.Editor " """ g_AutoConfFile """" 725 | } 726 | else 727 | { 728 | Run, % g_AutoConfFile 729 | } 730 | return 731 | 732 | 733 | ProcessInputCommand: 734 | ControlGetText, g_CurrentInput, %g_InputArea% 735 | ; https://github.com/goreliu/runz/issues/40 736 | ; 但如果改了这个,快速输入的话,搜索结果可能不更新 737 | ;GoSub, ProcessInputCommandCallBack 738 | ;return 739 | 740 | ; 如果使用异步的方式,TurnOnResultFilter 后会出问题,先绕一下 741 | if (SubStr(g_CurrentInput, 0, 1) == " ") 742 | { 743 | GoSub, ProcessInputCommandCallBack 744 | return 745 | } 746 | 747 | ; 为了避免搜索时间过长导致不再调用 ProcessInputCommand 748 | ; 不清楚这样做是否有其他问题 749 | SetTimer, ProcessInputCommandCallBack, 0 750 | return 751 | 752 | ProcessInputCommandCallBack: 753 | SetTimer, ProcessInputCommandCallBack, Off 754 | 755 | if (g_SkinConf.ShowInputBoxOnlyIfEmpty) 756 | { 757 | if (g_CurrentInput != "") 758 | { 759 | if (g_SkinConf.ShowCurrentCommand) 760 | { 761 | windowHeight := g_SkinConf.BorderSize * 4 762 | + g_SkinConf.EditHeight * 2 + g_SkinConf.DisplayAreaHeight 763 | } 764 | else 765 | { 766 | windowHeight := g_SkinConf.BorderSize * 3 767 | + g_SkinConf.EditHeight + g_SkinConf.DisplayAreaHeight 768 | } 769 | WinMove, %g_WindowName%, , , , , %windowHeight% 770 | } 771 | else 772 | { 773 | windowHeight := g_SkinConf.BorderSize * 2 + g_SkinConf.EditHeight 774 | WinMove, %g_WindowName%, , , , , %windowHeight% 775 | } 776 | 777 | if (g_SkinConf.RoundCorner > 0) 778 | { 779 | WinSet, Region, % "0-0 w" border * 2 + g_SkinConf.WidgetWidth " h" windowHeight 780 | . " r" g_SkinConf.RoundCorner "-" g_SkinConf.RoundCorner, % g_WindowName 781 | } 782 | } 783 | 784 | SearchCommand(g_CurrentInput) 785 | return 786 | 787 | SearchCommand(command = "", firstRun = false) 788 | { 789 | g_UseDisplay := false 790 | g_ExecInterval := -1 791 | result := "" 792 | ; 供去重使用 793 | fullResult := "" 794 | static resultToFilter := "" 795 | commandPrefix := SubStr(command, 1, 1) 796 | 797 | if (commandPrefix == ";" || commandPrefix == ":") 798 | { 799 | g_UseResultFilter := false 800 | g_UseRealtimeExec := false 801 | resultToFilter := "" 802 | g_PipeArg := "" 803 | 804 | if (commandPrefix == ";") 805 | { 806 | g_CurrentCommand := g_FallbackCommands[1] 807 | } 808 | else if (commandPrefix == ":") 809 | { 810 | g_CurrentCommand := g_FallbackCommands[2] 811 | } 812 | 813 | g_CurrentCommandList := Object() 814 | g_CurrentCommandList.Push(g_CurrentCommand) 815 | result .= Chr(g_FirstChar) ">| " 816 | . StrReplace(g_CurrentCommand, "function | ", "功能 | ") 817 | DisplaySearchResult(result) 818 | return result 819 | } 820 | else if (commandPrefix == "|" && Arg != "") 821 | { 822 | ; 记录管道参数 823 | if (g_PipeArg == "") 824 | { 825 | g_PipeArg := Arg 826 | } 827 | ; 去掉 |,然后按常规搜索处理 828 | command := SubStr(command, 2) 829 | if (SubStr(command, 1, 1) == "@") 830 | { 831 | command := SubStr(command, 1, 4) 832 | return 833 | } 834 | } 835 | else if (InStr(command, " ") && g_CurrentCommand != "") 836 | { 837 | g_PipeArg := "" 838 | 839 | ; 输入包含空格时锁定搜索结果 840 | 841 | if (g_UseResultFilter) 842 | { 843 | if (resultToFilter == "") 844 | { 845 | ControlGetText, resultToFilter, %g_DisplayArea% 846 | } 847 | 848 | ; 取出空格后边的参数 849 | needle := SubStr(g_CurrentInput, InStr(g_CurrentInput, " ") + 1) 850 | DisplayResult(FilterResult(resultToFilter, needle)) 851 | } 852 | else if (g_UseRealtimeExec) 853 | { 854 | RunCommand(g_CurrentCommand) 855 | resultToFilter := "" 856 | } 857 | else 858 | { 859 | resultToFilter := "" 860 | } 861 | 862 | return 863 | } 864 | else if (commandPrefix == "@") 865 | { 866 | g_UseResultFilter := false 867 | g_UseRealtimeExec := false 868 | resultToFilter := "" 869 | 870 | ; 搜索结果被锁定,直接退出 871 | return 872 | } 873 | 874 | g_UseResultFilter := false 875 | g_UseRealtimeExec := false 876 | resultToFilter := "" 877 | 878 | if (commandPrefix != "|") 879 | { 880 | g_PipeArg := "" 881 | } 882 | 883 | g_CurrentCommandList := Object() 884 | 885 | order := g_FirstChar 886 | 887 | for index, element in g_Commands 888 | { 889 | if (InStr(fullResult, element "`n") || inStr(g_ExcludedCommands, element "`n")) 890 | { 891 | continue 892 | } 893 | 894 | splitedElement := StrSplit(element, " | ") 895 | 896 | if (splitedElement[1] == "file") 897 | { 898 | SplitPath, % splitedElement[2], fileName, fileDir, , fileNameNoExt 899 | 900 | ; 只搜索和展示不带扩展名的文件名 901 | elementToSearch := fileNameNoExt 902 | if (g_Conf.Config.ShowFileExt) 903 | { 904 | elementToShow := "file | " . fileName " | " splitedElement[3] 905 | } 906 | else 907 | { 908 | elementToShow := "file | " . fileNameNoExt " | " splitedElement[3] 909 | } 910 | 911 | 912 | if (splitedElement.Length() >= 3) 913 | { 914 | elementToSearch .= " " . splitedElement[3] 915 | } 916 | 917 | if (g_Conf.Config.SearchFullPath) 918 | { 919 | ; TCMatch 在搜索路径时只搜索文件名,强行将 \ 转成空格 920 | elementToSearch := StrReplace(fileDir, "\", " ") . " " . elementToSearch 921 | } 922 | } 923 | else 924 | { 925 | elementToShow := splitedElement[1] " | " splitedElement[2] 926 | elementToSearch := StrReplace(splitedElement[2], "/", " ") 927 | elementToSearch := StrReplace(elementToSearch, "\", " ") 928 | 929 | if (splitedElement.Length() >= 3) 930 | { 931 | elementToShow .= " | " splitedElement[3] 932 | elementToSearch .= " " . splitedElement[3] 933 | } 934 | } 935 | 936 | if (command == "" || MatchCommand(elementToSearch, command)) 937 | { 938 | fullResult .= element "`n" 939 | g_CurrentCommandList.Push(element) 940 | 941 | if (order == g_FirstChar) 942 | { 943 | g_CurrentCommand := element 944 | result .= Chr(order++) . ">| " . elementToShow 945 | } 946 | else 947 | { 948 | result .= "`n" Chr(order++) . " | " . elementToShow 949 | } 950 | 951 | if (order - g_FirstChar >= g_DisplayRows) 952 | { 953 | break 954 | } 955 | ; 第一次运行只加载 function 类型 956 | if (firstRun && (order - g_FirstChar >= g_DisplayRows - 4)) 957 | { 958 | result .= "`n`n现有 " g_Commands.Length() " 条搜索项。" 959 | result .= "`n`n键入内容 搜索,回车 执行当前命令,Alt + 字母 执行,F1 帮助,Esc 关闭。" 960 | 961 | break 962 | } 963 | } 964 | } 965 | 966 | if (result == "") 967 | { 968 | if (IsLabel("Calc") && Eval(g_CurrentInput) != 0) 969 | { 970 | DisplayResult(Eval(g_CurrentInput)) 971 | return 972 | } 973 | 974 | g_UseFallbackCommands := true 975 | g_CurrentCommand := g_FallbackCommands[1] 976 | g_CurrentCommandList := g_FallbackCommands 977 | 978 | for index, element in g_FallbackCommands 979 | { 980 | if (index == 1) 981 | { 982 | result .= Chr(g_FirstChar - 1 + index++) . ">| " element 983 | } 984 | else 985 | { 986 | result .= "`n" 987 | result .= Chr(g_FirstChar - 1 + index++) . " | " element 988 | } 989 | } 990 | } 991 | else 992 | { 993 | g_UseFallbackCommands := false 994 | } 995 | 996 | if (g_SkinConf.HideCol2) 997 | { 998 | result := StrReplace(result, "file | ") 999 | result := StrReplace(result, "function | ") 1000 | result := StrReplace(result, "cmd | ") 1001 | result := StrReplace(result, "url | ") 1002 | } 1003 | else 1004 | { 1005 | result := StrReplace(result, "file | ", "文件 | ") 1006 | result := StrReplace(result, "function | ", "功能 | ") 1007 | result := StrReplace(result, "cmd | ", "命令 | ") 1008 | result := StrReplace(result, "url | ", "网址 | ") 1009 | } 1010 | 1011 | DisplaySearchResult(result) 1012 | return result 1013 | } 1014 | 1015 | DisplaySearchResult(result) 1016 | { 1017 | DisplayControlText(result) 1018 | 1019 | if (g_CurrentCommandList.Length() == 1 && g_Conf.Config.RunIfOnlyOne) 1020 | { 1021 | RunCommand(g_CurrentCommand) 1022 | } 1023 | 1024 | if (g_SkinConf.ShowCurrentCommand) 1025 | { 1026 | commandToShow := SubStr(g_CurrentCommand, InStr(g_CurrentCommand, " | ") + 3) 1027 | ControlSetText, %g_CommandArea%, %commandToShow%, %g_WindowName% 1028 | } 1029 | } 1030 | 1031 | FilterResult(text, needle) 1032 | { 1033 | result := "" 1034 | Loop, Parse, text, `n, `r 1035 | { 1036 | if (!InStr(A_LoopField, " | ") && MatchResult(A_LoopField, needle)) 1037 | { 1038 | result .= A_LoopField "`n" 1039 | } 1040 | else if (MatchResult(StrReplace(SubStr(A_LoopField, 5), "\", " "), needle)) 1041 | { 1042 | result .= A_LoopField "`n" 1043 | } 1044 | } 1045 | 1046 | return result 1047 | } 1048 | 1049 | TurnOnResultFilter() 1050 | { 1051 | if (!g_UseResultFilter) 1052 | { 1053 | g_UseResultFilter := true 1054 | 1055 | if (!InStr(g_CurrentInput, " ")) 1056 | { 1057 | ControlFocus, %g_InputArea% 1058 | Send, {space} 1059 | } 1060 | } 1061 | } 1062 | 1063 | TurnOnRealtimeExec() 1064 | { 1065 | if (!g_UseRealtimeExec) 1066 | { 1067 | g_UseRealtimeExec := true 1068 | 1069 | if (!InStr(g_CurrentInput, " ")) 1070 | { 1071 | ControlFocus, %g_InputArea% 1072 | Send, {space} 1073 | } 1074 | } 1075 | } 1076 | 1077 | SetExecInterval(second) 1078 | { 1079 | ; g_ExecInterval 为 0 时,表示可以进入间隔运行状态 1080 | ; g_ExecInterval 为 -1 时,表示状态以被打破,需要退出 1081 | if (g_ExecInterval >= 0) 1082 | { 1083 | g_ExecInterval := second * 1000 1084 | return true 1085 | } 1086 | else 1087 | { 1088 | SetTimer, %g_LastExecLabel%, Off 1089 | return false 1090 | } 1091 | } 1092 | 1093 | ClearInput: 1094 | ClearInput() 1095 | return 1096 | 1097 | ; 给插件用的函数 1098 | ClearInput() 1099 | { 1100 | ControlSetText, %g_InputArea%, , %g_WindowName% 1101 | ControlFocus, %g_InputArea% 1102 | } 1103 | 1104 | RunCurrentCommand: 1105 | RunCommand(g_CurrentCommand) 1106 | return 1107 | 1108 | ParseArg: 1109 | if (g_PipeArg != "") 1110 | { 1111 | Arg := g_PipeArg 1112 | return 1113 | } 1114 | 1115 | commandPrefix := SubStr(g_CurrentInput, 1, 1) 1116 | 1117 | ; 分号或者冒号的情况,直接取命令为参数 1118 | if (commandPrefix == ";" || commandPrefix == ":") 1119 | { 1120 | Arg := SubStr(g_CurrentInput, 2) 1121 | return 1122 | } 1123 | else if (commandPrefix == "@") 1124 | { 1125 | ; 处理调整过顺序的命令 1126 | Arg := SubStr(g_CurrentInput, 4) 1127 | return 1128 | } 1129 | 1130 | ; 用空格来判断参数 1131 | if (InStr(g_CurrentInput, " ") && !g_UseFallbackCommands) 1132 | { 1133 | Arg := SubStr(g_CurrentInput, InStr(g_CurrentInput, " ") + 1) 1134 | } 1135 | else if (g_UseFallbackCommands) 1136 | { 1137 | Arg := g_CurrentInput 1138 | } 1139 | else 1140 | { 1141 | Arg := "" 1142 | } 1143 | return 1144 | 1145 | MatchCommand(Haystack, Needle) 1146 | { 1147 | if (g_EnableTCMatch) 1148 | { 1149 | return TCMatch(Haystack, Needle) 1150 | } 1151 | 1152 | return InStr(Haystack, Needle) 1153 | } 1154 | 1155 | MatchResult(Haystack, Needle) 1156 | { 1157 | if (g_EnableTCMatch) 1158 | { 1159 | return TCMatch(Haystack, Needle) 1160 | } 1161 | 1162 | return InStr(Haystack, Needle) 1163 | } 1164 | 1165 | RunCommand(originCmd) 1166 | { 1167 | GoSub, ParseArg 1168 | 1169 | g_UseDisplay := false 1170 | g_DisableAutoExit := true 1171 | g_ExecInterval := 0 1172 | 1173 | splitedOriginCmd := StrSplit(originCmd, " | ") 1174 | cmd := splitedOriginCmd[2] 1175 | 1176 | if (splitedOriginCmd[1] == "file") 1177 | { 1178 | if (InStr(cmd, ".lnk")) 1179 | { 1180 | ; 处理 32 位 ahk 运行不了某些 64 位系统 .lnk 的问题 1181 | FileGetShortcut, %cmd%, filePath 1182 | if (!FileExist(filePath)) 1183 | { 1184 | filePath := StrReplace(filePath, "C:\Program Files (x86)", "C:\Program Files") 1185 | if (FileExist(filePath)) 1186 | { 1187 | cmd := filePath 1188 | } 1189 | } 1190 | } 1191 | 1192 | SplitPath, cmd, , fileDir, , 1193 | 1194 | if (Arg == "") 1195 | { 1196 | Run, %cmd%, %fileDir% 1197 | } 1198 | else 1199 | { 1200 | Run, %cmd% "%Arg%", %fileDir% 1201 | } 1202 | } 1203 | else if (splitedOriginCmd[1] == "function") 1204 | { 1205 | ; 第四个参数是参数 1206 | if (splitedOriginCmd.Length() >= 4) 1207 | { 1208 | Arg := splitedOriginCmd[4] 1209 | } 1210 | 1211 | if (IsLabel(cmd)) 1212 | { 1213 | GoSub, %cmd% 1214 | } 1215 | } 1216 | else if (splitedOriginCmd[1] == "cmd") 1217 | { 1218 | RunWithCmd(cmd) 1219 | } 1220 | else if (splitedOriginCmd[1] == "url") 1221 | { 1222 | url := splitedOriginCmd[2] 1223 | if (!Instr(url, "http")) 1224 | { 1225 | url := "http://" . url 1226 | } 1227 | 1228 | Run, %url% 1229 | } 1230 | 1231 | if (g_Conf.Config.SaveHistory && cmd != "DisplayHistoryCommands") 1232 | { 1233 | if (splitedOriginCmd.Length() == 3 && Arg != "") 1234 | { 1235 | g_HistoryCommands.InsertAt(1, originCmd " | " Arg) 1236 | } 1237 | else if (originCmd != "") 1238 | { 1239 | g_HistoryCommands.InsertAt(1, originCmd) 1240 | } 1241 | 1242 | if (g_HistoryCommands.Length() > g_Conf.Config.HistorySize) 1243 | { 1244 | g_HistoryCommands.Pop() 1245 | } 1246 | } 1247 | 1248 | if (g_Conf.Config.AutoRank) 1249 | { 1250 | ChangeRank(originCmd) 1251 | } 1252 | 1253 | g_DisableAutoExit := false 1254 | 1255 | if (g_Conf.Config.RunOnce && !g_UseDisplay) 1256 | { 1257 | if (!g_Conf.Config.KeepInputText) 1258 | { 1259 | GoSub, ClearInput 1260 | } 1261 | GoSub, HideOrExit 1262 | } 1263 | 1264 | if (g_ExecInterval > 0 && splitedOriginCmd[1] == "function") 1265 | { 1266 | SetTimer, %cmd%, %g_ExecInterval% 1267 | g_LastExecLabel := cmd 1268 | } 1269 | 1270 | g_PipeArg := "" 1271 | FullPipeArg := "" 1272 | } 1273 | 1274 | ChangeRank(cmd, show = false, inc := 1) 1275 | { 1276 | splitedCmd := StrSplit(cmd, " | ") 1277 | 1278 | if (splitedCmd.Length() >= 4 && splitedCmd[1] == "function") 1279 | { 1280 | ; 去掉参数 1281 | cmd := splitedCmd[1] " | " splitedCmd[2] " | " splitedCmd[3] 1282 | } 1283 | 1284 | cmdRank := g_AutoConf.GetValue("Rank", cmd) 1285 | if cmdRank is integer 1286 | { 1287 | g_AutoConf.DeleteKey("Rank", cmd) 1288 | cmdRank += inc 1289 | } 1290 | else 1291 | { 1292 | cmdRank := inc 1293 | } 1294 | 1295 | if (cmdRank != 0 && cmd != "") 1296 | { 1297 | ; 如果将到负数,都设置成 -1,然后屏蔽 1298 | if (cmdRank < 0) 1299 | { 1300 | cmdRank := -1 1301 | g_ExcludedCommands .= cmd "`n" 1302 | } 1303 | 1304 | g_AutoConf.AddKey("Rank", cmd, cmdRank) 1305 | } 1306 | else 1307 | { 1308 | cmdRank := 0 1309 | } 1310 | 1311 | if (show) 1312 | { 1313 | ToolTip, 调整 %cmd% 的权重到 %cmdRank% 1314 | SetTimer, RemoveToolTip, 800 1315 | } 1316 | } 1317 | 1318 | ; 比较耗时,必要时才使用,也可以手动编辑 RunZ.auto.ini 1319 | CleanupRank: 1320 | ; 先把 g_Commands 里的 Rank 信息清掉 1321 | LoadFiles(false) 1322 | 1323 | for command, rank in g_AutoConf.Rank 1324 | { 1325 | cleanup := true 1326 | for index, element in g_Commands 1327 | { 1328 | if (InStr(element, command) == 1) 1329 | { 1330 | cleanup := false 1331 | break 1332 | } 1333 | } 1334 | if (cleanup) 1335 | { 1336 | g_AutoConf.DeleteKey("Rank", command) 1337 | } 1338 | } 1339 | 1340 | Loop 1341 | { 1342 | g_AutoConf.Save() 1343 | 1344 | if (!FileExist(g_AutoConfFile)) 1345 | { 1346 | MsgBox, 配置文件 %g_AutoConfFile% 写入后丢失,请检查磁盘并点确定来重试 1347 | } 1348 | else 1349 | { 1350 | break 1351 | } 1352 | } 1353 | 1354 | LoadFiles() 1355 | return 1356 | 1357 | RunSelectedCommand: 1358 | if (SubStr(A_ThisHotkey, 1, 1) == "~") 1359 | { 1360 | ControlGetFocus, ctrl, 1361 | if (ctrl == g_InputArea) 1362 | { 1363 | return 1364 | } 1365 | } 1366 | 1367 | index := Asc(SubStr(A_ThisHotkey, 0, 1)) - g_FirstChar + 1 1368 | 1369 | RunCommand(g_CurrentCommandList[index]) 1370 | return 1371 | 1372 | IncreaseRank: 1373 | if (g_CurrentCommand != "") 1374 | { 1375 | ChangeRank(g_CurrentCommand, true) 1376 | LoadFiles() 1377 | } 1378 | return 1379 | 1380 | DecreaseRank: 1381 | if (g_CurrentCommand != "") 1382 | { 1383 | ChangeRank(g_CurrentCommand, true, -1) 1384 | LoadFiles() 1385 | } 1386 | return 1387 | 1388 | LoadFiles(loadRank := true) 1389 | { 1390 | g_Commands := Object() 1391 | g_FallbackCommands := Object() 1392 | 1393 | if (loadRank) 1394 | { 1395 | rankString := "" 1396 | for command, rank in g_AutoConf.Rank 1397 | { 1398 | if (StrLen(command) > 0) 1399 | { 1400 | if (rank >= 1) 1401 | { 1402 | rankString .= rank "`t" command "`n" 1403 | } 1404 | else 1405 | { 1406 | g_ExcludedCommands .= command "`n" 1407 | } 1408 | } 1409 | } 1410 | 1411 | if (rankString != "") 1412 | { 1413 | Sort, rankString, R N 1414 | 1415 | Loop, Parse, rankString, `n 1416 | { 1417 | if (A_LoopField == "") 1418 | { 1419 | continue 1420 | } 1421 | 1422 | g_Commands.Push(StrSplit(A_LoopField, "`t")[2]) 1423 | } 1424 | } 1425 | } 1426 | 1427 | 1428 | for key, value in g_Conf.Command 1429 | { 1430 | if (value != "") 1431 | { 1432 | g_Commands.Push(key . " | " . value) 1433 | } 1434 | else 1435 | { 1436 | g_Commands.Push(key) 1437 | } 1438 | } 1439 | 1440 | for index, element in g_Plugins 1441 | { 1442 | if (IsLabel(element)) 1443 | { 1444 | GoSub, %element% 1445 | } 1446 | else 1447 | { 1448 | MsgBox, 未在 %A_ScriptDir%\Plugins\%element%.ahk 中发现 %element% 标签,请修改! 1449 | } 1450 | } 1451 | 1452 | g_FallbackCommands := Object() 1453 | for key, value in g_Conf.FallbackCommand 1454 | { 1455 | if (IsLabel(StrSplit(key, " | ")[2])) 1456 | { 1457 | g_FallbackCommands.Push(key) 1458 | } 1459 | } 1460 | 1461 | if (g_FallbackCommands.Length() == 0) 1462 | { 1463 | g_FallbackCommands.Push("function | AhkRun | 使用 Ahk 的 Run() 运行") 1464 | } 1465 | 1466 | if (FileExist(A_ScriptDir "\Conf\UserFunctionsAuto.txt")) 1467 | { 1468 | userFunctionLabel := "UserFunctionsAuto" 1469 | if (IsLabel(userFunctionLabel)) 1470 | { 1471 | GoSub, %userFunctionLabel% 1472 | } 1473 | else 1474 | { 1475 | MsgBox, 未在 %A_ScriptDir%\Conf\UserFunctionsAuto.txt 中发现 %userFunctionLabel% 标签,请修改! 1476 | } 1477 | } 1478 | 1479 | if (FileExist(g_UserFileList)) 1480 | { 1481 | Loop, Read, %g_UserFileList% 1482 | { 1483 | g_Commands.Push(A_LoopReadLine) 1484 | } 1485 | } 1486 | 1487 | Loop, Read, %g_SearchFileList% 1488 | { 1489 | g_Commands.Push(A_LoopReadLine) 1490 | } 1491 | 1492 | if (g_Conf.Config.LoadControlPanelFunctions) 1493 | { 1494 | Loop, Read, %A_ScriptDir%\Core\ControlPanelFunctions.txt 1495 | { 1496 | g_Commands.Push(A_LoopReadLine) 1497 | } 1498 | } 1499 | } 1500 | 1501 | ; 用来显示控制界面 1502 | DisplayControlText(text) 1503 | { 1504 | ControlSetText, %g_DisplayArea%, % AlignText(text), %g_WindowName% 1505 | } 1506 | 1507 | ; 用来显示命令结果 1508 | DisplayResult(result := "") 1509 | { 1510 | textToDisplay := StrReplace(result, "`n", "`r`n") 1511 | ControlSetText, %g_DisplayArea%, %textToDisplay%, %g_WindowName% 1512 | g_UseDisplay := true 1513 | result := "" 1514 | textToDisplay := "" 1515 | } 1516 | 1517 | LoadHistoryCommands() 1518 | { 1519 | historySize := g_Conf.Config.HistorySize 1520 | 1521 | index := 0 1522 | for key, value in g_AutoConf.History 1523 | { 1524 | if (StrLen(value) > 0) 1525 | { 1526 | g_HistoryCommands.Push(value) 1527 | index++ 1528 | 1529 | if (index == historySize) 1530 | { 1531 | return 1532 | } 1533 | } 1534 | } 1535 | } 1536 | 1537 | DisplayHistoryCommands: 1538 | g_UseDisplay := false 1539 | result := "" 1540 | g_CurrentCommandList := Object() 1541 | g_CurrentLine := 1 1542 | 1543 | for index, element in g_HistoryCommands 1544 | { 1545 | if (index == 1) 1546 | { 1547 | result .= Chr(g_FirstChar + index - 1) . ">| " 1548 | g_CurrentCommand := element 1549 | } 1550 | else 1551 | { 1552 | result .= Chr(g_FirstChar + index - 1) . " | " 1553 | } 1554 | 1555 | splitedElement := StrSplit(element, " | ") 1556 | 1557 | result .= splitedElement[1] " | " splitedElement[2] 1558 | . " | " splitedElement[3] " #参数: " splitedElement[4] "`n" 1559 | 1560 | g_CurrentCommandList.Push(element) 1561 | } 1562 | 1563 | result := StrReplace(result, "file | ", "文件 | ") 1564 | result := StrReplace(result, "function | ", "功能 | ") 1565 | result := StrReplace(result, "cmd | ", "命令 | ") 1566 | result := StrReplace(result, "url | ", "网址 | ") 1567 | 1568 | DisplayControlText(result) 1569 | return 1570 | 1571 | ; 第三个参数不再是 fallback,备用,为了兼容不改变第四个参数的含义 1572 | @(label, info, fallback = false, key = "") 1573 | { 1574 | if (!IsLabel(label)) 1575 | { 1576 | MsgBox, 未找到 %label% 标签,请检查 %A_ScriptDir%\Conf\UserFunctions.ahk 文件格式! 1577 | return 1578 | } 1579 | 1580 | g_Commands.Push("function | " . label . " | " . info ) 1581 | 1582 | if (key != "") 1583 | { 1584 | Hotkey, %key%, %label% 1585 | } 1586 | } 1587 | 1588 | RunAndGetOutput(command) 1589 | { 1590 | tempFileName := "RunZ.stdout.log" 1591 | fullCommand = %ComSpec% /C "%command% > %tempFileName%" 1592 | 1593 | /* 1594 | fullCommand = bash -c "%command% &> %tempFileName%" 1595 | 1596 | if (!FileExist("c:\msys64\usr\bin\bash.exe")) 1597 | { 1598 | fullCommand = %ComSpec% /C "%command% > %tempFileName%" 1599 | } 1600 | */ 1601 | 1602 | RunWait, %fullCommand%, %A_Temp%, Hide 1603 | FileRead, result, %A_Temp%\%tempFileName% 1604 | FileDelete, %A_Temp%\%tempFileName% 1605 | return result 1606 | } 1607 | 1608 | RunWithCmd(command, onlyCmd = false) 1609 | { 1610 | if (!onlyCmd && FileExist("c:\msys64\usr\bin\mintty.exe")) 1611 | { 1612 | Run, % "mintty -e sh -c '" command "; read'" 1613 | } 1614 | else 1615 | { 1616 | Run, % ComSpec " /C " command " & pause" 1617 | } 1618 | } 1619 | 1620 | OpenPath(filePath) 1621 | { 1622 | if (!FileExist(filePath)) 1623 | { 1624 | return 1625 | } 1626 | 1627 | if (FileExist(g_Conf.Config.TCPath)) 1628 | { 1629 | TCPath := g_Conf.Config.TCPath 1630 | Run, %TCPath% /O /A /L="%filePath%" 1631 | } 1632 | else 1633 | { 1634 | SplitPath, filePath, , fileDir, , 1635 | Run, explorer "%fileDir%" 1636 | } 1637 | } 1638 | 1639 | GetAllFunctions() 1640 | { 1641 | result := "" 1642 | 1643 | for index, element in g_Commands 1644 | { 1645 | if (InStr(element, "function | ") == 1 and !InStr(result, element "`n")) 1646 | { 1647 | result .= "* | " element "`n" 1648 | } 1649 | } 1650 | 1651 | result := StrReplace(result, "function | ", "功能 | ") 1652 | 1653 | return AlignText(result) 1654 | } 1655 | 1656 | OpenCurrentFileDir: 1657 | filePath := StrSplit(g_CurrentCommand, " | ")[2] 1658 | OpenPath(filePath) 1659 | return 1660 | 1661 | DeleteCurrentFile: 1662 | filePath := StrSplit(g_CurrentCommand, " | ")[2] 1663 | 1664 | if (!FileExist(filePath)) 1665 | { 1666 | return 1667 | } 1668 | 1669 | FileRecycle, % filePath 1670 | GoSub, ReindexFiles 1671 | return 1672 | 1673 | ShowCurrentFile: 1674 | clipboard := StrSplit(g_CurrentCommand, " | ")[2] 1675 | ToolTip, % clipboard 1676 | SetTimer, RemoveToolTip, 800 1677 | return 1678 | 1679 | RemoveToolTip: 1680 | ToolTip 1681 | SetTimer, RemoveToolTip, Off 1682 | return 1683 | 1684 | 1685 | WM_MOUSEMOVE(wParam, lParam) 1686 | { 1687 | if (wparam = 1) ; LButton 1688 | { 1689 | PostMessage, 0xA1, 2, , , A ; WM_NCLBUTTONDOWN 1690 | } 1691 | 1692 | if (!g_Conf.Config.ChangeCommandOnMouseMove) 1693 | { 1694 | return 1695 | } 1696 | 1697 | MouseGetPos, , mouseY, , classnn, 1698 | if (classnn != g_DisplayArea) 1699 | { 1700 | return -1 1701 | } 1702 | 1703 | ControlGetPos, , y, , h, %g_DisplayArea% 1704 | lineHeight := h / g_DisplayRows 1705 | index := Ceil((mouseY - y) / lineHeight) 1706 | 1707 | if (g_CurrentCommandList[index] != "") 1708 | { 1709 | ChangeCommand(index - 1, true) 1710 | } 1711 | } 1712 | 1713 | WM_ACTIVATE(wParam, lParam) 1714 | { 1715 | if (g_DisableAutoExit) 1716 | { 1717 | return 1718 | } 1719 | 1720 | if (wParam >= 1) ; 窗口激活 1721 | { 1722 | return 1723 | } 1724 | else if (wParam <= 0) ; 窗口非激活 1725 | { 1726 | ; 这样有可能第一次显示主界面时,窗口失去焦点后不关闭 1727 | ; 暂时没有好的解决方法,如果改用 SetTimer 调用,会导致用快捷键显示主窗口失败 1728 | 1729 | if (!WinExist("RunZ.ahk")) 1730 | { 1731 | if (!g_Conf.Config.KeepInputText) 1732 | { 1733 | ControlSetText, %g_InputArea%, , %g_WindowName% 1734 | } 1735 | 1736 | GoSub, HideOrExit 1737 | } 1738 | } 1739 | } 1740 | 1741 | KeyHelpText() 1742 | { 1743 | return AlignText("" 1744 | . "* | 按键 | Shift + F1 | 显示置顶的按键提示`n" 1745 | . "* | 按键 | Alt + F4 | 退出置顶的按键提示`n" 1746 | . "* | 按键 | 回车 | 执行当前命令`n" 1747 | . "* | 按键 | Esc | 关闭窗口`n" 1748 | . "* | 按键 | Alt + | 加每列行首字符执行`n" 1749 | . "* | 按键 | Tab + | 再按每列行首字符执行`n" 1750 | . "* | 按键 | Tab + | 再按 Shift + 行首字符 定位`n" 1751 | . "* | 按键 | Win + j | 显示或隐藏窗口`n" 1752 | . "* | 按键 | Ctrl + j | 移动到下一条命令`n" 1753 | . "* | 按键 | Ctrl + k | 移动到上一条命令`n" 1754 | . "* | 按键 | Ctrl + f | 在输出结果中翻到下一页`n" 1755 | . "* | 按键 | Ctrl + b | 在输出结果中翻到上一页`n" 1756 | . "* | 按键 | Ctrl + h | 显示历史记录`n" 1757 | . "* | 按键 | Ctrl + n | 可增加当前功能的权重`n" 1758 | . "* | 按键 | Ctrl + p | 可减少当前功能的权重`n" 1759 | . "* | 按键 | Ctrl + l | 清除编辑框内容`n" 1760 | . "* | 按键 | Ctrl + r | 重新创建待搜索文件列表`n" 1761 | . "* | 按键 | Ctrl + q | 重启`n" 1762 | . "* | 按键 | Ctrl + d | 用 TC 打开第一个文件所在目录`n" 1763 | . "* | 按键 | Ctrl + s | 显示并复制当前文件的完整路径`n" 1764 | . "* | 按键 | Ctrl + x | 删除当前文件`n" 1765 | . "* | 按键 | Ctrl + i | 移动光标当行首`n" 1766 | . "* | 按键 | Ctrl + o | 移动光标当行尾`n" 1767 | . "* | 按键 | F2 | 编辑配置文件`n" 1768 | . "* | 按键 | F3 | 编辑自动写入的配置文件`n" 1769 | . "* | 功能 | 输入网址 | 可直接输入 www 或 http 开头的网址`n" 1770 | . "* | 功能 | `; | 以分号开头命令,用 ahk 运行`n" 1771 | . "* | 功能 | : | 以冒号开头的命令,用 cmd 运行`n" 1772 | . "* | 功能 | 无结果 | 搜索无结果,回车用 ahk 运行`n" 1773 | . "* | 功能 | 空格 | 输入空格后,搜索内容锁定") 1774 | } 1775 | 1776 | UpdateSendTo(create = true, overwrite = false) 1777 | { 1778 | lnkFilePath := StrReplace(A_StartMenu, "\Start Menu", "\SendTo\") "RunZ.lnk" 1779 | 1780 | if (!create) 1781 | { 1782 | FileDelete, %lnkFilePath% 1783 | return 1784 | } 1785 | 1786 | if (!overwrite && FileExist(lnkFilePath)) 1787 | { 1788 | return 1789 | } 1790 | 1791 | FileCreateShortcut, % A_ScriptDir "\RunZ.exe", % A_ScriptDir "\Core\SendToRunZ.lnk" 1792 | , , "%A_ScriptDir%\Core\RunZCmdTool.ahk", 发送到 RunZ, % A_ScriptDir "\RunZ.ico" 1793 | FileCopy, % A_ScriptDir "\Core\SendToRunZ.lnk" 1794 | , % StrReplace(A_StartMenu, "\Start Menu", "\SendTo\") "RunZ.lnk", 1 1795 | } 1796 | 1797 | UpdateStartupLnk(create = true, overwrite = false) 1798 | { 1799 | lnkFilePath := A_Startup "\RunZ.lnk" 1800 | 1801 | if (!create) 1802 | { 1803 | FileDelete, %lnkFilePath% 1804 | return 1805 | } 1806 | 1807 | if (!FileExist(lnkFilePath) || overwrite) 1808 | { 1809 | FileCreateShortcut, % A_ScriptDir "\RunZ.exe", %lnkFilePath% 1810 | , %A_ScriptDir%, RunZ.ahk --hide, RunZ, % A_ScriptDir "\RunZ.ico" 1811 | } 1812 | } 1813 | 1814 | ChangePath: 1815 | UpdateSendTo(g_Conf.Config.CreateSendToLnk, true) 1816 | UpdateStartupLnk(g_Conf.Config.CreateStartupLnk, true) 1817 | return 1818 | 1819 | AlignText(text) 1820 | { 1821 | col3MaxLen := g_SkinConf.DisplayCol3MaxLength 1822 | col4MaxLen := g_SkinConf.DisplayCol4MaxLength 1823 | col3Pos := 10 1824 | 1825 | StrSpace := " " 1826 | Loop, % col3MaxLen + col4MaxLen 1827 | StrSpace .= " " 1828 | 1829 | result := "" 1830 | 1831 | if (g_SkinConf.HideCol2) 1832 | { 1833 | ; 隐藏第二列的话,把第二列的空间分给第三列 1834 | col3MaxLen += 7 1835 | col3Pos := 5 1836 | 1837 | hasCol2 := true 1838 | Loop, Parse, text, `n, `r 1839 | { 1840 | if (SubStr(A_LoopField, 3, 1) != "|" || SubStr(A_LoopField, 8, 1) != "|") 1841 | { 1842 | hasCol2 := false 1843 | break 1844 | } 1845 | } 1846 | 1847 | if (hasCol2) 1848 | { 1849 | col3Pos := 10 1850 | } 1851 | } 1852 | 1853 | if (g_SkinConf.HideCol4IfEmpty) 1854 | { 1855 | Loop, Parse, text, `n, `r 1856 | { 1857 | if (StrSplit(SubStr(A_LoopField, col3Pos), " | ")[2] != "") 1858 | { 1859 | hasCol4 := true 1860 | break 1861 | } 1862 | } 1863 | 1864 | if (!hasCol4) 1865 | { 1866 | ; 加上中间的 " | " 1867 | col3MaxLen += col4MaxLen + 3 1868 | col4MaxLen := 0 1869 | } 1870 | } 1871 | 1872 | Loop, Parse, text, `n, `r 1873 | { 1874 | if (!InStr(A_LoopField, " | ")) 1875 | { 1876 | result .= A_LoopField "`r`n" 1877 | continue 1878 | } 1879 | 1880 | if (hasCol2) 1881 | { 1882 | ; 内容包含第二列,需要去掉 1883 | result .= SubStr(A_LoopField, 1, 4) 1884 | } 1885 | else 1886 | { 1887 | result .= SubStr(A_LoopField, 1, col3Pos - 1) 1888 | } 1889 | 1890 | splitedLine := StrSplit(SubStr(A_LoopField, col3Pos), " | ") 1891 | col3RealLen := StrLen(RegExReplace(splitedLine[1], "[^\x00-\xff]", "`t`t")) 1892 | 1893 | if (col3RealLen > col3MaxLen) 1894 | { 1895 | result .= SubStrByByte(splitedLine[1], col3MaxLen) 1896 | } 1897 | else 1898 | { 1899 | result .= splitedLine[1] . SubStr(StrSpace, 1, col3MaxLen - col3RealLen) 1900 | } 1901 | 1902 | if (col4MaxLen > 0) 1903 | { 1904 | result .= " | " 1905 | 1906 | col4RealLen := StrLen(RegExReplace(splitedLine[2], "[^\x00-\xff]", "`t`t")) 1907 | 1908 | if (col4RealLen > col4MaxLen) 1909 | { 1910 | result .= SubStrByByte(splitedLine[2], col4MaxLen) 1911 | } 1912 | else 1913 | { 1914 | result .= splitedLine[2] 1915 | } 1916 | } 1917 | 1918 | result .= "`r`n" 1919 | } 1920 | 1921 | return result 1922 | } 1923 | 1924 | WatchUserFileList: 1925 | FileGetTime, newUserFileListModifyTime, %g_UserFileList% 1926 | if (newUserFileListModifyTime == "") 1927 | { 1928 | FileAppend, , %g_UserFileList% 1929 | } 1930 | 1931 | if (lastUserFileListModifyTime != "" && lastUserFileListModifyTime != newUserFileListModifyTime) 1932 | { 1933 | LoadFiles() 1934 | } 1935 | lastUserFileListModifyTime := newUserFileListModifyTime 1936 | 1937 | FileGetTime, newConfFileModifyTime, %g_ConfFile% 1938 | if (lastConfFileModifyTime != "" && lastConfFileModifyTime != newConfFileModifyTime) 1939 | { 1940 | GoSub, RestartRunZ 1941 | } 1942 | lastConfFileModifyTime := newConfFileModifyTime 1943 | return 1944 | 1945 | SaveResultAsArg: 1946 | Arg := "" 1947 | ControlGetText, result, %g_DisplayArea% 1948 | 1949 | ; 处理隐藏第二列的情况 1950 | if (g_SkinConf.HideCol2) 1951 | { 1952 | FullPipeArg := "" 1953 | Loop, Parse, result, `n, `r 1954 | { 1955 | FullPipeArg .= SubStr(A_LoopField, 1, 2) "| 占位 | " SubStr(A_LoopField, 5) "`n" 1956 | } 1957 | } 1958 | else 1959 | { 1960 | FullPipeArg := result 1961 | } 1962 | 1963 | if (InStr(g_CurrentCommand, "file | ") == 1) 1964 | { 1965 | Arg .= StrSplit(g_CurrentCommand, " | ")[2] 1966 | } 1967 | else if (!InStr(result, " | ")) 1968 | { 1969 | Arg .= StrReplace(result, "`n", " ") 1970 | Arg := StrReplace(Arg, "`r") 1971 | } 1972 | else 1973 | { 1974 | if (g_SkinConf.HideCol2) 1975 | { 1976 | Loop, Parse, result, `n, `r 1977 | { 1978 | Arg .= Trim(StrSplit(A_LoopField, " | ")[2]) " " 1979 | } 1980 | } 1981 | else 1982 | { 1983 | Loop, Parse, result, `n, `r 1984 | { 1985 | Arg .= Trim(StrSplit(A_LoopField, " | ")[3]) " " 1986 | } 1987 | } 1988 | } 1989 | 1990 | Arg := Trim(Arg) 1991 | 1992 | ControlFocus, %g_InputArea% 1993 | ControlSetText, %g_InputArea%, | 1994 | Send, {End} 1995 | if (g_CommandFilter != "") 1996 | { 1997 | ; 第一个 | 代表要用管道执行,不然 g_PipeArg 会被清空 1998 | SearchCommand("|" g_CommandFilter) 1999 | g_CommandFilter := "" 2000 | } 2001 | return 2002 | 2003 | ; 格式: 2004 | ; 与 command1&command2 2005 | ; 或 command1|command2 2006 | ; 非 !command1 2007 | SetCommandFilter(command) 2008 | { 2009 | g_CommandFilter := command 2010 | } 2011 | 2012 | Help: 2013 | DisplayResult(KeyHelpText() . GetAllFunctions()) 2014 | return 2015 | 2016 | KeyHelp: 2017 | ToolTip, % KeyHelpText() 2018 | SetTimer, RemoveToolTip, 5000 2019 | return 2020 | 2021 | 2022 | #include %A_ScriptDir%\Lib\EasyIni.ahk 2023 | #include %A_ScriptDir%\Lib\TCMatch.ahk 2024 | #include %A_ScriptDir%\Core\Common.ahk 2025 | #include *i %A_ScriptDir%\Core\Plugins.ahk 2026 | ; 发送到菜单自动生成的命令 2027 | #include *i %A_ScriptDir%\Conf\UserFunctionsAuto.txt 2028 | -------------------------------------------------------------------------------- /RunZ.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goreliu/runz/27453eb51f96ad22b8c0e5e4e6adc140eb4f1488/RunZ.ico -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.2.2 2 | -------------------------------------------------------------------------------- /build: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | set -e 4 | 5 | version=$(cat VERSION) 6 | 7 | mkdir -p RunZ 8 | cp * RunZ -r 2>/dev/null || true 9 | 10 | cd RunZ || exit 1 11 | 12 | cp /mnt/c/mine/app/AutoHotkey/AutoHotkeyU32.exe RunZ.exe 13 | rm -f build 14 | rm -f Core/*.lnk 15 | rm -f Core/Plugins.ahk 16 | rm -f Conf/RunZ.ini 17 | rm -f Conf/RunZ.auto.ini 18 | rm -f Conf/SearchFileList.txt 19 | rm -f Conf/UserFunctionsAuto.txt 20 | rm -f Conf/UserFunctionsAuto.txt.bak 21 | rm -f Conf/UserFileList.txt 22 | rm -rf RunZ 23 | rm -rf Doc/.git 24 | rm -rf Doc/Icons 25 | rm -rf Doc/Images 26 | rm -f **/*64.dll 27 | 28 | echo -e "历史版本详见 Releases · goreliu/runz · GitHub" > Doc/更新历史.md.new 29 | echo "https://github.com/goreliu/runz/releases" >> Doc/更新历史.md.new 30 | echo >> Doc/更新历史.md.new 31 | cat Doc/更新历史.md >> Doc/更新历史.md.new 32 | 33 | for i (Doc/*.md*) { 34 | sed -i "1s/^/\xEF\xBB\xBF/g" $i 35 | # unix2dos $i 36 | sed -i 's/$/\r/' $i 37 | } 38 | 39 | mv Doc/更新历史.md.new Doc/更新历史.md 40 | mv Doc/Home.md Doc/介绍.md 41 | cp Doc/更新历史.md ~/tmp/RunZ\ 更新历史.txt 42 | 43 | cd .. 44 | a RunZ-$version.7z RunZ 45 | 46 | # 64 位版本 47 | 48 | cd RunZ 49 | cp /mnt/c/mine/app/AutoHotkey/AutoHotkeyU64.exe RunZ.exe 50 | rm -f Lib/Reserved/quricol32.dll 51 | cp ../Lib/Reserved/quricol64.dll Lib/Reserved/quricol64.dll 52 | rm -f Lib/TCMatch/tcmatch.dll 53 | cp ../Lib/TCMatch/tcmatch64.dll Lib/TCMatch/tcmatch64.dll 54 | sed -i 's/tcmatch.dll/tcmatch64.dll/g' Conf/RunZ.ini.help.txt 55 | 56 | cd .. 57 | a RunZ-x86_64-$version.7z RunZ 58 | 59 | mv RunZ-$version.7z ~/tmp 60 | mv RunZ-x86_64-$version.7z ~/tmp 61 | rm -rf RunZ 62 | --------------------------------------------------------------------------------