Каждый автор так или иначе снабжает свои скрипты метаинформацией, такой как название, описание, версия, автор, тема обсуждения на форуме, и т. п.
Сейчас эта информация может содержаться где угодно: в комментариях, или в каком-то диалоге, или в справке.
Естественно централизовано посмотреть её не получится.
Но раз каждый скрипт в любом случае содержит какую-то метаинформацию, то почему бы не заполнять её стандартизировано?
В результате мы получим возможность управлять скриптами централизованно, и реализовать разные интересные возможности, такие как изложенные ранее: http://forum.farmanager.com/viewtopic.p ... 66#p121966
Представляю экспериментальную реализацию некоторых идей:
Основные понятия:
Скрипт — это lua-файл. Он может содержать макросы или выполнять свои функции иным способом.
Скрипт может иметь вспомогательные файлы (cfg/lng/hlf).
Несколько скриптов могут формировать "пакет".
ScriptsBrowser.lua — утилита для работы со скриптами, запускается из меню плагинов.
main.png (24.01 KiB) Viewed 50079 times
sub-scripts.png (11.08 KiB) Viewed 50079 times
Info.png (20.01 KiB) Viewed 50079 times
help.png (25.7 KiB) Viewed 50079 times
regscript.lua — сам модуль, регистрирующий скрипты.
Должен быть подключен в _macroinit.lua: require"regscript"
Чтобы скрипт был зарегистрирован, он должен содержать примерно такой код:
local Info = Info or package.loaded.regscript or function(...) return ... end --luacheck: ignore 113/Info
local nfo = Info { _filename or ...,
name = "<name>";
id = "<unique id string>";
options = {a=1,b=2};
--etc
}
if not nfo then return nfo end
local O = nfo.options
Первая строка гарантирует что скрипт будет работать и без модуля регистрации. ... не просто троеточие, а выражение vararg, в данном случае позволяющее передать имя текущего файла.
Две последние строки тоже важны:
- проверка результата регистрации скрипта позволяет запретить выполнение (в случае несоответствия minfarversion, или когда его выполнение отключено другим образом)
- хранение собственных опций в таблице позволяет изменять их на лету в интерфейсе ScriptsBrowser а также переопределять их начальные значения (см. описание cfgscript.lua)
Все поля на данный момент опциональны, и их список открыт для обсуждения.
Пока предлагаю следующие:
name = "module: regscript.lua";
description = "collects metadata of luamacro scripts";
version = "0.1.1-alpha"; --в формате semver: http://semver.org/lang/ru/
author = "jd";
url = "http://forum.farmanager.com/viewtopic.php?p=121966#p121966";
id = "15660DC2-AE3F-41EE-8057-DC7428195908";
parent_id = ""; --id родительского скрипта
minfarversion = {3,0,0,4743,0}; --при несоответствии скрипт завершится
files = ""; --вспомогательные файлы скрипта
config = function(nfo,name) end; --функция конфигурации
help = function(nfo,name) end; --функция справки
execute = function(nfo,name) end; --функция исполняемая при запуске из ScriptBrowser
options = {}; --таблица с произвольными опциями скрипта
disabled = false; --запрет выполнения скрипта (см. ниже cfgscript.lua)
files
Задавая в поле files вспомогательные файлы скрипта, можно указывать абсолютный путь или путь относительно скрипта.
Поддерживаются переменные окружения.
Путь к Macros\scripts можно задать как ~\.
Шаблон * позволяет подставить имя скрипта, например files = "*_en.hlf;*_ru.hlf;"
options
Таблица с опциями, с указанием значений по-умолчанию. Смысл таблицы в том, что перечисленные опции можно изменить из браузера, а также переназначить во внешнем файле (см. cfgscript.lua)
функции
При запуске получают два аргумента: таблицу информации, и собственное имя в ней
Кроме того несколько полей зарезервированы для внутреннего использования: index, FileName, error, cfg.
Поле error создаётся в случае когда при загрузке обнаружены некорректные данные.
В том числе проверяются типы значений (добавляются только корректные поля).
cfgscript.lua — вспомогательный модуль, позволяющий переопределить начальные настройки скриптов не трогая их исходный код.
Настройки могут читаться либо из базы luamacro (уже работает, но ещё не реализован интерфейс для их записи), либо из заданного файла.
Чтобы прочитать их из файла, следует в _macroinit.lua поместить следующую команду: require"regscript".cfgload(fullpath)
Если fullpath не задан то используется файл Macros\scripts\scriptscfg.
Формат файла такой:
Параметр id обязателен.
Параметр disabled позволяет "отключить" скрипт.
Параметр options позволяет (пере)определить произвольные начальные опции.
Реальные примеры см. в scriptscfg.sample
cfgscript_test.lua — демонстрационный скрипт для иллюстрации того, что регистрация может быть полезна и в произвольных скриптах
Т.е. регистрировать можно не только макрофайлы из scripts, но и модули из modules, и вообще любые скрипты, например запускаемые из командной строки: lua:cfgscript_test.lua
InsertInfo.lua — вспомогательный макрос для вставки в скрипт шаблона с метаинформацией.
P.S.
Интерфейс самого модуля может быть интересен для применения в макробраузерах.
Сейчас он позволяет получить таблицу скрипта по индексу, по id, или по полному имени файла.
IgorZ wrote: 1. А что, minfarversion нельзя задавать строкой? Почему?
Соответствующие функции работают с таблицей, отсюда и таблица. Синтаксически таблица не сложнее строки, но строку пришлось бы всё равно конвертировать в таблицу, для обеспечения возможности сравнения версий.
Впрочем, если подумать, не очень сильный аргумент..
Если у вас есть доводы в пользу строки, то почему бы и нет.
Но меня тут смущает один момент: исторически в версии фара не используется компонент Revision, что можно увидеть например в заголовке окна фара.
Поэтому не очень понятно, какой должна быть строка.
В текущей неопубликованной версии ScriptManager minfarversion в окне информации отображается так же без Revision, например
IgorZ wrote: Что, пропускать часть позиций нельзя и надо обязательно указывать все пять чисел? Даже если так, всё равно некрасиво - надо перехватывать такие ситуации.
Согласен, падать не должно.
Насчёт 5 или 4 чисел даже не задумывался, не вручную заполняю а шаблоном.
Принимать и 4?
По факту в нашем случае достаточно и одной (билда), и врядли это когда-то изменится
IgorZ wrote: 1. А что, minfarversion нельзя задавать строкой? Почему?
Соответствующии функции работают с таблицей, отсюда и таблица. Синтаксически таблица не сложнее строки, но строку пришлось бы всё равно конвертировать в таблицу, для обеспечения возможности сравнения версий.
Впрочем, если подумать, не очень сильный аргумент..
Если у вас есть доводы в пользу строки, то почему бы и нет.
Соображение одно: версию скрипта можно задавать строкой, а требуемую версию Far - нет. Разные подходы вызывают недоумение. Однообразие было бы эстетически приятнее (кстати, я, вроде бы, ранее предлагал версию скрипта задавать таблицей - тоже вариант единообразия). Собственно, тоже, если подумать, не очень сильный аргумент..
John Doe wrote:Но меня тут смущает один момент: исторически в версии фара не используется компонент Revision, что можно увидеть например в заголовке окна фара.
Поэтому не очень понятно, какой должна быть строка.
В текущей неопубликованной версии ScriptManager minfarversion в окне информации отображается так же без Revision, например
Думаю, в случае версии Far строка должна соответствовать принятому нумерованию версии Far. Оно уже давно устоялось и вряд ли когда изменится.
John Doe wrote:
IgorZ wrote: Что, пропускать часть позиций нельзя и надо обязательно указывать все пять чисел? Даже если так, всё равно некрасиво - надо перехватывать такие ситуации.
Согласен, падать не должно.
Насчёт 5 или 4 чисел даже не задумывался, не вручную заполняю а шаблоном.
Принимать и 4?
А зачем там пятая, если по факту в Far она не используется в принципе? Оставить для совместимости, если надо, только вставить, где нужно, что-то вроде ver[5] = ver[5] or 0.
John Doe wrote:По факту в нашем случае достаточно и одной (билда), и врядли это когда-то изменится
При переходе с Far1 на Far2 счётчик билдов сбросился, а по макросам совместимость осталась. Так что, думаю, на всякий случай, все четыре лучше бы оставить, и, заодно, сверять по всем позициям. Да и смотрится красивее и понятнее, когда есть все четыре числа.
IgorZ wrote: версию скрипта можно задавать строкой, а требуемую версию Far - нет. Разные подходы вызывают недоумение.
Разные подходы тут неизбежны, поскольку semver невозможно в точности сопоставить VersionInfo, хотя бы по причине структурных отличий (куда накладываются ещё и исторические особенности использования в фаре).
IgorZ wrote: и, заодно, сверять по всем позициям.
Думал об этом, но счёл непринципиальным, ведь элементарно изменить в любой момент.
IgorZ wrote: Думаю, в случае версии Far строка должна соответствовать принятому нумерованию версии Far. Оно уже давно устоялось и вряд ли когда изменится.
Я как раз обратил внимание, что в фаре "принято" использовать 3 компонента, а не 4.
Но только для отображения, а в апи у нас да, честный VersionInfo.
Хотите указывать VersionInfo строкой? Если для вас это принципиально, то я не буду возражать.
И насчёт того чтобы компонент Stage принимать по умолчанию за 0 тоже.
Хотя и не вижу от всего этого никакой особой выгоды, ведь всё это вставляется шаблоном.
Делать?
IgorZ wrote: версию скрипта можно задавать строкой, а требуемую версию Far - нет. Разные подходы вызывают недоумение.
Разные подходы тут неизбежны, поскольку semver невозможно в точности сопоставить VersionInfo, хотя бы по причине структурных отличий (куда накладываются ещё и исторические особенности использования в фаре).
Ну, не знаю. Мне глаз царапнуло, я и задал вопрос.
John Doe wrote:
IgorZ wrote: и, заодно, сверять по всем позициям.
Думал об этом, но счёл непринципиальным, ведь элементарно изменить в любой момент.
Так текущий момент ничем не отличается в этом смысле от любого другого.
Возможно, это просто разные привычки. Я когда-то довольно много писал на ассемблере (в том числе игры), так что привычка заранее предусматривать и закрывать возможные дыры осталась с тех времён.
John Doe wrote:
IgorZ wrote: Думаю, в случае версии Far строка должна соответствовать принятому нумерованию версии Far. Оно уже давно устоялось и вряд ли когда изменится.
Я как раз обратил внимание, что в фаре "принято" использовать 3 компонента, а не 4.
Но только для отображения, а в апи у нас да, честный VersionInfo.
Хотите указывать VersionInfo строкой? Если для вас это принципиально, то я не буду возражать.
И насчёт того чтобы компонент Stage принимать по умолчанию за 0 тоже.
Хотя и не вижу от всего этого никакой особой выгоды, ведь всё это вставляется шаблоном.
Делать?
Непринципиально. Более того, версия скрипта, на мой субъективный взгляд, тоже красивее смотрелась бы в виде таблицы. А вот отсутствующие элементы таблицы принимать за 0 было бы, на мой взгляд, разумно.
P. S. Лично я шаблоном при вставке не пользовался. Возможно, из-за того, что вставка nfo для меня пока ещё больше эксперимент, а не вошла в привычку.
IgorZ wrote: Вот. Адрес можно задавать и таблицей, и строкой.
В спецификации пакета достаточно будет строки, имхо.
Но есть другой вопрос: как лучше поступить с LOCAL/GLOBAL?
В моей практике настройки лежат либо только в GLOBAL, либо в обоих базах (в ключе с тем же путём).
Если же делать совсем универсально, то надо указывать полный перечень ключей, с указанием LOCAL/GLOBAL, и этих ключей может быть не 2, а сколько угодно.
Как по мне, то это будет перебор.
Проще всего LOCAL/GLOBAL в спецификации не указывать, что я и предлагаю.
IgorZ wrote: Вот. Адрес можно задавать и таблицей, и строкой.
В спецификации пакета достаточно будет строки, имхо.
Ну не выкидывать же теперь возможность! Вы, коллега, сами же преложили в виде таблицы задавать, а теперь на попятную?
John Doe wrote:Но есть другой вопрос: как лучше поступить с LOCAL/GLOBAL?
В моей практике настройки лежат либо только в GLOBAL, либо в обоих базах (в ключе с тем же путём).
Если же делать совсем универсально, то надо указывать полный перечень ключей, с указанием LOCAL/GLOBAL, и этих ключей может быть не 2, а сколько угодно.
Как по мне, то это будет перебор.
Проще всего LOCAL/GLOBAL в спецификации не указывать, что я и предлагаю.
Неясно, как тогда действовать? Ладно, если данные только в одной базе, можно проверять обе и показывать ту, что есть, а если в обеих? Разве что предусмотреть клавишу "перейти на этот ключ в другой базе"? Кстати, неплохая идея независимо от всего.
Кстати, BookmarkManager хранит данные аж в трёх местах: локальные закладки, глобальные закладки и настройки. И как тут быть? Явно, надо предусмотреть возможность указывать несколько ключей. Как вариант, можно условиться, что несколько адресов задаются таблицей, а один можно и не таблицей с одним элементом, а просто строкой. Самую малость сложнее в обработке, но в тривиальных случаях упрощает заполнение nfo.
Да, для таблицы адреса можно задавать в виде описание=адрес. Думаю, будет наглядно и удобно.
IgorZ wrote: Ну не выкидывать же теперь возможность! ;)
Из dbedit да, конечно не выкидывать.
Но это не значит, что обязательно надо сразу применять именно тут.
IgorZ wrote: Разве что предусмотреть клавишу "перейти на этот ключ в другой базе"?
Именно
IgorZ wrote: Кстати, BookmarkManager хранит данные аж в трёх местах: локальные закладки, глобальные закладки и настройки. И как тут быть?
Зависит от целей.
Если рассматривать эту функцию как возможность менять параметры для простых скриптов, избавляющую их от реализации в каждом случае собственного интерфейса, то для BookmarkManager это вообще не очень актуально.
Но данную функцию можно рассматривать и более широко, как возможность экспорта/импорта/бэкапа.
В этом случае нужен полный перечень ключей.
И раз уж мы о BookmarkManager, то не могли бы вы на его примере проиллюстрировать ваши предложения.
В DBEdit (как впрочем и в других скриптах) заметил использование поля helptxt, которое показалось мне спорным.
Туда попала довольно специфическая информация, вряд ли интересная именно в Scripts Browser, учитывая что по ShiftF1 открывается полноценная справка (hlf).
Т.е. в данном случае это поле либо не стоит применять вообще, либо разместить там общее описание (то что в справке называется "О скрипте").
Также, предлагаю ещё раз взглянуть на поле history.По текущему содержанию вроде бы вопросов нет.
Но ведь лог изменений имеет свойство расти. Стоит ли пихать всё в nfo? (Помимо прочего это ещё и бессмысленный расход памяти).
Лично я бы предпочёл историю отдельным файлом, ссылка на который будет присутствовать в поле files.
John Doe wrote:В DBEdit (как впрочем и в других скриптах) заметил использование поля helptxt, которое показалось мне спорным.
Туда попала довольно специфическая информация, вряд ли интересная именно в Scripts Browser, учитывая что по ShiftF1 открывается полноценная справка (hlf).
Т.е. в данном случае это поле либо не стоит применять вообще, либо разместить там общее описание (то что в справке называется "О скрипте").
Я планировал разместить в этом поле короткую информацию об использовании скрипта на тот гипотетический случай, если файлы справки будут отсутствовать. Но, судя по замечанию, перестарался.
John Doe wrote:Также, предлагаю ещё раз взглянуть на поле history.По текущему содержанию вроде бы вопросов нет.
Но ведь лог изменений имеет свойство расти. Стоит ли пихать всё в nfo? (Помимо прочего это ещё и бессмысленный расход памяти).
Лично я бы предпочёл историю отдельным файлом, ссылка на который будет присутствовать в поле files.
Есть определённые сложности. На файл с историей нет ни писанных, ни исторически сложившихся чётких стандартов имени и расширения. Какие только варианты не встречаются: и changelog, и whatsnew, и history; без расширения, .txt, .язык_истории, .hst,.new... Как разбираться с таким зоопарком - не знаю. Наиболее логичным представляется или вводить отдельное поле для файла истории, или добавить в поле files возможность указывать типы файлов, как я предлагал раньше. Можно было бы, конечно, проигнорировать определение данного типа файла (положившись на то, что пользователь сам догадается, что это, а стандартный просмотр, независимый от типа файла, есть), но мы когда-то говорили о разборе истории в программе и использовании её, в частности, при установке пакетов. Если эти планы ещё живы, правильно было бы реализовывать их поддержку сразу по мере введения соответствующих сущностей.
IgorZ wrote: мы когда-то говорили о разборе истории в программе и использовании её, в частности, при установке пакетов.
Для файлов со стандартизированной структурой определённо понадобится отдельное поле.
Все прочие будучи перечислены в files уже сейчас вроде бы успешно определяются по маске, весь зоопарк.
IgorZ wrote: Если эти планы ещё живы, правильно было бы реализовывать их поддержку сразу по мере введения соответствующих сущностей.
Планы в планах.
Сущности вводить считаю пока преждевременным.
Столкнулся с проблемкой.
В редакторе options есть возможность удалить параметр. Но нет возможности сбросить на "умолчательное" значение (или я не нашёл). Было бы правильным при удалении параметра на самом деле не удалять его (что может привести к неработоспособности скрипта), а вернуть умолчательное значение. Можно, конечно, его вести снова, но надо же помнить имя! Т.е., если случайно удалили и lua не знаю, то до свидания любимы скрипт...
На самом деле я не проверял, возможно, для скрипта значение для удалённого параметра будет браться из текста. Но это не исправляет того факта, что поменять его из ScriptsBrowser-а будет невозможно, пока не заведёшь снова. Надо бы сделать "сброс" (пусть для всех параметров)...