Way to get code for options?

hi there,

when trying to port one’s setup for a given program to nix, a common task seems to be checking the available options, then putting those into nix code, configuring desired values.

i was wondering, has anyone maybe made a way to get generated nix code based on the available default/example values (if not also option descriptions)?

e.g. given an option programs.firefox.enable:

# Whether to enable the Firefox web browser.
programs.firefox.enable = false;
# programs.firefox.enable = true;

… except ideally for an entire option group (e.g. programs.firefox) at a time, ideally recursively.

Not to my knowledge, but this sounds like an LSP feature idea.

Both nil and nixd will already allow you to auto-complete NixOS options, though, and even give you some documentation, which feels like it fits a similar niche.

You can kinda do it in the repl, though it is very messy
For example:

nix-repl> :b with lib; inputs.nixpkgs.legacyPackages.x86_64-linux.writeText "test" (concatStringsSep "\n" (collect isString (mapAttrsRecursiveCond (x: !((isAttrs x) && (x ? "_type") && (x._type == "option"))) (p: x: concatStringsSep "\n" ["/* ${x.description} */" "${concatStringsSep "." (["programs" "firefox"] ++ map toString p)} = ${builtins.toJSON x.default}"]) nixosConfigurations.desktop.options.programs.firefox)))
This derivation produced the following outputs:
  out -> /nix/store/zxlplabbjx04x90l9pnhkx9hcabvkxsj-test

This is a snippet from the generated file:

/* AutoConfig files can be used to set and lock preferences that are not covered
by the policies.json for Mac and Linux. This method can be used to automatically
change user preferences or prevent the end user from modifiying specific
preferences by locking them. More info can be found in https://support.mozilla.org/en-US/kb/customizing-firefox-using-autoconfig.
 */
programs.firefox.autoConfig = ""
/* Whether to enable the Firefox web browser. */
programs.firefox.enable = false
/* The language packs to install.
 */
programs.firefox.languagePacks = []
/* Whether to enable Browserpass support. */
programs.firefox.nativeMessagingHosts.browserpass = false
/* Whether to enable Bukubrow support. */
programs.firefox.nativeMessagingHosts.bukubrow = false
/* Whether to enable Web eID support. */
programs.firefox.nativeMessagingHosts.euwebid = false
/* Whether to enable ff2mpv support. */
programs.firefox.nativeMessagingHosts.ff2mpv = false
/* Whether to enable fx_cast support. */
programs.firefox.nativeMessagingHosts.fxCast = false
/* Whether to enable GSConnect support. */
programs.firefox.nativeMessagingHosts.gsconnect = false
/* Whether to enable JabRef support. */
programs.firefox.nativeMessagingHosts.jabref = false

Edit: a slightly cleaner version:

let
        genOpts = with nixpkgs.lib; opts: path: (
                concatStringsSep
                        "\n"
                        (collect
                                isString
                                (mapAttrsRecursiveCond
                                        (x: !((isAttrs x) && (x ? "_type") && (x._type == "option")))
                                        (p: x: concatStringsSep "\n" [
                                                "/* ${x.description} */"
                                                "${concatStringsSep "." (path ++ map toString p)} = ${builtins.toJSON x.default}"
                                        ])
                                        (attrByPath path {} opts)
                                )
                        )
        );
in genOpts nixosConfigurations.desktop.options ["programs" "firefox"]

@TLATER thanks, i posted over at nixd.

@illustris that looks cool! if i might ask, how did you open the shell with the right variable scopes (nixpkgs / inputs / nixosConfigurations)?

In the above example, I used an existing nixos configuration from a flake. That’s the nixosConfigurations.desktop.options in the last line. You can also just define an ad-hoc nixos system to do the same thing:

nix-repl> :lf nixpkgs
Added 15 variables.

nix-repl> minimalNixos = lib.nixosSystem {system = "x86_64-linux"; modules = [];}

nix-repl> genOpts = with lib; opts: path: (
            concatStringsSep
              "\n"
              (collect
                isString
                (mapAttrsRecursiveCond
                  (x: !((isAttrs x) && (x ? "_type") && (x._type == "option")))
                  (p: x: concatStringsSep "\n" [
                    "/* ${x.description} */"
                    "${concatStringsSep "." (path ++ map toString p)} = ${builtins.toJSON x.default}"
                  ])
                  (attrByPath path {} opts)
                )
              )
            )

nix-repl> genOpts minimalNixos.options ["programs" "firefox"]
"/* AutoConfig files can be...
1 Like