Улучшение меню с дублирующимися хоткеями

Здесь обсуждается всё, что касается макросов.
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

Улучшение меню с дублирующимися хоткеями

Post by John Doe »

При наличии в меню или списке несколько пунктов с одинаковым хоткеем, фар всегда запускает первый из них.

Предлагаемый скрипт улучшает это поведение:
  • При первом нажатии в списке остаются только элементы с хоткеем, соответствующем нажатой клавише.
  • Последующие нажатия циклически перемещают курсор.
    Для того чтобы выбрать пункт можно использовать Enter, или Ctrl-<хоткей> (см. Дополнительные функции).
  • Нажатие Esc или F10 отменяет фильтр.
Дополнительные функции:
  • Если использовать хоткей с модификатором Ctrl, то хоткей срабатывает независимо от того, есть ли в списке дубликаты.
    При этом если курсор уже стоит на элементе с хоткеем, то будет выполнен именно этот элемент (а не первый по порядку).
  • Если использовать хоткей с модификатором Alt, то фильтрации не происходит, а только лишь перемещается курсор
Для корректной работы требуется FAR 3 build >=4215.
[attachment=0]ConcurrentHotkeys.7z[/attachment]
P.S.
В основе лежит идея отсюда: http://forum.farmanager.com/viewtopic.p ... 18#p126218
Attachments
ConcurrentHotkeys.7z
(1.8 KiB) Downloaded 264 times
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

Скрипт фильтра пользовательского меню

Post by John Doe »

sToLp wrote: А вот теперь подумалось: а может быть Вы сможете универсальный макрос предложить?
Можем:
  1. local F = far.Flags
  2.  
  3. Event { group="DialogEvent"; description="Concurrent hotkeys menu handler";
  4.  
  5.   condition=function(Event,param)
  6.  
  7.     return param.Msg==F.DN_LISTHOTKEY and Event==F.DE_DLGPROCINIT
  8.  
  9.   end;
  10.  
  11.   action=function(Event,param)
  12.  
  13.     local hDlg,ID,ItemIndex = param.hDlg,param.Param1,param.Param2
  14.  
  15.     if hDlg:send(F.DM_LISTINFO,ID).ItemsNumber~=Object.ItemCount then return end --macro api item indexes does not count hidden items
  16.  
  17.     local hk = Object.GetHotkey(ItemIndex)
  18.  
  19.     if Object.CheckHotkey(hk,ItemIndex+1)~=0 then
  20.  
  21.       hDlg:send(F.DM_SHOWDIALOG,0)
  22.  
  23.       local list = far.GetDlgItem(hDlg, ID)[6] --[6]  Selected/ListItems: integer/table
  24.  
  25.       for i=#list,1,-1 do
  26.  
  27.         if Object.GetHotkey(i)~=hk then
  28.  
  29.           local item = list[i]
  30.  
  31.           hDlg:send(F.DM_LISTUPDATE, ID,{Index=i,Text=item.Text,Flags=bor(item.Flags,F.LIF_HIDDEN)})
  32.  
  33.         end
  34.  
  35.       end
  36.  
  37.       Menu.Filter(4) --подправить высоту списка под количество элементов
  38.  
  39.       hDlg:send(F.DM_SHOWDIALOG,1)
  40.  
  41.       return 1
  42.  
  43.     end
  44.  
  45.   end;
  46.  
  47. }
P.S.
Ограничение: не предназначен для работы в отфильтрованных списках.
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

Скрипт фильтра пользовательского меню

Post by John Doe »

И заодно альтернативный вариант, без фильтрации.
Если в меню есть дублирующиеся хоткееи, то при нажатии соответствующих клавиш вместо выполнения будет происходить только позиционирование курсора (циклически).
  1. local F = far.Flags
  2.  
  3. local InitPos
  4.  
  5. Event { group="DialogEvent";
  6.  
  7.   condition=function(Event,param)
  8.  
  9.     return param.Msg==F.DN_CONTROLINPUT and Event==F.DE_DLGPROCINIT
  10.  
  11.   end;
  12.  
  13.   action=function(Event,param)
  14.  
  15.     InitPos = Object.CurPos
  16.  
  17.   end;
  18.  
  19. }
  20.  
  21. Event { group="DialogEvent";
  22.  
  23.   condition=function(Event,param)
  24.  
  25.     return param.Msg==F.DN_LISTHOTKEY and Event==F.DE_DLGPROCINIT
  26.  
  27.   end;
  28.  
  29.   action=function(Event,param)
  30.  
  31.     local hDlg,ID = param.hDlg,param.Param1
  32.  
  33.     if hDlg:send(F.DM_LISTINFO,ID).ItemsNumber~=Object.ItemCount then return end --macro api item indexes does not count hidden items
  34.  
  35.     local hk = Object.GetHotkey() --ItemIndex
  36.  
  37.     if Object.CheckHotkey(hk,Object.CurPos+1)==0 then return end
  38.  
  39.     local Pos = Object.CheckHotkey(hk,InitPos+1)
  40.  
  41.     if Pos~=0 then
  42.  
  43.       hDlg:send(F.DM_LISTSETCURPOS,ID,{SelectPos=Pos})
  44.  
  45.     end
  46.  
  47.     return true
  48.  
  49.   end;
  50.  
  51. }
User avatar
sToLp
Posts: 938
Joined: Thu 23 Jul, 2009 10:16
Has thanked: 114 times
Been thanked: 12 times

Скрипт фильтра пользовательского меню

Post by sToLp »

John Doe

Просто супер!

Вариант ConcurrentHotkeys2.lua больше подходит для компактных меню, полностью помещающихся на экране. А первый вариант — для объёмных, типа как в Macro Browser alt.

А нельзя ли сделать оба применимыми, например позиционирование с Alt, как подсказал HaRT?
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

Скрипт фильтра пользовательского меню

Post by John Doe »

Совместил два варианта, теперь по умолчанию фильтруется, а с Alt только позиционируется.
  1. local F = far.Flags
  2.  
  3. Event { group="DialogEvent"; description="Concurrent hotkeys menu handler";
  4.  
  5.   condition=function(Event,param)
  6.  
  7.     return param.Msg==F.DN_LISTHOTKEY and Event==F.DE_DLGPROCINIT
  8.  
  9.     and band(Mouse.LastCtrlState,0x1+0x2)==0
  10.  
  11.   end;
  12.  
  13.   action=function(Event,param)
  14.  
  15.     local hDlg,ID,ItemIndex = param.hDlg,param.Param1,param.Param2
  16.  
  17.     if hDlg:send(F.DM_LISTINFO,ID).ItemsNumber~=Object.ItemCount then return end --macro api item indexes does not count hidden items
  18.  
  19.     local hk = Object.GetHotkey() --ItemIndex
  20.  
  21.     if Object.CheckHotkey(hk,ItemIndex+1)~=0 then
  22.  
  23.       hDlg:send(F.DM_SHOWDIALOG,0)
  24.  
  25.       local list = far.GetDlgItem(hDlg, ID)[6] --[6]  Selected/ListItems: integer/table
  26.  
  27.       for i=#list,1,-1 do
  28.  
  29.         if Object.GetHotkey(i)~=hk then
  30.  
  31.           local item = list[i]
  32.  
  33.           hDlg:send(F.DM_LISTUPDATE, ID,{Index=i,Text=item.Text,Flags=bor(item.Flags,F.LIF_HIDDEN)})
  34.  
  35.         end
  36.  
  37.       end
  38.  
  39.       Menu.Filter(4) --подправить высоту списка под количество элементов
  40.  
  41.       hDlg:send(F.DM_SHOWDIALOG,1)
  42.  
  43.       return 1
  44.  
  45.     end
  46.  
  47.   end;
  48.  
  49. }
  50.  
  51.  
  52.  
  53. local InitPos
  54.  
  55. Event { group="DialogEvent";
  56.  
  57.   condition=function(Event,param)
  58.  
  59.     return param.Msg==F.DN_CONTROLINPUT and Event==F.DE_DLGPROCINIT
  60.  
  61.   end;
  62.  
  63.   action=function(Event,param)
  64.  
  65.     InitPos = Object.CurPos
  66.  
  67.   end;
  68.  
  69. }
  70.  
  71. Event { group="DialogEvent";
  72.  
  73.   condition=function(Event,param)
  74.  
  75.     return param.Msg==F.DN_LISTHOTKEY and Event==F.DE_DLGPROCINIT
  76.  
  77.   end;
  78.  
  79.   action=function(Event,param)
  80.  
  81.     local hDlg,ID,ItemIndex = param.hDlg,param.Param1,param.Param2
  82.  
  83.     local x,y = {},{}
  84.  
  85.     local ii = 0
  86.  
  87.     for i,item in ipairs(far.GetDlgItem(hDlg, ID)[6]) do --[6]  Selected/ListItems: integer/table
  88.  
  89.        if band(item.Flags,F.LIF_HIDDEN)==0 then
  90.  
  91.          ii = ii+1; x[i],y[ii] = ii,i
  92.  
  93.        end
  94.  
  95.     end
  96.  
  97.     local hk = Object.GetHotkey(x[ItemIndex])
  98.  
  99.     if Object.CheckHotkey(hk,ItemIndex+1)==0 then return end
  100.  
  101.     local Pos = Object.CheckHotkey(hk,y[InitPos]+1)
  102.  
  103.     if Pos~=0 then
  104.  
  105.       hDlg:send(F.DM_LISTSETCURPOS,ID,{SelectPos=y[Pos]})
  106.  
  107.     end
  108.  
  109.     return true
  110.  
  111.   end;
  112.  
  113. }
