Эмуляция клавиш AltHistory в стандартной истории

Здесь обсуждается всё, что касается макросов.
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Эмуляция клавиш AltHistory в стандартной истории

Post by DV »

Макрос, эмулирующий некоторые основные сочетания клавиш плагина AltHistory в стандартной истории FAR3.
Возможности:
* при показе истории сразу включен режим фильтра (для фильтрации элементов истории);
* нажатие Alt+F8 / Alt+F11 / Alt+F12 во время показа истории переключает её тип (например, из истории папок нажатием Alt+F11 можно перейти в историю просмотра/редактирования);
* нажатие Del очищает фильтр;
* нажатие Ctrl+PgUp переходит в указанную папку (из истории папок или просмотра/редактирования) и позиционирует на имя файла из истории просмотра/редактирования;
* нажатие Ctrl+PgDn переходит в указанную папку (из истории папок или просмотра/редактирования), позиционирует на имя файла из истории просмотра/редактирования и открывает этот файл в просмотрщике/редакторе;
* нажатие Shift+Enter в истории папок переходит в указанную папку на пассивной панели.
  1. local HistoryMenuType = {
  2.  
  3.   ViewEdit = 1,
  4.  
  5.   Folders  = 2,
  6.  
  7.   Commands = 3
  8.  
  9. }
  10.  
  11. local HistoryMenuId = {
  12.  
  13.   ViewEdit = "E770E044-23A8-4F4D-B268-0E602B98CCF9",
  14.  
  15.   Folders  = "FC3384A8-6608-4C9B-8D6B-EE105F4C5A54",
  16.  
  17.   Commands = "880968A6-6258-43E0-9BDC-F2B8678EC278"
  18.  
  19. }
  20.  
  21. local ItemAction = {
  22.  
  23.   SetFile  = 0,
  24.  
  25.   OpenFile = 1,
  26.  
  27.   SetDir   = 2
  28.  
  29. }
  30.  
  31. local MenuInvokeAreaIsShell = true
  32.  
  33. local SavedMenuId = ""
  34.  
  35.  
  36.  
  37. local function GetHistoryMenuId(menuType)
  38.  
  39.   if menuType == HistoryMenuType.ViewEdit then
  40.  
  41.     return HistoryMenuId.ViewEdit
  42.  
  43.   elseif menuType == HistoryMenuType.Folders then
  44.  
  45.     return HistoryMenuId.Folders
  46.  
  47.   elseif menuType == HistoryMenuType.Commands then
  48.  
  49.     return HistoryMenuId.Commands
  50.  
  51.   else
  52.  
  53.     return nil
  54.  
  55.   end
  56.  
  57. end
  58.  
  59.  
  60.  
  61. local function GetLocalizedStrings()
  62.  
  63.   local lang = far.lang or win.GetEnv("farlang")
  64.  
  65.   if lang == "Russian" then
  66.  
  67.     return {
  68.  
  69.       CmdView = "просмотр";
  70.  
  71.       CmdEdit = "редактор";
  72.  
  73.     }
  74.  
  75.   else
  76.  
  77.     return {
  78.  
  79.       CmdView = "view";
  80.  
  81.       CmdEdit = "edit";
  82.  
  83.     }
  84.  
  85.   end
  86.  
  87. end
  88.  
  89.  
  90.  
  91. local function GetShowMenuKeys(s)
  92.  
  93.   return string.format("%s AltEnd CtrlAltF", s)
  94.  
  95. end
  96.  
  97.  
  98.  
  99. local function IsAnyHistoryMenu()
  100.  
  101.   local menuId = Menu.Id
  102.  
  103.   return menuId == HistoryMenuId.ViewEdit or menuId == HistoryMenuId.Folders or menuId == HistoryMenuId.Commands
  104.  
  105. end
  106.  
  107.  
  108.  
  109. local function IsDirectory(path)
  110.  
  111.   return bit.band(mf.fattr(path), 0x00000010) ~= 0
  112.  
  113. end
  114.  
  115.  
  116.  
  117. local function StripPath(path)
  118.  
  119.   if path:len() >= 2 and path:sub(1, 1) == '"' and path:sub(path:len()) == '"' then
  120.  
  121.     path = path:sub(2, path:len() - 1)
  122.  
  123.   end
  124.  
  125.   if path:len() > 0 and (path:sub(path:len()) == '\\' or path:sub(path:len()) == '/') then
  126.  
  127.     path = path:sub(1, path:len() - 1)
  128.  
  129.   end
  130.  
  131.   -- mf.msgbox(path)
  132.  
  133.   return path
  134.  
  135. end
  136.  
  137.  
  138.  
  139. local function Panel_GoToFolderAndOpen(path, panelType, itemAction)
  140.  
  141.   local dir = ""
  142.  
  143.   local name = ""
  144.  
  145.   local cmdViewEdit = 0
  146.  
  147.   local i = mf.index(path, ":")
  148.  
  149.   if i > 0 then
  150.  
  151.     local prefix = mf.lcase(mf.substr(path, 0, i))
  152.  
  153.     local localizedStrings = GetLocalizedStrings()
  154.  
  155.     if prefix == localizedStrings.CmdView then
  156.  
  157.       cmdViewEdit = 1
  158.  
  159.     elseif prefix == localizedStrings.CmdEdit then
  160.  
  161.       cmdViewEdit = 2
  162.  
  163.     end
  164.  
  165.     if cmdViewEdit ~= 0 then
  166.  
  167.       path = mf.trim(mf.substr(path, i + 1))
  168.  
  169.     end
  170.  
  171.   end
  172.  
  173.   dir = path
  174.  
  175.   if itemAction == ItemAction.SetDir then
  176.  
  177.     i = mf.rindex(path, "\\")
  178.  
  179.     if i <= 0 then
  180.  
  181.       i = mf.rindex(path, "/")
  182.  
  183.     end
  184.  
  185.     if i > 0 then
  186.  
  187.       name = mf.substr(path, i + 1)
  188.  
  189.       dir = mf.substr(path, 0, i)
  190.  
  191.     end
  192.  
  193.   elseif not IsDirectory(path) then
  194.  
  195.     name = mf.fsplit(path, 0x0000000C)
  196.  
  197.     dir = mf.fsplit(path, 0x00000003)
  198.  
  199.   end
  200.  
  201.   Panel.SetPath(panelType, dir, name)
  202.  
  203.   if itemAction == ItemAction.OpenFile and mf.fexist(path) then
  204.  
  205.     if cmdViewEdit == 1 then
  206.  
  207.       viewer.Viewer(path, nil, nil, nil, nil, nil, far.Flags.VF_IMMEDIATERETURN + far.Flags.VF_NONMODAL)
  208.  
  209.     elseif cmdViewEdit == 2 then
  210.  
  211.       editor.Editor(path, nil, nil, nil, nil, nil, far.Flags.EF_IMMEDIATERETURN + far.Flags.EF_NONMODAL)
  212.  
  213.     end
  214.  
  215.   end
  216.  
  217. end
  218.  
  219.  
  220.  
  221. local function Menu_ReTitle()
  222.  
  223.   local windowInfo = far.AdvControl(far.Flags.ACTL_GETWINDOWINFO)
  224.  
  225.   local oldTitles = far.SendDlgMessage(windowInfo.Id, far.Flags.DM_LISTGETTITLES) or { Title = "", Bottom = "" }
  226.  
  227.   local newTitles = { Title = oldTitles.Title .. " []", Bottom = oldTitles.Bottom  }
  228.  
  229.   msgbox(newTitles.Title)
  230.  
  231.   far.SendDlgMessage(windowInfo.Id, far.Flags.DM_LISTSETTITLES, 0, newTitles)
  232.  
  233. end
  234.  
  235.  
  236.  
  237. Macro {
  238.  
  239.   area="Shell";
  240.  
  241.   description="View/Edit history (filtered)";
  242.  
  243.   key="AltF11";
  244.  
  245.   action = function()
  246.  
  247.     MenuInvokeAreaIsShell = true
  248.  
  249.     Keys( GetShowMenuKeys("AltF11") )
  250.  
  251.     -- Menu_ReTitle()
  252.  
  253.   end;
  254.  
  255. }
  256.  
  257.  
  258.  
  259. Macro {
  260.  
  261.   area="Shell";
  262.  
  263.   description="Folders history (filtered)";
  264.  
  265.   key="AltF12";
  266.  
  267.   action = function()
  268.  
  269.     MenuInvokeAreaIsShell = true
  270.  
  271.     Keys( GetShowMenuKeys("AltF12") )
  272.  
  273.   end;
  274.  
  275. }
  276.  
  277.  
  278.  
  279. Macro {
  280.  
  281.   area="Shell";
  282.  
  283.   description="Commands history (filtered)";
  284.  
  285.   key="AltF8";
  286.  
  287.   action = function()
  288.  
  289.     MenuInvokeAreaIsShell = true
  290.  
  291.     local filter = CmdLine.Value
  292.  
  293.     Keys( GetShowMenuKeys("AltF8") )
  294.  
  295.     if filter ~= "" then
  296.  
  297.       Menu.FilterStr(1, filter)
  298.  
  299.     end
  300.  
  301.   end;
  302.  
  303. }
  304.  
  305.  
  306.  
  307. Macro {
  308.  
  309.   area="Editor";
  310.  
  311.   description="View/Edit history (filtered)";
  312.  
  313.   key="AltF11";
  314.  
  315.   condition = function()
  316.  
  317.     return bit.band(Editor.State, 0x00000800) == 0
  318.  
  319.   end;
  320.  
  321.   action = function()
  322.  
  323.     MenuInvokeAreaIsShell = false
  324.  
  325.     Keys( GetShowMenuKeys("AltF11") )
  326.  
  327.   end;
  328.  
  329. }
  330.  
  331.  
  332.  
  333. Macro {
  334.  
  335.   area="Viewer";
  336.  
  337.   description="View/Edit history (filtered)";
  338.  
  339.   key="AltF11";
  340.  
  341.   condition = function()
  342.  
  343.     return bit.band(Viewer.State, 0x00000800) == 0
  344.  
  345.   end;
  346.  
  347.   action = function()
  348.  
  349.     MenuInvokeAreaIsShell = false
  350.  
  351.     Keys( GetShowMenuKeys("AltF11") )
  352.  
  353.   end;
  354.  
  355. }
  356.  
  357.  
  358.  
  359. Macro {
  360.  
  361.   area="Menu";
  362.  
  363.   description="View/Edit history (from other history)";
  364.  
  365.   key="AltF11";
  366.  
  367.   condition = function()
  368.  
  369.     return Menu.Id == HistoryMenuId.Commands or Menu.Id == HistoryMenuId.Folders
  370.  
  371.   end;
  372.  
  373.   action = function()
  374.  
  375.     local filter = Menu.FilterStr(0)
  376.  
  377.     Keys( "Esc " .. GetShowMenuKeys("AltF11") )
  378.  
  379.     Menu.FilterStr(1, filter)
  380.  
  381.   end;
  382.  
  383. }
  384.  
  385.  
  386.  
  387. Macro {
  388.  
  389.   area="Menu";
  390.  
  391.   description="Commands history (from other history)";
  392.  
  393.   key="AltF8";
  394.  
  395.   condition = function()
  396.  
  397.     return (Menu.Id == HistoryMenuId.ViewEdit or Menu.Id == HistoryMenuId.Folders) and MenuInvokeAreaIsShell
  398.  
  399.   end;
  400.  
  401.   action = function()
  402.  
  403.     local filter = Menu.FilterStr(0)
  404.  
  405.     Keys( "Esc " .. GetShowMenuKeys("AltF8") )
  406.  
  407.     Menu.FilterStr(1, filter)
  408.  
  409.   end;
  410.  
  411. }
  412.  
  413.  
  414.  
  415. Macro {
  416.  
  417.   area="Menu";
  418.  
  419.   description="Folders history (from other history)";
  420.  
  421.   key="AltF12";
  422.  
  423.   condition = function()
  424.  
  425.     return (Menu.Id == HistoryMenuId.ViewEdit or Menu.Id == HistoryMenuId.Commands) and MenuInvokeAreaIsShell
  426.  
  427.   end;
  428.  
  429.   action = function()
  430.  
  431.     local filter = Menu.FilterStr(0)
  432.  
  433.     Keys( "Esc " .. GetShowMenuKeys("AltF12") )
  434.  
  435.     Menu.FilterStr(1, filter)
  436.  
  437.   end;
  438.  
  439. }
  440.  
  441.  
  442.  
  443. Macro {
  444.  
  445.   area="Menu";
  446.  
  447.   description="History: clear the filter";
  448.  
  449.   key="Del";
  450.  
  451.   condition = function()
  452.  
  453.     return IsAnyHistoryMenu() and Menu.Filter(0, -1) ~= 0
  454.  
  455.   end;
  456.  
  457.   action = function()
  458.  
  459.     Menu.FilterStr(1, "")
  460.  
  461.   end;
  462.  
  463. }
  464.  
  465.  
  466.  
  467. Macro {
  468.  
  469.   area="Menu";
  470.  
  471.   description="History: go to folder and file";
  472.  
  473.   key="CtrlPgUp";
  474.  
  475.   condition = function()
  476.  
  477.     SavedMenuId = Menu.Id
  478.  
  479.     return IsAnyHistoryMenu()
  480.  
  481.   end;
  482.  
  483.   action = function()
  484.  
  485.     local path = StripPath(Menu.Value)
  486.  
  487.     Keys("Esc")
  488.  
  489.     if not MenuInvokeAreaIsShell then
  490.  
  491.       Keys("F12 0")
  492.  
  493.     end
  494.  
  495.     if SavedMenuId == HistoryMenuId.Commands then
  496.  
  497.       if mf.fexist(path) then
  498.  
  499.         local itemAction = ItemAction.SetFile
  500.  
  501.         if IsDirectory(path) then
  502.  
  503.           itemAction = ItemAction.SetDir
  504.  
  505.         end
  506.  
  507.         Panel_GoToFolderAndOpen(path, 0, itemAction)
  508.  
  509.       end
  510.  
  511.     elseif SavedMenuId == HistoryMenuId.Folders then
  512.  
  513.       Panel_GoToFolderAndOpen(path, 0, ItemAction.SetDir)
  514.  
  515.     else
  516.  
  517.       Panel_GoToFolderAndOpen(path, 0, ItemAction.SetFile)
  518.  
  519.     end
  520.  
  521.   end;
  522.  
  523. }
  524.  
  525.  
  526.  
  527. Macro {
  528.  
  529.   area="Menu";
  530.  
  531.   description="History: go to folder and file plus view/edit";
  532.  
  533.   key="CtrlPgDn";
  534.  
  535.   condition = function()
  536.  
  537.     return Menu.Id == HistoryMenuId.ViewEdit or Menu.Id == HistoryMenuId.Folders
  538.  
  539.   end;
  540.  
  541.   action = function()
  542.  
  543.     local path = StripPath(Menu.Value)
  544.  
  545.     Keys("Esc")
  546.  
  547.     if not MenuInvokeAreaIsShell then
  548.  
  549.       Keys("F12 0")
  550.  
  551.     end
  552.  
  553.     Panel_GoToFolderAndOpen(path, 0, ItemAction.OpenFile)
  554.  
  555.   end;
  556.  
  557. }
  558.  
  559.  
  560.  
  561. Macro {
  562.  
  563.   area="Menu";
  564.  
  565.   description="History: go to folder on the passive panel";
  566.  
  567.   key="ShiftEnter";
  568.  
  569.   condition = function()
  570.  
  571.     return Menu.Id == HistoryMenuId.Folders
  572.  
  573.   end;
  574.  
  575.   action = function()
  576.  
  577.     local path = StripPath(Menu.Value)
  578.  
  579.     Keys("Esc")
  580.  
  581.     Panel_GoToFolderAndOpen(path, 1, ItemAction.SetFile)
  582.  
  583.   end;
  584.  
  585. }
