Плагин DescSS позволял выполнять некоторые действия с описаниями файлов, как с именами файлов, а именно:
- установка и снятия пометки по маске аналогично NumPad+ (Grey+) и NumPad- (Grey-), используя вместо имён файлов описания;
- быстрый поиск файлов аналогично Alt-символ в панелях (Quick Search, он же Fast Find), используя опять-таки описания вместо имён файлов.
Так как плагин DescSS не работает под FAR3, были написаны макросы для его замены.
Набор содержит следующие макросы:
AltShiftS - пометка по маске.
AltShiftD - пометка по маске с начальной подстановкой маски ** для совпадения с любой частью описания.
AltShiftU - снятие пометки по маске.
Alt, - вызов диалога быстрого поиска по описанию.
AltSpace или Alt. - вызов диалога быстрого поиска с начальной подстановкой символа * для поиска с любого места описания. Кнопкосочетание AltSpace работает при установленном плагине XKeys.
В диалоге быстрого поиска задействованы следующие сочетания клавиш:
CtrlEnter или CtrlDown - к следующему совпадению.
CtrlShiftEnter или CtrlUp - к предыдущему совпадению.
CtrlEnd - к последнему совпадению.
CtrlHome - к первому совпадению.
Ins - инвертировать пометку текущего файла и перейти к следующему совпадению.
CtrlV или ShiftIns - вставить из буфера обмена. Вставка осуществляется до тех пор, пока есть совпадение.
AltSpace или Alt. или Alt, - те же клавиши, что и для вызова быстрого поиска по описанию для перехода к обычному Search (вызывается макрос, назначенный на Shell/Space, можно подставить любой другой).
Некоторые особенности использования масок:
Для проверки совпадения в макросах используется функция far.ProcessName, рассчитанная на работу с именами файлов, в то время как описания - это обычный текст. Из энциклопедии, mask может быть:
- маской;
- списком масок (разделённых запятой или точкой с запятой);
- маской исключения - одной или несколькими масками файлов, которой не должна соответствовать строка поиска. Маска исключения отделяется от основной маски символом "|";
- регулярным выражением. Текст регулярного выражения должен быть окружён символами "/".
Кроме того, в ФАРе используется нестандартная для масок Windows фича задания в квадратных скобках отдельных символов и диапазонов символов вида [c,x-z]. Следует учесть это в макросах пометки и снятия пометки.
При необходимости маску можно заключить в кавычки, тогда она воспринимается как одна единая маска.
В макросе быстрого поиска для максимального приближения к стандартному Search подразумевается, что
- маска заканчивается символом *. Т.е., даже если этот символ явно не задан, он будет автоматически добавляться при сравнении;
- маска рассматривается как единая, т.е. как если бы была заключена в кавычки при обычном вводе. Т.е. не рассматривается как список масок и без исключений. Поэтому в быстром поиске не работает поиск кавычек.
Возможны другие нюансы использования этой функции.
Особенности использования других макросов с диалогом быстрого поиска по описаниям:
Макрос быстрого поиска работает в области Dialog, поэтому в нём будут срабатывать другие макросы, назначенные на эту область. Если это нежелательно, в макросах для области Dialog можно использовать фильтр по GUID "83689A78-99EA-4B01-98DE-ED8135140B20" (диалог быстрого поиска) и "5A71088D-CB13-4F43-A314-C2B4D65C3D59" (select/unselect).
Особенности вызова других макросов из диалога быстрого поиска по описаниям:
Клавиши, не обрабатываемые диалоговой процедурой быстрого поиска, передаются ФАРу для дальнейшей обработки по следующему алгоритму:
- Закрывается диалог быстрого поиска. Область выполнения макросов становится Shell.
- Выполняется eval в текущей области. В соответствии с алгоритмом работы eval сначала проверяется область Shell, если в ней нет макроса, то Common.
- Если макрос в этих областях отсутствует, кнопкосочетание передаётся ФАРу "as is", но без левых/правых модификаторов.
Обычно макросы в области Shell дублируются для удобства в области Search. При таком подходе поведение макроса быстрого поиска по описаниям будет "почти" таким же, как и обычного быстрого поиска.
AltShiftS - пометка по маске.
AltShiftD - пометка по маске с начальной подстановкой маски ** для совпадения с любой частью описания.
AltShiftU - снятие пометки по маске.
Alt, - вызов диалога быстрого поиска по описанию.
AltSpace или Alt. - вызов диалога быстрого поиска с начальной подстановкой символа * для поиска с любого места описания. Кнопкосочетание AltSpace работает при установленном плагине XKeys.
В диалоге быстрого поиска задействованы следующие сочетания клавиш:
CtrlEnter или CtrlDown - к следующему совпадению.
CtrlShiftEnter или CtrlUp - к предыдущему совпадению.
CtrlEnd - к последнему совпадению.
CtrlHome - к первому совпадению.
Ins - инвертировать пометку текущего файла и перейти к следующему совпадению.
CtrlV или ShiftIns - вставить из буфера обмена. Вставка осуществляется до тех пор, пока есть совпадение.
AltSpace или Alt. или Alt, - те же клавиши, что и для вызова быстрого поиска по описанию для перехода к обычному Search (вызывается макрос, назначенный на Shell/Space, можно подставить любой другой).
Некоторые особенности использования масок:
Для проверки совпадения в макросах используется функция far.ProcessName, рассчитанная на работу с именами файлов, в то время как описания - это обычный текст. Из энциклопедии, mask может быть:
- маской;
- списком масок (разделённых запятой или точкой с запятой);
- маской исключения - одной или несколькими масками файлов, которой не должна соответствовать строка поиска. Маска исключения отделяется от основной маски символом "|";
- регулярным выражением. Текст регулярного выражения должен быть окружён символами "/".
Кроме того, в ФАРе используется нестандартная для масок Windows фича задания в квадратных скобках отдельных символов и диапазонов символов вида [c,x-z]. Следует учесть это в макросах пометки и снятия пометки.
При необходимости маску можно заключить в кавычки, тогда она воспринимается как одна единая маска.
В макросе быстрого поиска для максимального приближения к стандартному Search подразумевается, что
- маска заканчивается символом *. Т.е., даже если этот символ явно не задан, он будет автоматически добавляться при сравнении;
- маска рассматривается как единая, т.е. как если бы была заключена в кавычки при обычном вводе. Т.е. не рассматривается как список масок и без исключений. Поэтому в быстром поиске не работает поиск кавычек.
Возможны другие нюансы использования этой функции.
Особенности использования других макросов с диалогом быстрого поиска по описаниям:
Макрос быстрого поиска работает в области Dialog, поэтому в нём будут срабатывать другие макросы, назначенные на эту область. Если это нежелательно, в макросах для области Dialog можно использовать фильтр по GUID "83689A78-99EA-4B01-98DE-ED8135140B20" (диалог быстрого поиска) и "5A71088D-CB13-4F43-A314-C2B4D65C3D59" (select/unselect).
Особенности вызова других макросов из диалога быстрого поиска по описаниям:
Клавиши, не обрабатываемые диалоговой процедурой быстрого поиска, передаются ФАРу для дальнейшей обработки по следующему алгоритму:
- Закрывается диалог быстрого поиска. Область выполнения макросов становится Shell.
- Выполняется eval в текущей области. В соответствии с алгоритмом работы eval сначала проверяется область Shell, если в ней нет макроса, то Common.
- Если макрос в этих областях отсутствует, кнопкосочетание передаётся ФАРу "as is", но без левых/правых модификаторов.
Обычно макросы в области Shell дублируются для удобства в области Search. При таком подходе поведение макроса быстрого поиска по описаниям будет "почти" таким же, как и обычного быстрого поиска.
- --[=[ ----------------------------------------------------------------------------------------------
- Макросы для замены плагина DESCSS
- v.1.06 (C) 2013-2016 Smitis
- http://forum.farmanager.com/viewtopic.php?t=7846
- --]=] ----------------------------------------------------------------------------------------------
- ----------------------------------------------------------------------------------------------------
- -- Настройки. Персональные настройки можно держать в файле DescSS.cfg (см. пример DescSS.example.cfg)
- ----------------------------------------------------------------------------------------------------
- local cfg = {}
- -- Внимание! Используемый здесь AltSpace работает при наличие плагина XKeys.
- -- ДЛЯ ОТКЛЮЧЕНИЯ МАКРОСОВ И ГОРЯЧИХ КЛАВИШ ОСТАВИТЬ СТРОКУ ПУСТОЙ!
- cfg.sample = "" -- Пример: так отключать макросы
- -- Макросы для установки/снятия пометки
- cfg.dss_sel = "AltShiftS" -- макрос Select
- cfg.dss_unsel = "AltShiftU" -- макрос Unselect
- cfg.dss_fill = "AltShiftD" -- макрос Select with init
- cfg.dss_post = "* * Left" -- иницилизация маски для предыдущего макроса (макропоследовательность!)
- -- Макросы быстрого поиска
- cfg.dff_empty = "Alt," -- открыть пустой диалог
- cfg.dff_fill = "AltSpace" -- открыть непустой диалог
- cfg.dff_text = "*" -- иницилизация непустого диалога для предыдущего макроса (текст!)
- -- Диалоговая процедура быстрого поиска.
- -- Правые и левые модификаторы не проверяются для упрощения обработки!
- -- Несколько комбинаций перечисляются через пробел, регэкспы не поддерживаются.
- cfg.dff_next = "CtrlEnter CtrlNumEnter CtrlDown" -- следующее совпадение
- cfg.dff_prev = "CtrlShiftEnter CtrlShiftNumEnter CtrlUp" -- предыдущее совпадение
- cfg.dff_last = "CtrlEnd" -- последнее совпадение
- cfg.dff_first = "CtrlHome" -- первое совпадение
- cfg.dff_invert = "Ins" -- инвертировать пометку текущего файла/папки
- cfg.dff_insert = "CtrlV ShiftIns" -- вставка
- cfg.far = "Esc CtrlY CtrlX CtrlC" -- отдать ФАРу
- cfg.dummy = "Left Right Ctrl Alt Shift" -- ничего не делать с этими хоткеями
- cfg.search_empty = "Alt," -- выйти и открыть пустой Search
- cfg.search_fill = "AltSpace Alt." -- выйти и открыть непустой Search
- cfg.search_text = "*" -- иницилизация для непустого Search (текст!)
- cfg.cyclic = true -- использовать циклический поиск
- ----------------------------------------------------------------------------------------------------
- -- Загрузка персональных настроек
- ----------------------------------------------------------------------------------------------------
- --do local f,m=loadfile(debug.getinfo(1,"S").source:match("^@(.+)%.")..".cfg")
- do local f,m=loadfile((...):gsub("[^.]+$","cfg"))
- if f then setfenv(f,{cfg=cfg}) if not pcall(f) then msgbox("DescSS","\nCONFIG ERROR\n ",1)
- end end end
- ----------------------------------------------------------------------------------------------------
- -- Локализация
- ----------------------------------------------------------------------------------------------------
- local langs = { english = {}, russian = {} }
- langs.english.dss_sel = "Description Select"
- langs.english.dss_unsel = "Description Unselect"
- langs.english.dff_title = "Description"
- langs.russian.dss_sel = "Пометка по описанию"
- langs.russian.dss_unsel = "Снятие пометки по описанию"
- langs.russian.dff_title = "Описание"
- ----------------------------------------------------------------------------------------------------
- local F = far.Flags
- ----------------------------------------------------------------------------------------------------
- -- Выделение/снятие выделения по описаниям (Description Select/Unselect)
- ----------------------------------------------------------------------------------------------------
- local DescSSId = "5A71088D-CB13-4F43-A314-C2B4D65C3D59"
- local DescSSIdB = win.Uuid(DescSSId)
- far.Guids.DescriptionSelectUnselectId = DescSSId
- local dss_recur = false
- local dss_init = ""
- -- замена mf.fmatch
- local function dff_fmatch(fn,mask)
- --return mf.fmatch(fn,mask)==1
- return far.ProcessName(F.PN_CMPNAME,mask,fn)
- end
- -- Основная функция
- local function descriptions_select( sel, init )
- if Area.Search then Keys "Esc" end
- local lang = langs[win.GetEnv("FARLANG"):lower()] or langs.english
- local diz
- local Title = (sel==1) and lang.dss_sel or lang.dss_unsel
- local HistName = "DSS"
- local Flags = F.FIB_ENABLEEMPTY + F.FIB_BUTTONS + (init and F.FIB_NOUSELASTHISTORY or 0)
- dss_init = init
- dss_recur = type(init)~="string"
- mask = far.InputBox(DescSSIdB,Title,"",HistName,"",nil,nil,Flags)
- if mask == nil or mask == "" then return end
- local sel_fold = cfg.selfold or Far.GetConfig("Panel.SelectFolders") -- использовать пометку папок
- for index=1,APanel.ItemCount do
- if sel_fold or band(Panel.Item(0,index,2),0x10)==0 then
- diz = Panel.Item(0,index,11)
- if diz:len() > 0 then
- if dff_fmatch(diz,mask) then
- Panel.Select(0,sel,1,index)
- end
- end
- end
- end
- end
- if cfg.dss_post ~= "" and cfg.dss_fill ~= "" then
- Event { -- Установить строку иницилизации
- description="Description: Init string";
- group="DialogEvent";
- condition=function(event,param)
- if not dss_recur and event==F.DE_DLGPROCEND and param.Msg==F.DN_INITDIALOG then
- local info = param.hDlg:send(F.DM_GETDIALOGINFO)
- return info and info.Id==DescSSIdB
- end
- end;
- action=function(event,param)
- dss_recur = true -- исключить рекурсивный вход
- far.MacroPost('Keys("'..dss_init..'")')
- end;
- }
- end
- if cfg.dss_sel ~= "" then
- Macro { -- Выделить
- description="Description: Select";
- area="Shell Search";
- key=cfg.dss_sel;
- action=function()
- descriptions_select(1)
- end;
- }
- end
- if cfg.dss_fill ~= "" then
- Macro { -- Выделить с установкой начальной маски **
- description="Description: Select **";
- area="Shell Search";
- key=cfg.dss_fill;
- action=function()
- descriptions_select(1,"* * Left")
- end;
- }
- end
- if cfg.dss_unsel ~= "" then
- Macro { -- Снять выделение
- description="Description: Unselect";
- area="Shell Search";
- key=cfg.dss_unsel;
- action=function()
- descriptions_select(0)
- end;
- }
- end
- ----------------------------------------------------------------------------------------------------
- -- Быстрый поиск по описаниям (Description Fast Find = Description Quick Search)
- ----------------------------------------------------------------------------------------------------
- local DFF_ID = "83689A78-99EA-4B01-98DE-ED8135140B20"
- local DFF_GUID = win.Uuid(DFF_ID)
- local dff_hdlg
- local dff_mask = ""
- local dff_focus = 2 -- фокус поля ввода
- local item_property = 11
- -- Установить текст маски в поле ввода
- local function dff_print(text)
- far.SendDlgMessage(dff_hdlg,F.DM_SETTEXT,dff_focus,text)
- end
- -- Перерисовка диалога
- local function dff_redraw()
- far.SendDlgMessage(dff_hdlg,F.DM_REDRAW,0,0)
- end
- -- Сравнение описания файла по маске
- local function dff_match(mask,diz)
- -- При сравнении, в конец маски добавляем символ *, если его там нет
- -- Делаем фичу: непустая маска никогда не должна совпадать с пустым описанием, даже если маска *
- -- Короче, с пустым описанием может совпасть только пуская маска.
- return (diz ~= "" or mask == "" ) -- то же not (diz == "" and mask ~= "" )
- -- Заключаем всё в кавычки, что бы получить один регексп (особенность сравнения по маска mf.fmatch)
- --and dff_fmatch(diz,'"'..((mask:sub(-1)~='*') and (mask..'*') or mask)..'"')
- -- Вариант без заключения маски в кавычки
- and dff_fmatch(diz,(mask:sub(-1)~='*') and (mask..'*') or mask)
- end
- -- Сравнение описания файла с номером index по маске
- local function dff_imatch(mask,index)
- return dff_match(mask,Panel.Item(0,index,11))
- end
- -- Поиск следующего совпадения.
- -- При успехе возвращаем индекс найденного файла, иначе - 0.
- local function dff_next(mask)
- local current = Panel.SetPosIdx(0,0)
- local diz
- -- со следующего и до конца
- for index=current+1, APanel.ItemCount do
- diz = Panel.Item(0,index,11)
- if diz:len() > 0 then
- if dff_match(mask,diz) then
- return index
- end
- end
- end
- if not cfg.cyclic then return 0 end
- -- с первого до текущего
- for index=1, current do
- diz = Panel.Item(0,index,11)
- if diz:len() > 0 then
- if dff_match(mask,diz) then
- return index
- end
- end
- end
- return 0
- end
- -- Поиск предыдущего совпадения.
- -- При успехе возвращаем индекс найденного файла, иначе - 0.
- local function dff_prev(mask)
- local current = Panel.SetPosIdx(0,0)
- local diz
- -- с предыдущего и до начала
- for index=current-1, 1, -1 do
- diz = Panel.Item(0,index,11)
- if diz:len() > 0 then
- if dff_match(mask,diz) then
- return index
- end
- end
- end
- -- с последнего до текущего
- if not cfg.cyclic then return 0 end
- for index=APanel.ItemCount, current, -1 do
- diz = Panel.Item(0,index,11)
- if diz:len() > 0 then
- if dff_match(mask,diz) then
- return index
- end
- end
- end
- return 0
- end
- -- Поиск последнего совпадения
- local function dff_end(mask)
- local current = Panel.SetPosIdx(0,0)
- local diz
- for index=APanel.ItemCount, Panel.SetPosIdx(0,0), -1 do -- ??? Panel.SetPosIdx(0,0)+1
- diz = Panel.Item(0,index,11)
- if diz:len() > 0 then
- if dff_match(mask,diz) then
- return index
- end
- end
- end
- return 0
- end
- -- Поиск первого совпадения
- local function dff_home(mask)
- local diz
- for index=1, Panel.SetPosIdx(0,0) do -- ??? Panel.SetPosIdx(0,0)-1
- diz = Panel.Item(0,index,11)
- if diz:len() > 0 then
- if dff_match(mask,diz) then
- return index
- end
- end
- end
- return 0
- end
- -- Добавление одного символа к маске
- local function dff_char(char)
- local new_mask = dff_mask .. char
- local index
- if dff_imatch(new_mask,0) then
- -- Если маска совпадает с описанием текущего файла, никуда не перемещаемся
- dff_mask = new_mask
- dff_print(dff_mask)
- else
- index = dff_next(new_mask) -- следующее совпадение или 0
- if index > 0 then
- -- Если есть совпадение - переход,
- -- иначе символ никак не обрабатываем
- dff_mask = new_mask
- dff_print(dff_mask)
- Panel.SetPosIdx(0,index)
- dff_redraw()
- end
- end
- end
- -- Добавление нескольких символов к маске
- local function dff_chars(chars)
- local new_mask = dff_mask
- local index
- for i=1, chars:len() do
- new_mask = new_mask .. chars:sub(i,i)
- if dff_imatch(new_mask,0) then
- -- Если маска совпадает с описанием текущего файла,
- -- никуда не перемещаемся
- dff_mask = new_mask
- else
- index = dff_next(new_mask)
- if index > 0 then
- dff_mask = new_mask
- Panel.SetPosIdx(0,index)
- else
- -- если очередной символ добавить не удалось, заканчиваем вставку
- break
- end
- end
- end
- dff_print(dff_mask)
- dff_redraw()
- return
- end
- -- Вниз
- local function dff_down()
- if dff_mask:len() > 0 then
- -- При непустой маске ищем следующее совпадение
- index = dff_next(dff_mask)
- if index > 0 then
- Panel.SetPosIdx(0,index)
- end
- else
- -- При пустой маске просто перемещаемся на следующий файл
- if APanel.Eof then
- Panel.SetPosIdx(0,1)
- else
- Panel.SetPosIdx(0,Panel.SetPosIdx(0,0)+1)
- end
- end
- dff_redraw()
- end
- -- Вверх
- local function dff_up()
- if dff_mask:len() > 0 then
- -- При непустой маске ищем предыдущее совпадение
- index = dff_prev(dff_mask)
- if index > 0 then
- Panel.SetPosIdx(0,index)
- end
- else
- -- При пустой маске просто перемещаемся на предыдущий файл
- if APanel.Bof then
- Panel.SetPosIdx(0,-1)
- else
- Panel.SetPosIdx(0,Panel.SetPosIdx(0,0)-1)
- end
- end
- dff_redraw()
- end
- -- Для поиска клавиши в строке клавиш
- local function instr(s,k)
- return (" "..s:lower().." "):match(" "..k:lower().." ")
- end
- -- Создаём диалог
- local function dff_dialog(dlg_init)
- local lang = langs[win.GetEnv("FARLANG"):lower()]
- if not lang then lang = langs.english end
- local dlg_wid = 20 -- ширина строки ввода
- local dlg_x1 = APanel.Left and 2 or PPanel.Width+2
- local dlg_x2 = dlg_x1 + dlg_wid + 2
- local dlg_y1 = APanel.Height - 1
- local dlg_y2 = dlg_y1 + 2
- local exit_key = false
- local exit_keys = false
- if Area.Search then Keys "Esc" end
- dff_mask = ""
- local dlg_items =
- { -- X1,Y1,X2,Y2,_,sHistory,sMask,Flags,sData,...
- {F.DI_DOUBLEBOX,0,0,dlg_wid+1,2,0,0,0,0,lang.dff_title}, -- 01
- {F.DI_EDIT, 1,1,dlg_wid ,1,0,0,0,0,dff_mask}, -- 02
- }
- -- Диалоговая процедура (thanks ZG за помощь)
- local function dlg_proc(hDlg,Msg,Param1,Param2)
- if Msg==F.DN_INITDIALOG then
- -- Фокус будет на единственном поле ввода
- dff_focus = far.SendDlgMessage(dff_hdlg,F.DM_GETFOCUS,0,0)
- -- Снимаем признак "неизменённый", что бы не было выделения цветом
- far.SendDlgMessage(dff_hdlg,F.DM_EDITUNCHANGEDFLAG,dff_focus,0)
- dff_chars(dlg_init) -- начальная иницилизация маски с переходом к ближайшему совпадению
- return false
- elseif Msg==F.DN_CONTROLINPUT and Param1==dff_focus and Param2.EventType==F.MOUSE_EVENT then
- -- отключаем события мыши, чтобы не перемещался курсор
- return true
- elseif Msg==F.DN_CONTROLINPUT and Param1==dff_focus and Param2.EventType==F.KEY_EVENT and Param2.KeyDown then
- local k = far.InputRecordToName(Param2) -- клавиша "as is"
- local a = k:gsub("[RL]Ctrl","Ctrl"):gsub("[RL]Alt","Alt") -- для упрощения проверки
- local mask = ""
- local index, clp
- if a:len()==1 then
- -- Введён один символ
- dff_char(a)
- elseif a=="Space" or a=="ShiftSpace" then
- dff_char(" ")
- elseif a=="BackSlash" then
- dff_char("\\")
- elseif a=="BS" then
- -- Удаление последнего символа, перемещаться после этого не надо (совпадение уже проверенно)
- if dff_mask:len() > 0 then
- dff_mask = dff_mask:sub(1,-2)
- dff_print(dff_mask)
- end
- elseif instr(cfg.dff_next,a) then
- -- Перемещение к следующему совпадению
- dff_down()
- elseif instr(cfg.dff_prev,a) then
- -- Перемещение к предыдущему совпадению
- dff_up()
- elseif instr(cfg.dff_last,a) then
- -- Перемещение к последнему совпадению
- if dff_mask:len() > 0 then
- index = dff_end(dff_mask)
- if index > 0 then
- Panel.SetPosIdx(0,index)
- end
- else
- Panel.SetPosIdx(0,APanel.ItemCount)
- end
- dff_redraw()
- elseif instr(cfg.dff_first,a) then
- -- Перемещение к первому совпадению
- if dff_mask:len() > 0 then
- index = dff_home(dff_mask)
- if index > 0 then
- Panel.SetPosIdx(0,index)
- end
- else
- Panel.SetPosIdx(0,1)
- end
- dff_redraw()
- elseif instr(cfg.dff_invert,a) then
- -- Выделить и перейти к следующему
- Panel.Select(0,2,1)
- dff_down()
- elseif instr(cfg.dff_insert,a) then
- -- Вставка
- clp = mf.clip(0)
- if type(clp)=="string" and clp:len()>0 then
- dff_chars(clp)
- end
- elseif instr(cfg.far,a) then
- -- для обработки возвращаем управление ФАРу
- return false
- elseif instr(cfg.dummy,a) then
- -- Ничего не делаем
- elseif instr(cfg.search_empty,a) then
- -- Перейти к обычному Search
- exit_keys = "Alt<" -- комбинация клавиш, вызывающая обычный Search
- far.SendDlgMessage(hDlg,F.DM_CLOSE)
- elseif instr(cfg.search_fill,a) then
- -- Перейти к Search
- exit_keys = "Alt< " .. cfg.search_text
- far.SendDlgMessage(hDlg,F.DM_CLOSE)
- else
- exit_key = k
- far.SendDlgMessage(hDlg,F.DM_CLOSE)
- end
- return true
- end
- end -- dlg_proc
- local dlg_flags = F.FDLG_KEEPCONSOLETITLE + F.FDLG_NODRAWSHADOW + F.FDLG_SMALLDIALOG
- dff_hdlg = far.DialogInit(DFF_GUID,dlg_x1,dlg_y1,dlg_x2,dlg_y2,"",dlg_items,dlg_flags,dlg_proc)
- far.DialogRun(dff_hdlg)
- far.DialogFree(dff_hdlg)
- if exit_keys then
- Keys(exit_keys)
- elseif exit_key then
- if eval(exit_key,2)==-2 then
- Keys(exit_key)
- end
- end
- end
- -- Макросы
- if cfg.dff_empty ~= "" then
- Macro { -- Вызов диалога быстрого поиска
- description="Description: Fast Find";
- area="Shell Search";
- key=cfg.dff_empty;
- action=function() dff_dialog("") end;
- }
- end
- if cfg.dff_fill ~= "" then
- Macro { -- Вызов диалога быстрого поиска с начальной маской
- description="Description: Fast Find";
- area="Shell Search";
- key=cfg.dff_fill;
- action=function() dff_dialog(cfg.dff_text) end;
- }
- end
- ----------------------------------------------------------------------------------------------------
GeSHi © Codebox Plus Extension
- --[[ -----------------------------------------------------------------------------------------------
- Пример файла конфигурации для макросов DescSS.
- Файл должен лежать в той же папке, что и файл макросов, иметь тоже имя и расширение cfg.
- По умолчанию, если основной скрипт не переименован, имя должно быть DescSS.cfg
- Файл конфигурации представляет собой скрипт Lua. Если файл содержит синтаксические ошибки
- и не может быть обработам интерпретатором Lua, будет выдано сообщение:
- ╔═══ DescSS ═══╗
- ║ ║
- ║ CONFIG ERROR ║
- ║ ║
- ╟──────────────╢
- ║ { OK } ║
- ╚══════════════╝
- Если файл конфигурации отсутствует или содержит ошибки, будут использованны значения по умолчанию,
- заданные в основном скрипте. В случае отсутствия каких-либо параметров (например, они будут
- закоментированы), вместо них также будут использованы значения по умолчанию.
- В диалоговой процедуре правые и левые модификаторы не проверяются для упрощения обработки,
- регэкспы не поддерживаются.
- Внимание! Используемый здесь AltSpace работает при наличие плагина XKeys.
- ДЛЯ ОТКЛЮЧЕНИЯ МАКРОСОВ И ГОРЯЧИХ КЛАВИШ ОСТАВИТЬ СТРОКУ В КОВЫЧКАХ ПУСТОЙ!
- cfg.sample = "" -- Пример: так отключать макросы
- --]] -----------------------------------------------------------------------------------------------
- -- Макросы для установки/снятия пометки
- cfg.dss_sel = "AltShiftS" -- макрос Select
- cfg.dss_unsel = "AltShiftU" -- макрос Unselect
- cfg.dss_fill = "AltShiftD" -- макрос Select with init
- cfg.dss_post = "* * Left" -- иницилизация маски для предыдущего макроса (макропоследовательность!)
- -- Макросы быстрого поиска
- cfg.dff_empty = "Alt," -- открыть пустой диалог
- cfg.dff_fill = "AltSpace Alt." -- открыть непустой диалог
- cfg.dff_text = "*" -- иницилизация непустого диалога для предыдущего макроса (текст!)
- -- Диалоговая процедура быстрого поиска.
- -- Правые и левые модификаторы не проверяются, регэкспы не поддерживаются!
- cfg.dff_next = "CtrlEnter CtrlNumEnter CtrlDown" -- следующее совпадение
- cfg.dff_prev = "CtrlShiftEnter CtrlShiftNumEnter CtrlUp" -- предыдущее совпадение
- cfg.dff_last = "CtrlEnd" -- последнее совпадение
- cfg.dff_first = "CtrlHome" -- первое совпадение
- cfg.dff_invert = "Ins" -- инвертировать пометку текущего файла/папки
- cfg.dff_insert = "CtrlV ShiftIns" -- вставка
- cfg.far = "Esc CtrlY CtrlX CtrlC" -- отдать ФАРу
- cfg.dummy = "Left Right Ctrl Alt Shift" -- ничего не делать с этими хоткеями
- cfg.search_empty = "Alt," -- выйти и открыть пустой Search
- cfg.search_fill = "AltSpace Alt." -- выйти и открыть непустой Search
- cfg.search_text = "*" -- иницилизация для непустого Search (текст!)
- -- прочее
- cfg.cyclic = true -- использовать циклический поиск
- ----------------------------------------------------------------------------------------------------
GeSHi © Codebox Plus Extension
Обычный CtrlZ, если есть отмеченные файлы/папки, выполняется поочерёдно для них всех. Сколько лет пользуюсь описаниями, ни разу не понадобилось такая "пакетная" обработка. Поэтому были написаны макросы для работы только с описанием текущего файла и сохраняющие пометку. Дополнительно, макросы сохраняют предыдущее непустое описание при изменении/удалении, которое может быть восстановлено.
Набор содержит следующие макросы:
CtrlZ - макрос для замены обычного диалога редактирования описаний.
AltC - Копировать описание в буфер обмена.
AltZ - Вставить новое описание из буфера обмена.
AltV - Добавить к описанию через пробел содержимого буфера обмена.
AltX - Копировать описание в буфер обмена и затем удалить.
AltD - Удалить описание.
AltShiftZ - Вставить описание, которое было изменено/удалено макросами CtrlZ, AltZ, AltV, AltD
Примечания: Пометка сохраняется через внутренний буфер обмена. Откат пометки по CtrlM теряется.
CtrlZ - макрос для замены обычного диалога редактирования описаний.
AltC - Копировать описание в буфер обмена.
AltZ - Вставить новое описание из буфера обмена.
AltV - Добавить к описанию через пробел содержимого буфера обмена.
AltX - Копировать описание в буфер обмена и затем удалить.
AltD - Удалить описание.
AltShiftZ - Вставить описание, которое было изменено/удалено макросами CtrlZ, AltZ, AltV, AltD
Примечания: Пометка сохраняется через внутренний буфер обмена. Откат пометки по CtrlM теряется.
С версии 1.03 макрос CtrlZ был переименован в DescriptionEdit. Не забудьте удалить старый CtrlZ.lua!
- ----------------------------------------------------------------------------------------------------
- -- Работа с описаниями файлов
- -- v.1.03 (C) 2013-2016 Smitis
- ----------------------------------------------------------------------------------------------------
- local F = far.Flags
- local diz_prev = ""
- ----------------------------------------------------------------------------------------------------
- -- Замена стандартного диалога редактирования.
- -- Редактируется описание только текущего элемента панелей, не зависимо от выделения.
- -- Выделение сохраняется/восстанавливается через внутренний буфер. Откат через CtrlM теряется.
- ----------------------------------------------------------------------------------------------------
- local DescriptionEditId = "1B8B8080-09EE-4AB2-B723-1014C1C0A97E"
- local DescriptionEditIdB = win.Uuid(DescriptionEditId)
- --far.Guids.DescriptionEditId = DescriptionEditId
- local diz_changed = false
- local function diz_edit(init,changed)
- if Area.Search then Keys "Esc" end
- local selected = APanel.Selected
- local diz = Panel.Item(0,0,11)
- if init and type(init)=="string" then
- diz = init
- end
- diz_changed = changed
- local Title = "Describe file"
- local Prompt = "Enter description for " .. APanel.Current .. ":"
- local HistName = "DizText"
- local Flags = F.FIB_ENABLEEMPTY + F.FIB_BUTTONS + F.FIB_NOUSELASTHISTORY
- local diz_new = far.InputBox(DescriptionEditIdB,Title,Prompt,HistName,diz,nil,nil,Flags)
- if diz_new then
- diz_new = diz_new:gsub("^%s+",""):gsub("%s+$","") -- trim
- mf.clip(5,2)
- diz_prev = diz
- if selected then -- сохранить выделение
- Keys "CtrlShiftIns"
- Panel.Select(0,0)
- end
- Keys "CtrlZ"
- print(diz_new)
- Keys "Enter"
- if selected then -- восстановить выделение
- Panel.Select(0,1,2,mf.clip(0))
- end
- end
- end
- ----------------------------------------------------------------------------------------------------
- Event { -- сделать поле ввода "изменённое" для некоторых операций
- description="Description: Make unchanged";
- group="DialogEvent";
- condition=function(event,param)
- return event == F.DE_DLGPROCINIT
- and param.Msg == F.DN_DRAWDIALOGDONE
- and diz_changed
- and Dlg.Id == DescriptionEditId
- end;
- action=function(event,param)
- diz_changed = false -- исключить рекурсивный вход
- far.MacroPost('Keys("End")')
- end;
- }
- ----------------------------------------------------------------------------------------------------
- Macro { -- Описание только одного файла
- description="Description: Edit";
- area="Shell Search";
- key="CtrlZ";
- action=function()
- diz_edit()
- end;
- }
- ----------------------------------------------------------------------------------------------------
- Macro { -- Копирование описания в буфер обмена
- description="Description: Copy to clipboard";
- area="Shell Search";
- key="AltC";
- action=function()
- if Area.Search then Keys "Esc" end
- mf.clip(1,Panel.Item(0,0,11))
- end;
- }
- ----------------------------------------------------------------------------------------------------
- Macro { -- Новое описание из буфера обмена
- description="Description: New from clipboard";
- area="Shell Search";
- key="AltZ";
- action=function()
- diz_edit(mf.clip(0),true)
- end;
- }
- ----------------------------------------------------------------------------------------------------
- Macro { -- Добавить описание из буфера обмена к текущему описанию через пробел.
- description="Description: Append from clipboard";
- area="Shell Search";
- key="AltV";
- action=function()
- if Area.Search then Keys "Esc" end
- local diz = Panel.Item(0,0,11)
- if diz:len() > 0 then
- diz_edit(diz.." "..mf.clip(0),true)
- else
- diz_edit(mf.clip(0),true)
- end
- end;
- }
- ----------------------------------------------------------------------------------------------------
- Macro { -- Удалить описание в буфер обмена
- description="Description: Cut to clipboard";
- area="Shell Search";
- key="AltX";
- action=function()
- if Area.Search then Keys "Esc" end
- local diz = Panel.Item(0,0,11)
- if diz:len() > 0 then
- mf.clip(1,diz)
- local selected = APanel.Selected
- mf.clip(5,2)
- if selected then
- Keys "CtrlShiftIns"
- Panel.Select(0,0)
- end
- Keys "CtrlZ CtrlY Enter"
- if selected then
- Panel.Select(0,1,2,mf.clip(0))
- end
- end
- end;
- }
- ----------------------------------------------------------------------------------------------------
- Macro { -- Удалить описание
- description="Description: Delete";
- area="Shell Search";
- key="AltD";
- action=function()
- if Area.Search then Keys "Esc" end
- local diz = Panel.Item(0,0,11)
- if diz:len() > 0 then
- diz_prev = diz
- local selected = APanel.Selected
- mf.clip(5,2)
- if selected then
- Keys "CtrlShiftIns"
- Panel.Select(0,0)
- end
- Keys "CtrlZ CtrlY Enter"
- if selected then
- Panel.Select(0,1,2,mf.clip(0))
- end
- end
- end;
- }
- ----------------------------------------------------------------------------------------------------
- Macro { -- Восстановить описание
- description="Description: Restore";
- area="Shell Search";
- key="AltShiftZ";
- action=function()
- diz_edit(diz_prev)
- end;
- }
- ----------------------------------------------------------------------------------------------------
GeSHi © Codebox Plus Extension
СОВМЕСТИМОСТЬ С TC ТОЛЬКО ДЛЯ ОПИСАНИЙ В ANSI КОДИРОВКЕ!
Эти макросы требуют для работы модуль DialogClass
Нумерация версий совпадает с DescriptionEdit.
- --[=[ ------------------------------------------------------------------------------------------------------------------
- Работа с описаниями файлов, в том числе и с многострочными
- v.1.03 (C) 2013-2016 Smitis
- Приватная версия с дополнительным полем с именем файла.
- - Замена стандартного диалога редактирования.
- - Редактируется описание только текущего элемента панелей, не зависимо от выделения (Выделение сохраняется/восстанавливается через внутренний буфер. Восстановление предыдущего выделения через CtrlM теряется.)
- - Возможность редактирования многострочных описаний.
- Для работы требуется модуль DialogClass
- http://forum.farmanager.com/viewtopic.php?t=8523
- Обсуждение макросов для работы с описаниями
- http://forum.farmanager.com/viewtopic.php?t=7846
- Обсуждение многострочного редактора описаний
- http://forum.farmanager.com/viewtopic.php?t=285
- --]=] ------------------------------------------------------------------------------------------------------------------
- local F = far.Flags
- local dialog = require 'DialogClass'
- ------------------------------------------------------------------------------------------------------------------------
- local DescriptionMultiEditId = "75CA1288-4C06-4621-870E-A4FDD9E7319E"
- --far.Guids.DescriptionMultiEditId = DescriptionMultiEditId
- local HistoryLimitLen = 80 -- описания длиней чем HistoryLimitLen в историю добавляться не будут
- local DescriptionPrev = ""
- ------------------------------------------------------------------------------------------------------------------------
- -- Редактирование в окне с рамкой
- local MultiEditId = "736B91DE-2525-4296-9529-F0BAD8503B57"
- --far.Guids.MultiEditId = MultiEditId
- local function MultiEdit(x1,y1,x2,y2,text,title)
- dialog.New {
- Guid = MultiEditId,
- X1=x1, Y1=y1, X2=x2, Y2=y2, Frame=2,
- DlgProc = function(hDlg,Msg,Param1,Param2,D,DI)
- local coord, hfile, tmpfile
- if Msg==F.DN_DRAWDIALOGDONE then
- coord = D:Send(F.DM_GETDLGRECT,0,0)
- tmpfile = far.MkTemp()
- hfile = io.open(tmpfile,"w") hfile:write(text) hfile:close()
- editor.Editor(tmpfile,title,coord.Left+4,coord.Top+2,coord.Right-4,coord.Bottom-2, bor(F.EF_DISABLEHISTORY,F.EF_DISABLESAVEPOS),0,0,65001)
- hfile = io.open(tmpfile,"r") text = hfile:read("*a") hfile:close()
- win.DeleteFile(tmpfile)
- D:Send(F.DM_CLOSE)
- end
- end
- } ()
- return text
- end
- ------------------------------------------------------------------------------------------------------------------------
- local idtc = win.Utf16ToUtf8(win.MultiByteToWideChar(unicode.ascii.char(0x04,0xC2),win.GetACP())) -- идентификатор TC в UTF-8
- local function DescriptionEdit(init,changed)
- local Selected = APanel.Selected
- local Description = Panel.Item(0,0,11)
- local HistoryName = "DizText"
- local FileName = APanel.Current
- if Area.Search then Keys "Esc" end
- local D,DI = dialog.New {
- Guid = DescriptionMultiEditId,
- Title = "Describe file",
- W=76, H=8,
- DlgProc = function(hDlg,Msg,Param1,Param2,D,DI)
- if Msg==F.DN_INITDIALOG then
- -- для некоторых макросов требуется, чтобы поле не было "неизменённое"
- if changed then
- DI.Description:Unchanged(0)
- end
- elseif Msg==F.DN_CLOSE then
- -- не записываем в историю пустые, слишком большие и многострочные описания
- local text = DI.Description:GetText()
- if text~="" and text:len()<=HistoryLimitLen and text:find('\n')==nil then
- DI.Description:Send(F.DM_ADDHISTORY,text)
- end
- return true
- elseif Msg==F.DN_CONTROLINPUT and Param2.EventType==F.KEY_EVENT and Param2.KeyDown then
- local k = far.InputRecordToName(Param2):gsub('[RL]Ctrl','Ctrl')
- if k=="CtrlE" or k=="F4" then
- local coord = D:Send(F.DM_GETDLGRECT,0,0)
- --local text = DI.Description:GetText():gsub('\x02',''):gsub('\x03','\n')
- local text = DI.Description:GetText()
- if text:sub(-2)==idtc then -- проверка частичная, так как мы не знаем, из какой кодировки конвертировали в юникод
- idsymbol = text:sub(-1) -- это то, во что был преобразован id после конвертирования ANSI->UNICODE
- text = text:sub(1,-3):gsub('(\\*\\n)',
- function(s)
- if s:sub(1,-3):len()%2==0 then
- return s:sub(1,-3)..'\n' -- перед \n чётное число или 0 символов \
- end
- return s
- end
- ):gsub('\\\\','\\')
- end
- local newtext = MultiEdit(coord.Left,coord.Top-5,coord.Right,coord.Bottom+5,text,"Description Edit")
- if newtext ~= text then
- if newtext:find('\n') then
- newtext = newtext:gsub('\\','\\\\'):gsub('\n','\\n')..idtc
- end
- DI.Description:SetText(newtext)
- end
- return true
- end
- end
- end,
- Items = {
- {"t+", Text="Description:"},
- {"emh+@", Name="Description", Text=init or Description, History=HistoryName},
- {"s+"},
- {"b=!+", Name="OK"},
- {"b=", Name="Cancel"},
- },
- }
- D()
- if D.Ret ~= -1 and D.Ret ~= DI.Cancel.Id then
- if DI.Description.Text ~= Description then
- DescriptionPrev = Description
- Description = DI.Description.Text:gsub("^%s+",""):gsub("%s+$","") -- trim
- mf.clip(5,2)
- if Selected then -- сохранить выделение
- Keys "CtrlShiftIns"
- Panel.Select(0,0)
- end
- Far.DisableHistory(-1) -- добавляются в DlgProc
- Keys "CtrlZ"
- print(Description)
- Keys "Enter"
- if Selected then -- восстановить выделение
- Panel.Select(0,1,2,mf.clip(0))
- end
- end
- end
- end
- ------------------------------------------------------------------------------------------------------------------------
- Macro { -- Описание
- description="Description";
- area="Shell Search";
- key="CtrlAltZ";
- action=function()
- Keys "CtrlZ"
- end;
- }
- ------------------------------------------------------------------------------------------------------------------------
- Macro { -- Описание только одного файла
- description="Description: Edit";
- area="Shell Search";
- key="CtrlZ";
- action=function()
- DescriptionEdit()
- end;
- }
- ------------------------------------------------------------------------------------------------------------------------
- Macro { -- Копирование описания в буфер обмена
- description="Description: Copy to clipboard";
- area="Shell Search";
- key="AltC";
- action=function()
- if Area.Search then Keys "Esc" end
- mf.clip(1,Panel.Item(0,0,11))
- end;
- }
- ------------------------------------------------------------------------------------------------------------------------
- Macro { -- Новое описание из буфера обмена
- description="Description: New from clipboard";
- area="Shell Search";
- key="AltZ";
- action=function()
- if Area.Search then Keys "Esc" end
- local Clipboard = mf.clip(0)
- if type(Clipboard)=="string" then
- DescriptionEdit(Clipboard:gsub("[\r\n]+"," "),true)
- end
- end;
- }
- ------------------------------------------------------------------------------------------------------------------------
- Macro { -- Добавить описание из буфера обмена к текущему описанию через пробел.
- description="Description: Append from clipboard";
- area="Shell Search";
- key="AltV";
- action=function()
- if Area.Search then Keys "Esc" end
- local Clipboard = mf.clip(0)
- if type(Clipboard)=="string" and Clipboard:len()>0 then
- local Description = Panel.Item(0,0,11)
- if Description:len() > 0 then
- DescriptionEdit(Description.." "..Clipboard:gsub("[\r\n]+"," "),true)
- else
- DescriptionEdit(Clipboard,true)
- end
- end
- end;
- }
- ------------------------------------------------------------------------------------------------------------------------
- Macro { -- Удалить описание в буфер обмена. Это описание не будет помещено в DescriptionPrev
- description="Description: Cut to clipboard";
- area="Shell Search";
- key="AltX";
- action=function()
- if Area.Search then Keys "Esc" end
- local Description = Panel.Item(0,0,11)
- if Description:len() > 0 then
- Far.DisableHistory(-1) -- пустое описание не будет добавлено в историю
- mf.clip(1,Description)
- local selected = APanel.Selected
- mf.clip(5,2)
- if selected then
- Keys "CtrlShiftIns"
- Panel.Select(0,0)
- end
- Keys "CtrlZ CtrlY Enter"
- if selected then
- Panel.Select(0,1,2,mf.clip(0))
- end
- end
- end;
- }
- ------------------------------------------------------------------------------------------------------------------------
- Macro { -- Удалить описание. Это описание будет помещено в DescriptionPrev
- description="Description: Delete";
- area="Shell Search";
- key="AltD";
- action=function()
- if Area.Search then Keys "Esc" end
- local Description = Panel.Item(0,0,11)
- if Description:len() > 0 then
- Far.DisableHistory(-1) -- пустое описание не будет добавлено в историю
- DescriptionPrev = Description
- local selected = APanel.Selected
- mf.clip(5,2)
- if selected then
- Keys "CtrlShiftIns"
- Panel.Select(0,0)
- end
- Keys "CtrlZ CtrlY Enter"
- if selected then
- Panel.Select(0,1,2,mf.clip(0))
- end
- end
- end;
- }
- ------------------------------------------------------------------------------------------------------------------------
- Macro { -- Восстановить описание
- description="Description: Restore";
- area="Shell Search";
- key="AltShiftZ";
- action=function()
- DescriptionEdit(DescriptionPrev)
- end;
- }
- ------------------------------------------------------------------------------------------------------------------------
GeSHi © Codebox Plus Extension