-
-
Notifications
You must be signed in to change notification settings - Fork 24
/
CapsLockX.ahk
309 lines (281 loc) · 12.5 KB
/
CapsLockX.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
; ========== CapsLockX ==========
; 名称:CapsLockX 程序入口
; 描述:用于生成模块加载组件、集成模块帮助文件、智能重载 CapsLockX 核心等功能。
; 作者:snomiao
; 联系:[email protected]
; 支持:https://github.com/snomiao/CapsLockX
; 编码:UTF-8 with BOM
; 版权:Copyright © 2017-2024 Snowstar Laboratory. All Rights Reserved.
; 感谢:张工 QQ: 45289331 参与调试
; LICENCE: GNU GPLv3
; ========== CapsLockX ==========
if (A_IsAdmin) {
#SingleInstance Force ; 管理员权限下跳过对话框并自动替换旧实例
} else {
#SingleInstance, Off ; 普通用户无法替换管理员权限实例,故 Off,使用多开的方式修改配置文件触发管理员权限实例重载
}
#NoTrayIcon ; 隐藏托盘图标
SetWorkingDir, %A_ScriptDir%
#Include %A_ScriptDir%/Core/CapsLockX-Config.ahk
#Include %A_ScriptDir%/Core/CapsLockX-RunSilent.ahk
#Include %A_ScriptDir%/Core/CapsLockX-i18n.ahk
global CLX_ModuleDir := "./Modules"
; global CLX_用户模块路径 := CLX_ConfigDir "/Modules"
global CLX_CoreDir := "./Core"
; 版本
global CLX_Version
FileRead, CLX_Version, ./Core/version.txt
CLX_Version := CLX_Version ? CLX_Version : "未知版本"
global CLX_VersionName := "v" CLX_Version
; 加载过程提示
global 显示加载提示 := 1
global loadingTips := ""
; 对 核心模块 进行 编码清洗
CONVERT_FILE_TO_UTF8_WITH_BOM_ENCODING(CLX_CoreDir "/CapsLockX-Config.ahk")
CONVERT_FILE_TO_UTF8_WITH_BOM_ENCODING(CLX_CoreDir "/CapsLockX-Core.ahk")
CONVERT_FILE_TO_UTF8_WITH_BOM_ENCODING(CLX_CoreDir "/CapsLockX-RunSilent.ahk")
CONVERT_FILE_TO_UTF8_WITH_BOM_ENCODING(CLX_CoreDir "/CapsLockX-Update.ahk")
CONVERT_FILE_TO_UTF8_WITH_BOM_ENCODING(CLX_CoreDir "/CapsLockX-i18n.ahk")
; 复制用户模块
; TODO FIX:如果CLX已经开了的话,这一步会触发重启,这可能会导致一些文件冲突的BUG……
FileDelete, %CLX_ModuleDir%/*.user.ahk
FileDelete, %CLX_ModuleDir%/*.user.md
FileCopy %CLX_ConfigDir%/*.user.ahk, %CLX_ModuleDir%/, 1
FileCopy %CLX_ConfigDir%/*.user.md, %CLX_ModuleDir%/, 1
; 模块加载器路径
global CLX_ModulesRunner := "Core\CapsLockX-ModulesRunner.ahk"
global CLX_ModulesFunctions := "Core\CapsLockX-ModulesFunctions.ahk"
; LoadModules(CLX_ModulesRunner, CLX_ModulesFunctions)
; 判断安装方式
global NPM全局安装也 := InStr(A_ScriptFullPath, APPDATA) == 1 && InStr("node_modules", A_ScriptFullPath)
global GIT仓库安装也 := "true" == Trim(CLX_RunSilent("cmd /c git rev-parse --is-inside-work-tree"), "`r`n`t` ")
;
模块帮助向README编译()
; 隐藏 ToolTip
ToolTip
; 当 CI_TEST 启用时,仅测试编译效果,不启动核心
EnvGet ENVIROMENT, ENVIROMENT
; msgbox % DllCall("GetCommandLine", "str")
; msgbox % !!RegExMatch(DllCall("GetCommandLine", "str"), "/CI_TEST")
if ("CI_TEST" == ENVIROMENT || !!RegExMatch(DllCall("GetCommandLine", "str"), "/CI_TEST")) {
tooltip % "[INFO] MODULE LOAD OK, SKIP CORE"
OutputDebug, % "[INFO] MODULE LOAD OK, SKIP CORE"
ExitApp
} else {
CapsLockX启动()
}
; #Persistent
; SetTimer, CapsLockX启动, -1
Return
模块帮助向README编译(){
; 编译README.md
INPUT_README_FILE := "./README.md"
FileEncoding, UTF-8-Raw
FileRead, source, %INPUT_README_FILE%
; 编译一次
global 显示加载提示
显示加载提示 := 0
target := 模块编译和帮助README更新(source)
if (target == source) {
traytip MODULE_HELP_NOT_CHANGED
return "NOT_CHANGED"
}
; 如果不一样,就再编译一次,并且显示加载提示
显示加载提示 := 1
加载提示追加(t("模块帮助有变更"))
; 然后进行稳定性检查
source := 模块编译和帮助README更新(target)
if (target != source) {
MsgBox % t("警告:模块帮助未能稳定更新,如果你看到了这个消息,请联系雪星(QQ:997596439, 邮箱: [email protected])")
}
; 输出到 ./README.md (用于 github-pages )
; docs_target := 模块编译和帮助README更新(source, 1)
FileDelete % INPUT_README_FILE
FileAppend %target%, % INPUT_README_FILE, UTF-8-Raw
; 输出根目录 README.md (用于 github 首页)
; ; FileDelete ./README.md
; PREFIX := "<!-- THIS FILE IS GENERATED by CLX PLEASE MODIFY ./README.md -->`n`n"
; ; replace docs/media
; StringReplace, target, target, % "(./", % "(./docs/", All
; StringReplace, target, target, % "( ./", % "( ./docs/", All
; ; StringReplace, target, target, ./media/, ./docs/media/, All
; ; StringReplace, target, target, ./docs/, ./docs/, All
; FileAppend %PREFIX%%target%, ./README.md, UTF-8-Raw
; Reload
; ExitApp
}
加载提示追加(msg, clear = 0){
global 显示加载提示
if(!显示加载提示) return
if (clear || loadingTips == "") {
loadingTips := "CapsLockX " CLX_Version "`n"
}
loadingTips .= msg "`n"
}
加载提示显示(){
ToolTip % loadingTips
sleep 1000
}
模块编译和帮助README更新(sourceREADME){
lang := "en"
FileEncoding UTF-8-Raw
; 列出模块文件
ModuleFiles := ""
loop, Files, %CLX_ModuleDir%\*.ahk
{
; Do not Recurse into subfolders. 子文件夹由模块自己去include去加载
ModuleFiles .= A_LoopFileName "`n"
}
ModuleFiles := Trim(ModuleFiles, "`n")
Sort ModuleFiles
; 生成帮助
全部模块帮助 := ""
i := 0
loop, Parse, ModuleFiles, `n
{
i++
; 匹配模块名
模块文件 := A_LoopField
匹配结果 := false
匹配结果 := 匹配结果 || RegExMatch(A_LoopField, "O)((?:.*[-])*)(.*?)(?:\.user)?\.ahk", Match)
匹配结果 := 匹配结果 || RegExMatch(A_LoopField, "O)((?:.*[-])*)(.*?)(?:\.用户)?\.ahk", Match)
if (!匹配结果) {
Continue
}
模块文件名称 := Match[1] Match[2]
模块名称 := Match[2]
模块帮助内容 := ""
模块帮助文件 := ""
if (!模块帮助内容) {
模块帮助文件 := CLX_ModuleDir "/" 模块名称 ".md"
if (FileExist(模块帮助文件)) {
FileRead, 模块帮助内容, %模块帮助文件%
}
}
if (!模块帮助内容) {
模块帮助文件 := CLX_ModuleDir "/" 模块文件名称 ".md"
if (FileExist(模块帮助文件)) {
FileRead, 模块帮助内容, %模块帮助文件%
}
}
; 加载模块描述
FileRead, 模块文件内容, % CLX_ModuleDir "/" 模块文件
T%模块名称%_Disabled := CLX_Config("ModuleDisable", "T" 模块名称 "_Disabled", 0, "是否禁用模块:" 模块名称 (模块描述1 ? " - " 模块描述1 : "") )
if (模块帮助内容) {
模块帮助内容 := Trim(模块帮助内容, " `t`n")
加载提示追加(t("加载模块帮助:") . i . "-" . 模块名称)
全部模块帮助 .= "<!-- MODULE_FILE: " Match[1] Match[2] ".ahk" "-->" "`n`n"
; 替换资源链接的相对目录(图片gif等)
FileCopy, % CLX_ModuleDir . "\*.gif", .\docs\media\, 1
FileCopy, % CLX_ModuleDir . "\*.png", .\docs\media\, 1
; FileCopy, %CLX_ModuleDir%\*.gif, .\docs\media\, 1
; FileCopy, %CLX_ModuleDir%\*.png, .\docs\media\, 1
; 模块帮助内容 := RegExReplace(模块帮助内容, "m)\[(.*)\]\(\s*?\.\/(.*?)\)", "[$1](./media/$2)")
模块帮助内容 := RegExReplace(模块帮助内容, "m)\[(.*)\]\(\s*?\.\/(.*?)\)", "[$1](./docs/media/$2)")
; 没有标题的,给自动加标题
if (!RegExMatch(模块帮助内容, "^#")) {
; if (T%模块名称%_Disabled) {
; 模块帮助内容 .= "### " 模块名称 "模块(禁用)" "`n"
; } else {
; 模块帮助内容 .= "### " 模块名称 "模块" "`n"
; }
模块帮助内容 .= "### " 模块名称 "模块" "`n"
}
; translate to en
模块帮助内容 := t(模块帮助内容, lang)
; 替换标题层级
模块帮助内容 := RegExReplace(模块帮助内容, "(?<=^|\n)#", "###")
全部模块帮助 .= 模块帮助内容 . "`n`n"
}
if (T%模块名称%_Disabled) {
加载提示追加(t("跳过模块:") . i . " " . 模块名称)
} else {
; 这里引入模块代码
CONVERT_FILE_TO_UTF8_WITH_BOM_ENCODING(CLX_ModuleDir "/" 模块文件)
; 导入模块
模块初始化代码 .= "GoSub CLX_ModuleSetup_" i "`n"
模块导入代码 .= "`n" "#If" "`n" "`n"
模块导入代码 .= "CLX_ModuleSetup_" i ":" "`n"
if (模块帮助内容 && 模块帮助文件) {
模块导入代码 .= " " " " " " " " "CLX_THIS_MODULE_HELP_FILE_PATH = " 模块帮助文件 "`n"
} else {
模块导入代码 .= " " " " " " " " "CLX_THIS_MODULE_HELP_FILE_PATH := """"" "`n"
}
模块导入代码 .= " " " " " " " " "#Include " CLX_ModuleDir "/" 模块文件 "`n"
模块导入代码 .= "Return" "`n"
加载提示追加(t("运行模块:") . i . " " . 模块名称)
}
}
加载提示显示()
; 拼接模块加载器代码
常量语句 .= "; " . t("请勿直接编辑本文件,以下内容由核心加载器自动生成。雪星/(20210318)") . "`n"
常量语句 .= "global CLX_ModuleDir := " """" CLX_ModuleDir """" "`n"
常量语句 .= "global CLX_CoreDir := " """" CLX_CoreDir """" "`n"
常量语句 .= "global CLX_Version := " """" CLX_Version """" "`n"
常量语句 .= "global CLX_VersionName := " """" CLX_VersionName """" "`n"
模块运行器 .= 常量语句 "`n" 模块初始化代码
模块加载器 .= "Return" "`n" 模块导入代码
FileEncoding UTF-8
FileDelete %CLX_ModulesRunner%
FileAppend %模块运行器%, %CLX_ModulesRunner%
if (!FileExist(CLX_ModulesRunner)) {
msg =
msg .= t("Unable to write ModulesRunner.ahk, if you are install with chocolatey, run me as admin at the first time please.")
msg .= "`n"
msg .= t("注意:未能写入模块运行器,如果使用 chocolatey 首次安装后,请以管理员权限运行。")
msgbox %msg%
}
FileDelete %CLX_ModulesFunctions%
FileAppend %模块加载器%, %CLX_ModulesFunctions%
加载提示显示()
全部模块帮助 := Trim(全部模块帮助, " `t`n")
; 生成 README 替换代码
NeedleRegEx := "m)(\s*)(<!-- MODULE_HELP_BEGIN -->)([\s\S]*)\r?\n(\s*)(\r?\n<!-- MODULE_HELP_END -->)"
Replacement := "$1$2`n" 全部模块帮助 "`n$4$5"
targetREADME := RegExReplace(sourceREADME, NeedleRegEx, Replacement, Replaces)
; msgbox % 全部模块帮助
; 检查 README 替换情况
if (!Replaces) {
Run https://capslockx.snomiao.com/
MsgBox % t("加载模块帮助遇到错误。") . "`n" . t("已为你打开 CapsLockX 主页,请手动更新 CapsLockX")
MsgBox % targetREADME
Return sourceREADME
}
Return targetREADME
}
CapsLockX启动(){
CoreAHK := CLX_CoreDir "\CapsLockX-Core.ahk"
UpdatorAHK := CLX_CoreDir "\CapsLockX-Update.ahk"
; 为了避免运行时对更新模块的影响,先把 EXE 文件扔到 Temp 目录,然后再使用 Temp 里的 AHK 来运行本核心。
AHK_EXE_ROOT_PATH := "CapsLockX.exe"
AHK_EXE_CORE_PATH := "./Core/CapsLockX.exe"
AHK_EXE_TEMP_PATH := A_Temp "/CapsLockX-AHK.exe"
FileCopy, %AHK_EXE_ROOT_PATH%, %AHK_EXE_TEMP_PATH%, 1
if (!FileExist(AHK_EXE_TEMP_PATH)) {
FileCopy, %AHK_EXE_CORE_PATH%, %AHK_EXE_TEMP_PATH%, 1
}
if (!FileExist(AHK_EXE_TEMP_PATH)) {
AHK_EXE_TEMP_PATH := AHK_EXE_ROOT_PATH
}
; 运行更新组件
Run %AHK_EXE_TEMP_PATH% %UpdatorAHK%, %A_ScriptDir%
; 运行核心
; 启动
global T_AskRunAsAdmin := CLX_ConfigGet("Core", "T_AskRunAsAdmin", 0)
adminCommand := RegExMatch(DllCall("GetCommandLine", "str"), "/admin")
if (!A_IsAdmin && T_AskRunAsAdmin || adminCommand) {
RunWait *RunAs %AHK_EXE_TEMP_PATH% %CoreAHK%, %A_ScriptDir%
} else {
RunWait %AHK_EXE_TEMP_PATH% %CoreAHK%, %A_ScriptDir%
}
if (ErrorLevel) {
MsgBox, 4, % t("CapsLockX 错误"), % t("CapsLockX 异常退出,是否重载?")
IfMsgBox No
return
Reload
} else {
TrayTip, % t("CapsLockX 退出"), % t("CapsLockX 已退出。")
Sleep, 1000
}
ExitApp
}