Skip to content

Wish: нужен макровызов Plugin.SyncCall(GUID,"chkhash",file) который мог бы использваться в callback-е far.RecursuveSearch() для поиска и проверки хэшей #47

@VictorVG

Description

@VictorVG

Задачу изначально сформулировали так (имя поставившего её опустим):

ТЗ

скрипт с хоткеем (задается в теле скрипта)
если вызван на папке - шерстим папку на предмет вложенных файлов хэшсумм и проверяем их
опосля выводим статистику вида
путь -
найдено - X sfv файлов (| Y md5 файлов| Z sha файлов)
ошибок -

как обработать вызов если вызван на папке, при этом еще несколько элементов покрашено?
и проверить эти элементы - может среди них и обычные файлы затесались?

решение напрашивается само собой - far.RecursiveSearch():

far.RecursiveSearch(InitDir,Mask,UserFunc [,Flags[, ...]])

Параметры:
InitDir: строка
Маска: строка (может включать атрибуты - см. Примечание ниже)
UserFunc: функция
Флаги: флаги
...: дополнительные аргументы, любые значения Lua

Возвращает:
В случае, если поиск был остановлен UserFunc: все значения возвращаются UserFunc.
В случае, если больше не осталось файлов: ничего.
В случае ошибки в UserFunc: ничего.

Описание:

Для каждого найденного файла вызывается UserFunc со следующими аргументами:
(1) таблица tPluginPanelItem
(2) полный путь к найденному файлу
(3 ...) дополнительные аргументы (если есть), которые были переданы far.RecursiveSearch()

Если первое возвращаемое значение UserFunc не false или nil поиск остановливавется

Замечания:

2-й параметр (маска) может включать атрибуты файла после самой маски
после >> разделителя. Атрибуты обрабатываются по правилу:

  • Маленькая буква означает, что атрибут должен присутствовать.
  • Большая буква означает, что атрибут не должен присутствовать.

Пример: * | * .txt >> rA

константа FRSMODE

FRS_RETUPDIR = 0x0000000000000001,
FRS_RECUR = 0x0000000000000002,
FRS_SCANSYMLINK = 0x0000000000000004,
FRS_NONE = 0;

Если флагов более одного, то их можно указать значением FLAG =Flag1 + Flag2 + Flag3 + Flag4

и в её UserFunc() вызываем плагин имея tPluginPanelItem и путь к объекту, а он проверяет найденный хэш выводя результат проверки, и в случае если плагин сработал увеличиваем счётчик найденных хэшей. Первый вариант был таким:

local msk,cnt,ICId = "/.+\\.(md5|sfv|sha(1|3|256|512)|wrpl)/i",0,"E186306E-3B0D-48C1-9668-ED7CF64C0E65";
far.RecursiveSearch(far.GetCurrentDirectory(),msk..">>D",function(itm,pt)
  Plugin.Command(ICId,'"'..pt..'"')
  cnt=cnt+1;
end,6)
far.Message("Hash\'s found: "..cnt.." pcs")

но из-за особенности far.RecursiveSearch() (спасибо Шмуель подсказал):

Шмуель:

far.RecursiveSearch можно вызывать откуда угодно.

Plugin.Command можно вызывать только из макроса (lua:PluginCommand(...) это тоже макрос).
Но нельзя вызывать из condition макроса, нельзя вызывать из Event (ни из condition, ни из action)

Ага, сейчас проверил, PLugin.Command нельзя вызывать из callback функции
far.RecursiveSearch. Это потому, что callback вызывается Фаром, а не плагином.

Но если у этого плагина есть операции через Plugin.Call / Plugin.SyncCall, то
можно использовать Plugin.SyncCall - он работает везде.

Есть и другой вариант - в far.RecursiveSearch ты не вызываешь Plugin.Command,
а только собираешь данные файлов в таблицу-массив. После завершения
far.RecursiveSearch делаешь обычный цикл for по этой таблице, и внутри этого
цикла можешь свободно вызывать Plugin.Command.
сделал то, что изначально не хотел - сбор в таблицы и после цикл по ним:

  local icid="E186306E-3B0D-48C1-9668-ED7CF64C0E65"
  local msk,cnt,apt,anm = "/.+\\.(md5|sfv|sha(1|3|256|512)|wrpl)/i",0,{},{};
  Far.DisableHistory(-1)
  far.RecursiveSearch(far.GetCurrentDirectory(),msk..">>D",function(itm,fpath)
  cnt=cnt + 1;
  apt[cnt] = mf.fsplit(fpath,3);
  anm[cnt] = itm.FileName;
  end,6);
  if cnt >= 1 then
   local cdir,cfnm = far.GetCurrentDirectory(),APanel.Current;
   for i=1,cnt do
    Panel.SetPath(0,apt[i],anm[i]);
    Plugin.Command(icid,APanel.Current);
   end;
   far.Message("Hash\'s found: "..cnt.." pcs");
   Panel.SetPath(0,cdir,cfnm);
 end;

"срабатывает", но не всегда - что-то может и пропустить, потому вариант в Plugin.SyncCall() выглядит надёжным. С ним код упрощаем до минимума:

local icid="E186306E-3B0D-48C1-9668-ED7CF64C0E65"
local msk,cnt,cdir,cfnm = "/.+\\.(md5|sfv|sha(1|3|256|512)|wrpl)/i",0,far.GetCurrentDirectory(),APanel.Current;
  Far.DisableHistory(-1)
   far.RecursiveSearch(far.GetCurrentDirectory(),msk..">>D",function(itm,fpath)
     cnt=cnt + 1;
      panel.SetPanelDirectory(nil,1,fpath:sub(1,#fpath - #itm.FileName - 1))
     Plugin.SyncCall(icid,"chkhash",itm.FileName)
     cnt=cnt + 1;
   end,6);
   -- Panel.SetPath(0,cdir,cfnm); -- раскомментируем, если потребуется восстановить позиционирование курсора
   far.Message("Hash\'s found: "..cnt.." pcs");

и тут по идее и ломаться нечему, а если бы плагин по итогу проверки ещё бы выводил в API success - успешно, false - ошибка, notexist - файл не найден, userabort - во время счёта нажата Cancel или ESC то, счётчик можно было бы сделать точным: if Plugin.SyncCall(icid,"chkhash",itm.FileName) then cnt=cnt + 1 end; - а ошибки вывести в лог - мечта.:)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions