I dislike having code in a string as it disables editor LSP. I am setting up my Firefox config and have found that the convention for its settings is kinda weird:
settings = {
# Visuals
"browser.download.autohideButton" = true;
"browser.toolbars.bookmarks.visibility" = "tab";
"browser.urlbar.suggest.bookmark" = false;
"browser.urlbar.suggest.engines" = false;
"browser.urlbar.suggest.history" = false;
"browser.urlbar.suggest.openpage" = false;
"browser.urlbar.suggest.topsites" = false;
"browser.urlbar.trimHttps" = true;
"browser.compactmode.show" = true;
"browser.uidensity" = 1;
};
I’d far rather use nix syntax:
browser = {
download.autohideButton = true;
toolbars.bookmarks.visibility = "tab";
urlbar = {
trimHttps = true;
suggest = {
bookmark = false;
engines = false;
history = false;
openpage = false;
topsites = false;
};
};
compactmode.show = true;
uidensity = 1;
};
I couldn’t find any references online of people trying it, so after many hours of learning nix syntax and lib functions I came up with this:
flatten =
set:
let
recurse =
path:
lib.concatMapAttrs (
name: value:
if builtins.isAttrs value then
recurse (path ++ [ name ]) value
else
{ ${builtins.concatStringsSep "." (path ++ [ name ])} = value; }
);
in
recurse [ ] set;
This flattens a set into name value pairs with the path transformed into a string as the name.
nix-repl> example = { lvl1 = { lvl2 = true; lvl2uwu = "meow"; lvltwo = { lvl3 = "running out of names";};}; lvlone = "1337";}
nix-repl> flatten example
{
"lvl1.lvl2" = true;
"lvl1.lvl2uwu" = "meow";
"lvl1.lvltwo.lvl3" = "running out of names";
lvlone = "1337"; # Yes I know this name isnt a string but it works anyway and it took me hours to get this far
}
It is a modified version of mapAttrsRecursiveCond and while it’s okay, I think, I wanted to know if there is a better way of doing it?
The Home Manager documentation states
‹name› only supports int, bool, and string types for preferences, but home-manager will automatically convert all other JSON-compatible values into strings.
but trying to read the official documentation is unironically blank, so I am struggling to understand the link between JSON and Nix. This dot separated path in a string JSON syntax is not something I have come across so I am rather stumped.
And before anyone calls me out on it, yes, I know you can put nix formatted preferences directly into settings, but it turns the user.js into this unreadable mess. Am I being pedantic? Maybe, but I’m a nix user
user_pref("browser", "{\"compactmode\":{\"show\":true},\"download\":{\"autohideButton\":true},\"toolbars\":{\"bookmarks\":{\"visibility\":\"tab\"}},\"uidensity\":1,\"urlbar\":{\"suggest\":{\"bookmark\":false,\"engines\":false,\"history\":false,\"openpage\":false,\"topsites\":false},\"trimHttps\":true}}");