Ru-Board.club
← Вернуться в раздел «Тестирование»

» Far Manager - скрипты и плагины

Автор: Angel_Ka
Дата сообщения: 15.05.2016 19:19

Цитата:
в будущем не исключено и такое развитие событий

Благодарю Вас за оптимистический ответ! Приятно знать, что макрос развивается.
Автор: Angel_Ka
Дата сообщения: 16.05.2016 02:54
shmuz2
Глюк, проявлявшийся в плагиновых и в нативной временных панелях в Фар версий 4671 и 4672 в Win10entRu x64, теперь (в 4674) не проявляется! Проверено на сборке от skipik001.
Автор: Alexyz21
Дата сообщения: 16.05.2016 09:55
Shmuel

Код:
ffi.cdef[[
wchar_t* wmemset(wchar_t*, wchar_t, size_t);
]]
...
ptr = C.wcschr(name,TAB)
wmemset(ptr,ZERO,1)
...
Автор: shmuz2
Дата сообщения: 16.05.2016 11:56
Alexyz21
Не знаю почему, но wmemset действительно отсутствует, например, в msvcrt.dll. Пользуйтесь memset.
Вообще я не спец по вопросу какие ф-ции доступны и где. Пользуюсь Гуглом и утилитой Dependency Walker - то же можете сделать и вы.
Автор: Alexyz21
Дата сообщения: 16.05.2016 14:19
Задекларировал
void* memset(void*, int, size_t);

local BS,TAB,ZERO,ts = string.byte("\\"),string.byte("\t"),string.byte("\000")
заюзал
ptr = C.wcschr(name,TAB)
C.memset(ptr,0,1)
Результат:

Код: Exception: Access violation (write to 0x00000000)
Address: 0x77C37637 memset
Function: OpenW
Module: C:\Program Files\FAR\Plugins\LuaMacro\LuaMacro.dll
Автор: shmuz2
Дата сообщения: 16.05.2016 14:45
Alexyz21
- memset() вызван с неправильными значениями аргументов
- если б ptr указывал на TAB, не было бы exception
- LuaJIT поддерживает 64-битные целые
Автор: Alexyz21
Дата сообщения: 16.05.2016 16:12
Спасибо, буду разбираться. Спасибо ещё раз, вроде разобрался.
Автор: shmuz2
Дата сообщения: 16.05.2016 17:53
Angel_Ka
Анти-дубликатор выложен на форуме с русской справкой. Спасибо за участие.
Автор: Alexyz21
Дата сообщения: 16.05.2016 20:24
Обновил 4672 на 4674 - в 2 раза медленнее стали работать бачи RESearch, обрабатывающие текст в редакторе. Вернулся на 4671 - всё снова полетело на прежней скорости.
Автор: Angel_Ka
Дата сообщения: 16.05.2016 21:11
shmuz2

Цитата:
Анти-дубликатор выложен на форуме с русской справкой. Спасибо за участие.

Очень рад если действительно чуток подсобил. Удачи Вам в развитии макроса к общей пользе!

Если я правильно понял хелп, то макрос считает две строки "дубликатами" по отношению друг к другу, в т.ч. если они начинаются с одной и той же 20-символьной последовательности. Это "вшитая" установка? А можно ли настроить макрос на N-символьную последовательность от конца строки?

Alexyz21

Цитата:
Обновил 4672 на 4674 - в 2 раза медленнее стали работать бачи RESearch, обрабатывающие текст в редакторе.

Этого я ещё пока не изучал. И обстоятельно посмотреть, к сожалению, наверное не смогу и на этой неделе — начальник неожиданно дал задание готовить отчёт отдела к пятничному совещанию в верхах, и меня с собой туда тащит. И хотя я этого раньше не делал, но вижу, что сложного ничего нет. Просто муторно и очень времязатратно.
Автор: Alexyz21
Дата сообщения: 16.05.2016 21:16
Angel_Ka

Цитата:
А можно ли настроить макрос на N-символьную последовательность от конца строки?

Не надо с этим приставать, у него и так работы выше крыши. Сортировщик в редакторе сделал 70%, пока думаю что должно быть на входе и в каком формате.
Автор: Angel_Ka
Дата сообщения: 16.05.2016 21:29
Alexyz21

Цитата:
Сортировщик в редакторе сделал 70%, пока думаю что должно быть на входе и в каком формате.

ОГРОМНОЕ СПАСИБО! Вы меня несказанно обрадовали!
Автор: shmuz2
Дата сообщения: 16.05.2016 21:34
Angel_Ka

Цитата:
Если я правильно понял хелп, то макрос считает две строки "дубликатами" по отношению друг к другу, в т.ч. если они начинаются с одной и той же 20-символьной последовательности. Это "вшитая" установка?

Это же только пример из хелпа, взятый с потолка. Ничего такого вшитого нет.

Цитата:
А можно ли настроить макрос на N-символьную последовательность от конца строки?

Впишите в поле "Выражение" L:sub(-N) (вместо N подставьте то, что вам надо). Скорее всего, вам потребуется более сложное выражение, но не зная точно, чего вы хотите, я привёл вам простое.
Автор: Angel_Ka
Дата сообщения: 16.05.2016 21:37
Alexyz21

Цитата:
что должно быть на входе и в каком формате

Желательно бы содержание файла-списка. LuaFAR Search формирует его в 65001 с BOM.

А RESearch на Win10entRu x64 валится и в Фар 4674 x64, и в Фар 4674 x86.

Добавлено:
shmuz2

Цитата:
Впишите в поле "Выражение" L:sub(-N) (вместо N подставьте то, что вам надо).

Спасибо большое за разъяснение! Буду пробовать для накопления опыта.

Цитата:
но не зная точно, чего вы хотите ...

А я пока ещё сам не определился до конца чего хочу получить от макроса в результате. Просто пробую разные варианты. Приноравливаюсь к работе в редакторе. Я ведь с ним очень мало знаком, только самые простые действия. Кстати, с благодарностью к Вам с удовольствием применяю в редакторе архиудобный scite_like.
Автор: Alexyz21
Дата сообщения: 16.05.2016 22:15
Angel_Ka
0.1 [more]
Код: -- 0.1
local F = far.Flags
local ffi = require'ffi'
local C = ffi.C
local NULL = ffi.cast("void*",0)
local PANEL_ACTIVE = ffi.cast("HANDLE",-1)

local PanelMode,Desc1,Indi1 = 999,"Select duplicates","!?"
local guid = "FE9B8874-9651-434C-8182-72329F2371A5"
local uGuid = win.Uuid(guid)
local BS,TAB,ZERO,ts = string.byte("\\"),string.byte("\t"),string.byte("\000"),{nil,true,9999,true,false,2,2,true,false}
local freport = win.GetEnv("Temp").."\\Report.txt"

ffi.cdef[[
void free (void*);
unsigned long int wcstoul(const wchar_t*, wchar_t**, int);
unsigned long long int wcstoull(const wchar_t*, wchar_t**, int);
wchar_t* wmemset(wchar_t*, wchar_t, size_t);
void* memset(void*, int, size_t);
int wcscmp(const wchar_t*, const wchar_t*);
int _wcsicmp(const wchar_t*, const wchar_t*);
int wcsncmp(const wchar_t*, const wchar_t*, size_t);
int _wcsnicmp(const wchar_t*, const wchar_t*, size_t);
]]

