Задача интересная, хоть и специфическая.
На самом деле за всё время множество хотелок было по расширению метасимволов (не раз встречал как на форуме, так и на мантисе).
И всё обычно ограничивается обсуждением а многим ли это полезно, и какой метасимвол придумать (и не дофига ли и так непонятных закорючек).
Что если предоставить пользователю возможность самостоятельно запрограммировать нужную функциональность?
Синтаксически это будет как один метасимвол, но с параметрами.
Это по идее не очень сложно реализовать, но 10-20 часов работы просматриваются.
В принципе проверить полезность этой идеи можно прямо сейчас перехватом закрытия диалога "Apply command" (Ctrl-G). Естественно, сначала придумать какой-то новый метасимвол, включающий параметры, сопоставить ему Lua-функцию, возвращаемое значение которой будет подставлено в результирующую строку.
Shmuel wrote: ↑Wed 31 Oct, 2018 12:20
придумать какой-то новый метасимвол, включающий параметры, сопоставить ему Lua-функцию, возвращаемое значение которой будет подставлено в результирующую строку
В качестве отправной точки для обсуждения синтаксиса можно взять аналогичную функциональность из замены в плагине RESearch.
Shmuel wrote: ↑Wed 31 Oct, 2018 12:20
придумать какой-то новый метасимвол, включающий параметры
Как вариант, синтаксис может быть похож на используемый в lua при вызове функции: !*func(arg1,arg2), где аргументы указываются стандартным образом, т.е. строки в "кавычках", или в [[скобках]] (для экранирования).
Символ может быть и другим, можно и уйти от закорючек: !lua!func(arg1,arg2)
(А при вызове без параметров возможно и скобки не нужны.)
Todo
Наличие аргументов усложняют для парсера задачу вычленения метасимвола из строки, поэтому могут понадобиться какие-то правила экранирования.
Last edited by John Doe on Mon 05 Nov, 2018 15:42, edited 1 time in total.
Учитывая равную применяемость метасимволов в Ассоциациях (панельных, и командной строки), Меню Пользователя, и Применить Команду, определение может выглядеть так :
Поля description и id – опциональные, их значения по умолчанию – пустая строка.
name - имя, используемое для вызова функции в метасимволе. Предполагается что оно уникально.
flags - флаги, в настоящий момент нужен лишь один [поэтому возможно достаточно логического поля].
Флаг "runonce" (или "SelectedAtOnce") указывает фару, что при использовании в Применить команду требуется однократный вызов (не нужно повторять команду для каждого выделенного файла отдельно). То же самое поведение в настоящий момент мы наблюдаем при использовании метасимволов !@!, !$!, !&, !&~.
action - функция, выполняющая подстановку (замену символа на реальное значение).
[возможно правильнее использовать имя process]
Функция получает следующие аргументы:
Params - таблица, в которой передаются необходимые параметры.
Перечень параметров пока не вполне определён, поэтому передача через таблицу видится предпочтительнее позиционной, но впоследствии возможно разделить её на отдельные параметры.
В числе параметров необходимы следующие:
Item: таблица (вероятно), через которую передаются данные обрабатываемого файла. Какие именно данные доступны (fnparce.cpp) - вопрос к специалистам.
State: таблица, общая для всех вызовов action в пределах одного запуска "Применить команду", что позволяет использовать её для хранения состояние в процессе итераций.
[Возможно вместо отдельного аргумента стоит просто сохранять само окружение функции]
Source: number флаг, означающий источник вызова: ApplyCommand|UserMenu|Association|CmdLine.
preprocess: boolean флаг, означающий, что выполняется предварительная подстановка, для отображения в меню пользователя, или при конфликте ассоциаций.
В этом случае подстановка может отличаться, например, не будет показан диалог, и т.п. (возможны и другие сценарии). То же самое поведение в настоящий момент мы наблюдаем при использовании метасимволов !@!, !$! (см. справку), а также !?<title>?<init>!.
[Возможно, понадобятся и другие параметры, например строка ассоциации (или введённая в диалоге Применить команду), или та же строка, но уже с развёрнутыми метасимволами]
... - аргументы, передаваемые через метасимвол.
Возвращаемое значение: string, или nil, или false:
string строка для подстановки
nil пропустить элемент
не выполнять команду для этого элемента. В частности:
в Применить команду: пометка с файла не будет снята, переходим к следующей итерации.
в Ассоциациях: команда будет отсеяна при анализе подходящих ассоциаций (и не попадёт в меню конфликта). Аналогичное поведение в настоящий момент мы наблюдаем при использовании конструкций if defined/if exist (см. справку).
false прервать всю операцию. Аналогично nil, но в случае Применить команду:
пометка с файла не будет снята, прекращаем итерацию. То же самое поведение в настоящий момент мы наблюдаем при использовании метасимвола !?<title>?<init>! (при отмене диалога).
Кроме того, если идея получит развитие, то возможны дополнения, например дополнительный запуск функции после обработки нескольких выделенных файлов.
Last edited by John Doe on Thu 01 Nov, 2018 10:58, edited 3 times in total.
John Doe wrote: ↑Wed 31 Oct, 2018 13:59
Параметры функций обдумываю
Учитываете ли вы возможность передавать метасимволу не только какие-то данные одного элемента, но и все выделенные элементы (инлайн-списком или путём к файлу-списку)?
HaRT wrote: ↑Wed 31 Oct, 2018 14:05
Учитываете ли вы возможность передавать метасимволу не только какие-то данные одного элемента, но и все выделенные элементы (инлайн-списком или путём к файлу-списку)?
В том виде, как это сформулировали вы, ничего специально делать не потребуется: если фар будет предварительно раскрывать прочие метасимволы, то можно будет передать эти данные указав аргументом соответствующий метасимвол.
Только врядли это удобно, скрипту проще получить эти элементы самостоятельно, используя апи.
Edit: возможно впоследствии окажется удобным сразу получать данные, как таблицу элементов, но пока этот вопрос не принципиален.
Last edited by John Doe on Wed 31 Oct, 2018 15:58, edited 1 time in total.
John Doe wrote: ↑Wed 31 Oct, 2018 15:52
Указал требуемые действия, в зависимости от возвращаемого значения action.
nil === Пропустить: команда не выполняется, соответствующий элемент панели остаётся помеченым.
Ещё одна мысль, делающая обсуждаемую идею вдвойне привлекательной: а ведь так программируемые метасимволы могут служить условиями выполнения ассоциаций!
Напомню, что если файлу сопоставлено несколько ассоциаций, то при запуске показывается меню выбора.
Но сначала отсеиваются ассоциации, в которых присутствуют и не выполняются условия if exist / if defined.
И вот тут вместо этих ограниченных условий могут быть lua-скрипты, определяемые метасимволами.
Осталась неопределённость с параметрами action, поскольку мне неизвестно, какие в точности данные об обрабатываемых элементах (и контексте) предоставит фар.
Плюс, в тех местах, где требуетсяжелательна различная реакция фара в зависимости от результата подстановки, нет уверенности что это легко реализовать.
Предлагаю в список возвращаемых значений добавить true - команду не выполнять, пометку снять: функция уже сама всё сделала.
Может, вместо ... лучше таблицу? В ряде случаев это удобнее.
Все флаги в параметрах, наверное, логично убрать в State.
В итоге, функция будет выглядеть как имя(Item,State,Args)
Для Item, вероятно, наиболее логично использовать tPluginPanelItem.