Shmuel
Posts: 6840
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 530 times

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by Shmuel »

DV wrote:Вопрос: как теперь добиться того, чтобы, в частности:
- нажатие Delete очищало введенный фильтр, а не предлагало очистить всю историю;
Повесить макрос на Del, в condition вызывать Menu.Filter(0,-1), в action вызывать Menu.FilterStr(1,"").
DV wrote:При этом всё ещё остаётся непонятным, что означает флаг EF_IMMEDIATERETURN
Данный флаг описан в Энциклопедии.
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by DV »

Shmuel,
спасибо за наводку.
Вскоре выложу доработанный скрипт.
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by DV »

А как в макросе определить, откуда было вызвано меню?
Например, история просмотра/редактирования может быть вызвана как из файловой панели, так и из просмотрщика или редактора. Как определить, откуда именно?
Контекст вопроса таков: есть макрос, который должен срабатывать из меню. То есть макрос вызывается из меню, которое при вызове макроса уже показано. И как теперь узнать внутри макроса, было ли это меню вызвано из панелей или из просмотрщика/редактора? Пробовал проверять Area.Current, но при вызове макроса из меню он возвращает Menu...
User avatar
John Doe
Бюрократ
Posts: 13866
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 74 times
Been thanked: 428 times
Contact:

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by John Doe »