local function ToWChar(str)
str=win.Utf8ToUtf16(str)
local res=ffi.new("wchar_t[?]",#str/2+1)
ffi.copy(res,str)
return res
end

local function GetStartAndLenW(name)
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and name or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
local res=ffi.new("wchar_t[?]",len+1)
ffi.copy(res,name+len+ts[3],-ts[3]*2)
ffi.copy(res-ts[3],name,(len+ts[3])*2)
return res,len
else
return name,len
end
end

local function StartAndLenW(name)
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and name or ptr+1
--local len = tonumber(C.wcslen(name))
--local res=ffi.new("wchar_t[?]",len+1)
--ffi.copy(res,name,len*2)
ptr = C.wcschr(name,TAB)
C.memset(ptr,ZERO,2)
local len = tonumber(C.wcslen(name))
--C.memset(ptr,TAB,1)
local size = ptr==nil and name or ptr+1
local fnsz = tonumber(C.wcslen(size))
size = tonumber(C.wcstoul(size,NULL,0))
--len = len-fnsz-1
--local fnsz = ptr==nil and name or ptr-size
if ts[2] and ts[3]<0 and -ts[3]<len then
return name+len+ts[3],-ts[3],name,len,size,fnsz
elseif ts[2] and ts[3]>0 and ts[3]<len then
return name,ts[3],name,len,size,fnsz
else
return name,len,name,len,size,fnsz
end
end

local compare = function(p1,p2)
local st1,ln1 = GetStartAndLenW(p1[2])
local st2,ln2 = GetStartAndLenW(p2[2])
local res = ts[4] and C._wcsicmp(st1,st2) or C.wcscmp(st1,st2)
if res==0 and (ts[5] or not ts[2]) and ts[6]~=2 then res=p1[8]-p2[8] end
return res>0 and true or false
end

local Items = {
--[[01]] {F.DI_DOUBLEBOX, 3,1, 65,9, 0, 0,0, 0, "Select duplicates of FileName. Help: F1"},
--[[02]] {F.DI_CHECKBOX, 5,2, 26,2, 0, 0,0, 0, "Num&ber of symbols"},
--[[03]] {F.DI_EDIT, 27,2, 32,2, 0, 0,0, 0, ""},
--[[04]] {F.DI_CHECKBOX, 5,3, 20,3, 0, 0,0, 0, "Ignore &case"},
--[[05]] {F.DI_CHECKBOX, 38,3, 62,3, 0, 0,0, 0, "Ignore Full &Duplicates"},
--[[06]] {F.DI_CHECKBOX, 5,4, 21,4, 0, 0,0, F.DIF_3STATE, "&Sizes of FD:"},
--[[07]] {F.DI_CHECKBOX, 5,5, 26,5, 0, 0,0, F.DIF_3STATE, "&Attributes of FD:"},
--[[08]] {F.DI_CHECKBOX, 5,6, 35,6, 0, 0,0, 0, "Accuracy (&two-pass method)"},
--[[09]] {F.DI_CHECKBOX, 5,8, 15,8, 0, 0,0, 0, "Re&port"},
--[[10]] {F.DI_TEXT, -1,7, 0,0, 0, 0,0, F.DIF_SEPARATOR,""},
--[[11]] {F.DI_BUTTON, 0,8, 0,0, 0, 0,0, F.DIF_DEFAULTBUTTON+F.DIF_CENTERGROUP,"&Ok"},
--[[12]] {F.DI_BUTTON, 0,8, 0,0, 0, 0,0, F.DIF_CENTERGROUP,"Ca&ncel"}
}

local tts={}

local function DlgProc(hDlg,Msg,Param1,Param2)
local function Set1()
hDlg:send(F.DM_ENABLE,5,tts[2] and 1 or 0)
hDlg:send(F.DM_ENABLE,6,(tts[5] or not tts[2]) and 1 or 0)
hDlg:send(F.DM_ENABLE,7,(tts[5] or not tts[2]) and 1 or 0)
end
if Msg==F.DN_INITDIALOG then
for i=2,#Items-3 do tts[i]=ts[i] end
Set1()
hDlg:send(F.DM_SETTEXT,3,tts[3])
hDlg:send(F.DM_SETCHECK,2,tts[2] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,4,tts[4] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,5,tts[5] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,6,tts[6]==0 and F.BSTATE_UNCHECKED or tts[6]==1 and F.BSTATE_CHECKED or tts[6]==2 and F.BSTATE_3STATE)
hDlg:send(F.DM_SETTEXT,6,"&Sizes of FD: "..(tts[6]==0 and "<>" or tts[6]==1 and "==" or "--"))
hDlg:send(F.DM_SETCHECK,7,tts[7]==0 and F.BSTATE_UNCHECKED or tts[7]==1 and F.BSTATE_CHECKED or tts[7]==2 and F.BSTATE_3STATE)
hDlg:send(F.DM_SETTEXT,7,"&Attributes of FD: "..(tts[7]==0 and "<>" or tts[7]==1 and "==" or "--"))
hDlg:send(F.DM_ENABLE,8,(tts[6]==0 or tts[7]==0) and 1 or 0)
hDlg:send(F.DM_SETCHECK,8,tts[8] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,9,tts[9] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
elseif Msg==F.DN_BTNCLICK and (Param1==2 or Param1==4 or Param1==5 or Param1==8 or Param1==9) then
tts[Param1] = Param2~=0
if Param1==2 or Param1==5 then Set1() end
elseif Msg==F.DN_BTNCLICK and (Param1==6 or Param1==7) then
tts[Param1] = Param2
hDlg:send(F.DM_SETTEXT,Param1,(Param1==6 and "&Sizes of FD: " or "&Attributes of FD: ")..(Param2==0 and "<>" or Param2==1 and "==" or "--"))
hDlg:send(F.DM_ENABLE,8,Param2==0 and 1 or 0)
elseif Msg==F.DN_EDITCHANGE and Param1==3 then -- Number symbols
tts[3] = tonumber(hDlg:send(F.DM_GETTEXT,3)) or tts[3]
else
return
end
return true
end

Macro {
description="@ Select Duplicates FileName in Branch panel"; name="SDFN"; area="Editor";
action=function()
if far.Dialog(uGuid,-1,-1,69,11,nil,Items,nil,DlgProc)==#Items-1 then
local t0=far.FarClock()
for i=2,#Items-3 do ts[i]=tts[i] end
local pBL0,pBL1 = ffi.cast("BOOL*",0),ffi.cast("BOOL*",1)
_G.tsel = {}
--local function Comp(stA,lnA,stB,lnB) return ts[4] and C._wcsicmp(stA,stB) or C.wcscmp(stA,stB) end
local function Proc(i,x)
if ts[5] and x then
else
if ts[2] or not ts[2] and x then
tsel[i-1][1]=true
tsel[i][1]=true
end
end
end
local text,len,nw,l = "",0,win.Utf8ToUtf16("\n")
--local pc=ffi.cast("struct PluginStartupInfo*",far.CPluginStartupInfo()).PanelControl
local ec=ffi.cast("struct PluginStartupInfo*",far.CPluginStartupInfo()).EditorControl
local ei=ffi.new("struct EditorInfo")
ei.StructSize=ffi.sizeof(ei)
if ec(-1,"ECTL_GETINFO",0,ei) then
l=ei.TotalLines-1
local ss,ln
local egs=ffi.new("struct EditorGetString")
egs.StructSize=ffi.sizeof(egs)
local function PGPL(i)
egs.StringNumber=i
if ec(-1,"ECTL_GETSTRING",0,egs) then
local st1,ln1,st3,ln3,sz1,fnsz=StartAndLenW(ffi.cast("const unsigned short*",egs.StringText))
table.insert(tsel,{false,st1,ln1,st3,ln3,ffi.string(st1,ln1*2),ffi.string(st3,ln3*2),sz1--[[tonumber(win.Utf16ToUtf8(ffi.string(sz1,fnsz*2)))]]})
end
end
for i=0,l do PGPL(i) end
table.sort(tsel,compare)
for i=2,l+1 do
if ts[4] and (ts[2] and C._wcsnicmp(tsel[i][2],tsel[i-1][2],ts[3])==0 or C._wcsicmp(tsel[i][2],tsel[i-1][2])==0) then Proc(i,C._wcsicmp(tsel[i][4],tsel[i-1][4])==0 and not (ts[6]==0 and tsel[i][8]==tsel[i-1][8] or ts[6]==1 and tsel[i][8]~=tsel[i-1][8] or ts[6]==2 and false))
elseif not ts[4] and (ts[2] and C.wcsncmp(tsel[i][2],tsel[i-1][2],ts[3])==0 or C.wcscmp(tsel[i][2],tsel[i-1][2])==0) then Proc(i,C.wcscmp(tsel[i][4],tsel[i-1][4])==0 and not (ts[6]==0 and tsel[i][8]==tsel[i-1][8] or ts[6]==1 and tsel[i][8]~=tsel[i-1][8] or ts[6]==2 and false))
end
end
if ts[8] then
for i=2,l+1 do
if ts[6]==0 and tsel[i][8]==tsel[i-1][8] and ((ts[4] and (ts[2] and C._wcsnicmp(tsel[i][2],tsel[i-1][2],ts[3])==0 or C._wcsicmp(tsel[i][2],tsel[i-1][2])==0)) or (not ts[4] and (ts[2] and C.wcsncmp(tsel[i][2],tsel[i-1][2],ts[3])==0 or C.wcscmp(tsel[i][2],tsel[i-1][2])==0))) then
tsel[i-1][1]=false
tsel[i][1]=false
end
end
end
end
--Keys("ShiftF12")
if ts[9] then
--table.sort(tsel,function(a,b) return a[1]<b[1] end)
local TAB = win.Utf8ToUtf16("\t")
local h = io.open(freport,"wb")
io.close(h)
h = io.open(freport,"ab")
local s = "Items: "..#tsel..
"\nExecution time: "..(far.FarClock()-t0)..
" mcs\nNumber of symbols: "..(ts[2] and ts[3] or "all")..
"\nIgnore case: "..tostring(ts[4])..
"\nIgnore Full Duplicates: "..tostring(ts[5])..
((ts[5] or not ts[2]) and ("\nSizes of FD: "..(ts[6]==0 and "<>" or ts[6]==1 and "==" or "--")) or "")..
((ts[5] or not ts[2]) and ("\nAttributes of FD: "..(ts[7]==0 and "<>" or ts[7]==1 and "==" or "--")) or "")..
"\n"..string.rep("-",30).."\n"
h:write(win.Utf8ToUtf16(s))
for i=#tsel,1,-1 do if tsel[i][1] then h:write(tsel[i][7]..TAB..win.Utf8ToUtf16(tsel[i][8])..nw) end --[[table.remove(tsel)]] end
io.close(h)
far.Message("mcs: "..far.FarClock()-t0,"SDFN")
end
end
end;
}

Macro {
description = "SDFN - Help"; area = "Dialog"; key = "F1";
condition=function() return Area.Dialog and Dlg.Id==guid end;
action=function()
if Dlg.CurPos<=3 then far.Message("The number of first or last symbols to compare","Help: Number of symbols")
elseif Dlg.CurPos==4 then far.Message("Case of letters in FileName will be ignored","Help: Ignore case")
elseif Dlg.CurPos==5 then far.Message("Full duplicates of FileName will be ignored","Help: Ignore Full Duplicates")
elseif Dlg.CurPos==6 then far.Message("-- ignore, == equal, <> is not equal","Help: Sizes of FD")
elseif Dlg.CurPos==7 then far.Message("-- ignore, == equal, <> is not equal","Help: Attributes of FD")
elseif Dlg.CurPos==8 then far.Message("Two-pass method for\n<> (is not equal) options only","Help: Accuracy")
elseif Dlg.CurPos==9 then far.Message("mcs - total time of execution in mcs\nReport will be saved to:\n"..freport,"Help: Report",nil,"l")
end
end;
}
Автор: Angel_Ka
Дата сообщения: 16.05.2016 22:44
Alexyz21

Цитата:
0.1

Большое спасибо! Попробовал так: сделал на базе микротеста файл-список panel.temp плагином LuaFAR Search, загрузил его в редактор Фара и запустил макрос. Вылезла ошибка:

Код: LuaMacro

...\Profile\Macros\scripts\edi_lua\5ctShF3(Alexyz21)edi.lua:168: 'for' limit must be a number
Stack Traceback
Автор: Angel_Ka
Дата сообщения: 17.05.2016 05:45
Alexyz21

Вроде как получается, что кроме макроса-сортировщика нужен бы ещё и макрос, создающий на основе папок со всеми их подпапками бранч-списки. Причём как в классическом стиле — из одних только полных имён файлов, так и в продвинутом — содержательно расширенном так же и размерами этих файлов. Это я верно понимаю?
Автор: Alexyz21
Дата сообщения: 17.05.2016 09:55

Цитата:
Вроде как получается, что кроме макроса-сортировщика мне бы нужен ещё и макрос, создающий на основе папок со всеми их подпапками бранч-списки. Причём как в классическом стиле — из одних только полных имён файлов, так и в продвинутом — содержательно расширенном так же и размерами этих файлов. Это я верно понимаю?

Точно. Если хотим обработку размеров файлов, то, естественно, размеры должны присутствовать в списке, не может же скрипт брать их из астрала. Брать же их из ФС по путям крайне неэффективно. То же касается и атрибутов. Можно использовать и имеющийся у вас бранч-список, нужно только эмулировать размер у файлов, для чего в начало каждой строки вставить произвольное число с табуляцией, например 0\t. Выходной Report.txt будет содержать то, что мы нафильтровали согласно настроек в диалоге. Самое первое число - это номер строки в исходном файле, затем табуляция и затем исходная строка полностью.

0.2 [more]
Код: -- 0.2
local F = far.Flags
local ffi = require'ffi'
local C = ffi.C
local NULL = ffi.cast("void*",0)
local PANEL_ACTIVE = ffi.cast("HANDLE",-1)
local pBL0,pBL1 = ffi.cast("BOOL*",0),ffi.cast("BOOL*",1)

local PanelMode,Desc1,Indi1 = 999,"Select duplicates","!?"
local guid = "FE9B8874-9651-434C-8182-72329F2371A5"
local uGuid = win.Uuid(guid)
local ZERO,HTAB,BS,ts = ffi.cast("unsigned int",0),ffi.cast("unsigned int",9),string.byte("\\"),{nil,true,9999,true,false,2,2,true,false}
local freport = win.GetEnv("Temp").."\\Report.txt"

ffi.cdef[[
void free (void*);
unsigned long int wcstoul(const wchar_t*, wchar_t**, int);
unsigned long long int wcstoull(const wchar_t*, wchar_t**, int);
wchar_t* wmemset(wchar_t*, wchar_t, size_t);
void* memset(void*, int, size_t);
int wcscmp(const wchar_t*, const wchar_t*);
int _wcsicmp(const wchar_t*, const wchar_t*);
int wcsncmp(const wchar_t*, const wchar_t*, size_t);
int _wcsnicmp(const wchar_t*, const wchar_t*, size_t);
]]

local function ToWChar(str)
str=win.Utf8ToUtf16(str)
local res=ffi.new("wchar_t[?]",#str/2+1)
ffi.copy(res,str)
return res
end

local function GetStartAndLenW(name)
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and name or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
local res=ffi.new("wchar_t[?]",len+1)
ffi.copy(res,name+len+ts[3],-ts[3]*2)
ffi.copy(res-ts[3],name,(len+ts[3])*2)
return res,len
else
return name,len
end
end

local function StartAndLenW(name)
local ptr = C.wcschr(name,HTAB)
C.memset(ptr,ZERO,1)
local fnsz = tonumber(C.wcslen(name))
local size = tonumber(C.wcstoul(name,NULL,0))
C.memset(ptr,HTAB,1)
ptr = C.wcsrchr(name,BS)
name = ptr==nil and name or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
return name+len+ts[3],-ts[3],name,len,size,fnsz
elseif ts[2] and ts[3]>0 and ts[3]<len then
return name,ts[3],name,len,size,fnsz
else
return name,len,name,len,size,fnsz
end
end

local compare = function(p1,p2)
local st1,ln1 = GetStartAndLenW(p1[2])
local st2,ln2 = GetStartAndLenW(p2[2])
local res = ts[4] and C._wcsicmp(st1,st2) or C.wcscmp(st1,st2)
if res==0 and (ts[5] or not ts[2]) and ts[6]~=2 then res=p1[8]-p2[8] end
return res>0 and true or false
end

local Items = {
--[[01]] {F.DI_DOUBLEBOX, 3,1, 65,9, 0, 0,0, 0, "Select duplicates of FileName. Help: F1"},
--[[02]] {F.DI_CHECKBOX, 5,2, 26,2, 0, 0,0, 0, "Num&ber of symbols"},
--[[03]] {F.DI_EDIT, 27,2, 32,2, 0, 0,0, 0, ""},
--[[04]] {F.DI_CHECKBOX, 5,3, 20,3, 0, 0,0, 0, "Ignore &case"},
--[[05]] {F.DI_CHECKBOX, 38,3, 62,3, 0, 0,0, 0, "Ignore Full &Duplicates"},
--[[06]] {F.DI_CHECKBOX, 5,4, 21,4, 0, 0,0, F.DIF_3STATE, "&Sizes of FD:"},
--[[07]] {F.DI_CHECKBOX, 5,5, 26,5, 0, 0,0, F.DIF_3STATE, "&Attributes of FD:"},
--[[08]] {F.DI_CHECKBOX, 5,6, 35,6, 0, 0,0, 0, "Accuracy (&two-pass method)"},
--[[09]] {F.DI_CHECKBOX, 5,8, 15,8, 0, 0,0, 0, "Re&port"},
--[[10]] {F.DI_TEXT, -1,7, 0,0, 0, 0,0, F.DIF_SEPARATOR,""},
--[[11]] {F.DI_BUTTON, 0,8, 0,0, 0, 0,0, F.DIF_DEFAULTBUTTON+F.DIF_CENTERGROUP,"&Ok"},
--[[12]] {F.DI_BUTTON, 0,8, 0,0, 0, 0,0, F.DIF_CENTERGROUP,"Ca&ncel"}
}

local tts={}

local function DlgProc(hDlg,Msg,Param1,Param2)
local function Set1()
hDlg:send(F.DM_ENABLE,5,tts[2] and 1 or 0)
hDlg:send(F.DM_ENABLE,6,(tts[5] or not tts[2]) and 1 or 0)
hDlg:send(F.DM_ENABLE,7,(tts[5] or not tts[2]) and 1 or 0)
end
if Msg==F.DN_INITDIALOG then
for i=2,#Items-3 do tts[i]=ts[i] end
Set1()
hDlg:send(F.DM_SETTEXT,3,tts[3])
hDlg:send(F.DM_SETCHECK,2,tts[2] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,4,tts[4] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,5,tts[5] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,6,tts[6]==0 and F.BSTATE_UNCHECKED or tts[6]==1 and F.BSTATE_CHECKED or tts[6]==2 and F.BSTATE_3STATE)
hDlg:send(F.DM_SETTEXT,6,"&Sizes of FD: "..(tts[6]==0 and "<>" or tts[6]==1 and "==" or "--"))
hDlg:send(F.DM_SETCHECK,7,tts[7]==0 and F.BSTATE_UNCHECKED or tts[7]==1 and F.BSTATE_CHECKED or tts[7]==2 and F.BSTATE_3STATE)
hDlg:send(F.DM_SETTEXT,7,"&Attributes of FD: "..(tts[7]==0 and "<>" or tts[7]==1 and "==" or "--"))
hDlg:send(F.DM_ENABLE,8,(tts[6]==0 or tts[7]==0) and 1 or 0)
hDlg:send(F.DM_SETCHECK,8,tts[8] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,9,tts[9] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
elseif Msg==F.DN_BTNCLICK and (Param1==2 or Param1==4 or Param1==5 or Param1==8 or Param1==9) then
tts[Param1] = Param2~=0
if Param1==2 or Param1==5 then Set1() end
elseif Msg==F.DN_BTNCLICK and (Param1==6 or Param1==7) then
tts[Param1] = Param2
hDlg:send(F.DM_SETTEXT,Param1,(Param1==6 and "&Sizes of FD: " or "&Attributes of FD: ")..(Param2==0 and "<>" or Param2==1 and "==" or "--"))
hDlg:send(F.DM_ENABLE,8,Param2==0 and 1 or 0)
elseif Msg==F.DN_EDITCHANGE and Param1==3 then -- Number symbols
tts[3] = tonumber(hDlg:send(F.DM_GETTEXT,3)) or tts[3]
else
return
end
return true
end

Macro {
description="@ Filter Duplicates FileName in Editor"; name="SDFN"; area="Editor";
action=function()
if far.Dialog(uGuid,-1,-1,69,11,nil,Items,nil,DlgProc)==#Items-1 then
local t0=far.FarClock()
for i=2,#Items-3 do ts[i]=tts[i] end
_G.tsel = {}
local ec=ffi.cast("struct PluginStartupInfo*",far.CPluginStartupInfo()).EditorControl
local ei=ffi.new("struct EditorInfo")
ei.StructSize=ffi.sizeof(ei)
if ec(-1,"ECTL_GETINFO",0,ei) then
local LastLine=tonumber(ei.TotalLines)-1
local egs=ffi.new("struct EditorGetString")
egs.StructSize=ffi.sizeof(egs)
local function PGPL(i)
egs.StringNumber=i
if ec(-1,"ECTL_GETSTRING",0,egs) then
local st1,ln1,st3,ln3,sz1,fnsz=StartAndLenW(egs.StringText)
table.insert(tsel,{false,st1,ln1,st3,ln3,ffi.string(st1,ln1*2),ffi.string(st3,ln3*2),sz1--[[tonumber(win.Utf16ToUtf8(ffi.string(sz1,fnsz*2)))]],i+1,egs.StringText})
end
end
for i=0,LastLine do PGPL(i) end
table.sort(tsel,compare)
local function Proc(i,x)
if ts[5] and x then
else
if ts[2] or not ts[2] and x then
tsel[i-1][1]=true
tsel[i][1]=true
end
end
end
for i=2,LastLine+1 do
if ts[4] and (ts[2] and C._wcsnicmp(tsel[i][2],tsel[i-1][2],ts[3])==0 or C._wcsicmp(tsel[i][2],tsel[i-1][2])==0) then Proc(i,C._wcsicmp(tsel[i][4],tsel[i-1][4])==0 and not (ts[6]==0 and tsel[i][8]==tsel[i-1][8] or ts[6]==1 and tsel[i][8]~=tsel[i-1][8] or ts[6]==2 and false))
elseif not ts[4] and (ts[2] and C.wcsncmp(tsel[i][2],tsel[i-1][2],ts[3])==0 or C.wcscmp(tsel[i][2],tsel[i-1][2])==0) then Proc(i,C.wcscmp(tsel[i][4],tsel[i-1][4])==0 and not (ts[6]==0 and tsel[i][8]==tsel[i-1][8] or ts[6]==1 and tsel[i][8]~=tsel[i-1][8] or ts[6]==2 and false))
end
end
if ts[8] then
for i=2,LastLine+1 do
if ts[6]==0 and tsel[i][8]==tsel[i-1][8] and ((ts[4] and (ts[2] and C._wcsnicmp(tsel[i][2],tsel[i-1][2],ts[3])==0 or C._wcsicmp(tsel[i][2],tsel[i-1][2])==0)) or (not ts[4] and (ts[2] and C.wcsncmp(tsel[i][2],tsel[i-1][2],ts[3])==0 or C.wcscmp(tsel[i][2],tsel[i-1][2])==0))) then
tsel[i-1][1]=false
tsel[i][1]=false
end
end
end
end
--Keys("ShiftF12")
if ts[9] then
local h = io.open(freport,"wb")
io.close(h)
h = io.open(freport,"ab")
local s = "Items: "..#tsel..
"\nExecution time: "..(far.FarClock()-t0)..
" mcs\nNumber of symbols: "..(ts[2] and ts[3] or "all")..
"\nIgnore case: "..tostring(ts[4])..
"\nIgnore Full Duplicates: "..tostring(ts[5])..
((ts[5] or not ts[2]) and ("\nSizes of FD: "..(ts[6]==0 and "<>" or ts[6]==1 and "==" or "--")) or "")..
((ts[5] or not ts[2]) and ("\nAttributes of FD: "..(ts[7]==0 and "<>" or ts[7]==1 and "==" or "--")) or "")..
"\n"..string.rep("-",30).."\n"
h:write(s)
for i=#tsel,1,-1 do if tsel[i][1] then h:write(tsel[i][9].."\t"..win.Utf16ToUtf8(ffi.string(tsel[i][10],tonumber(C.wcslen(tsel[i][10]))*2)).."\n") end --[[table.remove(tsel)]] end
io.close(h)
far.Message("mcs: "..far.FarClock()-t0,"SDFN")
end
end
end;
}

Macro {
description = "SDFN - Help"; area = "Dialog"; key = "F1";
condition=function() return Area.Dialog and Dlg.Id==guid end;
action=function()
if Dlg.CurPos<=3 then far.Message("The number of first or last symbols to compare","Help: Number of symbols")
elseif Dlg.CurPos==4 then far.Message("Case of letters in FileName will be ignored","Help: Ignore case")
elseif Dlg.CurPos==5 then far.Message("Full duplicates of FileName will be ignored","Help: Ignore Full Duplicates")
elseif Dlg.CurPos==6 then far.Message("-- ignore, == equal, <> is not equal","Help: Sizes of FD")
elseif Dlg.CurPos==7 then far.Message("-- ignore, == equal, <> is not equal","Help: Attributes of FD")
elseif Dlg.CurPos==8 then far.Message("Two-pass method for\n<> (is not equal) options only","Help: Accuracy")
elseif Dlg.CurPos==9 then far.Message("mcs - total time of execution in mcs\nReport will be saved to:\n"..freport,"Help: Report",nil,"l")
end
end;
}
Автор: Angel_Ka
Дата сообщения: 17.05.2016 16:10
Alexyz21

Цитата:
0.2

Спасибо! Пробую.

Цитата:
Можно использовать и имеющийся у вас бранч-список, нужно только эмулировать размер у файлов, для чего в начало каждой строки вставить произвольное число с табуляцией, например 0\t.

В имеющемся бранч-списке, составленном но основе микротеста на 76 файлов, в начало каждой строки вставил произвольные, в т.ч. повторяющиеся, 3-значные числа, и после них реальный Tab. Запустил макрос с произвольной настройкой:

Код: [x] Number of symbols 9999
[x] Ignore case [x] Ignore Full Duplicates
[ ] Sizes of FD: <>
[?] Attributes of FD: --
[x] Accuracy (two-pass method)
Автор: Alexyz21
Дата сообщения: 17.05.2016 17:00
Report.txt, как можно видеть из кода создания списка рапорта:
Код: for i=#tsel,1,-1 do if tsel[i][1] then h:write(tsel[i][9].."\t"..win.Utf16ToUtf8(ffi.string(tsel[i][10],tonumber(C.wcslen(tsel[i][10]))*2)).."\n") end --[[table.remove(tsel)]] end
Автор: Angel_Ka
Дата сообщения: 17.05.2016 18:47

Цитата:
0.3

Код: SDFN

mcs: 994
Автор: Alexyz21
Дата сообщения: 17.05.2016 19:02
ничем не могу помочь - у меня работает

Добавлено:
13.1.2 [more]
Код: -- 13.1.2
local F = far.Flags
local ffi = require'ffi'
local C = ffi.C
local NULL = ffi.cast("void*",0)
local PANEL_ACTIVE = ffi.cast("HANDLE",-1)
local pBL0,pBL1 = ffi.cast("BOOL*",0),ffi.cast("BOOL*",1)

local PanelMode,Desc1,Indi1 = 999,"Select duplicates","!?"
local guid = "FE9B8874-9651-434C-8182-72329F2371A5"
local uGuid = win.Uuid(guid)
local BS,ts = string.byte("\\"),{nil,true,9999,true,false,2,2,true,false}
local freport = win.GetEnv("Temp").."\\Report.txt"
local Flags = C.SORT_STRINGSORT

ffi.cdef[[
void free (void*);
int wcscmp(const wchar_t*, const wchar_t*);
int _wcsicmp(const wchar_t*, const wchar_t*);
int wcsncmp(const wchar_t*, const wchar_t*, size_t);
int _wcsnicmp(const wchar_t*, const wchar_t*, size_t);
]]

local function ToWChar(str)
str=win.Utf8ToUtf16(str)
local res=ffi.new("wchar_t[?]",#str/2+1)
ffi.copy(res,str)
return res
end

local function GetStartAndLenW(name)
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and name or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
local res=ffi.new("wchar_t[?]",len+1)
ffi.copy(res,name+len+ts[3],-ts[3]*2)
ffi.copy(res-ts[3],name,(len+ts[3])*2)
return res,len
else
return name,len
end
end

local function StartAndLenW(name)
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and name or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
return name+len+ts[3],-ts[3],name,len
elseif ts[2] and ts[3]>0 and ts[3]<len then
return name,ts[3],name,len
else
return name,len,name,len
end
end

local Compare = function(p1,p2)
local st1,ln1 = GetStartAndLenW(p1.FileName)
local st2,ln2 = GetStartAndLenW(p2.FileName)
local sz1,sz2,fa1,fa2
if (ts[5] or not ts[2]) and ts[6]~=2 then sz1,sz2 = tonumber(p1.FileSize),tonumber(p2.FileSize) end
if (ts[5] or not ts[2]) and ts[7]~=2 then fa1,fa2 = tonumber(p1.FileAttributes),tonumber(p2.FileAttributes) end
--local res = ts[4] and C._wcsicmp(st1,st2) or C.wcscmp(st1,st2)
local res = -2 + C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st1,ln1,st2,ln2)
if res==0 and sz1 then res=sz1-sz2 end
if res==0 and fa1 then res=fa1-fa2 end
return res<0 and -1 or res>0 and 1 or 0
end

local Items = {
--[[01]] {F.DI_DOUBLEBOX, 3,1, 65,9, 0, 0,0, 0, "Select duplicates of FileName. Help: F1"},
--[[02]] {F.DI_CHECKBOX, 5,2, 26,2, 0, 0,0, 0, "Num&ber of symbols"},
--[[03]] {F.DI_EDIT, 27,2, 32,2, 0, 0,0, 0, ""},
--[[04]] {F.DI_CHECKBOX, 5,3, 20,3, 0, 0,0, 0, "Ignore &case"},
--[[05]] {F.DI_CHECKBOX, 38,3, 62,3, 0, 0,0, 0, "Ignore Full &Duplicates"},
--[[06]] {F.DI_CHECKBOX, 5,4, 21,4, 0, 0,0, F.DIF_3STATE, "&Sizes of FD:"},
--[[07]] {F.DI_CHECKBOX, 5,5, 26,5, 0, 0,0, F.DIF_3STATE, "&Attributes of FD:"},
--[[08]] {F.DI_CHECKBOX, 5,6, 35,6, 0, 0,0, 0, "Accuracy (&two-pass method)"},
--[[09]] {F.DI_CHECKBOX, 5,8, 15,8, 0, 0,0, 0, "Re&port"},
--[[10]] {F.DI_TEXT, -1,7, 0,0, 0, 0,0, F.DIF_SEPARATOR,""},
--[[11]] {F.DI_BUTTON, 0,8, 0,0, 0, 0,0, F.DIF_DEFAULTBUTTON+F.DIF_CENTERGROUP,"&Ok"},
--[[12]] {F.DI_BUTTON, 0,8, 0,0, 0, 0,0, F.DIF_CENTERGROUP,"Ca&ncel"}
}

local tts={}

local function DlgProc(hDlg,Msg,Param1,Param2)
local function Set1()
hDlg:send(F.DM_ENABLE,5,tts[2] and 1 or 0)
hDlg:send(F.DM_ENABLE,6,(tts[5] or not tts[2]) and 1 or 0)
hDlg:send(F.DM_ENABLE,7,(tts[5] or not tts[2]) and 1 or 0)
end
if Msg==F.DN_INITDIALOG then
for i=2,#Items-3 do tts[i]=ts[i] end
Set1()
hDlg:send(F.DM_SETTEXT,3,tts[3])
hDlg:send(F.DM_SETCHECK,2,tts[2] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,4,tts[4] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,5,tts[5] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,6,tts[6]==0 and F.BSTATE_UNCHECKED or tts[6]==1 and F.BSTATE_CHECKED or tts[6]==2 and F.BSTATE_3STATE)
hDlg:send(F.DM_SETTEXT,6,"&Sizes of FD: "..(tts[6]==0 and "<>" or tts[6]==1 and "==" or "--"))
hDlg:send(F.DM_SETCHECK,7,tts[7]==0 and F.BSTATE_UNCHECKED or tts[7]==1 and F.BSTATE_CHECKED or tts[7]==2 and F.BSTATE_3STATE)
hDlg:send(F.DM_SETTEXT,7,"&Attributes of FD: "..(tts[7]==0 and "<>" or tts[7]==1 and "==" or "--"))
hDlg:send(F.DM_ENABLE,8,(tts[6]==0 or tts[7]==0) and 1 or 0)
hDlg:send(F.DM_SETCHECK,8,tts[8] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,9,tts[9] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
elseif Msg==F.DN_BTNCLICK and (Param1==2 or Param1==4 or Param1==5 or Param1==8 or Param1==9) then
tts[Param1] = Param2~=0
if Param1==2 or Param1==5 then Set1() end
elseif Msg==F.DN_BTNCLICK and (Param1==6 or Param1==7) then
tts[Param1] = Param2
hDlg:send(F.DM_SETTEXT,Param1,(Param1==6 and "&Sizes of FD: " or "&Attributes of FD: ")..(Param2==0 and "<>" or Param2==1 and "==" or "--"))
hDlg:send(F.DM_ENABLE,8,Param2==0 and 1 or 0)
elseif Msg==F.DN_EDITCHANGE and Param1==3 then -- Number symbols
tts[3] = tonumber(hDlg:send(F.DM_GETTEXT,3)) or tts[3]
else
return
end
return true
end

Macro {
description="! Select Duplicates FileName in Branch panel"; name="SDFN"; area="Shell";
action=function()
if far.Dialog(uGuid,-1,-1,69,11,nil,Items,nil,DlgProc)==#Items-1 then
local t0=far.FarClock()
for i=2,#Items-3 do ts[i]=tts[i] end
Flags = ts[4] and bit.bor(Flags,C.NORM_IGNORECASE) or bit.band(Flags,bit.bnot(C.NORM_IGNORECASE))
--local PInfo=panel.GetPanelInfo(nil,1)
local PInfo=ffi.new("struct PanelInfo")
PInfo.StructSize=ffi.sizeof(PInfo)
local pc=ffi.cast("struct PluginStartupInfo*",far.CPluginStartupInfo()).PanelControl
if pc(PANEL_ACTIVE,"FCTL_GETPANELINFO",0,PInfo)==1 then
local pin,pif = tonumber(PInfo.ItemsNumber),tonumber(PInfo.Flags)
if pin>1 then
if bit.band(pif,F.PFLAGS_SELECTEDFIRST)>0 then Keys("ShiftF12") end
if bit.band(pif,F.PFLAGS_NUMERICSORT)>0 then pc(PANEL_ACTIVE,"FCTL_SETNUMERICSORT",0,NULL) end
local pfcss=bit.band(pif,F.PFLAGS_CASESENSITIVESORT)==0
if ts[4] and not pfcss or not ts[4] and pfcss then pc(PANEL_ACTIVE,"FCTL_SETCASESENSITIVESORT",ts[4] and 0 or 1,NULL) end
if bit.band(pif,F.PFLAGS_REVERSESORTORDER)==0 then pc(PANEL_ACTIVE,"FCTL_SETSORTORDER",1,NULL) end
Panel.LoadCustomSortMode(PanelMode,{Description=Desc1;Indicator=Indi1;Compare=Compare})
Panel.SetCustomSortMode(PanelMode,0)
local last,tsel,st0,ln0,st1,ln1,st2,ln2,st3,ln3,sz0,sz1,fa0,fa1 = 0,{}
--local function Comp(stA,lnA,stB,lnB) return ts[4] and C._wcsicmp(stA,stB) or C.wcscmp(stA,stB) end
--local function Comp(stA,lnA,stB,lnB) return -2 + C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,stA,lnA,stB,lnB) end
local function Proc(i,x)
if ts[5] and x then
else
if ts[2] or not ts[2] and x then
--if last<i-1 then pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL1) end
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL1)
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i,pBL1)
--last=i
if ts[9] then
--if #tsel==0 or Comp(tsel[#tsel][2],tsel[#tsel][3],st1,ln1)~=0 then
if #tsel==0 or C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,tsel[#tsel][2],tsel[#tsel][3],st1,ln1)~=2 then
table.insert(tsel,{2,st1,ln1,win.Utf16ToUtf8(ffi.string(st1,ln1*2))})
else
tsel[#tsel][1]=tsel[#tsel][1]+1
end
end
end
end
end
local function PGPI(i)
local ppi = ffi.new("struct FarGetPluginPanelItem")
ppi.StructSize = ffi.sizeof("struct FarGetPluginPanelItem")
ppi.Size = pc(PANEL_ACTIVE,"FCTL_GETPANELITEM",i,NULL)
if ppi.Size~=0 then
local buf = ffi.new("char[?]",ppi.Size)
ppi.Item = ffi.cast("struct PluginPanelItem*",buf)
pc(PANEL_ACTIVE,"FCTL_GETPANELITEM",i,ppi)
st1,ln1,st3,ln3=StartAndLenW(ffi.cast("const unsigned short*",ppi.Item.FileName))
if ts[6] then sz1=tonumber(ppi.Item.FileSize) end
if ts[7] then fa1=tonumber(ppi.Item.FileAttributes) end
end
end
PGPI(0)
pc(PANEL_ACTIVE,"FCTL_BEGINSELECTION",0,NULL)
for i=1,pin-1 do
st0,ln0,st2,ln2,sz0,fa0 = st1,ln1,st3,ln3,sz1,fa1
PGPI(i)
--if ts[4] and (ts[2] and C._wcsnicmp(st1,st0,ts[3])==0 or C._wcsicmp(st1,st0)==0) then Proc(i,C._wcsicmp(st3,st2)==0 and not (ts[6]==0 and sz1==sz0 or ts[6]==1 and sz1~=sz0 or ts[6]==2 and false) and not (ts[7]==0 and fa1==fa0 or ts[7]==1 and fa1~=fa0 or ts[7]==2 and false))
--elseif not ts[4] and (ts[2] and C.wcsncmp(st1,st0,ts[3])==0 or C.wcscmp(st1,st0)==0) then Proc(i,C.wcscmp(st3,st2)==0 and not (ts[6]==0 and sz1==sz0 or ts[6]==1 and sz1~=sz0 or ts[6]==2 and false) and not (ts[7]==0 and fa1==fa0 or ts[7]==1 and fa1~=fa0 or ts[7]==2 and false))
--end
if ts[2] and C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st0,ts[3],st1,ts[3])==2 or C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st0,-1,st1,-1)==2 then Proc(i,C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st2,-1,st3,-1)==2 and not (ts[6]==0 and sz1==sz0 or ts[6]==1 and sz1~=sz0 or ts[6]==2 and false) and not (ts[7]==0 and fa1==fa0 or ts[7]==1 and fa1~=fa0 or ts[7]==2 and false)) end
end
if ts[8] then
last,st0,ln0,st1,ln1,st2,ln2,st3,ln3,sz0,sz1,fa0,fa1 = 0
PGPI(0)
for i=1,pin-1 do
st0,ln0,st2,ln2,sz0,fa0 = st1,ln1,st3,ln3,sz1,fa1
PGPI(i)
if (ts[6]==0 and sz1==sz0 or ts[7]==0 and fa1==fa0) and (ts[2] and C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st0,ts[3],st1,ts[3])==2 or C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st0,-1,st1,-1)==2) then
--if last<i-1 then pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL0) end
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL0)
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i,pBL0)
--last=i
end
end
end
pc(PANEL_ACTIVE,"FCTL_ENDSELECTION",0,NULL)
pc(PANEL_ACTIVE,"FCTL_REDRAWPANEL",0,NULL)
--Keys("ShiftF12")
if ts[9] then
table.sort(tsel,function(a,b) return a[1]<b[1] end)
local h = io.open(freport,"wb")
io.close(h)
h = io.open(freport,"ab")
h:write("Items: "..#tsel..
"\nExecution time: "..(far.FarClock()-t0)..
" mcs\nNumber of symbols: "..(ts[2] and ts[3] or "all")..
"\nIgnore case: "..tostring(ts[4])..
"\nIgnore Full Duplicates: "..tostring(ts[5])..
((ts[5] or not ts[2]) and ("\nSizes of FD: "..(ts[6]==0 and "<>" or ts[6]==1 and "==" or "--")) or "")..
((ts[5] or not ts[2]) and ("\nAttributes of FD: "..(ts[7]==0 and "<>" or ts[7]==1 and "==" or "--")) or "")..
"\n\n")
for i=#tsel,1,-1 do h:write(tsel[i][1].."\t"..tsel[i][4].."\n") table.remove(tsel) end
io.close(h)
far.Message("mcs: "..far.FarClock()-t0,"SDFN")
end
end
end
end
end;
}

