How to create generic yaml/toml/ini files?

Hello to everyone

I would like to create my dotfiles in a declarative way. Unfortunately I can’t find the right solution for me. I know that there are several modules for home managers (e.g. Alacritty), which are intended for this. But I would need something “general”. Here as an example for Home-Manager, how I imagine it:

{ config, pkgs, ... }:

{

  home.file = {

    ".config/mysetup/file.yml".toYaml = {
      settings = {
        draw_bold_text_with_bright_colors = true;
        dynamic_title = true;
        live_config_reload = true;
        window.dimensions = {
          columns = 0;
          lines = 0;
        };
        scrolling = {
          history = 10000;
          multiplier = 3;
        };
      };
    };

  };

}

This would create the following file for me:

---
draw_bold_text_with_bright_colors: true
live_config_reload: true
dynamic_padding: true
window.dimensions:
  columns: 0
  lines: 0
scrolling:
  history: 10000
  multiplier: 3

Files I would have to create are mostly: yaml, ini or toml.

Is there a generic solution for this?

Thanks!

1 Like

use this as a “…”.source

(pkgs.formats.yaml { }).generate "something" {
  settings = {
    draw_bold_text_with_bright_colors = true;
    dynamic_title = true;
    live_config_reload = true;
    window.dimensions = {
      columns = 0;
      lines = 0;
    };
    scrolling = {
      history = 10000;
      multiplier = 3;
    };
  };
}

there’a also lib versions which do not create files

  xdg.configFile."wob/wob.ini".text = lib.generators.toINIWithGlobalSection { } {
    globalSection = {
      background_color = "1d202199";
      border_color = "3c3836FF";
      bar_color = "458588FF";
    };
    sections = { };
  };
2 Likes

Thank you very much. Would you have an example for home-manager? I use home-manager standalone on Arch Linux.

xdg.configFile."some/config.yaml".source = (pkgs.formats.yaml { }).generate "something" {
  settings = {
    draw_bold_text_with_bright_colors = true;
    dynamic_title = true;
    live_config_reload = true;
    window.dimensions = {
      columns = 0;
      lines = 0;
    };
    scrolling = {
      history = 10000;
      multiplier = 3;
    };
  };
};
1 Like

Perfect! Thanks @Artturin

@Artturin
Is it possible to add a comment block too the Yaml file?

You can add comments inside nix by prefixing them with #:

    live_config_reload = true;
    # comment
    window.dimensions = {
      columns = 0;
      lines = 0;
    };

but these will not show up in the final yaml file. You could instead provide the yaml source verbatim:

xdg.configFile."some/config.yaml".text = ''
  settings:
    draw_bold_text_with_bright_colors: true
    dynamic_title: true
    live_config_reload: true
    # comment
    window:
      dimensions:
        columns: 0
        lines: 0
    scrolling:
      history: 10000
      multiplier: 3
'';

Though I honestly wouldn’t recommend this. Another option is to use string names for fields:

xdg.configFile."some/config.yaml".source = (pkgs.formats.yaml { }).generate "something" {
  settings = {
    draw_bold_text_with_bright_colors = true;
    dynamic_title = true;
    live_config_reload = true;
    "#comment1" = "This is a comment!";
    window.dimensions = {
      columns = 0;
      lines = 0;
    };
    scrolling = {
      history = 10000;
      multiplier = 3;
    };
  };
};

Though depending on the tool you’re configuring here, this might throw an error like “unknown field” or “disallowed name” or so.

1 Like

@iFreilicht

String names for fields didn’t work:

  xdg.configFile."alacritty/new_alacritty.yml".source = (pkgs.formats.yaml { }).generate "alacritty-config" {
    colors = {
      normal = {
        black = "0x2e3436";
        "#test" = "test123";
      };
    };
  };
colors:
  normal:
    '#test': test123
    black: '0x2e3436'

Sometimes I need the --- i the first line of a YAML file. Any other ideas?
Thanks!

Depends on your definition of “working”, I guess. I commonly used this to add comments to JSON files if the parser didn’t allow them, but yeah, it’s not ideal.

If you only need the text in the first few lines, you could do it like this:

xdg.configFile."alacritty/new_alacritty.yml".source = (pkgs.concatText "alacritty-config" 
  [ 
    (builtins.toFile "comment-block"
      ''
        --- yaml comment block
      ''
    ) 
    ((pkgs.formats.yaml {}).generate "data-block"
      {
        colors = {
          normal = {
            black = "0x2e3436";
            "#test" = "test123";
          };
        };
      }) 
  ]);

Which is a little verbose, but gets the job done. You can put this into its own function to make it nicer to use:

yamlWithLeadingComment = comment: attrs: (pkgs.concatText "yaml-with-leading-comment" [ (builtins.toFile "comment-block" comment) ((pkgs.formats.yaml {}).generate "data-block" attrs) ])
xdg.configFile."alacritty/new_alacritty.yml".source = yamlWithLeadingComment
  ''
     --- yaml comment block
  ''
  {
    colors = {
      normal = {
        black = "0x2e3436";
        "#test" = "test123";
      };
    };
  };

BTW, the reason this is so annoyingly complicated with yaml is that the yaml formatter actually uses builtins.toJSON first, and then runs the tool json2yaml in a command line environment, so the result must be a file in the nix store, not just a string. If there were a builtins.toYAML, it would be as simple as:

xdg.configFile."alacritty/new_alacritty.json".source = 
  ''
    --- Leading comment
  '' + builtins.toYAML {
    colors = {
      normal = {
        black = "0x2e3436";
        "#test" = "test123";
      };
    };
  };

@iFreilicht

This gives me the following error:

error:
       … while evaluating the attribute 'activationPackage'

         at /nix/store/pxj5ql0c5597pjz35vyz16hizljm7jk7-home-manager/home-manager/modules/default.nix:54:3:

           53|
           54|   activationPackage = module.config.home.activationPackage;
             |   ^
           55|

       … while evaluating a branch condition

         at /nix/store/7vg7bb78m45bp0lx0hrlbx1l5m71n1s6-nixpkgs/nixpkgs/lib/lists.nix:57:9:

           56|       fold' = n:
           57|         if n == len
             |         ^
           58|         then nul

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: syntax error, unexpected '}', expecting ')'

       at /home/xxx/.config/home-manager/alacritty.nix:31:1:

           30|
           31| }
             | ^
           32|

Unfortunately I am still a beginner with Nix.

Oh whoops, sorry, in the last line I missed the final ) when copying. I updated my comment, can you try again?

Unfortunately no it still does not work:

~ » home-manager switch                                                                                                                                         1
error:
       … while evaluating the attribute 'activationPackage'

         at /nix/store/pxj5ql0c5597pjz35vyz16hizljm7jk7-home-manager/home-manager/modules/default.nix:54:3:

           53|
           54|   activationPackage = module.config.home.activationPackage;
             |   ^
           55|

       … while evaluating a branch condition

         at /nix/store/7vg7bb78m45bp0lx0hrlbx1l5m71n1s6-nixpkgs/nixpkgs/lib/lists.nix:57:9:

           56|       fold' = n:
           57|         if n == len
             |         ^
           58|         then nul

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: syntax error, unexpected '}', expecting ';'

       at /home/xxx/.config/home-manager/alacritty.nix:31:1:

           30|
           31| }
             | ^
           32|

Ok wow I also forgot the final semicolon :sweat_smile: I updated it again, but this time I actually tested it inside the repl, and it worked fine. If you get the same error again, please post the part of your file where you’ve pasted my code, including a few lines before and a few lines after it.

Merci! Thank you @iFreilicht :slight_smile: