前面幾天,我探索了 Lua 的變數型別、條件判斷、迴圈、標準函式庫等
在這過程中,我已經多少看過函數定義和使用了就算沒學過,看多了總會模仿阿
今天我就來正式的研究 Lua 函數怎麼寫
主題則是,自定義 CC: Tweaked 電腦開機時執行的程式碼!
之前我一直在研究開機時自動執行的 motd.lua
這次我想要讓電腦執行自己寫的 Lua 程式
挖掘開始!
首先,我已經知道開機時會自動執行 startup.lua
從這個線索往上溯源,可以找到 /rom/programs/shell.lua #591 有這一行
shell.run("/rom/startup.lua")
再繼續往上東翻西找,可以找到 /rom/bios.lua #977 有 Run the shell
這部分先不深入
但可以看出 startup.lua 被自動執行的脈絡
/rom/startup.lua 理論上是不能修改的,那我要怎麼自定義呢?
我東翻西找 startup 關鍵字,先看到 bios.lua #864 有這一段
-- Set default settings
settings.define("shell.allow_startup", {
default = true,
description = "Run startup files when the computer turns on.",
type = "boolean",
})
settings.define("shell.allow_disk_startup", {
default = commands == nil,
description = "Run startup files from disk drives when the computer turns on.",
type = "boolean",
})
看來就是設定是否允許跑 startup
接著搜尋 allow_startup、allow_disk_startup
可以看到 startup.lua #161 有這一段 Run the user created startup
-- Run the user created startup, either from disk drives or the root
local tUserStartups = nil
if settings.get("shell.allow_startup") then
tUserStartups = findStartups("/")
end
---------- 略 ----------
if tUserStartups then
for _, v in pairs(tUserStartups) do
shell.run(v)
end
end
答案呼之欲出了!我相信上面這一段有我要的東西~
來看看 findStartups 的函數定義
local function findStartups(sBaseDir)
local tStartups = nil
local sBasePath = "/" .. fs.combine(sBaseDir, "startup")
local sStartupNode = shell.resolveProgram(sBasePath)
if sStartupNode then
tStartups = { sStartupNode }
end
-- It's possible that there is a startup directory and a startup.lua file, so this has to be
-- executed even if a file has already been found.
if fs.isDir(sBasePath) then
if tStartups == nil then
tStartups = {}
end
for _, v in pairs(fs.list(sBasePath)) do
local sPath = "/" .. fs.combine(sBasePath, v)
if not fs.isDir(sPath) then
tStartups[#tStartups + 1] = sPath
end
end
end
return tStartups
end
這樣的函數定義,似乎跟其他語言大同小異,沒什麼好說的 ....
是這樣嗎?!
事實上,function 在 lua 世界裡面也是變數,型別就是 function!
如果忘記了,可以複習一下 Lua 變數型別與宣告
事實上,大家所看到的上面這一段宣告,只是 Lua 的語法糖
function findStartups(sBaseDir)
end
它原本的寫法是這樣
findStartups = function (sBaseDir)
end
如果再繼續找 shell.resolveProgram() 會看到 command:find("/")
這也是 Lua 的語法糖
原本的寫法是
string.find(command, "/")
還有一種寫法,我感到很陌生徬徨@@... 一時之間沒有了解,先筆記下來
string["find"](command, "/")
至於 local
則是限制這個變數的存取範圍
以上述為例,在 startup.lua 宣告 local,就是只能在 startup.lua 使用
否則任何地方都可以使用,這就是 Lua 的語言特性
任何變數沒有宣告 local 都是全域變數
回到一開始我想解決的問題,自定義開機程式
shell.resolveProgram(sBasePath) 會去找到 /startup.lua 和 /rom/startup.lua
所以只要自己新增 /startup.lua 即可在開機時自動執行
如果想要一次跑多個 Lua 程式檔
也可以新增多個檔案在 /startup/ 資料夾底下
今天先挖礦到這,下次我預計仍是會繼續研究 function