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

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

Автор: shmuz2
Дата сообщения: 14.05.2016 20:26
То, что буквально за секунду, я понимаю так, что воспроизводится и на малых базах файлов. Так?
Но выше вы писали, что можно обойтись и без LF Search, с помощью tmp:<dir /b /s /a-d. Это повторяется? Такой тест был бы предпочтителен, поскольку он со стандартным плагином.
Автор: Angel_Ka
Дата сообщения: 14.05.2016 20:29
Сейчас буду реализовывать следующий пункт:

Цитата:
- Если для повторения достаточно стандартной TmpPanel, попробуйте запустить Far только с ней, например из папки Far запустить
Far /pPlugins\TmpPanel и попробовать повторить опыт.


Добавлено:

Цитата:
То, что буквально за секунду, я понимаю так, что воспроизводится и на малых базах файлов. Так?

Да. Папка с файлами микротеста, на котой запускался плагин, содержит в себе и своих подпапках всего 76 файлов.

Добавлено:

Цитата:
выше вы писали, что можно обойтись и без LF Search, с помощью tmp:<dir /b /s /a-d. Это повторяется?

Сегодня это повторилось 3 раза с частотой примерно 1 раз на 20 запусков команды.

Теперь запустил Фар командой W:\Far\Far.exe /pW:\Far\Plugins\TmpPanel\ и 25 раз запускал в нём tmp:<dir /b /s /a-d, выходил из созданного бранча и вновь запускал команду. Увы, пока глюк не повторился.
Автор: shmuz2
Дата сообщения: 14.05.2016 21:02
Тогда продолжайте опыты с LF Search, если на нём хорошо повторяется.
Автор: Angel_Ka
Дата сообщения: 14.05.2016 21:05
А теперь запустил Фар командой W:\Far\Far.exe /pW:\Far\Plugins\TmpsPanel\, т.е. с единственным плагином "Врем. панель (LuaFAR)", и также 25 раз повторил запуск tmps:<dir /b /s /a-d. Глюк не проявился.

Добавлено:

Цитата:
Тогда продолжайте опыты с LF Search, если на нём хорошо повторяется.

Да, сейчас продолжу в рекомендованных Вами 4665 и 4637.
Автор: shmuz2
Дата сообщения: 14.05.2016 21:11
Производите опыты в тех условиях, когда повторяется хорошо, т.е. через поиск с диалога LF Search.
Автор: Angel_Ka
Дата сообщения: 14.05.2016 21:22
Перед тем как скачать указанные версии Фара, вспомнил о том, что на форуме Фара есть тема "Поведение при обнаружении проблем" и воспользовался рекомендацией, приведённой в её пункте
Цитата:
3.3. Запустите FAR c новым профилем и настройками по умолчанию:
far.exe -ro -s %TEMP%\farprofile\%RANDOM%

— запустил Фар командой W:\Far\Far.exe -ro -s %TEMP%\farprofile\%RANDOM% и на той же папке вызвал поиск плагином LF Search. Плагин отрабатывает нормально, без глюка. Запускал несколько раз.

То есть, если я правильно понимаю, дело в каких-то настройках Фара? Ведь плагины при этом тесте и макросы все на месте. И если это так, то как теперь определить какую из великого множества настроек нужно проверить?
Автор: shmuz2
Дата сообщения: 14.05.2016 21:27
Давайте, пожалуйста, не отклоняться от первоначального сценария.
Автор: Angel_Ka
Дата сообщения: 14.05.2016 21:31
Хорошо. Продолжаю.

Добавлено:
Скачал и установил 4665, скопировал туда папку с плагином LF Search, запустил Фар и затем поиск плагином в той же самой папке как и прежде W:\farProf\tstSort\ПРОБА2\ — плагин работает как положено. Перепроверил несколько раз.

Какие дальнейшие действия мне нужно предпринять?
Автор: shmuz2
Дата сообщения: 14.05.2016 21:51
На всякий случай: выложите где-нибудь базу плагина LF Search (8E11EA75-0303-4374-AC60-D1E38F865449.db) и дайте ссылку. Базу возьмите из того профиля, где наблюдается проблема.

Что делать ещё дальше - подумаю. Пока - ничего не надо.
Автор: Angel_Ka
Дата сообщения: 14.05.2016 21:59
Повторил опыт с 4637, результат, как и ожидалось, тот же — плагин нормально создаёт бранч.
Автор: Angel_Ka
Дата сообщения: 15.05.2016 05:56
Alexyz21

