lib.strings: add trim
and trimWith
`strings.trim` returns a copy of the string with all leading and trailing whitespace removed. `strings.trimWith` does the same thing, but calling code can decide whether to trim the start and/or end of the string.
This commit is contained in:
parent
d1e70dde57
commit
aad87c2aa8
lib
@ -105,7 +105,7 @@ let
|
|||||||
hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
|
hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
|
||||||
escapeShellArg escapeShellArgs
|
escapeShellArg escapeShellArgs
|
||||||
isStorePath isStringLike
|
isStorePath isStringLike
|
||||||
isValidPosixName toShellVar toShellVars
|
isValidPosixName toShellVar toShellVars trim trimWith
|
||||||
escapeRegex escapeURL escapeXML replaceChars lowerChars
|
escapeRegex escapeURL escapeXML replaceChars lowerChars
|
||||||
upperChars toLower toUpper addContextFrom splitString
|
upperChars toLower toUpper addContextFrom splitString
|
||||||
removePrefix removeSuffix versionOlder versionAtLeast
|
removePrefix removeSuffix versionOlder versionAtLeast
|
||||||
|
@ -157,6 +157,68 @@ rec {
|
|||||||
*/
|
*/
|
||||||
replicate = n: s: concatStrings (lib.lists.replicate n s);
|
replicate = n: s: concatStrings (lib.lists.replicate n s);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove leading and trailing whitespace from a string.
|
||||||
|
|
||||||
|
Whitespace is defined as any of the following characters:
|
||||||
|
" ", "\t" "\r" "\n"
|
||||||
|
|
||||||
|
Type: trim :: string -> string
|
||||||
|
|
||||||
|
Example:
|
||||||
|
trim " hello, world! "
|
||||||
|
=> "hello, world!"
|
||||||
|
*/
|
||||||
|
trim = trimWith {
|
||||||
|
start = true;
|
||||||
|
end = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove leading and/or trailing whitespace from a string.
|
||||||
|
|
||||||
|
Whitespace is defined as any of the following characters:
|
||||||
|
" ", "\t" "\r" "\n"
|
||||||
|
|
||||||
|
Type: trimWith :: Attrs -> string -> string
|
||||||
|
|
||||||
|
Example:
|
||||||
|
trimWith { start = true; } " hello, world! "}
|
||||||
|
=> "hello, world! "
|
||||||
|
trimWith { end = true; } " hello, world! "}
|
||||||
|
=> " hello, world!"
|
||||||
|
*/
|
||||||
|
trimWith =
|
||||||
|
{
|
||||||
|
# Trim leading whitespace
|
||||||
|
start ? false,
|
||||||
|
# Trim trailing whitespace
|
||||||
|
end ? false,
|
||||||
|
}:
|
||||||
|
s:
|
||||||
|
let
|
||||||
|
# Define our own whitespace character class instead of using
|
||||||
|
# `[:space:]`, which is not well-defined.
|
||||||
|
chars = " \t\r\n";
|
||||||
|
|
||||||
|
# To match up until trailing whitespace, we need to capture a
|
||||||
|
# group that ends with a non-whitespace character.
|
||||||
|
regex =
|
||||||
|
if start && end then
|
||||||
|
"[${chars}]*(.*[^${chars}])[${chars}]*"
|
||||||
|
else if start then
|
||||||
|
"[${chars}]*(.*)"
|
||||||
|
else if end then
|
||||||
|
"(.*[^${chars}])[${chars}]*"
|
||||||
|
else
|
||||||
|
"(.*)";
|
||||||
|
|
||||||
|
# If the string was empty or entirely whitespace,
|
||||||
|
# then the regex may not match and `res` will be `null`.
|
||||||
|
res = match regex s;
|
||||||
|
in
|
||||||
|
optionalString (res != null) (head res);
|
||||||
|
|
||||||
/* Construct a Unix-style, colon-separated search path consisting of
|
/* Construct a Unix-style, colon-separated search path consisting of
|
||||||
the given `subDir` appended to each of the given paths.
|
the given `subDir` appended to each of the given paths.
|
||||||
|
|
||||||
|
@ -369,6 +369,72 @@ runTests {
|
|||||||
expected = "hellohellohellohellohello";
|
expected = "hellohellohellohellohello";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Test various strings are trimmed correctly
|
||||||
|
testTrimString = {
|
||||||
|
expr =
|
||||||
|
let
|
||||||
|
testValues = f: mapAttrs (_: f) {
|
||||||
|
empty = "";
|
||||||
|
cr = "\r";
|
||||||
|
lf = "\n";
|
||||||
|
tab = "\t";
|
||||||
|
spaces = " ";
|
||||||
|
leading = " Hello, world";
|
||||||
|
trailing = "Hello, world ";
|
||||||
|
mixed = " Hello, world ";
|
||||||
|
mixed-tabs = " \t\tHello, world \t \t ";
|
||||||
|
multiline = " Hello,\n world! ";
|
||||||
|
multiline-crlf = " Hello,\r\n world! ";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
leading = testValues (strings.trimWith { start = true; });
|
||||||
|
trailing = testValues (strings.trimWith { end = true; });
|
||||||
|
both = testValues strings.trim;
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
leading = {
|
||||||
|
empty = "";
|
||||||
|
cr = "";
|
||||||
|
lf = "";
|
||||||
|
tab = "";
|
||||||
|
spaces = "";
|
||||||
|
leading = "Hello, world";
|
||||||
|
trailing = "Hello, world ";
|
||||||
|
mixed = "Hello, world ";
|
||||||
|
mixed-tabs = "Hello, world \t \t ";
|
||||||
|
multiline = "Hello,\n world! ";
|
||||||
|
multiline-crlf = "Hello,\r\n world! ";
|
||||||
|
};
|
||||||
|
trailing = {
|
||||||
|
empty = "";
|
||||||
|
cr = "";
|
||||||
|
lf = "";
|
||||||
|
tab = "";
|
||||||
|
spaces = "";
|
||||||
|
leading = " Hello, world";
|
||||||
|
trailing = "Hello, world";
|
||||||
|
mixed = " Hello, world";
|
||||||
|
mixed-tabs = " \t\tHello, world";
|
||||||
|
multiline = " Hello,\n world!";
|
||||||
|
multiline-crlf = " Hello,\r\n world!";
|
||||||
|
};
|
||||||
|
both = {
|
||||||
|
empty = "";
|
||||||
|
cr = "";
|
||||||
|
lf = "";
|
||||||
|
tab = "";
|
||||||
|
spaces = "";
|
||||||
|
leading = "Hello, world";
|
||||||
|
trailing = "Hello, world";
|
||||||
|
mixed = "Hello, world";
|
||||||
|
mixed-tabs = "Hello, world";
|
||||||
|
multiline = "Hello,\n world!";
|
||||||
|
multiline-crlf = "Hello,\r\n world!";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
testSplitStringsSimple = {
|
testSplitStringsSimple = {
|
||||||
expr = strings.splitString "." "a.b.c.d";
|
expr = strings.splitString "." "a.b.c.d";
|
||||||
expected = [ "a" "b" "c" "d" ];
|
expected = [ "a" "b" "c" "d" ];
|
||||||
|
Loading…
Reference in New Issue
Block a user