DV wrote:Контекст вопроса таков: есть макрос, который должен срабатывать из меню. То есть макрос вызывается из меню, которое при вызове макроса уже показано. И как теперь узнать внутри макроса, было ли это меню вызвано из панелей или из просмотрщика/редактора?
Список окон доступен из api luafar.
Но подозреваю что вашу задачу можно переформулировать проще.
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by DV »

John Doe wrote:Но подозреваю что вашу задачу можно переформулировать проще.
Конкретная задача:
1. Есть меню истории просмотра/редактирования, вызванное либо из файловой панели, либо из просмотрщика/редактора
2. В этом меню я нажимаю Alt+F12. Требуется следующая реакция:
- если меню было вызвано из файловой панели, то показать историю папок;
- если же меню было вызвано из редактора или просмотрщика, то ничего не делать.
User avatar
John Doe
Бюрократ
Posts: 13866
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 74 times
Been thanked: 428 times
Contact:

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by John Doe »

Для 1 как я понимаю у вас есть макрос.
В нём перед вызовом меню вы можете сохранить Area.Current в какой-либо переменной (общей для всех макросов файла)
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by DV »

John Doe,
Всё верно.
А как объявить такую глобальную переменную, сохраняющую значение между вызовами разных макросов?
User avatar
John Doe
Бюрократ
Posts: 13866
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 74 times
Been thanked: 428 times
Contact:

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by John Doe »

