mirror of
https://github.com/nix-community/home-manager
synced 2024-11-14 07:09:45 +01:00
senpai: switch to scfg format
This commit is contained in:
parent
211ebad3e7
commit
b316a65c99
15 changed files with 275 additions and 20 deletions
|
@ -99,4 +99,97 @@
|
|||
in attrs: ''
|
||||
${concatStringsSep "\n" (mapAttrsToList convertAttributeToKDL attrs)}
|
||||
'';
|
||||
|
||||
toSCFG = { }:
|
||||
let
|
||||
inherit (lib) concatStringsSep mapAttrsToList any;
|
||||
inherit (builtins) typeOf replaceStrings elem;
|
||||
|
||||
# ListOf String -> String
|
||||
indentStrings = let
|
||||
# Although the input of this function is a list of strings,
|
||||
# the strings themselves *will* contain newlines, so you need
|
||||
# to normalize the list by joining and resplitting them.
|
||||
unlines = lib.splitString "\n";
|
||||
lines = lib.concatStringsSep "\n";
|
||||
indentAll = lines: concatStringsSep "\n" (map (x: " " + x) lines);
|
||||
in stringsWithNewlines: indentAll (unlines (lines stringsWithNewlines));
|
||||
|
||||
# String -> Bool
|
||||
specialChars = s:
|
||||
any (char: elem char (reserved ++ [ " " "'" "{" "}" ]))
|
||||
(lib.stringToCharacters s);
|
||||
|
||||
# String -> String
|
||||
sanitizeString =
|
||||
replaceStrings reserved [ ''\"'' "\\\\" "\\r" "\\n" "\\t" ];
|
||||
|
||||
reserved = [ ''"'' "\\" "\r" "\n" " " ];
|
||||
|
||||
# OneOf [Int Float String Bool] -> String
|
||||
literalValueToString = element:
|
||||
lib.throwIfNot (elem (typeOf element) [ "int" "float" "string" "bool" ])
|
||||
"Cannot convert value of type ${typeOf element} to SCFG literal."
|
||||
(if element == false then
|
||||
"false"
|
||||
else if element == true then
|
||||
"true"
|
||||
else if typeOf element == "string" then
|
||||
if element == "" || specialChars element then
|
||||
''"${sanitizeString element}"''
|
||||
else
|
||||
element
|
||||
else
|
||||
toString element);
|
||||
|
||||
# Bool -> ListOf (OneOf [Int Float String Bool]) -> String
|
||||
toOptParamsString = cond: list:
|
||||
lib.optionalString (cond) (lib.pipe list [
|
||||
(map literalValueToString)
|
||||
(concatStringsSep " ")
|
||||
(s: " " + s)
|
||||
]);
|
||||
|
||||
# Attrset Conversion
|
||||
# String -> AttrsOf Anything -> String
|
||||
convertAttrsToSCFG = name: attrs:
|
||||
let
|
||||
optParamsString = toOptParamsString (attrs ? "_params") attrs._params;
|
||||
in ''
|
||||
${name}${optParamsString} {
|
||||
${indentStrings (convertToAttrsSCFG' attrs)}
|
||||
}'';
|
||||
|
||||
# Attrset Conversion
|
||||
# AttrsOf Anything -> ListOf String
|
||||
convertToAttrsSCFG' = attrs:
|
||||
mapAttrsToList convertAttributeToSCFG
|
||||
(lib.filterAttrs (name: val: !isNull val && name != "_params") attrs);
|
||||
|
||||
# List Conversion
|
||||
# String -> ListOf (OneOf [Int Float String Bool]) -> String
|
||||
convertListOfFlatAttrsToSCFG = name: list:
|
||||
let optParamsString = toOptParamsString (list != [ ]) list;
|
||||
in "${name}${optParamsString}";
|
||||
|
||||
# Combined Conversion
|
||||
# String -> Anything -> String
|
||||
convertAttributeToSCFG = name: value:
|
||||
lib.throwIf (name == "") "Directive must not be empty"
|
||||
(let vType = typeOf value;
|
||||
in if elem vType [ "int" "float" "bool" "string" ] then
|
||||
"${name} ${literalValueToString value}"
|
||||
else if vType == "set" then
|
||||
convertAttrsToSCFG name value
|
||||
else if vType == "list" then
|
||||
convertListOfFlatAttrsToSCFG name value
|
||||
else
|
||||
throw ''
|
||||
Cannot convert type `(${typeOf value})` to SCFG:
|
||||
${name} = ${toString value}
|
||||
'');
|
||||
in attrs:
|
||||
lib.optionalString (attrs != { }) ''
|
||||
${concatStringsSep "\n" (convertToAttrsSCFG' attrs)}
|
||||
'';
|
||||
}
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.senpai;
|
||||
cfgFmt = pkgs.formats.yaml { };
|
||||
let cfg = config.programs.senpai;
|
||||
in {
|
||||
options.programs.senpai = {
|
||||
enable = mkEnableOption "senpai";
|
||||
|
@ -16,23 +14,30 @@ in {
|
|||
};
|
||||
config = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = cfgFmt.type;
|
||||
freeformType = types.attrsOf types.anything;
|
||||
options = {
|
||||
addr = mkOption {
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
The address (host[:port]) of the IRC server. senpai uses TLS
|
||||
connections by default unless you specify no-tls option. TLS
|
||||
connections default to port 6697, plain-text use port 6667.
|
||||
The address (`host[:port]`) of the IRC server. senpai uses TLS
|
||||
connections by default unless you specify tls option to be false.
|
||||
TLS connections default to port 6697, plain-text use port 6667.
|
||||
|
||||
UR`ircs://`, `irc://`, and `irc+insecure://` URLs are supported,
|
||||
in which case only the hostname and port parts will be used. If
|
||||
the scheme is `ircs/irc+insecure`, tls will be overriden and set
|
||||
to true/false accordingly.
|
||||
'';
|
||||
};
|
||||
nick = mkOption {
|
||||
|
||||
nickname = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
Your nickname, sent with a NICK IRC message. It mustn't contain
|
||||
spaces or colons (:).
|
||||
'';
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
@ -41,17 +46,28 @@ in {
|
|||
reside world-readable in the Nix store.
|
||||
'';
|
||||
};
|
||||
no-tls = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Disables TLS encryption.";
|
||||
|
||||
password-cmd = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
default = null;
|
||||
example = [ "gopass" "show" "irc/guest" ];
|
||||
description = ''
|
||||
Alternatively to providing your SASL authentication password
|
||||
directly in plaintext, you can specify a command to be run to
|
||||
fetch the password at runtime. This is useful if you store your
|
||||
passwords in a separate (probably encrypted) file using `gpg` or a
|
||||
command line password manager such as `pass` or `gopass`. If a
|
||||
password-cmd is provided, the value of password will be ignored
|
||||
and the first line of the output of `password-cmd` will be used
|
||||
for login.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
example = literalExpression ''
|
||||
{
|
||||
addr = "libera.chat:6697";
|
||||
nick = "nicholas";
|
||||
address = "libera.chat:6697";
|
||||
nickname = "nicholas";
|
||||
password = "verysecurepassword";
|
||||
}
|
||||
'';
|
||||
|
@ -63,9 +79,27 @@ in {
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = with cfg.config; [
|
||||
{
|
||||
assertion = !isNull password-cmd -> isNull password;
|
||||
message = "senpai: password-cmd overrides password!";
|
||||
}
|
||||
{
|
||||
assertion = !cfg.config ? addr;
|
||||
message = "senpai: addr is deprecated, use address instead";
|
||||
}
|
||||
{
|
||||
assertion = !cfg.config ? nick;
|
||||
message = "senpai: nick is deprecated, use nickname instead";
|
||||
}
|
||||
{
|
||||
assertion = !cfg.config ? no-tls;
|
||||
message = "senpai: no-tls is deprecated, use tls instead";
|
||||
}
|
||||
];
|
||||
home.packages = [ cfg.package ];
|
||||
xdg.configFile."senpai/senpai.yaml".source =
|
||||
cfgFmt.generate "senpai.yaml" cfg.config;
|
||||
xdg.configFile."senpai/senpai.scfg".text =
|
||||
lib.hm.generators.toSCFG { } cfg.config;
|
||||
};
|
||||
|
||||
meta.maintainers = [ hm.maintainers.malvo ];
|
||||
|
|
|
@ -136,6 +136,7 @@ in import nmtSrc {
|
|||
./modules/programs/sapling
|
||||
./modules/programs/sbt
|
||||
./modules/programs/scmpuff
|
||||
./modules/programs/senpai
|
||||
./modules/programs/sftpman
|
||||
./modules/programs/sioyek
|
||||
./modules/programs/sm64ex
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
{ generators-tokdl = ./tokdl.nix; }
|
||||
{
|
||||
generators-tokdl = ./tokdl.nix;
|
||||
generators-toscfg-empty = ./toscfg-empty.nix;
|
||||
generators-toscfg-example = ./toscfg-example.nix;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
home.file."result.txt".text = lib.hm.generators.toKDL { } {
|
||||
home.file."tokdl-result.txt".text = lib.hm.generators.toKDL { } {
|
||||
a = 1;
|
||||
b = "string";
|
||||
c = ''
|
||||
|
@ -47,7 +47,7 @@
|
|||
|
||||
nmt.script = ''
|
||||
assertFileContent \
|
||||
home-files/result.txt \
|
||||
home-files/tokdl-result.txt \
|
||||
${./tokdl-result.txt}
|
||||
'';
|
||||
}
|
||||
|
|
0
tests/lib/generators/toscfg-empty-result.txt
Normal file
0
tests/lib/generators/toscfg-empty-result.txt
Normal file
11
tests/lib/generators/toscfg-empty.nix
Normal file
11
tests/lib/generators/toscfg-empty.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
home.file."toscfg-empty-result.txt".text = lib.hm.generators.toSCFG { } { };
|
||||
|
||||
nmt.script = ''
|
||||
assertFileContent \
|
||||
home-files/toscfg-empty-result.txt \
|
||||
${./toscfg-empty-result.txt}
|
||||
'';
|
||||
}
|
12
tests/lib/generators/toscfg-err-dir-empty-name.nix
Normal file
12
tests/lib/generators/toscfg-err-dir-empty-name.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
home.file."toscfg-err-dir-empty-name-result.txt".text =
|
||||
lib.hm.generators.toSCFG { } { "" = [ ]; };
|
||||
|
||||
nmt.script = ''
|
||||
assertFileContent \
|
||||
home-files/toscfg-err-dir-empty-name-result.txt \
|
||||
${./toscfg-err-dir-empty-name-result.txt}
|
||||
'';
|
||||
}
|
10
tests/lib/generators/toscfg-example-result.txt
Normal file
10
tests/lib/generators/toscfg-example-result.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
dir {
|
||||
blk1 p1 "\"p2\"" {
|
||||
sub1 arg11 arg12
|
||||
sub2 arg21 arg22
|
||||
sub3 arg31 arg32 {
|
||||
sub-sub1
|
||||
sub-sub2 arg321 arg322
|
||||
}
|
||||
}
|
||||
}
|
24
tests/lib/generators/toscfg-example.nix
Normal file
24
tests/lib/generators/toscfg-example.nix
Normal file
|
@ -0,0 +1,24 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
home.file."toscfg-example-result.txt".text = lib.hm.generators.toSCFG { } {
|
||||
dir = {
|
||||
blk1 = {
|
||||
_params = [ "p1" ''"p2"'' ];
|
||||
sub1 = [ "arg11" "arg12" ];
|
||||
sub2 = [ "arg21" "arg22" ];
|
||||
sub3 = {
|
||||
_params = [ "arg31" "arg32" ];
|
||||
sub-sub1 = [ ];
|
||||
sub-sub2 = [ "arg321" "arg322" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileContent \
|
||||
home-files/toscfg-example-result.txt \
|
||||
${./toscfg-example-result.txt}
|
||||
'';
|
||||
}
|
4
tests/modules/programs/senpai/default.nix
Normal file
4
tests/modules/programs/senpai/default.nix
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
senpai-example-settings = ./example-settings.nix;
|
||||
senpai-empty-settings = ./empty-settings.nix;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
address irc.libera.chat
|
||||
nickname Guest123456
|
20
tests/modules/programs/senpai/empty-settings.nix
Normal file
20
tests/modules/programs/senpai/empty-settings.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
programs.senpai = {
|
||||
enable = true;
|
||||
package = config.lib.test.mkStubPackage { };
|
||||
config = {
|
||||
address = "irc.libera.chat";
|
||||
nickname = "Guest123456";
|
||||
};
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileContent \
|
||||
home-files/.config/senpai/senpai.scfg \
|
||||
${./empty-settings-expected.conf}
|
||||
'';
|
||||
};
|
||||
}
|
13
tests/modules/programs/senpai/example-settings-expected.conf
Normal file
13
tests/modules/programs/senpai/example-settings-expected.conf
Normal file
|
@ -0,0 +1,13 @@
|
|||
address irc.libera.chat
|
||||
channel #rahxephon
|
||||
colors {
|
||||
prompt 2
|
||||
}
|
||||
highlight guest senpai lenon
|
||||
nickname Guest123456
|
||||
pane-widths {
|
||||
nicknames 16
|
||||
}
|
||||
password-cmd gopass show irc/guest
|
||||
realname "Guest von Lenon"
|
||||
username senpai
|
27
tests/modules/programs/senpai/example-settings.nix
Normal file
27
tests/modules/programs/senpai/example-settings.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{ config, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
programs.senpai = {
|
||||
enable = true;
|
||||
package = config.lib.test.mkStubPackage { };
|
||||
config = {
|
||||
address = "irc.libera.chat";
|
||||
nickname = "Guest123456";
|
||||
password-cmd = [ "gopass" "show" "irc/guest" ];
|
||||
username = "senpai";
|
||||
realname = "Guest von Lenon";
|
||||
channel = [ "#rahxephon" ];
|
||||
highlight = [ "guest" "senpai" "lenon" ];
|
||||
pane-widths = { nicknames = 16; };
|
||||
colors = { prompt = 2; };
|
||||
};
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileContent \
|
||||
home-files/.config/senpai/senpai.scfg \
|
||||
${./example-settings-expected.conf}
|
||||
'';
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue