-
-
Notifications
You must be signed in to change notification settings - Fork 14k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lib/generators: add RFC42-style libconfig format #208747
Conversation
a2fe50f
to
fb8147a
Compare
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/prs-ready-for-review/3032/1647 |
I'm wondering, wouldn't it be better to write these generators in a generic programming language, converting from the |
@infinisil: I think that is the way forward generally but |
It's just that this adds a whole bunch of code that's slow to evaluate, hard to debug, test and maintain. And yes that's half of nixpkgs already but I don't think it's a good idea to make this worse. Others might review and merge this PR, and I won't interfere with that, but personally I'm gonna abstain from this and focus on cleaner code instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with infinisil, and the semantics are fragile; see comment.
else if isFloat x then | ||
num ind x | ||
else if isString x then | ||
if isNumber x then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't assign meaning without context. Such assumptions are likely to lead to bugs.
"12A" -> "12A"
"12B" -> "12B"
...
"12L" -> 12
This is not how Nix works. Strings are strings. If you want a number, you write a number, or call a function that returns one.
Instead, you could represent these special with special wrappers instead mkOctal
, etc, but do you really need multiple ways to write the same number?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but do you really need multiple ways to write the same number?
Spec says there are a few scalar types and @anund previously said:
~ This [couldn't] currently generate valid config for the example. :(
Other then that mk{Octal|…}
seems reasonable but annoying, future note: make it return just a simple { _type = …; … }
attrset.
I'll get to this Eventually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Playing with https://github.com/PixlOne/logiops/blob/master/logid.example.cfg as an example.
devices = [
{
#<snip> out direct translations
buttons = [
{
cid: (toLibConfig.mkOctal "0xc3");
action =
{
type: "Gestures";
gestures: [
{
direction: "Up";
mode: "OnRelease";
action =
{
type: "Keypress";
keys: (toLibConfig.mkArray ["KEY_UP"]);
};
}
];
};
}
];
}
];
#nesting would also need to work
(toLibConfig.mkArray [(toLibConfig.mkOctal "0x3")]);
Is that the sort of wrappers you have in mind @roberth?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If NixOS/nix#7578 is implemented, the hex and octal numbers won't need any sort of escaping or wrapping. That is, unless the program parsing the config makes decisions based on the syntax used, which would be decimal regardless of what base the module user used to configured the number.
I don't think we have many examples of wrappers yet, but in the module system we generally use a representation that's an attrset with a _type
attribute. For example:
mkOverride = priority: content:
{ _type = "override";
inherit priority content;
};
I don't think we have any examples of formats using this approach. (I kind of expected at least something RFC42-like to use this, so sorry for my brevity earlier)
We could add a general mkUnescape
to lib
, but otherwise I don't know exactly where to put it. Perhaps we could have (formats.foo {}).type
and also (formats.foo {}).lib
?
The meaning of this mkUnescape
is that it would take a string and concatenate it directly into the config file without any processing (except perhaps re-indenting, for some formats). This is in contrast to regular strings, which should be escaped to become strings in the target config language. This means that the string is reinterpreted according to the target configuration language syntax, and this would allow a user to specify any syntax, assuming it's going to be valid in the end. This includes such things as hex: lib.mkUnescape "0xc3"
would do the job.
cc @infinisil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not to say that a formats.libconfig.mkOctal
wouldn't be nice to have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also notice I've mixed up octal and hex in my example(s).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A quick survey: octal is 0o[0-7]+ in python/haskell, 0[0-7]+ in java/c/golang/libconfig. This might be a format that requires a wrapper. (or a pattern of read as octal write as decimal?)
str = ind: x: literal ind ''"${x}"''; | ||
key = ind: x: literal ind "${x}: "; | ||
path = ind: x: literal ind (toString x); | ||
lit = ind: x: literal ind "${x}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be escaped and/or validated, but that would be better to do in a proper program as infinisil suggests.
The type system for libconfig includes types not expressible directly in nix (or json). Lists and Arrays can't be unambiguously selected given a nix list. (a List is close to a nix list, an Array must contain only scalars of the same type). It's unclear if there are consumers of libconfig files that would need to care about a Group vs Array vs List. Expressible numbers include For logiops in particular the usually documented config style includes references to octal number values. Ideally experimenting with packages in Nixos doesn't also come with experimenting with translating config examples. With that context I have trouble interpreting the intention of RFC 42. Something like |
In this PR I poked your patch a bit more to get the behavior closer to what we want. (though I don't remember the specifics very confidently ATM) and perfection is the enemy of good. (no
deferring on @roberth's thread →
Yes and although I'm not sure if these should block this PR I think
This is kind of a wider "found problem" with RFC 42 and I have ran into it before but it's usually been resolved quickly by opening the docs and looking at the example or defaults. (see @#167388)
RFC42 is already widely deployed (search has 51 merged results) and with all of the things I've tried so far this hasn't been that much of a problem? I'm pretty sure neither of us are calibrated just right, but after all of the nixpkgs NixOS modules I've consumed I have yet to touch |
You are right, this work is in the land of compromise. I'm no expert in what's being done in the scope of nix options. Consider the above a mixture of documentation on the mismatch between nix and libconfig and an open ended request for a pattern, any pattern, to use in cases where nix types are insufficient for the target config schema. (I favour a One of the least enjoyable loops in nix happens when grabbing a new package with a nix options example of |
fb8147a
to
28a27cd
Compare
Proceeded by #246115. |
Description of changes
Hey again. I've split out the
libconfig
serializer from #167388 and took the time to acknowledge a few more edge-cases, as well as adding a test and auto-validator.Things done
sandbox = true
set innix.conf
? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)nixos/doc/manual/md-to-db.sh
to update generated release notes