Commit 61311665 authored by Profpatsch's avatar Profpatsch
Browse files

lib: add ini configuration generator

Many configurations are INI-style files. Attribute sets can be mapped
rather painlessly to the INI format.
This adds a function toINI inside a new generators library section.
Also, unit tests for the default values are provided.
parent ba73dbbd
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ let

  # misc
  debug = import ./debug.nix;
  generators = import ./generators.nix;
  misc = import ./deprecated.nix;

  # domain-specific
@@ -39,7 +40,7 @@ in
            customisation maintainers meta sources
            modules options types
            licenses platforms systems
            debug misc
            debug generators misc
            sandbox fetchers;
  }
  # !!! don't include everything at top-level; perhaps only the most

lib/generators.nix

0 → 100644
+53 −0
Original line number Diff line number Diff line
/* Functions that generate widespread config file
 * formats from nix data structures.
 * Tests can be found in ./tests.nix
 */
with import ./trivial.nix;
let
  libStr = import ./strings.nix;
  libAttr = import ./attrsets.nix;

  flipMapAttrs = flip libAttr.mapAttrs;
in

{

  /* Generates an INI-style config file from an
   * attrset of sections to an attrset of key-value pairs.
   *
   * generators.toINI {} {
   *   foo = { hi = "${pkgs.hello}"; ciao = "bar"; };
   *   baz = { "also, integers" = 42; };
   * }
   *
   *> [baz]
   *> also, integers=42
   *>
   *> [foo]
   *> ciao=bar
   *> hi=/nix/store/y93qql1p5ggfnaqjjqhxcw0vqw95rlz0-hello-2.10
   *
   * The mk* configuration attributes can generically change
   * the way sections and key-value strings are generated.
   *
   * For more examples see the test cases in ./tests.nix.
   */
  toINI = {
    # apply transformations (e.g. escapes) to section names
    mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
    # format a setting line from key and value
    mkKeyValue    ? (k: v: "${libStr.escape ["="] k}=${toString v}")
  }: attrsOfAttrs:
    let
        # map function to string for each key val
        mapAttrsToStringsSep = sep: mapFn: attrs:
          libStr.concatStringsSep sep
            (libAttr.mapAttrsToList mapFn attrs);
        mkLine = k: v: mkKeyValue k v + "\n";
        mkSection = sectName: sectValues: ''
          [${mkSectionName sectName}]
        '' + libStr.concatStrings (libAttr.mapAttrsToList mkLine sectValues);
    in
      # map input to ini sections
      mapAttrsToStringsSep "\n" mkSection attrsOfAttrs;
}
+51 −0
Original line number Diff line number Diff line
@@ -130,4 +130,55 @@ runTests {
    expected = false;
  };


  /* Generator tests */
  # these tests assume attributes are converted to lists
  # in alphabetical order

  testToINIEmpty = {
    expr = generators.toINI {} {};
    expected = "";
  };

  testToINIEmptySection = {
    expr = generators.toINI {} { foo = {}; bar = {}; };
    expected = ''
      [bar]

      [foo]
    '';
  };

  testToINIDefaultEscapes = {
    expr = generators.toINI {} {
      "no [ and ] allowed unescaped" = {
        "and also no = in keys" = 42;
      };
    };
    expected = ''
      [no \[ and \] allowed unescaped]
      and also no \= in keys=42
    '';
  };

  testToINIDefaultFull = {
    expr = generators.toINI {} {
      "section 1" = {
        attribute1 = 5;
        x = "Me-se JarJar Binx";
      };
      "foo[]" = {
        "he\\h=he" = "this is okay";
      };
    };
    expected = ''
      [foo\[\]]
      he\h\=he=this is okay

      [section 1]
      attribute1=5
      x=Me-se JarJar Binx
    '';
  };

}