User avatar
sToLp
Posts: 938
Joined: Thu 23 Jul, 2009 10:16
Has thanked: 114 times
Been thanked: 12 times

Улучшение меню с дублирующимися хоткеями

Post by sToLp »

John Doe

Ну у Вас и производительность! Мощно!

В пользовательском меню и в меню конфликтов макросов третий вариант работает вроде как надо по обеим направлениям: и по фильтру, и по позиционированию.

Исправлено: ввиду малого числа совпадений хоткеев (и практически всех парных) в этих меню глючность позиционирования не проявлялась. Но стоило только добавить третье совпадение, как она тут же обнаружилась.


А в Macro Browser alt. позиционирование глючит: то переход производится только между двумя ближайшими одинаковыми хоткеями, а то и вовсе один и тот же хоткей попеременно то вверху видимой части экрана показывается, то внизу.

Добавлено: это отчётливо подтверждается и в меню "Ассоциации для файлов".
Last edited by sToLp on Sat 06 Dec, 2014 08:18, edited 1 time in total.
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

Улучшение меню с дублирующимися хоткеями

Post by John Doe »

sToLp wrote: позиционирование глючит
Это какая-то неведомая херня.
Похоже баги в фаре, причём в 2х местах:
http://forum.farmanager.com/viewtopic.p ... 93#p126293
http://forum.farmanager.com/viewtopic.p ... 94#p126294
User avatar
sToLp
Posts: 938
Joined: Thu 23 Jul, 2009 10:16
Has thanked: 114 times
Been thanked: 12 times

Улучшение меню с дублирующимися хоткеями

Post by sToLp »

Уточнил своё предыдущее сообщение.
siberia-man
Posts: 131
Joined: Sat 28 Jun, 2014 23:07
Has thanked: 2 times
Been thanked: 9 times

Улучшение меню с дублирующимися хоткеями

Post by siberia-man »

Code: Select all

1,3d0                                                          
<                                                              
< -- http://forum.farmanager.com/viewtopic.php?f=15&t=9197     
<                                                              
46d42                                                          
<     local y = {}                                             
Одна неинициализированная переменная бросает ошибку.

