91 lines
3.2 KiB
Nix
91 lines
3.2 KiB
Nix
{ debug, list, string, type, ... }:
|
|
let
|
|
Indentation
|
|
= type.enum "Indentation"
|
|
{
|
|
less = null;
|
|
more = null;
|
|
};
|
|
in
|
|
{
|
|
inherit(Indentation) less more;
|
|
|
|
# string -> string | [ string | bool | null ] -> string
|
|
__functor#: self -> string | [ string | Indentation | null ] -> string
|
|
= self:
|
|
{ initial ? "", tab ? " ", ... }:
|
|
body:
|
|
(
|
|
list.fold
|
|
(
|
|
# S -> null | string | bool -> S
|
|
# where S: { depth: uint, indent: string, result: string }
|
|
{ cache, depth, indent, lineNumber, result, tab } @ state:
|
|
line:
|
|
type.matchPrimitiveOrPanic line
|
|
{
|
|
null = state;
|
|
string
|
|
= state
|
|
// {
|
|
lineNumber = lineNumber + 1;
|
|
result = "${result}${indent}${line}\n";
|
|
};
|
|
set
|
|
= state
|
|
// (
|
|
if Indentation.isInstanceOf line
|
|
then
|
|
Indentation.match line
|
|
{
|
|
more
|
|
= let
|
|
depth' = depth + 1;
|
|
cache'
|
|
= if list.length cache <= depth'
|
|
then
|
|
cache ++ [ "${list.foot cache}${tab}" ]
|
|
else
|
|
cache;
|
|
in
|
|
{
|
|
cache = cache';
|
|
depth = depth';
|
|
indent = list.get cache' depth';
|
|
};
|
|
less
|
|
= if depth > 0
|
|
then
|
|
let
|
|
depth'= depth - 1;
|
|
in
|
|
{
|
|
depth = depth';
|
|
indent= list.get cache depth';
|
|
}
|
|
else
|
|
debug.panic [] "Cannot indent less than zero." null;
|
|
}
|
|
else
|
|
debug.panic [] "Got set, but either string or Indentation was expected!" null
|
|
);
|
|
}
|
|
)
|
|
{
|
|
cache = [ initial ];
|
|
depth = 0;
|
|
indent = initial;
|
|
lineNumber = 0;
|
|
result = "";
|
|
inherit tab;
|
|
}
|
|
(
|
|
type.matchPrimitiveOrPanic body
|
|
{
|
|
list = body;
|
|
string = string.splitLines body;
|
|
}
|
|
)
|
|
).result;
|
|
}
|