Skip to content

SysIDs for Plugins (idea partially from memo plugin and far2m / far3)#3317

Merged
elfmz merged 1 commit intoelfmz:masterfrom
akruphi:plugins_id
Apr 3, 2026
Merged

SysIDs for Plugins (idea partially from memo plugin and far2m / far3)#3317
elfmz merged 1 commit intoelfmz:masterfrom
akruphi:plugins_id

Conversation

@akruphi
Copy link
Copy Markdown
Contributor

@akruphi akruphi commented Mar 24, 2026

Now we can call plugins from macros using callplugin(0xAAAAAAAA) which is independent on language and hotkey in Plugin menu via F11.

A pluguin's SysID may see via far:about or in plugin's source code.

Be careful: open plugin only from appropriate places.


@shmuz просьба подсказать алгоритм генерации SysIDs для плагинов. Есть ли какой-то удобный инструмент?

Сейчас в far2l есть плагины, отсутствующие в far2m (edsort, farftp, hexitor, ImageViewer, truncate) - как и какие для них сгенерировать IDs?

Также несколько вопросов - интересует опыт как это решено в far2m / far3
(перетаскивать даже древние реализации plugin.call и plugin.menu я пока не готов):

  1. Cейчас, если макросом запустить часть плагинов не из допустимого места
    (например drawline не из редактора), то весь far2l подвисает,
    то как логичнее:
    • добавлять внутрь PluginManager::CallPlugin( проверку на контекст запуска и не запускать из недопустимого контекста?
    • или лучше это внутри каждого плагина прописать проверки в OpenPlugin
    • или не обращать внимание - пусть вся вина и ответственность изначально на авторе макроса?
  2. Зачем в farplug-wide.h переменная DWORD SysID сидела под #ifdef FAR_USE_INTERNALS?
    Я убрал это условие, но точно ли это не противоречит какой-то древней логике?

@shmuz
Copy link
Copy Markdown
Contributor

shmuz commented Mar 24, 2026

просьба подсказать алгоритм генерации SysIDs для плагинов. Есть ли какой-то удобный инструмент?

Подойдёт любой нормальный рандом-генератор, в диапазоне целых чисел от 0 до 0xFFFFFFFF (то есть 32 бита).
Конкретно я генерирую GUID и беру первые 32 бита.
Для тех плагинов far2m, что есть и в far3, беру эти биты из гуида far3.

Cейчас, если макросом запустить часть плагинов не из допустимого места (например drawline не из редактора), то весь far2l подвисает,

Плагин должен проверять значение OpenFrom в функции OpenPlugin(W) и соответственно реагировать. Если он не хочет поддерживать макросы, то в ответ на OPEN_FROMMACRO должен вернуть INVALID_HANDLE_VALUE. Если хочет, то должен проверить, из какой области его вызвали (с помощью ACTL_GETWINDOWINFO или ACTL_KEYMACRO/MCMD_GETAREA).

Зачем в farplug-wide.h переменная DWORD SysID сидела под #ifdef FAR_USE_INTERNALS?
Я убрал это условие, но точно ли это не противоречит какой-то древней логике?

Скорее всего это не повредит.

@akruphi
Copy link
Copy Markdown
Contributor Author

akruphi commented Mar 24, 2026

Конкретно я генерирую GUID и беру первые 32 бита. Для тех плагинов far2m, что есть и в far3, беру эти биты из гуида far3.

Из чего именно в far2m генерируется? Из имени каталога плагина или полного названия плагина?

Плагин должен проверять значение OpenFrom в функции OpenPlugin(W) и соответственно реагировать. Если он не хочет поддерживать макросы, то в ответ на OPEN_FROMMACRO должен вернуть INVALID_HANDLE_VALUE. Если хочет, то должен проверить, из какой области его вызвали (с помощью ACTL_GETWINDOWINFO или ACTL_KEYMACRO/MCMD_GETAREA).

Вариант простого сравнения после отбрасывания бита OPEN_FROMMACRO допустим (т.е. (OpenFrom & ~OPEN_FROMMACRO) == OPEN_PLUGINSMENU или (OpenFrom & OPEN_FROM_MASK) == OPEN_EDITOR) или при этом возможны сюрпризы и предпочтительно использовать перечисленные функции?

@akruphi akruphi marked this pull request as draft March 24, 2026 21:21
@shmuz
Copy link
Copy Markdown
Contributor

shmuz commented Mar 24, 2026

Из чего именно в far2m генерируется? Из имени каталога плагина или полного названия плагина?

Не, гуиды генерируются не из чего-то, а просто вызывается функция без параметров.
В far3 и far2m эта функция встроенная.
Наверняка в линуксе можно генерировать гуиды какой-то командой из терминала.
Также можно их генерировать он-лайн генераторами в интернете.

Вариант простого сравнения после отбрасывания бита OPEN_FROMMACRO допустим (т.е. (OpenFrom & ~OPEN_FROMMACRO) == OPEN_PLUGINSMENU или (OpenFrom & OPEN_FROM_MASK) == OPEN_EDITOR) или при этом возможны сюрпризы и предпочтительно использовать перечисленные функции?

Я уже успел об этом хорошо забыть (с 2012 года много воды утекло). Видимо, функциональности, описанной в энциклопедии, должно хватить, и не надо тех функций, о которых говорил в прошлом сообщении.

@akruphi
Copy link
Copy Markdown
Contributor Author

akruphi commented Mar 24, 2026

Я уже успел об этом хорошо забыть (с 2012 года много воды утекло). Видимо, функциональности, описанной в энциклопедии, должно хватить, и не надо тех функций, о которых говорил в прошлом сообщении.

Спасибо за упоминание энциклопедии - там оказывается при наличии OPEN_FROMMACRO младшем байте не OPENPLUGIN_OPENFROM, а FARMACROAREA - запутанная премудрость древних гигантов.

@akruphi akruphi marked this pull request as ready for review March 24, 2026 21:47
@elfmz
Copy link
Copy Markdown
Owner

elfmz commented Mar 27, 2026

Cори за глупый вопрос, а почему нельзя human-readable строками? Оптимизацию вызова потом сделать совершенно несложно. Даже можно 8символьными строками, и хранить их в uint64_t, этого вполне хватит, multiarc, netrocks - все это вполне себе 8символьное

@shmuz
Copy link
Copy Markdown
Contributor

shmuz commented Mar 27, 2026

@elfmz
32-битные SysID придуманы не сейчас, а примерно в 2009 году.
Их цель - обеспечить уникальную идентификацию плагина.
В оригинальном Фаре для Windows количество сторонних плагинов в десятки или сотни раз превышает количество плагинов в поставке Фара.
И никто не может гарантировать, что два или более авторов не назовут свой плагин одинаково, например "browser" или "xml" или ещё что-то распространённое.

Far3 пошёл дальше, в нём вместо SysID используются GUID'ы. Тут уже полная гарантия уникальности. Ну и есть механизм, предотвращающий загрузку плагина с гуидом, который уже загружен.

@akruphi
Copy link
Copy Markdown
Contributor Author

akruphi commented Mar 27, 2026

Cори за глупый вопрос, а почему нельзя human-readable строками? Оптимизацию вызова потом сделать совершенно несложно. Даже можно 8символьными строками, и хранить их в uint64_t, этого вполне хватит, multiarc, netrocks - все это вполне себе 8символьное

Здесь я с удивлением на примере плагина memo увидел, что SysID и callplugin работают и в far2l. Затем уже исходил из принципа минимальных изменений там, где слабо разбираюсь, ну и не отклоняться от традиций windows far2 без нужды.

Сейчас склоняюсь, что сам вызов callplugin не очень удобен - плагин должен уметь его обрабатывать. Полезнее из far2m / far3 перенести как минимум макрофункцию plugin.menu - чтобы вызов ощущался плагином как будто его вызвали из меню - судя по https://api.farmanager.com/ru/macro/macrocmd/prop_func/general.html вроде эта функция была в начальном far3 ещё до отбрасывания старой классической макросистемы - может как-нибудь руки дойдут там в старых коммитах подсмотреть.

@shmuz
Copy link
Copy Markdown
Contributor

shmuz commented Mar 28, 2026

Сейчас склоняюсь, что сам вызов callplugin не очень удобен - плагин должен уметь его обрабатывать.

Тут надо рассматривать, пожалуй, не удобство, а предоставляемые возможности.

В API far2 callplugin получает из макроса параметр (целое число или строку) и, таким образом, макрос может запускать разные действия плагина. То, что плагин это должен обрабатывать, это естественно, без труда не вытащишь рыбку...

В API far3/far2m callplugin (который там называется Plugin.Call) получает из макроса произвольное количество параметров произвольных типов и может возвращать произвольное количество величин произвольных типов.

@akruphi akruphi force-pushed the plugins_id branch 2 times, most recently from a6630ec to 43b9788 Compare March 29, 2026 09:26
@shmuz
Copy link
Copy Markdown
Contributor

shmuz commented Mar 31, 2026

@akruphi Вроде плагин Python не получил SysID в этом PR.

@akruphi
Copy link
Copy Markdown
Contributor Author

akruphi commented Apr 1, 2026

@akruphi Вроде плагин Python не получил SysID в этом PR.

Да. Я не стал туда залезать, ибо Python сам по себе не запускается, а запускается каждый из его внутренних подплагинов, которым соответствует свой из ~/.config/far2l/plugins/python/*.py. Т.е. вроде бы навешивать SysID именно на python бессмысленно.

При это в части *.py присутствует ModuleNumber с комментарием # GUID - в некоторых он даже прописан внутри def _OpenPlugin(self, OpenFrom):, но я не понял откуда брать его численное значение, поэтому не проверял через макросы.

@shmuz
Copy link
Copy Markdown
Contributor

shmuz commented Apr 1, 2026

ибо Python сам по себе не запускается, а запускается каждый из его внутренних подплагинов

Сам по себе запускается, после чего зовёт требуемый подплагин.
В отношении SysID плагин Python ничем не отличается от других плагинов.

При незначительной доработке плагина можно организовать вызов подплагинов из макросов, передавая в callplugin строку, соответствующую командной строке, например callplugin(SysID, "ucharmap").

@akruphi
Copy link
Copy Markdown
Contributor Author

akruphi commented Apr 1, 2026

Сам по себе запускается, после чего зовёт требуемый подплагин. В отношении SysID плагин Python ничем не отличается от других плагинов.

При незначительной доработке плагина можно организовать вызов подплагинов из макросов, передавая в callplugin строку, соответствующую командной строке, например callplugin(SysID, "ucharmap").

Спасибо. Подумаю. Какой для python plugin назначен ID в far2m?

Судя по #3173 (comment) автор python далее их развитием активно заниматься не планирует.

@shmuz
Copy link
Copy Markdown
Contributor

shmuz commented Apr 1, 2026

Спасибо. Подумаю.

Поскольку без сотрудничества с автором это ничего не даст, наверное лучше не добавлять. То есть зря я эту тему поднял :(

Какой для python plugin назначен ID в far2m?

0x7E9585C2
И для информации :)
В far3 и far2m идентификатор плагина используется гораздо шире, чем в far2, и не только в макро-API, но и в плагин-API. Если плагин не указал идентификатор или идентификатор нулевой, плагин вообще не загружается.

@akruphi
Copy link
Copy Markdown
Contributor Author

akruphi commented Apr 1, 2026

@shmuz большое спасибо за советы и участие.

Вопрос - из всех добавленных в плагины SysID у двух плагинов inside и multiarc он почему-то не применился (у остальных far:about SysID показывает, а тут нет - значит он нулевой). Буду благодарен за подсказку почему так и надо ли что-то где-то исправлять.

@shmuz
Copy link
Copy Markdown
Contributor

shmuz commented Apr 1, 2026

@akruphi

void PluginA::ConvertPluginInfo(oldfar::PluginInfo &Src, PluginInfo *Dest)
{
	FreePluginInfo();
	PI.StructSize = sizeof(PI);
	PI.Flags = Src.Flags;
+	PI.SysID = Src.SysID;

Now we can call plugins from macros using `callplugin(0xAAAAAAAA)`
which is independent on language and hotkey in Plugin menu via F11.
A pluguin's SysID may see via `far:about` or in plugin's source code.
Be careful: open plugin only from appropriate places.
@akruphi
Copy link
Copy Markdown
Contributor Author

akruphi commented Apr 1, 2026

@shmuz спасибо большое. Оба замечания внес (и SysID у python и PluginA::ConvertPluginInfo) - вроде работает. Может кому в макросах и пригодится.

Логику обработки вызовов в самих плагинах в этом PR далее не трогаю.

@elfmz elfmz merged commit ae4cb34 into elfmz:master Apr 3, 2026
12 checks passed
@akruphi akruphi deleted the plugins_id branch April 3, 2026 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants