Summary#
Text.TrimStart(s) and Text.TrimEnd(s) remove whitespace from one end of a string (Text.Trim(s) does
both). Give any of the three a second argument and it removes those CHARACTERS instead — C#'s
TrimEnd(params char[]), with the set written as a string (a single char works too: s.TrimEnd('/')). Text.PadStart(s, width, pad) and Text.PadEnd(s, width, pad) grow a string to at least width
characters by adding a fill on the left or right. Padding never shortens a string, and the fill may be a whole
string. C#'s own names work too, exactly as C# writes them: s.PadLeft(5, '0'), s.PadRight(8) (a space fill).
Signature#
Text.TrimStart(<string> s) -> string // strip leading whitespace
Text.TrimEnd(<string> s) -> string // strip trailing whitespace
Text.TrimStart(<string> s, <string> chars) -> string // …or strip any of THESE characters
Text.TrimEnd(<string> s, <string> chars) -> string
Text.Trim(<string> s, <string> chars) -> string // both ends
Text.PadStart(<string> s, <int> width, <string> pad) -> string // fill on the LEFT to `width`
Text.PadEnd(<string> s, <int> width, <string> pad) -> string // fill on the RIGHT to `width`
s.PadLeft(<int> width[, <char> pad]) -> string // C#'s name for PadStart — no pad is a SPACE
s.PadRight(<int> width[, <char> pad]) -> string // C#'s name for PadEndDescription#
Trimming characters rather than whitespace#
The second argument is a SET, not a suffix: every character in it is stripped from that end, repeatedly, exactly as
C#'s char[] overload does. So TrimEnd("/") removes as many trailing slashes as there are, and TrimEnd("/\\")
removes either kind.
string JoinUrl(string baseUrl, string path) {
return Text.TrimEnd(baseUrl, "/") + "/" + Text.TrimStart(path, "/");
}⚠ It is a set of characters, so TrimEnd(url, "/api") strips any trailing /, a, p or i — not the word
"api". That is C#'s behaviour too, and it is the one thing about these overloads that surprises people.
Trimming uses the full Unicode whitespace set#
TrimStart/TrimEnd strip every leading/trailing whitespace character, not just the ASCII space — a tab, a
newline, a no-break space ( ), an ideographic space ( ) are all removed. Only the named end is touched:
Text.TrimStart(" hi ") is "hi " (trailing spaces survive).
Padding never truncates, and takes a WIDTH not a count-to-add#
width is the target length, not "how many characters to add". If the string is already at least that
long it comes back unchanged: Text.PadStart("hello", 3, "0") is "hello". Otherwise the gap is filled
to reach exactly width.
The pad is a STRING, cut to fit the gap#
The fill is repeated and then cut to exactly the deficit, so a multi-character pad can end mid-repeat:
Text.PadStart("7", 3, "ab") fills two characters — "ab7" — and Text.PadEnd("7", 4, "ab") is "7aba".
An empty pad is a no-op (it cannot fill anything), so Text.PadStart("x", 5, "") is "x" — it does not
loop forever. For zero-padding a number, a format specifier like D5 or "00000" is usually clearer than
padding a string — see format specifiers.
C#'s PadLeft / PadRight#
s.PadLeft(width, '0') and s.PadRight(width) are the SAME two verbs under C#'s names — PadLeft is PadStart,
PadRight is PadEnd — and take C#'s arguments: a char fill, or none at all for a space. So the line a C# author
writes compiles as written, and means what it meant there.
A character repeated: new string(c, n)#
C#'s new string('-', 40) — a rule, a bar of a given width, a column of filler — is the character n times, and it
compiles as written (it is Text.Repeat over the character). A count of zero or less is the empty string.
All of these run in memory on a value already in hand, on the server and in the browser alike.
Examples#
// Trim stray whitespace, then right-justify into a fixed-width column with leading zeros.
string Ticket(string code) {
return Text.PadStart(Text.TrimEnd(Text.TrimStart(code)), 6, "0");
}[Test]
void Text_affix_answers() {
Assert.Equal("000042", Ticket(" 42 "));
Assert.Equal("hi ", Text.TrimStart(" hi ")); // only the leading end
Assert.Equal(" hi", Text.TrimEnd(" hi "));
Assert.Equal("hi", Text.TrimStart(" hi")); // an ideographic space is whitespace too
Assert.Equal("007", Text.PadStart("7", 3, "0"));
Assert.Equal("ab7", Text.PadStart("7", 3, "ab")); // multi-char pad, cut to the 2-char gap
Assert.Equal("hello", Text.PadStart("hello", 3, "0")); // already long enough → unchanged
Assert.Equal("x", Text.PadStart("x", 5, "")); // empty pad → no-op, never an infinite loop
Assert.Equal("700", Text.PadEnd("7", 3, "0"));
Assert.Equal("7aba", Text.PadEnd("7", 4, "ab"));
Assert.Equal("00042", "42".PadLeft(5, '0')); // C#'s names, C#'s arguments
Assert.Equal("ab |", "ab".PadRight(4) + "|"); // no fill → a space
Assert.Equal("----", new string('-', 4)); // C#'s repeated-character constructor
}See also#
- Text.Length, Text.IsEmpty, Text.IsBlank, Text.Contains, Text.StartsWith, Text.EndsWith —
Text.Length, and the emptiness checks - format specifiers — zero-padding a number (
D5,"00000"), usually better than padding a string - Text.TitleCase — the other in-memory string builtins