Macro {
description = "SDFN - Help"; area = "Dialog"; key = "F1";
condition=function() return Area.Dialog and Dlg.Id==guid end;
action=function()
if Dlg.CurPos<=3 then far.Message("The number of first or last symbols to compare","Help: Number of symbols")
elseif Dlg.CurPos==4 then far.Message("Case of letters in FileName will be ignored","Help: Ignore case")
elseif Dlg.CurPos==5 then far.Message("Full duplicates of FileName will be ignored","Help: Ignore Full Duplicates")
elseif Dlg.CurPos==6 then far.Message("-- ignore, == equal, <> is not equal","Help: Sizes of FD")
elseif Dlg.CurPos==7 then far.Message("-- ignore, == equal, <> is not equal","Help: Attributes of FD")
elseif Dlg.CurPos==8 then far.Message("Two-pass method for\n<> (is not equal) options only","Help: Accuracy")
elseif Dlg.CurPos==9 then far.Message("mcs - total time of execution in mcs\nReport will be saved to:\n"..freport,"Help: Report",nil,"l")
end
end;
}
Автор: Angel_Ka
Дата сообщения: 17.05.2016 19:16
Проверил 0.3 в Фар x86 — та же история...

Добавлено:

Цитата:
13.1.2

Сейчас посмотрю.
Автор: Alexyz21
Дата сообщения: 17.05.2016 19:20
поправил счётчик в 0.3, обновил выше. Смотрите то, что вы ему скармливаете, отвечает ли оно настройкам и формату.