Тест макроса Select Duplicates FileName in Branch panel версии 13.0.4, на бранче из 711 984 файлов, созданном плагином LuaFAR Search.

Код: 1). настройки по умолчанию

[x] Number of symbols 9999
[x] Ignore case [ ] Ignore Full Duplicates

файлов: 508 867 mcs: 16 453 473 17 635 307 17 801 993

2)
[ ] Number of symbols 9999
[x] Ignore case [ ] Ignore Full Duplicates
[?] Sizes of FD: --
[?] Attributes of FD: --

файлов: 508 867 mcs: 17 813 332 17 656 129 17 775 330

3).
[ ] Number of symbols 9999
[ ] Ignore case [ ] Ignore Full Duplicates
[?] Sizes of FD: --
[?] Attributes of FD: --

файлов: 501 034 mcs: 17 422 805 17 406 961 17 392 165

4).
[ ] Number of symbols 9999
[ ] Ignore case [ ] Ignore Full Duplicates
[ ] Sizes of FD: <>
[?] Attributes of FD: --

файлов: 230 330 mcs: 16 380 254 16 236 734 16 152 869

5).
[ ] Number of symbols 9999
[ ] Ignore case [ ] Ignore Full Duplicates
[x] Sizes of FD: ==
[?] Attributes of FD: --

файлов: 353 457 mcs: 16 519 078 16 490 075 16 756 702
Автор: Alexyz21
Дата сообщения: 15.05.2016 07:42
13.0.5 [more]
Код: -- 13.0.5
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,ts = string.byte("\\"),{nil,true,9999,true,false,2,2,false}
local freport = win.GetEnv("Temp").."\\Report.txt"

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)
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,8, 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,7, 15,7, 0, 0,0, 0, "Re&port"},
--[[09]] {F.DI_TEXT, -1,6, 0,0, 0, 0,0, F.DIF_SEPARATOR,""},
--[[10]] {F.DI_BUTTON, 0,7, 0,0, 0, 0,0, F.DIF_DEFAULTBUTTON+F.DIF_CENTERGROUP,"&Ok"},
--[[11]] {F.DI_BUTTON, 0,7, 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_SETCHECK,8,tts[8] 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) 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 "--"))
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,10,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)
--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 tsel,st0,ln0,st1,ln1,st2,ln2,st3,ln3,sz0,sz1,fa0,fa1 = {}
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
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL1)
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i,pBL1)
if ts[8] then
if #tsel==0 or Comp(tsel[#tsel][2],tsel[#tsel][3],st1,ln1)~=0 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
--C.free(ffi.gc(buf,nil))
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
end
pc(PANEL_ACTIVE,"FCTL_ENDSELECTION",0,NULL)
pc(PANEL_ACTIVE,"FCTL_REDRAWPANEL",0,NULL)
--Keys("ShiftF12")
if ts[8] 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("mcs - total time of execution in mcs\nReport will be saved to:\n"..freport,"Help: Report",nil,"l")
end
end;
}
Автор: Angel_Ka
Дата сообщения: 15.05.2016 07:50

Цитата:
13.0.5

БОЛЬШОЕ СПАСИБО! Увидел, приступаю к изучению.

И БЛАГОДАРЮ Вас за предупреждение - пояснение! Если макрос находит больше одинаковых/похожих, чем это умозрительно предполагается, то это даже и лучше. Пусть будет так.

Автор: Alexyz21
Дата сообщения: 15.05.2016 07:58
в 2 раза это я конечно погорячился, основное время 80-90% времени съедает сортировка, так что можно подумать над этим.
Автор: Angel_Ka
Дата сообщения: 15.05.2016 08:30

Цитата:
основное время 80-90% времени съедает сортировка

Полагаю, что ту сортировку, которая нужна по технологии в процессе работы самого макроса, лучше без нужны не трогать. А ту сортировку, которую макрос делает по окончании своей работы, чтобы результаты её были явственно видны, по-моему, можно бы и опустить.

Ведь когда помеченные файлы потом копируются куда-то, то безразлично как они при этом отсортированы. А если пользователю зачем-то нужно будет дополнительно проанализировать результаты работы макроса, то он и сам как ему надо отсортирует.

Поэтому, на мой взгляд, сортировка, которая нужна макросу технологически, в данном случае была бы предпочтительнее. А следующая по ранжиру — сортировка по имени.
Автор: Alexyz21
Дата сообщения: 15.05.2016 09:06
Сортировка делается единожды согласно настроек диалога, именно она потребяет основное время. Выделение делается уже после сортировки.

