--[[--------------------------------------------------------------------------------------------------------------------
Folder Shortcuts Menu v. 3.02 (c) 2013-2022 Smitis
http://forum.farmanager.com/viewtopic.php?t=7873
--]]--------------------------------------------------------------------------------------------------------------------
local F = far.Flags
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
function FSM_Goto(fsm)
local ap = 1 -- на какой панели открываем (0-пассивная, 1-активная), изменяем при открытии дискового меню
local pa = math.fmod(ap+1,2) -- инвертируем (0->1,1->0) (это заготовка на будущее для сохранения положения панелей)
if fsm.a.folder and panel.SetPanelDirectory(nil,ap,{Name=fsm.a.folder,Param=fsm.a.param,PluginId=win.Uuid(fsm.a.plugin),File=fsm.a.host}) then
-- Сначала в самый конец, потом к верхнему файлу (это обеспечит прокрутку списка) и только потом текущему файлу
Panel.SetPosIdx(pa,-1)
Panel.SetPos(pa,fsm.a.top)
Panel.SetPos(pa,fsm.a.file)
panel.RedrawPanel(nil,ap)
end
if fsm.p and fsm.p.folder and panel.SetPanelDirectory(nil,pa,{Name=fsm.p.folder,Param=fsm.p.param,PluginId=win.Uuid(fsm.p.plugin),File=fsm.p.host}) then
Panel.SetPosIdx(ap,-1)
Panel.SetPos(ap,fsm.p.top)
Panel.SetPos(ap,fsm.p.file)
panel.RedrawPanel(nil,pa)
end
end
------------------------------------------------------------------------------------------------------------------------
CommandLine {
description = "Folder shorcuts menu";
prefixes = "fsm";
action = function(prefix,data)
local code,err = loadstring('return '..data:gsub("!!","!"))
if not err then
local result,fsm = pcall(code)
if result then
FSM_Goto(fsm)
return
end
end
-- TODO: Сообщение об ошибке
end;
}
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
-- Подготовить строку с информацией для вставки
local function FSM_Format(fsm)
local fmt = '%s={folder="%s",param="%s",plugin="%s",host="%s",file="%s",top="%s"}'
local r = 'fsm:{'..fmt:format('a',fsm.a.folder,fsm.a.param,fsm.a.plugin,fsm.a.host,fsm.a.file,fsm.a.top)
if fsm.p then
r = r .. ',' .. fmt:format('p',fsm.p.folder,fsm.p.param,fsm.p.plugin,fsm.p.host,fsm.p.file,fsm.p.top)
end
return (r..'}'):gsub("!","!!"):gsub("\\","\\\\")
end
------------------------------------------------------------------------------------------------------------------------
-- Получить информацию о панели (активной или пассивной)
local function FSM_GetPanelInfo(ap)
local pa = math.fmod(ap+1,2) -- инвертируем 0/1
local dir = panel.GetPanelDirectory(nil,ap)
local inf = panel.GetPanelInfo(nil,ap)
return {
folder = dir.Name,
param = dir.Param,
plugin = win.Uuid(dir.PluginId),
host = dir.File,
file = Panel.Item(pa,inf.CurrentItem,0),
top = Panel.Item(pa,inf.TopPanelItem,0),
--viewmode = inf.ViewMode,
--sortmode = inf.SortMode,
--flags = inf.Flags,
}
end
------------------------------------------------------------------------------------------------------------------------
-- Вставить ссылку в текущую позицию меню
local function FSM_Insert(both)
local fsm = {}
fsm.a = FSM_GetPanelInfo(1)
if both then
fsm.p = FSM_GetPanelInfo(0)
end
-- Название пункта меню
local label = APanel.Path0
if APanel.HostFile ~= "" then
label = APanel.HostFile
elseif APanel.Path ~= "" then
label = APanel.Path
end
label = label:match("([^\\/]+)$"):gsub("!","!!") -- убрать путь и удвоить «!»
-- Вставка пункта меню
Keys "Ins Enter Tab" print(label) Keys "Tab"
print(FSM_Format(fsm))
Keys "CtrlEnter"
end
------------------------------------------------------------------------------------------------------------------------
Macro { -- Добавить в открытое меню
description = "Folder Shortcuts Menu: Add shortcut";
area = "UserMenu";
id = "D7C1870E-2434-4640-B9DD-AFF120CC5203";
key = "Ctrl-";
action = function() FSM_Insert(false) end;
}
------------------------------------------------------------------------------------------------------------------------
Macro { -- Добавить в открытое меню для обеих панелей
description = "Folder Shortcuts Menu: Add shortcut 2";
area = "UserMenu";
id = "E9725979-5D60-487E-BF1C-E3ACE3C68289";
key = "Ctrl=";
action = function() FSM_Insert(true) end;
}
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
local dialog = require "DialogClass"
local EditShortcutId = "30D09200-B62D-4F3A-B61B-99BED13F8E81"
-- Здесь потом можно будет сделать что-нибудь полезное
local function FSM_DlgProc(hDlg,Msg,Param1,Param2,D,DI)
if Msg==F.DN_CONTROLINPUT 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") -- для упрощения проверки
elseif Msg==F.DN_CLOSE and Param1==DI.OkButton.Id then
end
end
-- Если UserMenu - открыть пункт на редактирование.
-- Если диалог редактирования, редактируем ссылку.
-- Иначе оставляем как есть.
local function FSM_Edit()
local result
local fsm = {} -- таблица с данными ссылки
local di = {} -- элементы диалога
local dv = {} -- редактируемые значения из диалога
if Area.UserMenu then Keys "ShiftF4" end
if not Area.Dialog or Dlg.Id~=far.Guids.EditUserMenuId then return end
local info = far.AdvControl(F.ACTL_GETWINDOWINFO)
local hdlg = info.Id
di.data = hdlg:send(F.DM_GETDLGITEM,8)
if band(di.data[9],F.DIF_HIDDEN)~=0 then -- пункт скрыт, это диалог для подменю
return
end
dv.data = di.data[10]:match('^fsm:(.+)')
if not dv.data then -- это не ссылка
return
end
di.hotkey = hdlg:send(F.DM_GETDLGITEM,3)
dv.hotkey = di.hotkey[10]:gsub("!!","!")
di.label = hdlg:send(F.DM_GETDLGITEM,5)
dv.label = di.label[10]:gsub("!!","!")
local code,err = loadstring('return '..dv.data:gsub("!!","!"))
if not err then
result,fsm = pcall(code)
if result then
fsm.p = fsm.p or {}
local D,DI = dialog.New {
Guid = EditShortcutId,
Title = "Edit Shortcut",
W = 76, H = 25,
DlgProc = FSM_DlgProc,
}
DI {"t+", Text="Hot key:"}
DI.HotKey {"e", C=10, W=3, Text=dv.hotkey}
DI {"t", C=15, Text="Label:"}
DI.Label {"e@", C=25, Text=dv.label}
DI {"s+", Text="Active panel"}
DI {"t+", Text="Folder:"}
DI.SetAFolder {"b;", C=-6, Text="Set&1",
ItemProc = function(hDlg,Msg,Param2,self,D,DI)
if Msg==F.DN_BTNCLICK then
fsm.a = FSM_GetPanelInfo(1)
DI.AFolder:SetText(fsm.a.folder)
DI.AParam:SetText(fsm.a.param)
DI.APlugin:SetText(fsm.a.plugin)
DI.AHost:SetText(fsm.a.host)
DI.AFile:SetText(fsm.a.file)
return true
end
end,
}
DI.AFolder {"e+", Text=fsm.a.folder}
DI {"t+", Text="Param:"}
DI {"t", C=-36, Text="Plugin Id:"}
DI.AParam {"e+", W=28, Text=fsm.a.param}
DI.APlugin {"e", C=-36, Text=fsm.a.plugin}
DI {"t+", Text="Host file:"}
DI.AHost {"e+", Text=fsm.a.host}
DI {"t+", Text="Current file:"}
DI.AFile {"e+", Text=fsm.a.file}
DI {"s+", Text="Passive panel"}
DI {"t+", Text="Folder:"}
DI.SetPFolder {"b;", C=-6, Text="Set&2",
ItemProc = function(hDlg,Msg,Param2,self,D,DI)
if Msg==F.DN_BTNCLICK then
fsm.p = FSM_GetPanelInfo(0)
DI.PFolder:SetText(fsm.p.folder)
DI.PParam:SetText(fsm.p.param)
DI.PPlugin:SetText(fsm.p.plugin)
DI.PHost:SetText(fsm.p.host)
DI.PFile:SetText(fsm.p.file)
return true
end
end,
}
DI.PFolder {"e+", Text=fsm.p.folder}
DI {"t+", Text="Param:"}
DI {"t", C=-36, Text="Plugin Id:"}
DI.PParam {"e+", W=28, Text=fsm.p.param}
DI.PPlugin {"e", C=-36, Text=fsm.p.plugin}
DI {"t+", Text="Host file:"}
DI.PHost {"e+", Text=fsm.p.host}
DI {"t+", Text="Current file:"}
DI.PFile {"e+", Text=fsm.p.file}
DI {"s+",L=-1}
DI.OkButton {"b=!+", Text="OK"}
DI.CancelButton {"b=", Text="Cancel"}
--DI.SwapButton {"b=", Text="&Swap"}
D()
if D.Ret==-1 or D.Ret==DI.CancelButton.Id then -- выходим без сохранения
Keys "Esc"
if Area.Dialog then -- диалог подтверждения выхода без сохранения
Keys "CtrlEnter"
end
elseif D.Ret==DI.OkButton.Id then -- выходим с сохранением
dv.hotkey = DI.HotKey.Text
dv.label = DI.Label.Text
fsm.a.folder = DI.AFolder.Text
fsm.a.param = DI.AParam.Text
fsm.a.plugin = DI.APlugin.Text
fsm.a.host = DI.AHost.Text
fsm.a.file = DI.AFile.Text
fsm.p.folder = DI.PFolder.Text
fsm.p.param = DI.PParam.Text
fsm.p.plugin = DI.PPlugin.Text
fsm.p.host = DI.PHost.Text
fsm.p.file = DI.PFile.Text
di.hotkey[10] = dv.hotkey
hdlg:send(F.DM_SETDLGITEM,3,di.hotkey)
di.label[10] = dv.label:gsub("!","!!")
hdlg:send(F.DM_SETDLGITEM,5,di.label)
di.data[10] = FSM_Format(fsm)
hdlg:send(F.DM_SETDLGITEM,8,di.data)
Keys "CtrlEnter"
end
end
else
-- TODO: обработка ошибки
--dbg("Error loadstring")
end
end
------------------------------------------------------------------------------------------------------------------------
Macro {
description = "Folder Shortcuts Menu: Edit";
area = "UserMenu";
key = "CtrlF4";
condition = function()
return Menu.ItemStatus()==1
end;
action = FSM_Edit;
}
------------------------------------------------------------------------------------------------------------------------
Macro {
description = "Folder Shortcuts Menu: Edit";
area = "Dialog";
key = "CtrlF4";
condition = function()
return Dlg.Id==far.Guids.EditUserMenuId
end;
action = FSM_Edit;
}
------------------------------------------------------------------------------------------------------------------------