Добавлено:

Код: 123    Z:\Temp\Ab.txt
123    Z:\Temp0\Фыва.txt
230    Z:\Temp9\1.txt
123    Z:\Temp7\aB.txt
123    Z:\Temp4\фЫвА.txt
1203    Z:\Temp\0.txt
234    Z:\Temp2\1.txt
230    Z:\Temp6\1.txt
123    Z:\Temp8\0.txt
1123    Z:\Temp\0.txt
1123    Z:\Temp1\1.txt
123    Z:\Temp\0.txt
300    Z:\Temp\0.txt
Автор: Angel_Ka
Дата сообщения: 17.05.2016 19:36

Цитата:
13.1.2

Код: [x] Number of symbols 9999
[x] Ignore case [x] Ignore Full Duplicates
[ ] Sizes of FD: <>
[?] Attributes of FD: --
[ ] Accuracy (two-pass method)
Автор: Angel_Ka
Дата сообщения: 17.05.2016 21:49
Тест трёх версий макроса Select Duplicates FileName in Branch panel
на бранче из 712 062 файлов, созданном плагином LuaFAR Search

Код: [ ] Number of symbols 9999
[x] Ignore case [ ] Ignore Full Duplicates
[ ] Sizes of FD: <>
[ ] Attributes of FD: <>
[ ] Accuracy

