local _NAME = "module: rebind.lua"
local minfarbuild = 3748 --requires Far 3.0 build >3747
local F = far.Flags
local build = select(4,far.AdvControl(F.ACTL_GETFARMANAGERVERSION,true)) --3,0,0,3363,0
if build<minfarbuild
and 2~=far.Message(("FAR 3 build %s or newer required.\nYour build: %s")
:format(minfarbuild,build),_NAME,"Cancel;Continue","lw")
then return
end
local REBIND --settings loaded from base
local LoadedMacros
local new_fields = {"uid","rebinded","defline","disabled"}
local usedUids = {}
local auto_uids,no_warnings
local function Setup(options)
assert(type(options)=="table")
auto_uids,no_warnings = options.auto_uids,options.no_warnings
end
local function MakeUid(file,descr)
return ("≈%q: %s"):format(file:match"[^\\]+$",descr or 'nil') -- ±≠≡∞ƒ≈
end
local function AddMacroNew(m)
if type(m)~="table" then return end
if m.guid then return mf.AddMacro(m) end
local info = debug.getinfo(2,"lS") --todo check timings
m.defline = info.currentline --m.defline or info.currentline
m.uid = m.uid or auto_uids and MakeUid(info.source,m.description) --m.FileName or info.source
if not m.uid then
--just skip
elseif not usedUids[m.uid] then --uid is unique
local Binding = REBIND[m.uid] or {}
m.disabled = Binding.disabled
m.rebinded = Binding.key and m.key
m.key = Binding.key or m.key
else
m.uid = nil
if not no_warnings then far.Message(m.uid,"uid is not unique!",nil,"w") end
end
local id = mf.AddMacro(m)
--if id and m.FileName then LoadedMacros[id].FileName = m.FileName end
if m.uid then usedUids[m.uid] = id end
return id
end
do --playing with upvalues: get LoadedMacros, set AddMacro
local function getUpvalue(f,name)
for i=1,1000 do
local k,v = debug.getupvalue (f, i)
if k==nil then break end
if k==name then return v, i end
end
end
local utils = getUpvalue(eval,"utils")
local AddMacro,iAddMacro = getUpvalue(utils.LoadMacros,"AddMacro")
if not mf.AddMacro then
mf.AddMacro = AddMacro
local AddMacro_fields,iAddMacro_fields = getUpvalue(mf.AddMacro,"AddMacro_fields")
for i=1,#new_fields do AddMacro_fields[#AddMacro_fields+1] = new_fields[i] end
debug.setupvalue (mf.AddMacro,iAddMacro_fields,AddMacro_fields)
end
LoadedMacros = assert(getUpvalue(mf.AddMacro,"LoadedMacros") or false)
debug.setupvalue (utils.LoadMacros,iAddMacro,AddMacroNew)
end
local function Rebind (m) --static rebinding not using LuaMacro base
m.uid = m.uid or m.FileName and m.description and
MakeUid(m.FileName, m.description)
if type(m)~='table' or not m.uid then
far.Message(_NAME,"macro uid must be specified!",nil,"w")
return
end
REBIND[m.uid] = { disabled=m.disabled, key=m.key }
end
local function LoadBindings(file)
file = file or win.GetEnv('FARPROFILE') .. [[\Macros\scripts\bindings]]
local f,err = loadfile(file)
if err then far.Message(err,_NAME,nil,"w"); return end
local success,res = pcall(setfenv(f, {Rebind=Rebind}))
if not success then far.Message(res,_NAME,nil,"w"); return end
end
REBIND = {}
return {
Setup=Setup,
Rebind=Rebind,
LoadBindings=LoadBindings,
}