Введение в опции Denix
Опции Denix представляют собой обёртку для lib.mkOption. Это означает, что любую опцию Denix можно создать, используя стандартный lib.mkOption, и использование опций Denix является необязательным.
Зачем использовать опции Denix?
Использование lib.mkOption может быть громоздким, и каждый раз писать что-то вроде:
nix
lib.mkOption {type = lib.types.listOf lib.types.str; default = [];}- неудобно, особенно когда опции в вашей конфигурации используются повсеместно. Вместо этого можно написать более лаконично:
nix
delib.listOfOption delib.str []Таким образом, вместо создания опции через указание всех параметров, можно использовать функции Denix для более читабельного и аккуратного кода.
Принцип работы
Функции, связанные с опциями, делятся на четыре основных типа:
Создание опции с типом N
*Option <default>- например,strOption "foo".*OfOption <secondType> <default>- например,listOfOption str ["foo" "bar"].*ToOption <secondType> <default>- например,lambdaToOption int (x: 123).
Добавление к типам опции X тип N
allow* <option>- например,allowStr ....allow*Of <secondType> <option>- например,allowListOf str ....allow*To <secondType> <option>- например,allowLambdaTo int ....
Прямое изменение attribute set опции
noDefault <option>- удаляет атрибутdefaultиз опции. Используется редко, так как редко бывают опции без значения по умолчанию.noNullDefault <option>- удаляет атрибутdefaultиз опции, если его значение равноnull. Используется для логики значений по умолчанию, где допускается их отсутствие.readOnly <option>- добавляет атрибутreadOnlyсо значениемtrue.apply <option> <apply>- добавляет атрибутapplyс переданным значением.description <option> <description>- добавляет атрибутdescriptionс переданным значением.
Генерация конкретной опции/опций
singleEnableOption <default> { name, ... }- создаёт attribute set с помощью выраженияdelib.setAttrByStrPath "${name}.enable" (boolOption default). Обычно это используется вdelib.module :: options, с её передаваемыми аргументами, поэтому достаточно написать:
nix
options = delib.singleEnableOption <default>;singleCascadeEnableOption { parent, ... }- создаёт attribute set с помощьюsingleEnableOptionвыше, но используетparent.enableдля<default>. Пример:
nix
# если имя (name) текущего модуля это "programs.category.example",
# то он будет включен по умолчанию если "programs.category" включен.
# будет ошибка, если "programs.category.enable" не существует.
options = delib.singleCascadeEnableOption;moduleOptions <opts> <args>- создаёт attribute set с<opts>для пути текущего модуля. Обычно, необходимо использоватьnameещё раз, чтобы обозначить опции, но эта функция делает это автоматически.<args>это набор передаваемых аргументов. Если<opts>это функция, тогда<args>является её аргументом. Пример:
nix
# имя текущего модуля это "programs.category.example".
# если не хватает `singleEnableOption`:
options = with delib; moduleOptions {
enable = boolOption true;
device = strOption "desktop";
};
# блок опций выше эквивалентен блоку ниже:
options.programs.category.example = with delib; {
enable = boolOption true;
device = strOption "desktop";
};
# а если не хватает `singleCascadeEnableOption`:
options = with delib; moduleOptions ({ parent, ... }: {
enable = boolOption parent.enable;
device = strOption "desktop";
}); # обратите внимание на скобки
# снова, блок опций выше эквивалентен блоку ниже:
options = with delib; { parent, ... }: {
programs.category.example = {
enable = boolOption parent.enable;
device = strOption "desktop";
};
};Список актуальных опций можно найти в исходном коде: github:yunfachi/denix?path=lib/options.nix
Примеры
| Denix | lib.mkOption |
|---|---|
portOption 22 | mkOption {type = types.port; default = 22;} |
noDefault (portOption null) | mkOption {type = types.port;} |
noNullDefault (if myconfig.server.enable then "127.0.0.1:4533" else null) | mkOption {type = types.str;} // (if myconfig.server.enable then {default = "127.0.0.1:4533";} else {}) |
allowNull (portOption null) | mkOption {type = types.nullOr types.port; default = null;} |
allowStr (portOption "22") | mkOption {type = types.strOr types.port; default = "22";} |
listOfOption port [] | mkOption {type = types.listOf types.port; default = [];} |
readOnly (noDefault (portOption null)) | mkOption {type = types.port; readOnly = true;} |
singleEnableOption true {name = "git";} | git.enable = mkEnableOption "git" // {default = true;} |
(Обычно
{name = "git";}указывать не требуется, так как эта функция в основном используется вdelib.module :: options)