13.1.0 файлов: 6 785 mcs: 15 005 030 15 714 763 15 836 019

13.1.1 6 785 15 836 736 15 810 729 15 830 501

13.1.2 6 785 19 271 666 20 448 218 20 393 371


[ ] Number of symbols 9999
[x] Ignore case [ ] Ignore Full Duplicates
[ ] Sizes of FD: <>
[ ] Attributes of FD: <>
[x] Accuracy

13.1.0 файлов: 5 165 mcs: 19 422 650 19 410 859 19 362 774

13.1.1 5 165 19 501 415 19 545 029 19 607 535

13.1.2 5 165 24 565 051 24 538 978 24 359 611


[ ] Number of symbols 9999
[ ] Ignore case [ ] Ignore Full Duplicates
[ ] Sizes of FD: <>
[ ] Attributes of FD: <>
[x] Accuracy

13.1.0 файлов: 5 136 mcs: 19 114 988 19 154 725 19 040 027

13.1.1 5 136 19 102 833 19 036 609 19 113 483

13.1.2 5 136 24 655 049 24 661 265 24 649 704


[ ] Number of symbols 9999
[ ] Ignore case [ ] Ignore Full Duplicates
[ ] Sizes of FD: <>
[ ] Attributes of FD: <>
[ ] Accuracy