13.1.0 [more]
Код: -- 13.1.0
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,ts = string.byte("\\"),{nil,true,9999,true,false,2,2,true,false}
local freport = win.GetEnv("Temp").."\\Report.txt"

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)
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, 17,6, 0, 0,0, 0, "Accu&racy"},
--[[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
local pBL0,pBL1 = ffi.cast("BOOL*",0),ffi.cast("BOOL*",1)
--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 tsel,st0,ln0,st1,ln1,st2,ln2,st3,ln3,sz0,sz1,fa0,fa1 = {}
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
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL1)
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i,pBL1)
if ts[9] then
if #tsel==0 or Comp(tsel[#tsel][2],tsel[#tsel][3],st1,ln1)~=0 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
--C.free(ffi.gc(buf,nil))
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
end
if ts[8] then
st0,ln0,st1,ln1,st2,ln2,st3,ln3,sz0,sz1,fa0,fa1 = nil
PGPI(0)
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) and (ts[6]==0 and sz1==sz0 or ts[7]==0 and fa1==fa0) then pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL0) pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i,pBL0)
elseif not ts[4] and (ts[2] and C.wcsncmp(st1,st0,ts[3])==0 or C.wcscmp(st1,st0)==0) and (ts[6]==0 and sz1==sz0 or ts[7]==0 and fa1==fa0) then pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL0) pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i,pBL0)
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 algorithm 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
Дата сообщения: 15.05.2016 09:48

Цитата:
Сортировка делается единожды согласно настроек диалога

Понятно.

Цитата:
20% - вполне терпимо

Абсолютно точно.

Цитата:
13.1.0

Отлично! Приступил.


Добавлено:
Тест макроса Select Duplicates FileName in Branch panel (13.0.5 и 13.1.0) на бранче из 711 984 файлов, созданном плагином LuaFAR Search.

Код: 13.0.5

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

файлов: 6 785 mcs: 15 985 623 15 985 219 15 978 116


13.1.0

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

файлов: 6 785 mcs: 16 003 079 16 010 975 15 948 648


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

файлов: 5 165 mcs: 20 038 812 19 894 211 20 043 961
Автор: Alexyz21
Дата сообщения: 15.05.2016 12:12
13.1.1 [more]
Код: -- 13.1.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,ts = string.byte("\\"),{nil,true,9999,true,false,2,2,true,false}
local freport = win.GetEnv("Temp").."\\Report.txt"

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)
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
local pBL0,pBL1 = ffi.cast("BOOL*",0),ffi.cast("BOOL*",1)
--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 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
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
--C.free(ffi.gc(buf,nil))
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
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[4] and (ts[2] and C._wcsnicmp(st1,st0,ts[3])==0 or C._wcsicmp(st1,st0)==0)) or (not ts[4] and (ts[2] and C.wcsncmp(st1,st0,ts[3])==0 or C.wcscmp(st1,st0)==0))) 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
Дата сообщения: 15.05.2016 12:15

Цитата:
13.1.1

Замечательно!

Тест макроса Select Duplicates FileName in Branch panel на бранче из 711 984 файлов, созданном плагином LuaFAR Search.

Код: 13.1.0 и 13.1.1 соответственно
[ ] Number of symbols 9999
[x] Ignore case [ ] Ignore Full Duplicates
[ ] Sizes of FD: <>
[ ] Attributes of FD: <>
[ ] Accuracy

файлов: 6 785
mcs: 16 003 079 16 010 975 15 948 648
mcs: 15 990 571 16 042 631 16 053 227

13.1.0 и 13.1.1 соответственно
[ ] Number of symbols 9999
[x] Ignore case [ ] Ignore Full Duplicates
[ ] Sizes of FD: <>
[ ] Attributes of FD: <>
[x] Accuracy

файлов: 5 165
mcs: 20 038 812 19 894 211 20 043 961
mcs: 19 989 546 19 823 666 19 986 241

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

файлов: 6 629
mcs: 19 235 132 19 261 153 19 111 242

13.1.1
[ ] Number of symbols 9999
[ ] Ignore case [ ] Ignore Full Duplicates
[ ] Sizes of FD: <>
[ ] Attributes of FD: <>
[x] Accuracy (two-pass method)

файлов: 5 136
mcs: 19 543 759 19 613 307 19 568 119
Автор: Alexyz21
Дата сообщения: 15.05.2016 13:01
Angel_Ka
попробуйте 4672, есть разница с предыдущими версиями FAR?
Автор: Angel_Ka
Дата сообщения: 15.05.2016 13:05
shmuz2

