Макрос написан по мотивам анси-плагина Change Active Drive by Ilya V. Gershman
Стрелки (или другие назначенные клавиши) в сочетании с LeftCtrl/LeftAlt/RightCtrl/RightAlt/Shift в указанных комбинациях меняют диск для левой/правой/активной/пассивной (в зависимости от настроек) панели. Замечания и предложения принимаются с благодарностью.
Версия 1.0. Начальная.
Версия 1.1. Добавлены опции: использовать/игнорировать Shift/стрелки; игнорировать/обрабатывать закрытые панели. Не пытаемся обрабатывать нефайловые панели (всё равно смена диска не работает).
Версия 2.0. Переделана логика. Теперь макрос вызывается и работает до конца, а не при каждом нажатии. Больше нет конфликта с Bookmark (c) Max Rusov и другими макросами, назначенными на отпускание одиночного модификатора. Мелкие правки. Сделана версия для чистого LuaMacro.
Версия 2.1. Небольшая оптимизация алгоритма, переход с mf.* на стандартные средства Lua. Теперь во вложении.
Версия 2.2. Ещё чуть оптимизации. Включаем отключенную панель перед изменением диска для неё. Не меняем диск, если выбрали его же; если на панели не локальный диск, запомним и выведем для него отдельный символ. Возможность исключать отдельные диски из списка. Альтернативный режим управления (Ctrl меняет на активной панели, Alt на пассивной).
Версия 2.2.1 Исправление ошибок. Добавлена настройка включения панели.
Версия 2.2.2 Исправлена ошибка с перерисовкой панели, когда диск не сменился, и ситуация с погашенной панелью.
Версия 2.2.3 Внесена правка в связи со сменой DisableOutput на EnableOutput. Работает как со старым, так и с новым вариантом.
Версия 2.2.4 После очередного рефакторинга Far-а вылезла мелкая, но досадная ошибка с mmode. Исправлена.
Версия 2.2.5 Правка скрипта (использование возможностей, появившихся после его написания), причёсывание. Теперь работает и с плагиновыми панелями, а также в области поиска. Требует версию Far 3.0.3209+.
Версия 2.2.6 Если рабочая панель Info/QView/Tree, то переключаем в другой. Небольшая полировка неровностей.
Версия 2.2.7 Подсвечивается изначальный диск. Оптимизация.
Версия 2.2.7a Экспериментально: изначальный диск не только подсвечивается, но и выводится строчной буквой. Для возврата на него введена клавиатурная комбинация "Home" с текущим модификатором.
Версия 3.0.0 - Настройка скрипта (вызывается по выбору "?" в конце списка, быстрый переход по нажатию "End"), хранение настроек в БД. Скрипт добавлен в меню плагинов. Кроме дисков, можно переходить на плагины. Список плагинов настраивается. Локализация. Добавлена контекстная справка (вызывается везде, даже при переключении дисков). Рефакторинг, исправление ошибок.
Версия 3.0.1 - Добавлено сохранение порядка плагинов в строке. Исправление ошибок.
Версия 3.0.1a- "Опечатка в хелпе: End - позиционирование курсора на ситволе окна конфигурации; необъявленные переменные: FarLang, L"
Версия 3.0.2 - Исправлена ошибка со случаем, когда скрипт стартует с начальным диском, входящим в список исключаемых. Настройка строки вывода мини-панели.
Версия 3.0.3 - Исправлены ошибки в конфигурации: не вызывалась настройка списка плагинов, поправлено окно диалога и русский языковой файл.
Версия 3.0.4 - В меню настройки плагинов: символ пометки "&" корректно отображается, Enter отрабатывает в любой позиции.
Версия 3.0.5 - Выбор символа плагина: при нажатии клавиш и комбинаций с длинными названиями (Ctrl, AltQ, etc) возникала ошибка. Исправлено.
Версия 3.0.6 - Esc - отмена выбора диска, Enter - переход на диск.
Версия 3.0.7 - Рефакторинг работы с плагинами. Мелкие правки.
Версия 3.0.8 - Настройка вывода символов панели с разделением пробелами. Настройка выделения текущего диска нижним регистром. Рефакторинг. Мелкие правки.
Версия 3.1.0 - Более гибкая настройка управления. Переработана справка.
Версия 3.1.1 - Мелкие правки.
Версия 3.2.0 - Максимально гибкая настройка управления. Смена места хранения данных. Мелкие правки.
Версия 3.3.0 - Диски и плагины можно назначать на разные комбинации. После смены клавиш скрипты перезагружаются. Убрана область Menu из определения пункта меню плагинов. При выводе справки используется язык справки фара. Справка допилена. Nfo. Мелкие правки.
Версия 3.3.1 - Нажатие буквы диска/символа плагина перемещает курсор в панели. Изменён способ выделения начального диска в панели. Рефакторинг.
Версия 3.3.2 - Можно указывать несколько строк вывода, панель будет выводиться в каждой.
Версия 4.0.0 - Панели переключения могут быть постоянными и всплывающими при наведении мыши. Рефакторинг.
Версия 4.0.1 - Укрощение курсора в поле "Диски, исключаемые из списка" диалога настроек.
Версия 4.1.0 - Горизонтальная позиция мини-панели настраивается. Скрипт добавляется в меню дисков. Подсказки. Рефакторинг.
Версия 4.1.1 - Исправлена подсказка для конфигурации. Рефакторинг.
Версия 4.1.2 - Исправлена подсказка мини-панели. Дополнена справка о подсказке. Доработан вид меню выбора плагинов в конфигурации. Добавлен показ в подсказке метки тома для дисков. Рефакторинг.
Версия 4.1.3 - Исправлена подсказка мини-панели (перевод в UTF8). Исправлена ошибка с набором не буквы для исключаемого диска в настройках.
Версия 4.1.4 - Исправлена загрузка значений из БД. Исправлена сортировка плагинов в диалоге настройки.
local DrvList = "" -- заготовка под список дисков в системе
local drvs = win.GetLogicalDriveStrings()
for i = 1,#drvs do
local d = drvs[i]:sub(1,1)
if not ExcludeDrives:find(d) then DrvList = DrvList..d end -- если не исключён - добавим
end
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Mon 19 May, 2014 11:39
by IgorZ
Версия 2.2.4: Исправлена мелкая, но досадная ошибка с mmode. Вылезла после какого-то из последних рефакторингов. Выложена.
local DrvList = "" -- заготовка под список дисков в системе
local drvs = win.GetLogicalDriveStrings()
for i = 1,#drvs do
local d = drvs[i]:sub(1,1)
if not ExcludeDrives:find(d) then DrvList = DrvList..d end -- если не исключён - добавим
end
1. Проверка дисков на тип ("no root directory") необходима в linux под wine (без неё там вылазит порой куча мусора, что, в частности, мешает переключать вслепую).
2. С вышеуказанной проверкой на быстрых машинах предложенный вариант практически не даёт выигрыша, а на сильно медленных отрабатывает даже медленнее (25 мс против 16).
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Mon 19 May, 2014 11:51
by John Doe
А что там с mmode? Разве вопрос не решается добавлением flags="EnableOutput";?
Ещё замечу что:
- exit() можно смело заменить на return
- Действие макроса можно расширить и на панели Info QView Tree (может и на Search)
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Tue 20 May, 2014 09:03
by AleXH
onlyVisible и useShift логично было бы сделать логическими переменными true/false
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Mon 26 May, 2014 06:21
by IgorZ
Версия 2.2.5: Правка скрипта (использование нововведений, появившихся после его написания, ~700 билдов Far-а назад ), причёсывание. Теперь работает и с плагиновыми панелями, а также в области поиска. Требует версию Far 3.0.3209+, а не 3.0.3054+, как предыдущая.
John Doe wrote:А что там с mmode? Разве вопрос не решается добавлением flags="EnableOutput";?
Скрипт старенький. Когда он писался, я ещё только изучал Lua (собственно, на нём и изучал), а EnableOutput ещё не было, как и кое-чего другого. Так оно и тянулось. Поправил.
John Doe wrote:- exit() можно смело заменить на return
Можно, но это чистая вкусовщина с моей стороны. Функционально одно и то же, а exit() кажется мне более наглядным. Впрочем, теперь я вынес эту часть в condition, и exit() не нужен.
John Doe wrote:- Действие макроса можно расширить и на панели Info QView Tree (может и на Search)
На Info/QView/Tree не работает - не меняется диск. На Search расширил.
AleXH wrote:onlyVisible и useShift логично было бы сделать логическими переменными true/false
IgorZ wrote:На Info/QView/Tree не работает - не меняется диск.
При этом пассивная панель ведь файловая, и на ней сменить диск возможно.
Просмотрев скрипт свежим взглядом заметил, что в цикле repeat/until 100 раз в секунду перерисовывается панелька дисков.
(Хотя визуально ничего не дёргается, вероятно фар оптимизирует).
Кстати можно обойтись без EnableOutput, используя far.Text()
P.S.
Ещё несколько мыслей:
- SkipShift можно обработать раньше, в определении макроса.
- Не баг, но функции cond/act правильнее сделать локальными
- В условии cond имхо имеет смысл перенести вычисление WPanel в блок if/else. В ущерб компактности, зато конечный пользователь легче сможет подстроить под сеья желаемое поведение.
Посмотрел имеющийся у меня архив старых версий. Не было такого. Возможно, Вы это у себя самостоятельно правили? А, вспомнил. Я выкинул DisableOutput и вставил mmode, чтобы работала и на старых, и на новых версиях Far-а. Сейчас уже вряд ли нужна совместимость.
John Doe wrote:
IgorZ wrote:На Info/QView/Tree не работает - не меняется диск.
При этом пассивная панель ведь файловая, и на ней сменить диск возможно.
Менять на другой панели? Вроде идея неплохая. Сделал.
John Doe wrote:Кстати можно обойтись без EnableOutput, используя far.Text()
Нельзя. Я почему и заметил ошибку с mmode: после рефакторинга он перестал работать, и панелька дисков вообще не стала отображаться. Точнее, весь вывод на экран стал накапливаться в буфере и выводиться разом, по итогам отработки скрипта, а не сразу в очередной итерации цикла. Пример:
Если раскомментировать строчку, работает нормально. Иначе - вываливает всё в конце. Кстати, возможно, это ошибка плагина, но не уверен. Определённая логика в таком поведении есть.
John Doe wrote:- SkipShift можно обработать раньше, в определении макроса.
Логично. Сделал.
John Doe wrote:- Не баг, но функции cond/act правильнее сделать локальными
Банально забыл поставить.
John Doe wrote:- В условии cond имхо имеет смысл перенести вычисление WPanel в блок if/else. В ущерб компактности, зато конечный пользователь легче сможет подстроить под сеья желаемое поведение.
DrvNum = DrvNum==0and len or DrvNum>len and1or DrvNum -- корректировка выхода за начало/конец
far.Text(DrvStart,0,far.AdvControl(GetColor,StdColor),"["..DrvList.."]")-- отрисуем список дисков
far.Text(DrvStart+DrvNum,0,far.AdvControl(GetColor,SelColor),DrvList:sub(DrvNum,DrvNum))-- и курсор
far.Text()
end
Key = mf.waitkey(10)
until band(Mouse.LastCtrlState,bMods[KeyMod])==0
Это просто для информации, я не утверждаю что тут есть хоть какие-то преимущества перед EnableOutput.
IgorZ wrote:
John Doe wrote:- В условии cond имхо имеет смысл перенести вычисление WPanel в блок if/else. В ущерб компактности, зато конечный пользователь легче сможет подстроить под сеья желаемое поведение.
DrvNum = DrvNum==0and len or DrvNum>len and1or DrvNum -- корректировка выхода за начало/конец
far.Text(DrvStart,0,far.AdvControl(GetColor,StdColor),"["..DrvList.."]")-- отрисуем список дисков
far.Text(DrvStart+DrvNum,0,far.AdvControl(GetColor,SelColor),DrvList:sub(DrvNum,DrvNum))-- и курсор
far.Text()
end
Key = mf.waitkey(10)
until band(Mouse.LastCtrlState,bMods[KeyMod])==0
Это просто для информации, я не утверждаю что тут есть хоть какие-то преимущества перед EnableOutput.
Ага, понял (про этот нюанс far.Text() я, если честно, просто забыл). Недостаток: дополнительный исполняющийся в цикле код. По факту несущественно, но вообще следует избегать.
Key,KeyMod = key,key:match("..%l+")-- запомним клавишу и модификатор
if Key:find("Ctrl")andnot CmdLine.Empty thenreturnend-- Ctrl/стрелки отдаём в командную строку, если не пуста
if AlternativeMods then
WPanel = KeyMod:find("Ctrl")and APanel or PPanel
else
if KeyMod=="Shift"then
WPanel = APanel
else
WPanel =(KeyMod=="Ctrl"or KeyMod=="RAlt")==APanel.Left and APanel or PPanel
end
end
returnnot OnlyVisible or WPanel.Visible
end
А смысл? Проще не стало. Если кому надо разобраться в работе и/или переделать - и так справится. Может, я что-то недопонимаю?
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Tue 27 May, 2014 10:22
by John Doe
IgorZ wrote:Недостаток: дополнительный исполняющийся в цикле код. По факту несущественно, но вообще следует избегать.
В предложенном варианте код выполняется вовсе не в цикле, а только по факту нажатия.
В вашем же да, 100 раз в секунду исполняется значительный объём ненужного кода (вчера уже писал об этом: незачем вызывать функции вывода на экран если ничего не изменилось).
Плюс, цвета можно сразу запомнить (даже до макроса), и не вычислять для каждой итерации заново.
IgorZ wrote:А смысл? Проще не стало. Если кому надо разобраться в работе и/или переделать - и так справится. Может, я что-то недопонимаю?
Идиома a = b or c это действительно просто.
А разбирать двустрочное нагромождение логических выражений это уже задача.
WPanel = (not AltMode and (KeyMod=="Ctrl" or KeyMod=="RAlt")==APanel.Left or
(AltMode and KeyMod:find("C")) or KeyMod=="Shift") and APanel or PPanel -- рабочая панель
P.S.
Разумеется ваш вариант вполне корректен, и в компактности записи есть своя прелесть.
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Tue 27 May, 2014 13:12
by John Doe
Закомментировал вызов panel.RedrawPanel и ничего не изменилось.
Видимо лишний.
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Wed 28 May, 2014 04:52
by IgorZ
Версия 2.2.7: подсвечивается начальный диск, оптимизация всего, что попалось на глаза.
John Doe wrote:
IgorZ wrote:Недостаток: дополнительный исполняющийся в цикле код. По факту несущественно, но вообще следует избегать.
В предложенном варианте код выполняется вовсе не в цикле, а только по факту нажатия.
В вашем же да, 100 раз в секунду исполняется значительный объём ненужного кода (вчера уже писал об этом: незачем вызывать функции вывода на экран если ничего не изменилось).
Мы о разном. Насчёт исполнения в цикле, согласен, поправлю, но я о другом: в коде в цикле стоит и выполняется оператор, который не выполняет асолютно никакой полезной работы (при наличии EnableOutput или, как раньше, mmode(1,0)).
Кстати,
- некорректно. mf.waitkey может ввести любую клавишу. Получится, что всё нажатое, кроме KeyMod.."Right" будет работать, как KeyMod.."Left". Ну это так, придирки.
John Doe wrote:Плюс, цвета можно сразу запомнить (даже до макроса), и не вычислять для каждой итерации заново.
Тут согласен, заодно добавлю подсветку начального диска (полезно, если рабочая панель погашена).
John Doe wrote:
IgorZ wrote:А смысл? Проще не стало. Если кому надо разобраться в работе и/или переделать - и так справится. Может, я что-то недопонимаю?
Идиома a = b or c это действительно просто.
А разбирать двустрочное нагромождение логических выражений это уже задача.
WPanel = (not AltMode and (KeyMod=="Ctrl" or KeyMod=="RAlt")==APanel.Left or
(AltMode and KeyMod:find("C")) or KeyMod=="Shift") and APanel or PPanel -- рабочая панель
P.S.
Разумеется ваш вариант вполне корректен, и в компактности записи есть своя прелесть.
Ради эксперимента отформатировал выражение, не меняя его (только скобок добавил для единообразия. Насколько изменилась читабельность?
John Doe wrote:Закомментировал вызов panel.RedrawPanel и ничего не изменилось.
Видимо лишний.
Рудимент от тех времён, когда не использовал far.SaveScreen/far.RestoreScreen. Убрал.
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Wed 28 May, 2014 09:36
by John Doe
IgorZ wrote:Мы о разном. Насчёт исполнения в цикле, согласен, поправлю, но я о другом: в коде в цикле стоит и выполняется оператор, который не выполняет асолютно никакой полезной работы (при наличии EnableOutput или, как раньше, mmode(1,0)).
Во-первых, "в цикле" предполагает какое-то существенное число повторений, у нас же только по нажатию клавиши.
Во-вторых, я вовсе не предлагал добавлять вызов far.Text() при включённом флаге EnableOutput.
Что касается полезной работы, то следует учитывать, что при EnableOutput ведь тоже выполняется дополнительная работа, хоть и неявно.
Для информации:
фар буферизирует вывод, и флаг EnableOutput вовсе не гарантирует, что сброс буфера произойдёт в тот момент, когда вы этого ожидаете (пример).
Другой пример: в вашем скрипте сброс буфера происходит не в каждом из 3х вхождений far.Text, а после mf.waitkey.
И никакой EnableOutput (или mmode) не помог бы, не будь там вызова mf.waitkey (или другой функции, сбрасывающей буфер).
Но да, конкретно в этом скрипте mf.waitkey есть, поэтому как-то специально сбрасывать буфер нет нужды.
if WPanel.Left then Keys("CtrlF1") else Keys("CtrlF2") end
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Fri 30 May, 2014 05:52
by IgorZ
Версия 2.2.7a: Экспериментально: изначальный диск не только подсвечивается, но и выводится строчной буквой. Для возврата на него введена клавиатурная комбинация "Home" с текущим модификатором.
Предлагаю подсвечивать тут не фон, а текст, а то похоже на второй курсор.
В скрипте используются стандартные цвета текущей раскраски Far-а. В частности, для кусора - цвета курсора, а для начального диска - цвета выделенного файла (или, соответственно, выделенного файла под курсором). Так что, если у Вас буква начального диска на фоне другого цвета, значит, так настроен Ваш Far (Параметры/Цвета/Панель/Выбранный текст и Выделенный курсор).
В текущей версии для пробы дополнил выделение текущего диска размером буквы (у меня раскраска настроена так, что выбранные файлы выделяются только галкой, а цветом нет, так что выделение диска цветом у меня не работает). Все диски - заглавными буквами, а изначальный - строчной. Если интересно, можно попробовать вариант наоборот: все строчными, а начальный - заглавной. Для этого надо раскомментировать все строки, у которых в комментарии стоит "!!lower" и закоментировать предыдущие. Лично мне не понравилось, но на вкус и цвет все фломастеры разные.
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Fri 30 May, 2014 06:46
by AleXH
Я себе сделал так: фон синий (стандартная схема), все буквы заглавные, голубые на синем, исходный диск жёлтый на синем, выбираемый диск жёлтый на красном.
Re: Переключение дисков по Ctrl/Alt/Shift+<-/->
Posted: Fri 04 Jul, 2014 19:43
by John Doe
Подумалось, что неплохо бы добавить на линейку дисков и плагины.
Для иллюстрации (довольно топорно) модифицировал CtrlAltMenuDisk2.2.7.
В начале файла можно задать список плагинов (guid каждого, символ для каждого, и главное: строку определяющую какие плагины и в каком порядке будут выводится:
local NetBox = win.Uuid"42E4AEB1-A230-44F4-B33C-F195BB654931"
local TmpPanel = win.Uuid"B77C964B-E31E-4D4C-8FE5-D6B0C6853E7C"
local Proclist = win.Uuid"1E26A927-5135-48C6-88B2-845FB8945484"
local Branch = win.Uuid"148FE5E0-7129-4269-B30F-A1A866DD009A"
local network = win.Uuid"773B5051-7C5F-4920-A201-68051C4176A4"
local SameFolder = win.Uuid"06771932-E01F-4259-A7A5-A899DEC06FC7"
local Plugins ={
["$"]=TmpPanel,
["^"]=Proclist,
["*"]=Branch,
["\\"]=network,
["="]=SameFolder,
}
local PlugStr ="$^*="
).
(Если автору идея не понравится, то выделю в отдельную тему)
P.S.
SameFolder пока меняет папку на пассивной панели, а не на выбранной. Но и нормально сделать не сложно. Как собственно и добавить на линейку не только плагин, а вообще произвольную пользовательскую функцию (если это вообще кому-то интересно).