Code: Select all
local ffi=require("ffi")
local C=ffi.C
local function safe_cdef(name,def)
if not pcall(ffi.sizeof,name) then ffi.cdef(def) end
end
safe_cdef("SECURITY_ATTRIBUTES",[[
typedef struct _SECURITY_ATTRIBUTES {
unsigned long nLength;
void* lpSecurityDescriptor;
int32_t bInheritHandle;
} SECURITY_ATTRIBUTES;
]])
safe_cdef("STARTUPINFOW",[[
typedef struct _STARTUPINFOW {
unsigned long cb;
wchar_t* lpReserved;
wchar_t* lpDesktop;
wchar_t* lpTitle;
unsigned long dwX;
unsigned long dwY;
unsigned long dwXSize;
unsigned long dwYSize;
unsigned long dwXCountChars;
unsigned long dwYCountChars;
unsigned long dwFillAttribute;
unsigned long dwFlags;
unsigned short wShowWindow;
unsigned short cbReserved2;
unsigned char* lpReserved2;
void* hStdInput;
void* hStdOutput;
void* hStdError;
} STARTUPINFOW;
]])
safe_cdef("PROCESS_INFORMATION",[[
typedef struct _PROCESS_INFORMATION {
void* hProcess;
void* hThread;
unsigned long dwProcessId;
unsigned long dwThreadId;
} PROCESS_INFORMATION;
]])
ffi.cdef[[
int32_t CreatePipe(void** hReadPipe,void** hWritePipe,SECURITY_ATTRIBUTES* lpPipeAttributes,unsigned long nSize);
int32_t CreateProcessW(const wchar_t* lpApplicationName,wchar_t* lpCommandLine,SECURITY_ATTRIBUTES* lpProcessAttributes,SECURITY_ATTRIBUTES* lpThreadAttributes,int32_t bInheritHandles,unsigned long dwCreationFlags,void* lpEnvironment,const wchar_t* lpCurrentDirectory,STARTUPINFOW* lpStartupInfo,PROCESS_INFORMATION* lpProcessInformation);
int32_t ReadFile(void* hFile,void* lpBuffer,unsigned long nNumberOfBytesToRead,unsigned long* lpNumberOfBytesRead,void* lpOverlapped);
int32_t CloseHandle(void* hObject);
void* GetStdHandle(unsigned long nStdHandle);
int32_t IsTextUnicode(const void* lpv,int iSize,int* lpiResult);
]]
local advapi32=ffi.load("advapi32")
local CREATE_NO_WINDOW=0x8000000
local STD_INPUT_HANDLE=-10
local STARTF_USESTDHANDLES=0x00000100
local IS_TEXT_UNICODE_ASCII16=0x0001
local IS_TEXT_UNICODE_STATISTICS=0x0002
local function ToWChar(str)
str=win.Utf8ToUtf16(str)
local result=ffi.new("wchar_t[?]",#str/2+1)
ffi.copy(result,str)
return result
end
local function split(data,callback)
while true do
local s,f=string.find(data,"[\n\r]")
if s then
local line=string.sub(data,1,s-1)
callback(line)
if string.sub(data,s,f+1)=="\r\n" then f=f+1 end
data=string.sub(data,f+1)
else
break
end
end
return data
end
local function Execute(command,folder,callback)
local pipe_security=ffi.new("SECURITY_ATTRIBUTES")
pipe_security.nLength=ffi.sizeof(pipe_security)
pipe_security.bInheritHandle=true
local pipe_in,pipe_out=ffi.new("void*[1]"),ffi.new("void*[1]")
if C.CreatePipe(pipe_in,pipe_out,pipe_security,0) then
local startup=ffi.new("STARTUPINFOW")
startup.cb=ffi.sizeof(startup)
startup.dwFlags=STARTF_USESTDHANDLES
startup.hStdInput=C.GetStdHandle(STD_INPUT_HANDLE)
startup.hStdOutput=pipe_out[0];
startup.hStdError=pipe_out[0];
local info=ffi.new("PROCESS_INFORMATION")
if C.CreateProcessW(ffi.NULL,ToWChar(command),ffi.NULL,ffi.NULL,true,CREATE_NO_WINDOW,ffi.NULL,ToWChar(folder),startup,info)~=0 then
C.CloseHandle(pipe_out[0])
local size=1024
local buffer=ffi.new("char[?]",size)
local readed=ffi.new("unsigned long[1]")
local unicode=ffi.new("int[1]")
unicode[0]=bit64.bor(IS_TEXT_UNICODE_ASCII16,IS_TEXT_UNICODE_STATISTICS)
local output=""
while true do
C.ReadFile(pipe_in[0],buffer,size,readed,ffi.NULL)
if readed[0]==0 then
break
else
output=output..(advapi32.IsTextUnicode(buffer,readed[0],unicode)==0 and win.OemToUtf8 or win.Utf16ToUtf8)(ffi.string(buffer,readed[0]))
output=split(output,callback)
end
end
if #output>0 then callback(output) end
C.CloseHandle(info.hThread)
C.CloseHandle(info.hProcess)
end
C.CloseHandle(pipe_in[0])
end
end
return Execute
- execute_v2.7z
- (2.32 KiB) Downloaded 553 times
Code: Select all
F=far.Flags
Compile=(command,folder,match)->
editor.SaveFile!
execute=require"execute"
rect=far.AdvControl F.ACTL_GETFARRECT
width,height=rect.Right-rect.Left-5,rect.Bottom-rect.Top-5
start=false
items={{"DI_LISTBOX",3,1,width-4,height-2,{}}}
DlgProc=(dlg,msg,param1,param2)->
if msg==F.DN_ENTERIDLE and not start
start=true
far.SendDlgMessage dlg,F.DM_LISTSETTITLES,1,Title:"Waiting..."
execute command,folder,(line)->far.SendDlgMessage dlg,F.DM_LISTADD,1,{{Text:line}}
far.SendDlgMessage dlg,F.DM_LISTSETTITLES,1,Title:"Done!"
dialog=far.DialogInit win.Uuid"7575E5CC-BDD2-4797-A651-ADA938C0190C",-1,-1,width,height,nil,items,0,DlgProc
if 1 == far.DialogRun dialog
item=far.SendDlgMessage dialog,F.DM_LISTGETITEM,1,far.SendDlgMessage(dialog,F.DM_LISTGETCURPOS,1).SelectPos
if item
filewitherror,line,pos=match(item.Text)
if filewitherror
editor.Editor filewitherror,filewitherror,0,0,-1,-1,bit64.bor(F.EF_NONMODAL,F.EF_IMMEDIATERETURN,F.EF_OPENMODE_USEEXISTING)
if line
editor.SetPosition -1,line,pos
far.DialogFree dialog
Macro
area:"Editor"
key:"F9"
description:"test execute"
filemask:"*.cpp,*.cc"
action:->
path,file,ext=editor.GetInfo!.FileName\match[[(.-)([^\\]-(%.?[^%.\\]*))$]]
Compile [[g++ -O3 -Wall -Wextra -c -o nul "]]..path..file..[["]],path,(line)->line\match [[(.-[^\\]-):([0-9]+):([0-9]+): ]]
! | Message from: John Doe |
Альтернативная версия модуля, с дополнительными функциями, см. тут: viewtopic.php?p=167895#p167895 |