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 ./layout/cds.lib
| | 2| INCLUDE ./sch/cds.lib
| | 3| 略 ...
| |-- layout
| | `-- cds.lib ------- cat --> 1| DEFINE layout_lib1 ./layout_lib1
| | 2| DEFINE layout_lib2 ./layout_lib2
| | 3| 略略 ...
| |-- sch
| | `-- cds.lib ------- cat --> 1| 略略略 ...
| `-- 略略略略 ...
`-- 略略略略略 ...
可以看到,對於 cds.lib 檔案來說,INCLDUE
/ DEFINE
都可以使用相對路徑。
而在 Skill 中使用 load()
/ loadi()
函式卻不能支援相對路徑:
*Error* load: can't access file - "./dir/test.il"
*Error* load: error while loading file - "/home/yeung/tmp/load.il" at line 1
在上一篇隨筆 檔案讀寫 & 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()
作為 __DIR__
函式的返回值。
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
這個函式用來將 相對路徑 轉為 絕對路徑 。
當輸入路徑 path 為 ~
或者 /
開頭時,說明已經是絕對路徑了,這種情況直接原封不動返回。
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 完所有檔案。
繼續優化可以再識別 Shell 環境中的變數。