[AHK2] 使用#Include-二
开始
上一次,我们提到了如何使用#Include
,以及使用时应注意的问题,现在我们就来解决这个问题。
如何保证资源路径始终是正确的?
思路
我们仿造nodeJs的Path.resolve(),实现一个ahk的resolve()。
但要注意的一点是:
- 使用静态变量
Workdir
代替__dirname
因为我们没有这样一个__dirname
变量,只有自己造。
接下来,就是实现各种情况的path拼接了,需要考虑的方面十分多,总结包括以下几点:
- 以
.
开头 - 以
..
开头 - 以盘符开头
- 以路径开头
- 以绝对路径开头
- 以相对路径开头
同时,还要考虑多参及分隔符统一的情况。
实现
为解决多参问题,我们先分为无、单参和多参进行处理,先处理简单的,在对付难的。
具体细节我便不再多讲,代码都有完整的注释。
需要注意的是,我算法并不好,所以采用的只是简单的循环判断。不过结果肯定没问题:(
resolve()实现
; param: paths
; ret: absolute path --> string
; desc: convert to absolute path
static Resolve(params*) {
len := params.Length
; 单参,默认以当前目录为基准
if !len || (len == 1 && (params[1] == '' || params[1] == '.')) { ; 无参,参数为空值及.返回当前目录
return StrReplace(Path.Workdir, '\', Path.Sep)
} else if (len == 1) {
if (params[1] ~= '^\.[\\/]') { ; ./开头,直接去除开头./,再规范化后即可返回
; 去除开头的./
_path := Path.Workdir SubStr(params[1], 2)
; 统一分隔符
_path := StrReplace(_path, '/', '\')
; 去除末尾 \
_path := RTrim(_path, '\')
; 规范化
_path := StrReplace(_path, '\', Path.Sep)
return _path
}
else if (params[1] ~= '^\.\.[\\/]') { ; ../ 开头的单参,连接目录路径后放行
params[1] := Path.Workdir params[1]
}
else if (params[1] ~= '^\.\.$') { ; .. 添加sep后放行
params[1] := Path.Workdir params[1] Path.Sep
}
else { ;无法处理
return StrReplace(Path.Workdir, '\', Path.Sep)
}
}
; 多参
for index, param in params {
if !param ; 跳过空值
continue
if param ~= '^[\\/]' { ; 如果以分隔符开头,则清除先前的路径
_path := param
}
else if (index == 1) ; 第一个参数,不加sep
_path .= param
else ; 添加分隔符
_path .= '\' param
}
; 统一分隔符
_path := StrReplace(_path, '/', '\')
; 替换 ..
while (_path ~= 'i)\.\.') {
; 找到..位置
subStart := InStr(_path, '..')
; 找到..前第二个\位置
subEnd := InStr(_path, '\', , -(StrLen(_path) - subStart) - 3)
; 裁剪出待替换字串
sub := SubStr(_path, subEnd, subStart - subEnd + 2)
; MsgBox subStart '--' subEnd '`n' sub '`n' _path
_path := StrReplace(_path, sub, '')
if !sub
throw Error('invalid param! current path--> ' _path)
}
; 替换 .\
_path := StrReplace(_path, '.\', '')
; 去除末尾 \
_path := RTrim(_path, '\')
; 规范化
_path := StrReplace(_path, '\', Path.Sep)
; 判断是否带盘符,无则添加当前盘符
if _path ~= 'i)^\w:[\\/]'
return _path
; 判断是否添加全路径
else if _path ~= '^[\\/]' {
drive := SubStr(Path.Workdir, 1, 1)
return drive ':' _path
}
else {
scriptDir := StrReplace(Path.Workdir, '/', Path.Sep)
scriptDir := StrReplace(Path.Workdir, '\', Path.Sep)
return scriptDir Path.sep _path
}
}
测试
以下是测试用例:
其中,注释为正确结果
if A_LineFile == A_ScriptFullPath {
MsgBox Path.Resolve() ; C:\Users\u\Desktop\AhkPlanE\utils
MsgBox Path.Resolve('.') ; C:\Users\u\Desktop\AhkPlanE\utils
MsgBox Path.Resolve('./') ; C:\Users\u\Desktop\AhkPlanE\utils
MsgBox Path.Resolve('..') ; C:\Users\u\Desktop\AhkPlanE
MsgBox Path.Resolve('../') ; C:\Users\u\Desktop\AhkPlanE
MsgBox Path.Resolve('./abc\') ; C:\Users\u\Desktop\AhkPlanE\utils\abc
MsgBox Path.Resolve('..\abc\..\def') ; C:\Users\u\Desktop\AhkPlanE\def
MsgBox Path.Resolve('C:\Users\u\Desktop\AhkPlanE', '../') ; C:\Users\u\Desktop
MsgBox Path.Resolve('C:\Users\u\Desktop\AhkPlanE', '../res/light/../abc') ; C:\Users\u\Desktop\res\abc
MsgBox Path.Resolve('/ic', '../a/b', '.\d') ; C:\a\b\d
MsgBox Path.Resolve('abc', '/ic', '../a/b', '.\d') ; C:\a\b\d
}
join()实现
另外,顺便增加一个简单的拼接方法。
; param: separator | paths
; ret: path --> string
; desc: Connect paths using separator
static Join(sep, params*) {
for index, param in params
str .= param . sep
return SubStr(str, 1, -StrLen(sep))
}
静态变量
; 设置当前目录
static Workdir := '' || A_ScriptDir
static Sep := '/'
其中,Sep
为resolve统一后的分隔符。
workdir的使用
回到之前的a、b.ahk例子中,现在a脚本的资源引用需要这样书写:
this.AddPicture('yp h30 w50 vPic', Path.Resolve(Path.Workdir, 'res/light.png'))
以a脚本启动时便需要设置workdir
变量:
Path.Workdir := Path.Resolve(A_ScriptDir, '../')
PlanEGui.Show({ theme: 'light' })
而b脚本无需修改。
以此便解决了资源引用的问题,只需手动设置Workdir
即可(谁叫我们没有呢XD),同时,Resolve()也可在其他地方使用。由测试用例中可见它的功能还是很强大的。
[AHK2] 使用#Include-二更多相关文章
JavaScript CSS Vue3 实现一个简单的Loading
配置和使用nvm免安装版本(nvm-noinstall.zip)
HarmonyOS:使用Node-API实现ArkTS与C/C++跨语言交互
【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (一):项目简介及安装依赖
【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (四):状态码的使用
【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (五):POST上传文件的设置
【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (六):token的设置
【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (七):MongoDB的设置
【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (三):Cors的设置及.env文件的设置
【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (二):项目文件夹架构及路由的设置
【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (八):API说明(暂时完结,后续考虑将在线版mongoDB变为本地版)
报error:0308010C:digital envelope routines::unsupported错--nodejs版本过高(nvm安装(更换)不同版本nodejs)
小结---安装nvm解决node版本不兼容的问题(node版本切换)