[|[ Skill ] load 函数优化,识别相对路径

https://www.cnblogs.com/yeungchie/
在 cds.lib 文件中定义库的路径,为了规范库定义的管理,经常这样做:

. |-- cds.lib ------------------- cat --> 1| INCLUDE ./common/cds.lib `-- common |-- cds.lib --------------- cat --> 1| INCLUDE ./project/cds.lib |2| INCLUDE ./project/cds.lib |-- project ||-- cds.lib ----------- cat --> 1| INCLUDE ./project/cds.lib ||2| INCLUDE ./project/cds.lib ||3| INCLUDE ./project/cds.lib ||-- layout ||`-- cds.lib ------- cat --> 1| DEFINE layout_lib1 ./layout_lib1 ||2| DEFINE layout_lib2 ./layout_lib2 ||3| 略 ... ||-- sch ||`-- cds.lib ------- cat --> 1| 略略 ... |`-- 略略略 ... `-- 略略略略 ...

可以看到,对于每一个 cds.lib 文件自身来说,里面用的都是相对路径。
同样的用法在 Skill 中使用 load() / loadi() 函数却不能支持相对路径:
*Error* load: can't access file - "./dir/test.il" 【[|[ Skill ] load 函数优化,识别相对路径】在上一篇随笔 文件读写 & IO 句柄 整理的内容中,发现内置的句柄 piport 可以获取当前文件的路径这一特性,于是有了这一篇。
几个函数 __FILE__
在 Perl 中 __FILE__ 用来获取当前文件的路径,这里模仿一个。
procedure(__FILE__() get_filename(piport) ); __FILE__

  • 运行:
    printf("Current path: %s\n" (__FILE__)) ; Current path: /home/yeung/tmp/load.il

__DIR__
正则处理,从 __FILE__ 结果中提取父目录的路径。
需要注意的是,如果是在 CIW 中执行的 __FILE__,它的返回值会是 *ciwInPort*,这种情况直接返回当前路径 getWorkingDir
procedure(__DIR__(\@optional path((__FILE__)) "t") if(pcreMatchp("^\\*.+\\*$" path) getWorkingDir() pcreReplace(pcreCompile("(?<=/)[^/]+/*$") path "" 0) ) ); __DIR__

  • 运行:
    printf("Current directory: %s\n" (__DIR__)) ; Current directory: /home/yeung/tmp/

ycReadRelPath
这个函数用来将 相对路径 转为 绝对路径 。
当路径为 ~ 或者 / 开头是,说明已经是绝对路径了,这种情况直接原封不动返回。
procedure(ycReadRelPath(\@optional file("") "t") let((path) path = if(pcreMatchp("^[~/]" file) file sprintf(nil "%s/%s" (__DIR__) file) ) simplifyFilename(path t) ); let ); ycReadRelPath

  • 运行:
    printf("Target path: %s\n" ycReadRelPath("./init/load.il")) ; Target path: /home/yeung/tmp/dir/test.il

ycLoad
优化 load 函数。
预留一个 ignores 参数用来优化 loadi 函数。
procedure(ycLoad(file \@optional ignore "tg") let((path) path = ycReadRelPath(file) unless(isFile(path) error("ycLoad: not a valid file - %A" path) ) unless(isReadable(path) error("ycLoad: can't access file - %A" path) ) if(ignore loadi(path) load(path)) ) ); ycLoad

ycLoadi
优化 loadi 函数。
同样可以忽略 load 过程中遇到的错误,打印错误消息,然后继续 load 。
procedure(ycLoadi(file "t") ycLoad(file t) ); ycLoadi

效果
  • 没有 ycLoad 之前
    let((home wind sync) home = "/home/yeung/script/skill/tools/" wind = list("hiForm.il" "windCtrl.il") sync = list("syncView.il" "support3rd.il") foreach(x wind load(strcat(home "src/wind/" x)) ) foreach(x sync load(strcat(home "/src/sync/" x)) ) ); let

    非常啰嗦。
    其次如果父文件夹改了名,或者移动了位置,还得一个个文件打开检查路径并修改,还要增加无意义的版本。
    copy 给别人也不能傻瓜式操作,直接 load 报个错:
    *Error* load: can't access " 唉 你 这 脚 本 有 问 题 啊 ? "
  • 有了 ycLoad 之后
    ycLoad("src/wind/hiForm.il") ycLoad("src/wind/windCtrl.il") ycLoad("src/sync/syncView.il") ycLoad("src/sync/support3rd.il")

    "优雅地" load 完所有文件。
    [|[ Skill ] load 函数优化,识别相对路径
    文章图片

    推荐阅读