Забыл добавить: происходит только в случае, одного найденного элемента. Проверял на списке выбора синтаксиса far colorer
siberia-man
Posts: 131
Joined: Sat 28 Jun, 2014 23:07
Has thanked: 2 times
Been thanked: 9 times

Улучшение меню с дублирующимися хоткеями

Post by siberia-man »

Хотелка: По Alt+letter позиционировать курсор, даже если в списке один элемент.

В lua/luafar не очень хорошо разбираюсь. Поэтому пока решил так:

Code: Select all

--    if Object.CheckHotkey(hk,x[ItemIndex]+1)==0 then return end
Что тоже имеет свой плюс. Видим, что выбираем.
User avatar
sToLp
Posts: 938
Joined: Thu 23 Jul, 2009 10:16
Has thanked: 114 times
Been thanked: 12 times

Улучшение меню с дублирующимися хоткеями

Post by sToLp »

siberia-man wrote:Хотелка: По Alt+letter позиционировать курсор, даже если в списке один элемент.
... Видим, что выбираем.
Поддерживаю.

И вот это бы ещё добавить: "по символу с Ctrl — сразу применение пункта списка".
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

Улучшение меню с дублирующимися хоткеями

Post by John Doe »

siberia-man wrote: Хотелка: По Alt+letter позиционировать курсор, даже если в списке один элемент.
Ок.
sToLp wrote: И вот это бы ещё добавить: "по символу с Ctrl — сразу применение пункта списка".
"Применение" и без Ctrl работает.
Но не в MBA. Посмотрю как-нибудь.
User avatar
sToLp
Posts: 938
Joined: Thu 23 Jul, 2009 10:16
Has thanked: 114 times
Been thanked: 12 times

Улучшение меню с дублирующимися хоткеями

Post by sToLp »

John Doe wrote:"Применение" и без Ctrl работает.
Но не в MBA. Посмотрю как-нибудь.
Да, "применение" по Enter`у в большинстве меню работает.
Но тут 3 существенных момента.
Пользователь нацелен на хоткей, держит его под пальцем. Только что нажимал Alt-хоткей. И ему сподручнее в этот момент нажать Ctrl-хоткей, нежели переключится на Enter. Это во-первых.
Во-вторых, у той, как я полагаю, довольно большой группы пользователей, которая практикует плагин AltHistory, есть уже привычка работать с Ctrl-хоткей.
В третьих, расширить арсенал команд, работающих в МВА, дополнительной возможностью, совпадающей с популярной тенденцией, было бы весьма полезно.
Спасибо Вам за готовность заняться этим!

И ещё одно пожелание. А нельзя ли ещё сделать так, чтобы после сброса пользователем отфильтрованного меню (по Esc или F10) происходил возврат к родительскому меню? Причём для МВА это особенно желательно.
User avatar
John Doe
Бюрократ
Posts: 13851
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 428 times
Contact:

Улучшение меню с дублирующимися хоткеями

Post by John Doe »

sToLp wrote: Пользователь нацелен на хоткей, держит его под пальцем. Только что нажимал Alt-хоткей. И ему сподручнее в этот момент нажать Ctrl-хоткей, нежели переключится на Enter.
А при чём тут Enter? Достаточно нажать тот же хоткей без Alt.
sToLp wrote: А нельзя ли ещё сделать так, чтобы после сброса пользователем отфильтрованного меню (по Esc или F10) происходил возврат к родительскому меню?
Можно по Esc/F10 полностью снимать все фильтры.
Но конкретно для MBA нужно делать иначе, и обсуждать в другой теме (вижу вы и там написали уже).
siberia-man
Posts: 131
Joined: Sat 28 Jun, 2014 23:07
Has thanked: 2 times
Been thanked: 9 times

Улучшение меню с дублирующимися хоткеями

Post by siberia-man »

John Doe wrote: Можно по Esc/F10 полностью снимать все фильтры.
По ESC (как действие по умолчанию) было бы здорово снимать все фильтры и возвращаться к первоначальному виду списка.
Post Reply

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