Как Вы помните, перенаправление "потока" (оператор <) в Win10 бузит. Поэтому консольная команда создания файла-списка dir /b /s /a-d>filelist.tmps создаёт его с изъянами.

При этом ни нативный поисковик, ни поисковик плагина LuaFAR Search, к сожалению, не умеют создавать файл-список. Они создают сразу бранч. Из которого впоследствии только и можно создать файл-список. А это на больших базах очень долго.

По возможности, добавьте, пожалуйста в плагин LuaFAR Search функцию создания файла-списка сразу по итогам поиска.

Добавлено:
Alexyz21

Цитата:
попробуйте 4672, есть разница с предыдущими версиями FAR?

У меня настроено автообновление, и поэтому с утра я работаю в 4672. Разницы с 4671 я не заметил. Сейчас посмотрю в 4665 и 4637, они со вчерашнего дня установлены тоже.
Автор: Alexyz21
Дата сообщения: 15.05.2016 13:23

Цитата:
Сейчас посмотрю в 4665 и 4637

Не надо - дело оказалось не в версии, а в LuaMacro? - Время исполнения плавает в пределах +-10%.
Автор: Angel_Ka
Дата сообщения: 15.05.2016 13:28

Цитата:
Не надо

Хорошо. Если чего-то надо, пишите, пожалуйста. На буднях неизвестно как будет со временем. Может выдастся, а может и нет.
Автор: Alexyz21
Дата сообщения: 15.05.2016 13:59
Angel_Ka
13.1.1 по сути финальная, ошибок в выделении вроде не вижу и доработок по ней у меня больше нет.
Автор: shmuz2
Дата сообщения: 15.05.2016 14:19
Angel_Ka

Цитата:
По возможности, добавьте, пожалуйста в плагин LuaFAR Search функцию создания файла-списка сразу по итогам поиска

Не, это добавлять не буду.
Это можно сделать простым макросом (всего несколько строк, если без диалога), используя ф-цию far.RecursiveSearch.
Автор: Angel_Ka
Дата сообщения: 15.05.2016 16:30
Alexyz21

Цитата:
13.1.1 по сути финальная

Хорошо. БОЛЬШОЕ СПАСИБО!
А я эту версию тогда по максимуму пока постараюсь покачать по сочетаниям опций, и на б0льшей базе попробую.

Добавлено:
shmuz2

Цитата:
Это можно сделать простым макросом (всего несколько строк, если без диалога), используя ф-цию far.RecursiveSearch.

Так это может даже и лучше! Попробую сначала сам макрос сделать. БЛАГОДАРЮ Вас за подсказку!

Добавлено:
shmuz2
С любезной подсказки уважаемого Alexyz21 я начал изучать, насколько мне хватает понимания, работу Вашего макроса Duplicate Fighter (Анти-дубликатор).

И для сначала, для облегчения его освоения, сделал полу-машинный перевод файла dupfighter_eng на русский язык: [more=dupfighter_rus]
Код: .Language=Russian,Russian (Русский)
.PluginContents=Анти-дубликатор

@Contents

#Объем переработки:#
Диапазон строк, содержащих выбор, или содержимое всего файла (если нет выбора).

#Обычный блок:#
Вся строка обрабатывается, если какая-либо часть её выбрана.

#Вертикальный блок:#
Только выбранная часть строки обрабатывается. Действие (если таковое имеется)
будет применяться ко всей строке.

#Понятие "дубликат":#
Две строки считаются "дубликатами" в отношении друг к другу, если они идентичны
(или становятся таковыми после некоторого преобразования, произведённого пользователем).

#Примеры:#
a) две строки идентичны.
b) две строки становятся идентичными после удаления пробелов на обоих их концах.
c) две строки начинаются с той же последовательности 20 символов.

#Диалог:#

-- -- -- -- -- -- -- Анти-дубликатор (Smuel) -- -- -- -- -- -- --
- -
- (•) 1 Удалить дубликаты [ ] Сохранять пустые строки -
- ( ) 2 Очистить дубликаты [ ] Показывать статистику -
- ( ) 3 Удалить неуникальные -
- ( ) 4 Очистить неуникальные -
- -
- [ ] Использовать выражение [x] Преобразовать в булевое -
- Выражение: -
- L:lower() &#8595;-
- -
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
- { OK } [ Отмена ] -
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
#Опции:#
#(•) 1 Удалить дубликаты# : удалить все повторяющиеся строки, кроме первой в каждой группе дублей
#(•) 2 Очистить дубликаты# : очистить все повторяющиеся строки, кроме первой в каждой группе дублей
#(•) 3 Удалить неуникальные# : удалить все повторяющиеся строки (включая первую)
#(•) 4 Очистить неуникальные# : очистить все повторяющиеся строки (включая первую)

