166 lines
5.7 KiB
Nix
166 lines
5.7 KiB
Nix
{ debug, integer, list, path, string, type, ... }:
|
|
let
|
|
Item
|
|
= (
|
|
type.enum "Item"
|
|
{
|
|
Attribute = string;
|
|
Index = integer;
|
|
File = string;
|
|
Root = string;
|
|
}
|
|
)
|
|
// {
|
|
format
|
|
= self:
|
|
Item.match self
|
|
{
|
|
Attribute = { value, ... }: ".${string.escapeKey value}";
|
|
File = { value, ... }: "@(${value})";
|
|
Index = { value, ... }: "[${integer.toString value}]";
|
|
Root = { value, ... }: "<${value}>";
|
|
};
|
|
format'
|
|
= self:
|
|
Item.match self
|
|
{
|
|
Attribute = { value, ... }: ".${string.escapeKey value}";
|
|
File = { value, ... }: "";
|
|
Index = { value, ... }: "[${integer.toString value}]";
|
|
Root = { value, ... }: "<${value}>";
|
|
};
|
|
};
|
|
|
|
Context
|
|
= type "Context"
|
|
{
|
|
inherit from;
|
|
__public__ = [ ];
|
|
};
|
|
|
|
getFileName
|
|
= fileName:
|
|
let
|
|
ext
|
|
= string.slice
|
|
((string.length fileName') - extLength)
|
|
extLength
|
|
fileName';
|
|
extLength = 4;
|
|
fileName' = string.toString fileName;
|
|
in
|
|
if ext == ".nix" then fileName'
|
|
else "${fileName'}/default.nix";
|
|
|
|
extend
|
|
= let
|
|
addAttribute
|
|
= { absolute, relative, ... } @ self:
|
|
attribute:
|
|
self
|
|
// {
|
|
absolute = absolute ++ [ (Item.Attribute attribute) ];
|
|
relative = relative ++ [ (Item.Attribute attribute) ];
|
|
};
|
|
|
|
addFile
|
|
= { absolute, relative, ... } @ self:
|
|
fileName:
|
|
let
|
|
fileName' = getFileName fileName;
|
|
in
|
|
self
|
|
// {
|
|
absolute = absolute ++ [ (Item.File fileName') ];
|
|
fileName = fileName';
|
|
relative = [ (Item.File fileName') ];
|
|
};
|
|
|
|
addIndex
|
|
= { absolute, relative, ... } @ self:
|
|
index:
|
|
self
|
|
// {
|
|
absolute = absolute ++ [ (Item.Index index) ];
|
|
relative = relative ++ [ (Item.Index index) ];
|
|
};
|
|
|
|
extendWith
|
|
= { ... } @ self:
|
|
{
|
|
attribute ? null,
|
|
fileName ? null,
|
|
index ? null,
|
|
}:
|
|
let
|
|
self'
|
|
= if attribute != null
|
|
then
|
|
addAttribute self attribute
|
|
else
|
|
self;
|
|
self''
|
|
= if index != null
|
|
then
|
|
addIndex self' index
|
|
else
|
|
self';
|
|
in
|
|
if fileName != null
|
|
then
|
|
addFile self'' fileName
|
|
else
|
|
self'';
|
|
in
|
|
{ ... } @ self:
|
|
source:
|
|
if Context.isInstanceOf source
|
|
then
|
|
source
|
|
else
|
|
type.matchPrimitiveOrPanic source
|
|
{
|
|
int = addIndex self source;
|
|
list = list.fold extend self source;
|
|
path = addFile self source;
|
|
set = extendWith self source;
|
|
string = addAttribute self source;
|
|
};
|
|
|
|
format = string.concatMapped Item.format;
|
|
format' = string.concatMapped Item.format';
|
|
formatAbsolute = { absolute, ... }: format absolute;
|
|
formatAbsolute' = { absolute, ... }: format' absolute;
|
|
formatFileName = { fileName, ... }: string.toString fileName;
|
|
formatRelative = { relative, ... }: format relative;
|
|
formatRelative' = { relative, ... }: "$${format' relative}";
|
|
|
|
from
|
|
= root:
|
|
Context.instanciate
|
|
{
|
|
absolute = [ (Item.Root (toRoot root)) ];
|
|
fileName
|
|
= if path.isInstanceOf root
|
|
then
|
|
root
|
|
else
|
|
"$";
|
|
relative = [ (Item.Root (toRoot root)) ];
|
|
__functor = extend;
|
|
__toString = formatAbsolute;
|
|
};
|
|
|
|
toRoot
|
|
= root:
|
|
type.matchPrimitiveOrPanic root
|
|
{
|
|
path = getFileName root;
|
|
string = root;
|
|
};
|
|
in
|
|
Context
|
|
// {
|
|
inherit formatAbsolute formatAbsolute' formatFileName formatRelative formatRelative';
|
|
}
|