13.1.0 файлов: 6 629 mcs: 15 510 255 15 479 868 15 390 978

13.1.1 6 629 15 444 191 15 319 008 15 435 343

13.1.2 6 629 20 084 308 20 467 580 20 662 961
Автор: Angel_Ka
Дата сообщения: 18.05.2016 23:01
0.3 в обновлённом Far b4678 x64

Код: 1123    Z:\Temp1\1.txt
123    Z:\Temp\0.txt
11234    Z:\Temp1\1.txt
300    Z:\Temp\0.txt
1212    Z:\Temp\абвгдеёжзийклмнопрстуфхцчшщьыъэюя.pdf
0    Z:\Temp\абвгдеёжзийклмнопрстуфхцчшщьыъэюя.pdf
Автор: shmuz2
Дата сообщения: 18.05.2016 23:20
Angel_Ka
У вас переставлены позиции твёрдого и мягкого знаков в алфавите.
Автор: Angel_Ka
Дата сообщения: 18.05.2016 23:28
shmuz2

Цитата:
переставлены позиции твёрдого и мягкого знаков в алфавите

Спасибо, что заметили! Издержки слепого набора. В данном случае мою оплошность оставлю служить артефактом — это типа как опечатки в документах, могут служить подтверждением их подлинности.

off:
— Одна секретарша говорит другой: "А я могу печатать со скоростью 2 тысячи знаков в минуту!"
— "Неужели?!"
— "Такая фигня получается!"