#[x] Сохранять пустые строки#
Если флажок установлен, т.е. опция выставлена, то пустые строки пропускаются (не считаются дублями).
Строки, состоящие целиком из пробельных символов, также пропускаются.

#[x] Показывать статистику#
Если флажок установлен, то по выполнению действия будут показаны некоторые статистические данные.

#[x] Использовать выражение#
Если флажок не установлен, то две строки считаются дублями только тогда, когда они идентичны.
Если флажок установлен, то окно редактирования #Выражение# должно содержать #Lua выражение#, которое будет применено
к каждой выбраной строке (или ее части в случае вертикального блока) и сравниваться будут результаты выражения, а не сами строки.

#*# Выражения могут использовать переменную #L#, то есть текст строки.
#*# Если выражение это текст или число, то данное значение будет использоваться при сравнении.
#*# Если выражение имеет значение false/nil/nothing то строка считается НЕ-ДУБЛИКАТОМ (NON-DUPLICATE).
#*# В иных случаях для сравнения используется содержимое строки.

#Примеры выражений, применённых к любой строке или по номеру:#
#L:lower()#
Две строки считать дубликатами, если они отличаются только регистром.
#L:sub(10,20)#
Две строки считаются дубликатами, если их [10,20] подстроки равны. -- непонятно
#L:len()#
Две строки считаются дубликатами, если они имеют одинаковую длину.
#L:match("foobar")#
Две строки считаются дубликатами, если они обе содержат подстроку "foobar".

#[x] Преобразовать в булевое#
Если флажок установлен, то результат выражения преобразуется в логическое значение, которое: не не X.
В этом случае:
- строка со значением false не является дубликатом, она не участвует в сравнениях.
- строка со значением true участвует в сравнениях.

#Примеры выражений, пробразовываемые в булевое:#
#L:match("foobar")#
Строка считается дубликатом, если она содержит подстроку "foobar".
#not L:match("foobar")#
Строка считается дубликатом, если она не содержит подстроку "foobar".
#L:match("foo") and L:match("bar")#
Строка считается дубликатом, если она содержит как "foo" так и "bar".
Автор: Alexyz21
Дата сообщения: 15.05.2016 17:39

Цитата:
Не могли бы Вы подсказать как цивильно вживить русский файл помощи в данный макрос?

Это называется режим справочника - от 3-х до 5-и

Grep спасёт отца русской демократии! в папке с макросами ищем lang - в скрипте DBEdit.lua IgorZ находим:

Код: function LoadLang() --[[загрузить настройки языка]]
local FL = win.GetEnv("FARLANG"):sub(1,3) -- язык (первые 3 буквы)
FL = win.GetFileAttr(PathName..FL..".lng") and FL or "Eng" -- скорректируем: если такого файла нет, берём английский
if FarLang~=FL then FarLang,L = FL,dofile(PathName..FL..".lng") end -- если не совпадает с текущим, обновим язык
end
Автор: shmuz2
Дата сообщения: 15.05.2016 17:45
Angel_Ka

Цитата:
Не могли бы Вы подсказать как цивильно вживить русский файл помощи в данный макрос?

Выложите этот файл где-то, я не доверяю копипасте с этого форума. Потом я его просмотрю и добавлю (может занять некоторое время).
Автор: Angel_Ka
Дата сообщения: 15.05.2016 18:50
Alexyz21

Цитата:
Это называется режим справочника - от 3-х до 5-и

Есть и такое, конечно, но основной причиной задать по сути детский вопрос было то, что как то неловко самому влезать в чужой макрос.

При этом я очень благодарен Вам за совет и подробное пояснение к нему! До такого самому надо долго додумываться. А теперь благодаря Вашей любезности можно попробовать на практике несколько раз потренироваться, и этот опыт полезно осядет в копилку знаний-умений.

Добавлено:
shmuz2

Цитата:
Потом я его просмотрю и добавлю

Спасибо большое!
А может и новшества какие внесёте в сам макрос?
Любопытство одолевает.
Автор: shmuz2
Дата сообщения: 15.05.2016 19:10

Цитата:
А может и новшества какие внесёте в сам макрос?

Новшества на данный момент не запланированы, а в будущем не исключено и такое развитие событий.

Страницы: 123456789101112

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


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