gotar wrote: ↑Thu 25 Jun, 2020 18:12Я-то думал вызвать far.MacroLoadAll, но хотел бы посмотреть и Ваш код
мой код на основе вашего кода, отдаю должок
Code: Select all
<YOUR-MODULE-NAME-HERE>.fnc_load_macro_one = function(mcr_info, mcr_path)
mcr_path = far.ConvertPath(mcr_path, 1)
-- CLEANING OLD VERSION OF THE MACRO FILE (PREVIOUSLY LODADED)
-- I WILL EXPLAIN fnc_clean_mcr_src_all(..) LATER ON
<YOUR-MODULE-NAME-HERE>.fnc_clean_mcr_src_all(mcr_path)
local fnc, msg = loadfile(mcr_path)
if not fnc
then far.Message(msg, "Error loading macro file", nil, "w") return
end
local env_m = {
Macro = function(srctable) mf.AddMacro(srctable, mcr_path) end,
Event = function(srctable) mf.AddMacro(srctable, mcr_path) end
}
setmetatable(env_m, mt_g)
setfenv(fnc, env_m)
local ret, msg = pcall(fnc)
if not ret then
far.Message(msg, "Error loading macro func", nil, "w")
end
end
Code: Select all
-- HAVING ABOVE ROUTINE FOR SINGLE MACRO,
-- LOADING FROM ENTIRE DIRECTORY:
<YOUR-MODULE-NAME-HERE>.fnc_load_macro_dir = function(src_dir)
far.RecursiveSearch(
src_dir --[["." - current dir]],
"*.lua",
<YOUR-MODULE-NAME-HERE>.fnc_load_macro_one,
0
)
end
Самое главное иметь функцию для очистки от предыдущей версий
Но тут вещи немного усложняются, внутри моих функций вызываются другие,
которые в свою очередь обращаются к хитро вытащенным наружу внутренним обьектам плагина LuaMacro
Code: Select all
<YOUR-MODULE-NAME-HERE>.fnc_clean_mcr_src_all = function(mcr_src)
<YOUR-MODULE-NAME-HERE>.fnc_clean_mcr_src_tbl(mcr_src, <YOUR-MODULE-NAME-HERE>.utils.LoadedMacros)
for ii_area, tbl_area in pairs(<YOUR-MODULE-NAME-HERE>.utils.Areas)
do for ii_key, tbl_key in pairs(tbl_area)
do <YOUR-MODULE-NAME-HERE>.fnc_clean_mcr_src_tbl(mcr_src, tbl_key)
end
end
end
Code: Select all
<YOUR-MODULE-NAME-HERE>.fnc_clean_mcr_src_tbl = function(mcr_src, tbl_mcr)
local mcr_cnt = #tbl_mcr
local mcr_rem = 0
local ii_mcr
for ii = 1, mcr_cnt - mcr_rem
do ii_mcr = tbl_mcr[ii]
if ii_mcr.FileName == mcr_src
then mcr_rem = mcr_rem + 1
end
if mcr_rem > 0
then tbl_mcr[ii] = tbl_mcr[ii + mcr_rem]
end
end
end
А те самые внутренние обьекты плагина LuaMacro добываются таким образом,
находясь в _macroinit.lua:
Code: Select all
local all_the_stuff = {}
for ii = 0, 1000 do
local mcr_src, mcr_inf, LastWriteTime, tbl_locals, tbl_upvals, dbg_info = <YOUR-MODULE-NAME-HERE>.fnc_get_src_info(nil, ii, nil, 2, 2, false)
if not dbg_info then break end
if tbl_upvals.LoadedMacros then
<YOUR-MODULE-NAME-HERE>.utils = tbl_upvals
<YOUR-MODULE-NAME-HERE>.utils_locals = tbl_locals
break
end
all_the_stuff[ii] = {mcr_src = mcr_src, mcr_inf = mcr_inf, LastWriteTime = LastWriteTime, tbl_locals = tbl_locals, tbl_upvals = tbl_upvals, dbg_info = dbg_info}
end
Используем эту функцию, написанную в очередном приступе умопомрачения,
но полезную следующим поколениям умопомрачившихся:
Code: Select all
<YOUR-MODULE-NAME-HERE>.fnc_get_src_info = function(src_thr, src_lev, show_info, mode_locals, mode_upvals, with_nums, tbl_locals, tbl_upvals)
if type(src_thr) ~= "thread" and
type(src_thr) ~= "nil"
then
src_thr, src_lev, show_info, mode_locals, mode_upvals, tbl_locals, tbl_upvals = nil,
src_thr, src_lev, show_info, mode_locals, mode_upvals, tbl_locals, tbl_upvals
end
local dbg_info, LoadedMacros, mcr_src, mcr_inf
if not tbl_upvals then tbl_upvals = {} end
if not tbl_locals then tbl_locals = {} end
local dbg_props = nil -- "nSlfu"
local is_same_thr = not src_thr or coroutine.running() == src_thr
if is_same_thr
then dbg_info = debug.getinfo(src_lev, dbg_props) -- "nSlfu" ?
else dbg_info = debug.getinfo(src_thr, src_lev, dbg_props)
end
if dbg_info
then local fnc_name, fnc_code, curr_line = <YOUR-MODULE-NAME-HERE>.fnc_guess_func_name(dbg_info)
if not dbg_info.name then
dbg_info.name = fnc_name
end
dbg_info.currentline_txt = curr_line
dbg_info.source_code = fnc_code
mcr_src = dbg_info.source:sub(2)
mcr_inf = win.GetFileInfo(mcr_src)
if mode_upvals and mode_upvals > 0
then for ii = 1, dbg_info.nups
do local n, v = debug.getupvalue(dbg_info.func, ii)
if band(mode_upvals, 2) == 2 then
tbl_upvals[with_nums and "["..ii.."] "..n or n] = v or "<NIL>"
end
end
end
if mode_locals and mode_locals > 0
then local ii = 0
while true
do ii = ii + 1
local n, v
if is_same_thr
then n, v = debug.getlocal(src_lev, ii)
else n, v = debug.getlocal(src_thr, src_lev, ii)
end
if not n then break end
if band(mode_locals, 2) == 2 then
tbl_locals[with_nums and "["..ii.."] "..n or n] = v or "<NIL>"
end
end
end
elseif type(src_lev) == "string"
then mcr_inf = win.GetFileInfo(src_lev)
if mcr_inf then mcr_src = src_lev end
end
if mcr_src then mcr_src = far.ConvertPath(mcr_src, 1) end
return mcr_src, mcr_inf, mcr_inf and mcr_inf.LastWriteTime, tbl_locals, tbl_upvals, dbg_info
end -- end of fnc_get_src_info
.. в которой функции в свою очередь используются такие (когда же это кончится):
Code: Select all
<YOUR-MODULE-NAME-HERE>.fnc_guess_func_name = function(dbg_info)
local line_str, line_def, line_cur, src_code
local src_code = ""
if type(dbg_info.source) == "string" and dbg_info.source:sub(1, 1) == "@"
then
local fileH, err = io.open(dbg_info.source:sub(2), "r")
if not fileH
then return "?"
end
for line_num = 1, dbg_info.lastlinedefined
do line_str = fileH:read("*l")
if not line_str then break end
if line_num == dbg_info.linedefined
then line_def = line_str
end
if line_num == dbg_info.currentline
then line_cur = line_str
end
if line_num >= dbg_info.linedefined and
line_num <= dbg_info.lastlinedefined
then src_code = src_code..line_str..string.char(10)..string.char(13)
end
end
fileH:close()
else
local line_num = 0
for line_str in string.gmatch(dbg_info.source, "([^\n]+)\n-")
do line_num = line_num + 1
if line_num == dbg_info.linedefined
then line_def = line_str
end
if line_num == dbg_info.currentline
then line_cur = line_str
end
if line_num >= dbg_info.linedefined and
line_num <= dbg_info.lastlinedefined
then src_code = src_code..line_str..string.char(10)..string.char(13)
end
end
end
if src_code == "" then src_code = nil end
return line_def and <YOUR-MODULE-NAME-HERE>.fnc_parse_fnc_def(line_def) or "?", src_code, line_cur
end -- end of fnc_guess_func_name
Code: Select all
<YOUR-MODULE-NAME-HERE>.fnc_parse_fnc_def = function(line)
assert(type(line) == "string")
local match = line:match("^%s*function%s+(%w+)")
if match then
return match
end
match = line:match("^%s*local%s+function%s+(%w+)")
if match then
return match
end
match = line:match("^%s*local%s+(%w+)%s+=%s+function")
if match then
return match
end
match = line:match("%s*function%s*%(") -- this is an anonymous function
if match then
return "(anonymous)"
end
return "(anonymous)"
end -- end of fnc_parse_fnc_def
Кажется все.
Думаю теперь Вы поняли почему я так долго не мог собраться это показывать