Для этого подойдёт локальная переменная, объявленная ранее, вне определений макросов.
Почитайте macroapi_manual.ru.chm::/14.html, Upvalues
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by DV »

Спасибо, обновил скрипт (в первом сообщении). Теперь сочетания Ctrl+PgUp и Ctrl+PgDn работают в том числе из просмотрщика и редактора.
Shmuel
Posts: 6840
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 530 times

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by Shmuel »

DV
Неправильно: return IsAnyHistoryMenu() and Menu.Filter(0, -1)
Правильно: return IsAnyHistoryMenu() and Menu.Filter(0, -1) ~= 0
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by DV »

Спасибо, поправил.
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by DV »

Последние изменения:
- для Ctrl+PgUp и Ctrl+PgDn добавлена работоспособность под русским языком интерфейса (префиксы "view:" и "edit:" превращаются в "просмотр:" и "редактор:")
- при непустой командной строке вызов Alt+F8 из файловой панели сразу устанавливает фильтр, соответствующий тексту командной строки.
DV
Posts: 455
Joined: Mon 07 Aug, 2006 08:23
Has thanked: 31 times
Been thanked: 15 times

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by DV »

Мне ещё понравилась идея с установкой первоначального заголовка меню, как сделано в MenuAutoFilter.lua.
Это можно было бы сделать как-то так, если бы не загадочная переменная "ID элемента диалога":

Сбивает с толку то, что DM_LISTGETTITLES каким-то образом обходится без указания этого самого ID, а DM_LISTSETTITLES требует его обязательно. Пробовал в качестве ID подставлять nil, 0 и windowInfo.Pos - не помагает.
В скрипте MenuAutoFilter.lua значение этого ID сохраняется в процессе обработки какого-то Event - но, может, в моём случае можно получить этот ID прямо на месте? (С такими штуками как Event пока не знаком.)
User avatar
John Doe
Бюрократ
Posts: 13866
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 74 times
Been thanked: 428 times
Contact:

Re: Эмуляция клавиш AltHistory в стандартной истории

Post by John Doe »

Не думаю что DM_LISTSETTITLES вам поможет.
Дело в том, что пока фильтр активен - заголовок вообще не отображается.

В первых версиях я использовал такой фокус (в момент открытия меню):

Code: Select all

      mmode(1,0)
      local k = mf.waitkey() --trick to keep menu title
      Menu.Filter(set,1)
      Keys(k)
Это позволяет сохранить заголовок до первого нажатия клавиши.
Однако ввиду недоработок в фаре этот способ не всегда хорошо работает.
Post Reply

Return to “Обсуждение макросов”