Skip to content

Instantly share code, notes, and snippets.

@johnd0e
Last active June 29, 2023 21:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johnd0e/aa4116a5bbfd29937eab72859b7abb49 to your computer and use it in GitHub Desktop.
Save johnd0e/aa4116a5bbfd29937eab72859b7abb49 to your computer and use it in GitHub Desktop.
[FAR macro] RClickEx — Right Click Menu Activator

RClickEx — Right Click Menu Activator

Скрипт позволяет использовать правую клавишу мыши в панелях для вызова контекстного меню (посредством EMenu), не теряя возможности выделения файлов этой же клавишей.

Возможны несколько вариантов активации:

  • Удержанием правой клавиши
  • Кликом правой клавишей с модификатором Ctrl/Shift (см. ниже)
  • Кликом двумя клавишами одновременно (не имеет значения какая из клавиш нажата первой, но требуется Far 3 build >= 6171)

Через меню конфигурации плагинов доступны такие настройки:

  • показывать графическое / или текстовое меню
  • срабатывать при удержании ПКМ / или при нажатии ПКМ+ЛКМ
  • для режима с удержанием клавиши: время задержки (мс), после которого вызывается меню
  • можно отключить особую обработку клика с модификатором (будет активироваться обычным образом, в зависимости от выбранного режима).

Особенности:

  • Срабатывает только если курсор мыши находится над файловой панелью, в плагиновой работает если файлы на ней реальные. За пределами панелей (на пустом месте) никаких функций не предусмотрено.
  • Обрабатываются нажатия [Ctrl+][Shift+]MsRClick
    • Ctrl позволяет (однократно) инвертировать настройку графическое / текстовое меню
    • Shift открывает "расширенное" меню
  • Вызов графического меню происходит после отпускания клавиши (в целях обхода бага).
  • Подразумевается, что настройка (far:config) Panel.RightClickSelect=true, ведь в противном случае скрипт просто не имеет смысла.

Первоначальная идея отсюда: https://forum.farmanager.com/viewtopic.php?t=7200

