diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/default.nix | 6 | ||||
| -rw-r--r-- | lib/types.nix | 2 | ||||
| -rw-r--r-- | lib/xml.nix | 88 | 
3 files changed, 95 insertions, 1 deletions
| diff --git a/lib/default.nix b/lib/default.nix index 347830e..8ba55b5 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -9,6 +9,7 @@ let      krops = import ../submodules/krops/lib;      shell = import ./shell.nix { inherit lib; };      types = nixpkgs-lib.types // import ./types.nix { inherit lib; }; +    xml = import ./xml.nix { inherit lib; };      eq = x: y: x == y;      ne = x: y: x != y; @@ -145,6 +146,11 @@ let      in        filter (x: x != []) ([acc.chunk] ++ acc.chunks); +    warnOldVersion = oldName: newName: +      if compareVersions oldName newName != -1 then +        trace "Upstream `${oldName}' gets overridden by `${newName}'." newName +      else +        newName;    };  in diff --git a/lib/types.nix b/lib/types.nix index 17c1688..45c0098 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -539,7 +539,7 @@ rec {    # POSIX.1‐2013, 3.278 Portable Filename Character Set    filename = mkOptionType {      name = "POSIX filename"; -    check = test "([0-9A-Za-z._])[0-9A-Za-z._-]*"; +    check = test "[0-9A-Za-z._][0-9A-Za-z._-]*";      merge = mergeOneOption;    }; diff --git a/lib/xml.nix b/lib/xml.nix new file mode 100644 index 0000000..1605244 --- /dev/null +++ b/lib/xml.nix @@ -0,0 +1,88 @@ +{ lib }: +with lib; +with builtins; +rec { + +  # Use `term` to construct XML. +  # +  # Examples: +  # +  #   (term "bool" null null) +  #   (term "cool" null []) +  #   (term "fool" { hurr = "durr"; } null) +  #   (term "hool" null [ +  #     (term "tool" null null) +  #   ]) +  # +  # See `render` for how these get transformed into actuall XML documents. +  # +  term = name: attrs: content: { +    inherit name attrs content; +  }; + +  empty = term null null null; + +  # Ref http://www.w3.org/TR/xml/#syntax +  # +  # Example: +  # +  #   (quote "<cheez!>")                 #===>   <cheez!> +  # +  quote = let +    sub = { +      "&" = "&"; +      "<" = "<"; +      ">" = ">"; +      "'" = "'"; +      "\"" = """; +    }; +  in +    stringAsChars (c: sub.${c} or c); + +  # Turn an XML element to an XML document string. +  doc = t: +    "<?xml version='1.0' encoding='UTF-8'?>${render t}"; + +  # Render an XML element to a string. +  # +  # Rendering `empty` yields the empty string. +  # +  # Examples: +  # +  #   (term "bool" null null)                 #===>   <bool/> +  #   (term "cool" null [])                   #===>   <cool></cool> +  #   (term "fool" { hurr = "durr"; } null)   #===>   <fool hurr="durr"/> +  #   (term "hool" null [ +  #     (term "tool" null null) +  #   ])                                      #===>   <hool><tool/></hool> +  # +  render = let +    render-attrs = attrs: +      getAttr (typeOf attrs) { +        null = ""; +        set = concatStrings (mapAttrsToList (n: v: " ${n}=\"${v}\"") attrs); +      }; + +    render-content = content: +      getAttr (typeOf content) { +        bool = toJSON content; +        int = toJSON content; +        list = concatMapStrings render content; +        string = quote content; +      }; +  in +    { name, attrs, content }: +    # XXX we're currently encoding too much information with `null`.. +    if name == null +      then +        if content == null +          then "" +          else content +      else let +        attrs' = render-attrs attrs; +        content' = render-content content; +      in +        if content == null +          then "<${name}${attrs'}/>" +          else "<${name}${attrs'}>${content'}</${name}>"; +} | 