Добавлено:

И вот ещё нашёл на форуме Фара — оказывается для того, чтобы файл создавался в нужной кодировке, можно воспользоваться макросом, сделанным по Вашей подсказке:

Код: Event {
description="Set 65001 codepage";
group="EditorEvent"; filemask="Report.txt";
action=function(Id,Event,Param)
if Event == far.Flags.EE_READ then
editor.SetParam(nil, "ESPT_CODEPAGE", 65001)
editor.SetParam(nil, "ESPT_TABSIZE", 4) --- размер табуляции
editor.SetParam(nil, "ESPT_SETBOM", "TRUE") --- вставить BOM
end
end;
}
Автор: Alexyz21
Дата сообщения: 19.05.2016 13:24
0.5 [more]
Код: -- 0.5
local F = far.Flags
local ffi = require'ffi'
local C = ffi.C
local NULL = ffi.cast("void*",0)
local pHTAB = ffi.cast("void*",win.Utf8ToUtf16("\t"))
local PANEL_ACTIVE = ffi.cast("HANDLE",-1)
local pBL0,pBL1 = ffi.cast("BOOL*",0),ffi.cast("BOOL*",1)
--local msvcr120 = ffi.load("msvcr120")

local PanelMode,Desc1,Indi1 = 999,"Select duplicates","!?"
local guid = "FE9B8874-9651-434C-8182-72329F2371A5"
local uGuid = win.Uuid(guid)
local ZERO,HTAB,BS = ffi.cast("unsigned int",0),ffi.cast("unsigned int",9),string.byte("\\")
local ts = {nil,true,9999,true,false,2,2,true,false}
local freport = win.GetEnv("Temp").."\\Report.txt"
local Flags = C.SORT_STRINGSORT
local TAB=win.Utf8ToUtf16("\t")

ffi.cdef[[
void free (void*);
char* setlocale(int, const char*);
unsigned long int wcstoul(const wchar_t*, wchar_t**, int);
unsigned long long int wcstoull(const wchar_t*, wchar_t**, int);
wchar_t* wmemset(wchar_t*, wchar_t, size_t);
void* memset(void*, int, size_t);
int wcscmp(const wchar_t*, const wchar_t*);
int _wcsicmp(const wchar_t*, const wchar_t*);
int wcsncmp(const wchar_t*, const wchar_t*, size_t);
int _wcsnicmp(const wchar_t*, const wchar_t*, size_t);
]]

local function ToWChar(str)
str=win.Utf8ToUtf16(str)
local res=ffi.new("wchar_t[?]",#str/2+1)
ffi.copy(res,str)
return res
end

local function GetStartAndLenW(name)
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and name or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
local res=ffi.new("wchar_t[?]",len+1)
ffi.copy(res,name+len+ts[3],-ts[3]*2)
ffi.copy(res-ts[3],name,(len+ts[3])*2)
return res,len
else
return name,len
end
end

local function StartAndLenW(name)
local size = tonumber(C.wcstoul(name,pHTAB,0))
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and name or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
return name+len+ts[3],-ts[3],name,len,size
elseif ts[2] and ts[3]>0 and ts[3]<len then
return name,ts[3],name,len,size
else
return name,len,name,len,size
end
end

local compare = function(p1,p2)
local st1,ln1 = GetStartAndLenW(p1[4])
local st2,ln2 = GetStartAndLenW(p2[4])
--local res = ts[4] and C._wcsicmp(st1,st2) or C.wcscmp(st1,st2)
local res = -2 + C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st1,ln1,st2,ln2)
if res==0 and ts[6]~=2 then res=p1[6]-p2[6] end
return res>0 and true or false
end

local Items = {
--[[01]] {F.DI_DOUBLEBOX, 3,1, 65,9, 0, 0,0, 0, "Select duplicates of FileName. Help: F1"},
--[[02]] {F.DI_CHECKBOX, 5,2, 26,2, 0, 0,0, 0, "Num&ber of symbols"},
--[[03]] {F.DI_EDIT, 27,2, 32,2, 0, 0,0, 0, ""},
--[[04]] {F.DI_CHECKBOX, 5,3, 20,3, 0, 0,0, 0, "Ignore &case"},
--[[05]] {F.DI_CHECKBOX, 38,3, 62,3, 0, 0,0, 0, "Ignore Full &Duplicates"},
--[[06]] {F.DI_CHECKBOX, 5,4, 21,4, 0, 0,0, F.DIF_3STATE, "&Sizes of FD:"},
--[[07]] {F.DI_CHECKBOX, 5,5, 26,5, 0, 0,0, F.DIF_3STATE, "&Attributes of FD:"},
--[[08]] {F.DI_CHECKBOX, 5,6, 35,6, 0, 0,0, 0, "Accuracy (&two-pass method)"},
--[[09]] {F.DI_CHECKBOX, 5,8, 15,8, 0, 0,0, 0, "Re&port"},
--[[10]] {F.DI_TEXT, -1,7, 0,0, 0, 0,0, F.DIF_SEPARATOR,""},
--[[11]] {F.DI_BUTTON, 0,8, 0,0, 0, 0,0, F.DIF_DEFAULTBUTTON+F.DIF_CENTERGROUP,"&Ok"},
--[[12]] {F.DI_BUTTON, 0,8, 0,0, 0, 0,0, F.DIF_CENTERGROUP,"Ca&ncel"}
}

local tts={}

local function DlgProc(hDlg,Msg,Param1,Param2)
--local function Set1()
-- hDlg:send(F.DM_ENABLE,5,tts[2] and 1 or 0)
-- hDlg:send(F.DM_ENABLE,6,(tts[5] or not tts[2]) and 1 or 0)
-- hDlg:send(F.DM_ENABLE,7,(tts[5] or not tts[2]) and 1 or 0)
--end
if Msg==F.DN_INITDIALOG then
for i=2,#Items-3 do tts[i]=ts[i] end
--Set1()
hDlg:send(F.DM_SETTEXT,3,tts[3])
hDlg:send(F.DM_SETCHECK,2,tts[2] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,4,tts[4] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,5,tts[5] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,6,tts[6]==0 and F.BSTATE_UNCHECKED or tts[6]==1 and F.BSTATE_CHECKED or tts[6]==2 and F.BSTATE_3STATE)
hDlg:send(F.DM_SETTEXT,6,"&Sizes of FD: "..(tts[6]==0 and "<>" or tts[6]==1 and "==" or "--"))
hDlg:send(F.DM_SETCHECK,7,tts[7]==0 and F.BSTATE_UNCHECKED or tts[7]==1 and F.BSTATE_CHECKED or tts[7]==2 and F.BSTATE_3STATE)
hDlg:send(F.DM_SETTEXT,7,"&Attributes of FD: "..(tts[7]==0 and "<>" or tts[7]==1 and "==" or "--"))
--hDlg:send(F.DM_ENABLE,8,(tts[6]==0 or tts[7]==0) and 1 or 0)
hDlg:send(F.DM_SETCHECK,8,tts[8] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,9,tts[9] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
elseif Msg==F.DN_BTNCLICK and (Param1==2 or Param1==4 or Param1==5 or Param1==8 or Param1==9) then
tts[Param1] = Param2~=0
--if Param1==2 or Param1==5 then Set1() end
elseif Msg==F.DN_BTNCLICK and (Param1==6 or Param1==7) then
tts[Param1] = Param2
hDlg:send(F.DM_SETTEXT,Param1,(Param1==6 and "&Sizes of FD: " or "&Attributes of FD: ")..(Param2==0 and "<>" or Param2==1 and "==" or "--"))
--hDlg:send(F.DM_ENABLE,8,Param2~=2 and 1 or 0)
elseif Msg==F.DN_EDITCHANGE and Param1==3 then -- Number symbols
tts[3] = tonumber(hDlg:send(F.DM_GETTEXT,3)) or tts[3]
else
return
end
return true
end

Macro {
description="@ Filter Duplicates FileName in Editor"; name="SDFN"; area="Editor";
action=function()
if far.Dialog(uGuid,-1,-1,69,11,nil,Items,nil,DlgProc)==#Items-1 then
local t0 = far.FarClock()
for i=2,#Items-3 do ts[i]=tts[i] end
Flags = ts[4] and bit.bor(Flags,C.NORM_IGNORECASE) or bit.band(Flags,bit.bnot(C.NORM_IGNORECASE))
local tsel = {}
local ec=ffi.cast("struct PluginStartupInfo*",far.CPluginStartupInfo()).EditorControl
local ei=ffi.new("struct EditorInfo")
ei.StructSize=ffi.sizeof(ei)
if ec(-1,"ECTL_GETINFO",0,ei) then
local LastLine=tonumber(ei.TotalLines)-1
local egs=ffi.new("struct EditorGetString")
egs.StructSize=ffi.sizeof(egs)
local function PGPL(i)
egs.StringNumber=i
if ec(-1,"ECTL_GETSTRING",0,egs) then
local st1,ln1,st3,ln3,sz1=StartAndLenW(egs.StringText)
table.insert(tsel,{false,st1,ln1,st3,ln3,sz1,i+1,egs.StringText})
end
end
for i=0,LastLine do PGPL(i) end
table.sort(tsel,compare)
--local h = io.open(freport.."0","wb")
--io.close(h)
--h = io.open(freport.."0","ab")
--for i=#tsel,1,-1 do h:write(tsel[i][7].."\t"..tostring(tsel[i][1]).."\t"..win.Utf16ToUtf8(ffi.string(tsel[i][8],tonumber(C.wcslen(tsel[i][8]))*2)..TAB..ffi.string(tsel[i][2],tsel[i][3]*2)..TAB..ffi.string(tsel[i][4],tsel[i][5]*2)).."\t"..tsel[i][6].."\n") --[[table.remove(tsel)]] end
--io.close(h)
for i=2,LastLine+1 do
--if ts[4] and (ts[2] and C._wcsnicmp(tsel[i][2],tsel[i-1][2],ts[3])==0 or C._wcsicmp(tsel[i][2],tsel[i-1][2])==0) then Proc(i,C._wcsicmp(tsel[i][4],tsel[i-1][4])==0 and not (ts[6]==0 and tsel[i][6]==tsel[i-1][6] or ts[6]==1 and tsel[i][6]~=tsel[i-1][6] or ts[6]==2 and false))
--elseif not ts[4] and (ts[2] and C.wcsncmp(tsel[i][2],tsel[i-1][2],ts[3])==0 or C.wcscmp(tsel[i][2],tsel[i-1][2])==0) then Proc(i,C.wcscmp(tsel[i][4],tsel[i-1][4])==0 and not (ts[6]==0 and tsel[i][6]==tsel[i-1][6] or ts[6]==1 and tsel[i][6]~=tsel[i-1][6] or ts[6]==2 and false))
--end
if C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,tsel[i-1][2],tsel[i-1][3],tsel[i][2],tsel[i][3])==2 then
local x=C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,tsel[i-1][4],tsel[i-1][5],tsel[i][4],tsel[i][5])==2
local y=ts[6]==0 and tsel[i-1][6]~=tsel[i][6] or ts[6]==1 and tsel[i-1][6]==tsel[i][6] or ts[6]==2
if not ts[5] and (not ts[2] and x and y or ts[2] and y) or ts[5] and (ts[6]==0 and tsel[i-1][6]==tsel[i][6] or ts[6]==1 and tsel[i-1][6]~=tsel[i][6]) then
tsel[i-1][1]=true
tsel[i][1]=true
end
end
end
-- -ts[5] and ts[6]==0
-- +ts[5] and ts[6]==1
-- +not ts[5] and ts[6]==0
-- -not ts[5] and ts[6]==1
if ts[8] then
for i=2,LastLine+1 do
if ((ts[5] and ts[6]==1 or not ts[5] and ts[6]==0) and tsel[i-1][6]==tsel[i][6]) and C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,tsel[i-1][4],tsel[i-1][5],tsel[i][4],tsel[i][5])==2 then
tsel[i-1][1]=false
tsel[i][1]=false
end
end
end
end
--Keys("ShiftF12")
if ts[9] then
local h = io.open(freport,"wb")
io.close(h)
local count=0
for i=1,#tsel do if tsel[i][1] then count=count+1 end end
h = io.open(freport,"ab")
local s = "Items: "..count.."/"..#tsel..
"\nExecution time: "..(far.FarClock()-t0)..
" mcs\nNumber of symbols: "..(ts[2] and ts[3] or "all")..
"\nIgnore case: "..tostring(ts[4])..
"\nIgnore Full Duplicates: "..tostring(ts[5])..
"\nSizes of FD: "..(ts[6]==0 and "<>" or ts[6]==1 and "==" or "--")..
"\nAttributes of FD: "..(ts[7]==0 and "<>" or ts[7]==1 and "==" or "--")..
"\nAccuracy (two-pass): "..tostring(ts[8])..
"\n"..string.rep("-",30).."\n"
h:write(s)
for i=#tsel,1,-1 do if tsel[i][1] then h:write(tsel[i][7].."\t"..win.Utf16ToUtf8(ffi.string(tsel[i][8],tonumber(C.wcslen(tsel[i][8]))*2)).."\n") end table.remove(tsel) end
io.close(h)
far.Message("mcs: "..far.FarClock()-t0,"SDFN")
end
end
end;
}

Macro {
description = "SDFN - Help"; area = "Dialog"; key = "F1";
condition=function() return Area.Dialog and Dlg.Id==guid end;
action=function()
if Dlg.CurPos<=3 then far.Message("The number of first or last symbols to compare","Help: Number of symbols")
elseif Dlg.CurPos==4 then far.Message("Case of letters in FileName will be ignored","Help: Ignore case")
elseif Dlg.CurPos==5 then far.Message("Full duplicates of FileName will be ignored","Help: Ignore Full Duplicates")
elseif Dlg.CurPos==6 then far.Message("-- ignore, == equal, <> is not equal","Help: Sizes of FD")
elseif Dlg.CurPos==7 then far.Message("-- ignore, == equal, <> is not equal","Help: Attributes of FD")
elseif Dlg.CurPos==8 then far.Message("Two-pass method for\n<> (is not equal) options only","Help: Accuracy")
elseif Dlg.CurPos==9 then far.Message("mcs - total time of execution in mcs\nReport will be saved to:\n"..freport,"Help: Report",nil,"l")
end
end;
}

Страницы: 123456789101112

Предыдущая тема: кл


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.