local F = far.Flags
local _name = "alias.doskey"
local _filename = not _filename and ... or _filename:match[[^\\%?\(.+)$]]
local _aliasfile = _filename:match[[(.+\).+$]].._name
local ffi = require("ffi")
local C = ffi.C
local Shell32 = ffi.load"Shell32.dll"
local function safe_typedef(name,def)
if not pcall(ffi.sizeof,name) then ffi.cdef(def) end
end
local function safe_const(name,def)
if not pcall(function(const)return ffi.C[const] end,name) then ffi.cdef(def) end
end
safe_typedef("SHELLEXECUTEINFO",[[
//http://msdn.microsoft.com/library/bb759784
typedef struct _SHELLEXECUTEINFO {
DWORD cbSize;
ULONG fMask;
HWND hwnd;
LPCTSTR lpVerb;
LPCTSTR lpFile;
LPCTSTR lpParameters;
LPCTSTR lpDirectory;
int nShow;
HINSTANCE hInstApp;
LPVOID lpIDList;
LPCTSTR lpClass;
HKEY hkeyClass;
DWORD dwHotKey;
union {
HANDLE hIcon;
HANDLE hMonitor;
} DUMMYUNIONNAME;
HANDLE hProcess;
} SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;
]])
safe_const("SEE_MASK_NO_CONSOLE",[[static const ULONG SEE_MASK_NO_CONSOLE = 0x00008000;]])
ffi.cdef[[
//http://msdn.microsoft.com/library/bb762154
BOOL ShellExecuteExW(
SHELLEXECUTEINFO *pExecInfo
);
]]
local FALSE,TRUE = 0,1
local function wchar(str)
str = win.Utf8ToUtf16(str)
local buffer = ffi.new("wchar_t[?]",#str/ffi.sizeof"wchar_t"+1)
ffi.copy(buffer,str)
return buffer
end
local seInfo = ffi.new("SHELLEXECUTEINFO",ffi.sizeof("SHELLEXECUTEINFO"),C.SEE_MASK_NO_CONSOLE)
local function ShellExecuteEx(file,params)
seInfo.lpFile = wchar(file)
seInfo.lpParameters = wchar(params)
if Shell32.ShellExecuteExW(seInfo)==TRUE then
return true
else
return nil, tonumber(ffi.cast("int",seInfo.hInstApp))
end
end
local cmd = win.GetEnv"COMSPEC"
local function Reload()
local info = win.GetFileInfo(_aliasfile)
if not info then
far.Message(("File is absent: '%s'"):format(_aliasfile),"Console aliases",nil,"w")
return
end
local scr,time = far.SaveScreen(),Far.UpTime
far.Message("Loading...","Console aliases","")
ShellExecuteEx(cmd,('/c"doskey rr=doskey/macrofile="%s"" 1<&2 >nul'):format(_aliasfile))
ShellExecuteEx(cmd,('/c"doskey/macrofile="%s"" 1<&2 >nul'):format(_aliasfile))
local delay = 200-(Far.UpTime-time)
if delay>0 then mf.sleep(delay) end
far.RestoreScreen(scr)
end
Event { description="Load aliases";
group="EditorEvent"; filemask=_name;
condition=function(id,Event)
return Event==F.EE_CLOSE
and editor.GetInfo(id).FileName:lower()==_aliasfile:lower()
end;
action=function(id,Event)
local EditorInfo = editor.GetInfo()
if band(EditorInfo.CurState,F.ECSTATE_MODIFIED)~=0 then Reload(_aliasfile) end
end;
}
Macro { description="Load aliases";
area="Shell"; key="auto"; flags="RunAfterFARStart";
action=Reload;
}