На форуме выкладываются множество макросов. Некоторые идут целыми пакетами.
Очевидно что не все макросы могут быть нужны пользователю, а значит они напрасно занимают клавиши.
Или макросы хочется использовать с другими сочетаниями, а не с теми, которые определил автор.
Можно конечно просто отредактировать макросы, но при каждом обновлении процедуру придётся повторить.
Ниже предлагается простое централизованное решение, позволяющее отключить любой сторонний макрос, или переопределить его клавиатурную комбинацию.
Прототип обсуждался ранее, а теперь всё это можно делать интерактивно, с помощью одного из двух альтернативных макро браузеров:
Del — запретить/разрешить макрос. Запрещённый макрос отображается серым.
ShiftF4 — (пере)назначить сочетание клавиш.
В диалоге можно указать несколько клавиш или регэксп. Пустая строка отменяет переназначение.
После этого все макросы перезагружаются, чтобы изменения вступили в силу.
Переназначенные макросы индицируются звёздочкой перед клавишей.
к перечисленным выше комбинациям клавиш также расширяется дополнительное меню фильтров Misc,
добавляются такие пункты:
rebinded — макросы с переназначенными клавишами
disabled — запрещённые макросы
(db) — макросы, настройки которых прочитаны из базы
(file) — макросы, настройки которых прочитаны из файла bindings
rebindable — макросы, которые возможно переназначить
no id — макросы без идентификатора
Все настройки (состояние запрета и переназначенные клавиши) сохраняются в базе, и загружаются при запуске фара.
Также поддерживается альтернативный способ хранения настроек, в файле %FARPROFILE%\Macros\scripts\bindings.
В MacroBrowser alt для этого служит комбинация CtrlShiftF4, открывающая редактор, и вставляющая шаблон для настройки текущего макроса.
Для макросов, переназначенных таким образом, клавиши Del и ShiftF4 действуют иначе: открывают файл настроек в нужном месте.
Формат файла настроек не описываю, т.к. всё должно быть понятно при вставке шаблона по CtrlShiftF4.
Пример получившегося файла:
Всё что требуется для работы перечисленных функций — это подключить в _macroinit.lua модуль rebind: require"rebind".
На практике полезно дополнительно настроить модуль:
local rebind = require"rebind"
if type(rebind)=="table" then
rebind.Setup {auto_uids=true,no_warnings=true} -- опционально: разрешаем автоназначение идентификаторов, без вывода ошибок
rebind.LoadBindings() -- опционально: загружаем настройки из файла "bindings"
end
Об идентификаторах макросов:
В идеале в определение каждого макроса следует добавить поле id с уникальным идентификатором.
Или разрешить автоматическую их генерацию (auto_uids=true) на основе имени файла и описания макроса.
При загрузке макросов возможна ситуация, когда id получается неуникальным.
В этом случае тут же будет предложено его исправить.
Можно отключить предупреждения (no_warnings=true), проблем не будет, но некоторые макросы невозможно будет переназначить.
Требования: Far 3.0 build >4743 (luamacro build 580)
Пара предложений по rebind:
1. Почему бы не назначать uid и клавиатурным макросам, и обработчикам событий тоже. Это позволит:
1.1. Отключать и те, и другие при необходимости;
1.2. Сделать полезный задел на будущее.
2. Неплохо было бы сделать функцию генерации uid внешней. А то мне она понадобилась - так пришлось лезть в код rebind и копировать оттуда кусок. Некрасиво и неправильно.
1. Обработчикам событий бесспорно. А клавиатурным макросам не вижу смысла.
2. Запросто, правда задумана она внутренней, и понятия не имею зачем вам понадобилась.
Вообще rebind ждёт переделка.
Дополнительные данные (сейчас ~4 элемента) хранятся прямо в таблице макроса, т.е. во внутренней структуре LuaMacro, что не очень хорошо.
Вместо этого в таблице макроса будет храниться только один элемент — таблица (или даже userdata) с метаметодами.
shmuel 28.10.2015 13:23:40 +0200 - build 538
1. Изменение API: загрузочные функции 'Macro' и 'Event' теперь возвращают true в случае успеха,
а не число-идентификатор макроса/события, как было раньше.
--- Old\rebind.lua Wed Jan 14 12:09:42 2015
+++ rebind.lua Sat Nov 07 13:54:59 2015
@@ -51,14 +51,13 @@
if not no_warnings then editBadUid(m.uid,info.source:sub(2,-1),info.currentline) end
m.uid = nil
end
- local id = mf.AddMacro(m)
- if id then
- local Macro = LoadedMacros[id]
+ local Macro = mf.AddMacro(m)
+ if Macro then
for _,field in ipairs(new_fields) do Macro[field] = Macro[field] or m[field] end
--Macro.FileName = m.FileName or Macro.FileName
if m.uid then usedUids[m.uid] = Macro.id end
end
- return id
+ return Macro
end
do --get LoadedMacros, set AddMacro
--- Old\rebind.lua Wed Jan 14 12:09:42 2015
+++ rebind.lua Sat Nov 07 13:54:59 2015
@@ -51,14 +51,13 @@
if not no_warnings then editBadUid(m.uid,info.source:sub(2,-1),info.currentline) end
m.uid = nil
end
- local id = mf.AddMacro(m)
- if id then
- local Macro = LoadedMacros[id]
+ local Macro = mf.AddMacro(m)
+ if Macro then
for _,field in ipairs(new_fields) do Macro[field] = Macro[field] or m[field] end
--Macro.FileName = m.FileName or Macro.FileName
if m.uid then usedUids[m.uid] = Macro.id end
end
- return id
+ return Macro
end
do --get LoadedMacros, set AddMacro
.
В процессе эксплуатации выяснилось, что исправление было недостаточным:
у функции загрузки появился второй параметр (имя файла);
уровень вложенности вызова функции увеличился на 1.
local function AddMacroNew(m,filename)
if type(m)~="table" then return end
if m.guid then return mf.AddMacro(m,filename) end --MCTL_ADDMACRO
local currentline = debug.getinfo(3,"l").currentline --todo check timings
--if currentline==-1 then le(debug.getinfo(3)) end --fixme
m.defline = currentline~=-1 and currentline --m.defline or info.currentline
m.uid = m.uid or auto_uids and MakeUid(filename,m.description) --m.FileName or filename
if not m.uid then
--just skip
elseif not usedUids[m.uid] then --check if uid is unique
local Binding = REBIND[m.uid] or {}
if Binding.key then m.rebinded,m.key = m.key,Binding.key end
m.disabled = Binding.disabled
m.bindfrom = Binding.bindfrom
else
if not no_warnings then editBadUid(m.uid,filename,currentline) end
m.uid = nil
end
local Macro = mf.AddMacro(m,filename)
if Macro then
for _,field in ipairs(new_fields) do Macro[field] = Macro[field] or m[field] end
if m.uid then usedUids[m.uid] = Macro.id end
end
return Macro
end
if m.guid and m.guid[1]==guid[1] and m.callbackId==callbackId and not m.disabled then
Если guid окажется не таблицей, то попытка индексирования приведёт к ошибке.
Глубоко не копал, может это и проверяется в другом месте.
Собственно, будущая версия rebind уже хранит свои данные иначе, и в общем-то нет препятствий использовать поле с любым именем.
Поэтому просьба всех заинтересованных высказаться, стоит ли uid переименовывать в guid
John Doe wrote: Если guid окажется не таблицей, то попытка индексирования приведёт к ошибке.
Глубоко не копал, может это и проверяется в другом месте.
Это нигде не проверяется, но при нормальной работе (то-есть, если не модифицировать внутренности LuaMacro библиотекой debug), данная ошибка невозможна.