local Info = Info or package.loaded.regscript or function(...) return ... end --luacheck: ignore 113/Info
local nfo = Info { _filename or ...,
name = "RClickEx";
description = "Right Click Menu Activator";
version = "0.3"; --http://semver.org/lang/ru/
author = "jd";
url = "https://forum.farmanager.com/viewtopic.php?t=13250";
id = "D841C948-BE8A-4ACB-97F4-53205783A971";
minfarversion = {3,0,0,6171,0};
files = "README.md";
--config = function(nfo,name) end;
--help = function(nfo,name) end;
--options = {};
--disabled = true;
}
if not nfo or nfo.disabled then return end
--local O = nfo.options
if not Far.GetConfig"Panel.RightClickSelect" then
far.Message([[
This macro requires Panel.RightClickSelect=true
(see far:config)]],...,nil,"wl")
return
end
local S = mf.mload(nfo.author, nfo.name) or {
GUImenu = true,
HoldMode = true,
NoDelay = true,
HoldDelay = 500,
}
local MinDelay = 20
local _TXT,_GUI = 1,2
local cmds = {"rclk_txt:", "rclk_gui:"}
local F = far.Flags
local CTRL = bit64.bor(0x4,0x8) -- RCtrl,LCtrl
local color = far.AdvControl(F.ACTL_GETCOLOR, far.Colors.COL_PANELBOX)
local function eMenu (nSel)
if nSel and nSel~=APanel.SelCount+PPanel.SelCount then
Panel.Select(0,2,1); far.Text() -- invert
end
local cmd = S.GUImenu and _GUI or _TXT
if bit64.band(Mouse.LastCtrlState, CTRL)~=0 then
cmd = 3-cmd --invert
end
if cmd==_GUI then
local scr = far.SaveScreen()
far.Text(Mouse.X, Mouse.Y, color, "..release.."); far.Text()
repeat
mf.waitkey(MinDelay)
until bit64.band(Mouse.Button, F.RIGHTMOST_BUTTON_PRESSED)==0
far.RestoreScreen(scr)
end
mf.postmacro(Plugin.Command, "742910F1-02ED-4542-851F-DEE37C2E13B2", cmds[cmd])
end
local BOTH = bit64.bor(F.FROM_LEFT_1ST_BUTTON_PRESSED, F.RIGHTMOST_BUTTON_PRESSED)
local function On2Click (timer, ClickPos, nSel)
if bit64.band(Mouse.Button, F.RIGHTMOST_BUTTON_PRESSED)==0 or ClickPos~=Object.CurPos then
timer:Close()
elseif bit64.band(Mouse.Button, BOTH)==BOTH then
timer:Close()
eMenu(nSel)
end
end
local function OnHold (timer, ClickPos, nSel)
timer:Close()
if Mouse.Button==F.RIGHTMOST_BUTTON_PRESSED and ClickPos==Object.CurPos then
eMenu(nSel)
end
end
local function checkPanel (pnl, x, y, deadTop, deadBottom)
local pi = panel.GetPanelInfo(nil,pnl)
if x>pi.PanelRect.left and x<pi.PanelRect.right and
y>=pi.PanelRect.top+deadTop and y<=pi.PanelRect.bottom-deadBottom and
bit64.band(pi.Flags, F.PFLAGS_VISIBLE)==F.PFLAGS_VISIBLE then
return bit64.band(pi.Flags, F.PFLAGS_PLUGIN)==0 or bit64.band(pi.Flags, F.PFLAGS_REALNAMES)==F.PFLAGS_REALNAMES
end
end
local descr = nfo.name.." — "..nfo.description
local timer
Macro { description=descr;
area="Shell Tree"; key="MsRClick ShiftMsRClick CtrlMsRClick CtrlShiftMsRClick";
id="208B186D-4B57-4734-9476-6A390FBE55DD";
condition=function() -- https://github.com/FarPluginsArchive/farplug-alvls/blob/master/rcl2apps/rcl2apps.cpp
local deadTop = (Far.GetConfig"Panel.Layout.ColumnTitles" and 1 or 0)
+ (Far.GetConfig"Interface.ShowMenuBar" and 1 or 0)
local deadBottom = Far.GetConfig"Panel.Layout.ColumnTitles" and 2 or 0
local x,y = Mouse.X, Mouse.Y
return checkPanel(1,x,y,deadTop,deadBottom)
or checkPanel(0,x,y,deadTop,deadBottom)
end;
action=function()
if timer and not timer.Closed then timer:Close() end
Keys"MsLClick" -- set cursor to clicked file
if S.NoDelay and mf.akey(1,1)~="MsRClick" then
eMenu()
return
end
local nSel = APanel.SelCount+PPanel.SelCount
Keys"AKey"
timer = far.Timer(S.HoldMode and S.HoldDelay or MinDelay,
S.HoldMode and OnHold or On2Click,
Object.CurPos,
nSel)
end;
}
MenuItem {
description=descr;
menu="Config";
guid="AADCDA31-7835-450E-AE4C-35D2620B9CF4";
text=nfo.name;
action=function()
local Props = {
Title=nfo.name,
Id=win.Uuid"DE560C2A-CEA0-4EEB-A494-AADC772E6EEC"
}
repeat
local Items = {
{text="Use GUI menu",
toggle="GUImenu", checked=S.GUImenu},
{text = "Act on:", separator=true},
{text = "Right button hold",
mode="Hold", checked=S.HoldMode},
{text = "Right+Left buttons click",
mode="2Buttons", checked=not S.HoldMode},
{text = "No delay with Ctrl/Shift",
toggle="NoDelay", checked=S.NoDelay},
{separator=true},
{text = "Hold delay: "..S.HoldDelay.." ms",
action=function()
local Id = win.Uuid"2E95C789-D37B-49E2-BABB-1032BA327A5F"
local Prompt = "Enter hold delay for right button"
local res = far.InputBox(Id, nfo.name, Prompt, nfo.name.."HoldDelay", S.HoldDelay)
res = res and S.HoldDelay~=res and tonumber(res)
S.HoldDelay = res or S.HoldDelay
return res
end;
grayed=not S.HoldMode},
}
local item, pos = far.Menu(Props, Items)
Props.SelectIndex = pos
if item then
local tosave = true
if item.mode then
if not item.checked then
S.HoldMode = not S.HoldMode
else
tosave = false
end
elseif item.toggle then
S[item.toggle] = not S[item.toggle]
elseif item.action then
tosave = item.action()
end
if tosave then
mf.msave(nfo.author, nfo.name, S)
end
end
until not item
end;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment