This repository has been archived on 2024-11-13. You can view files and clone it, but cannot push or open issues or pull requests.
fediversity.eu/lib.nix

123 lines
3.4 KiB
Nix

{ lib }:
rec {
/**
Create a URL-safe slug from any string
*/
slug = str:
let
# Replace non-alphanumeric characters with hyphens
replaced = join ""
(
builtins.map
(c:
if (c >= "a" && c <= "z") || (c >= "0" && c <= "9")
then c
else "-"
)
(with lib; stringToCharacters (toLower str)));
# Remove leading and trailing hyphens
trimHyphens = s:
let
matched = builtins.match "(-*)([^-].*[^-]|[^-])(-*)" s;
in
with lib; optionalString (!isNull matched) (builtins.elemAt matched 1);
collapseHyphens = s:
let
result = builtins.replaceStrings [ "--" ] [ "-" ] s;
in
if result == s then s else collapseHyphens result;
in
trimHyphens (collapseHyphens replaced);
join = lib.concatStringsSep;
splitLines = s: with builtins; filter (x: !isList x) (split "\n" s);
indent = prefix: s:
with lib.lists;
let
lines = splitLines s;
in
join "\n" (
[ (head lines) ]
++
(map (x: if x == "" then x else "${prefix}${x}") (tail lines))
);
relativePath = path1': path2':
let
inherit (lib.path) subpath;
inherit (lib) lists;
path1 = subpath.components path1';
path2 = subpath.components path2';
commonPrefixLength = with lists;
findFirstIndex (i: i.fst != i.snd)
{ fst = null; snd = null; }
(zipLists path1 path2);
relativeComponents = with lists;
[ "." ] ++ (replicate (length path1 - commonPrefixLength - 1) "..") ++
(drop commonPrefixLength path2);
in
join "/" relativeComponents;
/**
Recursively list all Nix files from a directory, except the top-level `default.nix`
Useful for module system `imports` from a top-level module.
**/
nixFiles = dir: with lib.fileset;
toList (difference
(fileFilter ({ hasExt, ... }: hasExt "nix") dir)
(dir + "/default.nix")
);
types = rec {
collection = elemType:
let
unparenthesize = class: class == "noun";
desc = type:
types.optionDescriptionPhrase unparenthesize type;
desc' = type:
let
typeDesc = lib.types.optionDescriptionPhrase unparenthesize type;
in
if type.descriptionClass == "noun"
then
typeDesc + "s"
else
"many instances of ${typeDesc}";
in
lib.types.mkOptionType {
name = "collection";
description = "separately specified ${desc elemType} for a collection of ${desc' elemType}";
merge = loc: defs:
map
(def:
let
merged = lib.mergeDefinitions
(loc ++ [ "[definition ${toString def.file}]" ])
elemType
[{ inherit (def) file; value = def.value; }];
in
if merged ? mergedValue then merged.mergedValue else merged.value
)
defs;
check = elemType.check;
getSubOptions = elemType.getSubOptions;
getSubModules = elemType.getSubModules;
substSubModules = m: collection (elemType.substSubModules m);
functor = (lib.defaultFunctor "collection") // {
type = collection;
wrapped = elemType;
payload = { };
};
nestedTypes.elemType = elemType;
};
};
}