Skip to content

Commit c76ea4c

Browse files
SeddryckAppVeyor bot
andauthored
feat: functions to clean and collapse whitespaces (#237)
* feat: functions to clean and collapse whitespaces * Update the automatically generated documentation related to the list of functions and predicates --------- Co-authored-by: AppVeyor bot <no-reply@nbiguity.io>
1 parent e504197 commit c76ea4c

File tree

7 files changed

+337
-219
lines changed

7 files changed

+337
-219
lines changed

Expressif.Testing/Functions/Text/CharFunctionsTest.cs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ public class CharFunctionsTest
1414
[TestCase("***123***456*78****", "*", "12345678")]
1515
[TestCase("******", "*", "")]
1616
[TestCase("(null)", "*", "(null)")]
17+
[TestCase(null, "*", "(null)")]
1718
[TestCase("(empty)", "*", "(empty)")]
1819
[TestCase("(blank)", "*", "(blank)")]
1920
[TestCase("(blank)", " ", "(empty)")]
20-
public void RemoveChars_Valid(string value, char charToRemove, string expected)
21+
public void RemoveChars_Valid(string? value, char charToRemove, string expected)
2122
=> Assert.That(new RemoveChars(() => (charToRemove)).Evaluate(value)
2223
, Is.EqualTo(expected));
2324

@@ -26,10 +27,11 @@ public void RemoveChars_Valid(string value, char charToRemove, string expected)
2627
[TestCase("***123***456*78****", "*", "-", "---123---456-78----")]
2728
[TestCase("******", "*", "-", "------")]
2829
[TestCase("(null)", "*", "-", "(null)")]
30+
[TestCase(null, "*", "-", "(null)")]
2931
[TestCase("(empty)", "*", "-", "(empty)")]
3032
[TestCase("(blank)", "*", "-", "(blank)")]
3133
[TestCase("(blank)", " ", "-", "(blank)")]
32-
public void ReplaceChars_Valid(string value, char charToReplace, char replacingChar, string expected)
34+
public void ReplaceChars_Valid(string? value, char charToReplace, char replacingChar, string expected)
3335
=> Assert.That(new ReplaceChars(() => charToReplace, () => replacingChar).Evaluate(value)
3436
, Is.EqualTo(expected));
3537

@@ -38,21 +40,57 @@ public void ReplaceChars_Valid(string value, char charToReplace, char replacingC
3840
[TestCase("12345678", new[] { '2', '8', '4' }, "248")]
3941
[TestCase("12314561789", new[] { '2', '1', '4' }, "12141")]
4042
[TestCase("(null)", new[] { '2', '1', '4' }, "(null)")]
43+
[TestCase(null, new[] { '2', '1', '4' }, "(null)")]
4144
[TestCase("(empty)", new[] { '2', '1', '4' }, "(empty)")]
4245
[TestCase("(blank)", new[] { '2', '1', '4' }, "(blank)")]
4346
[TestCase("(blank)", new[] { '2', '1', '4' }, "(blank)")]
44-
public void FilterChars_Chars_Valid(string value, char[] filter, string expected)
47+
public void FilterChars_Chars_Valid(string? value, char[] filter, string expected)
4548
=> Assert.That(new FilterChars(() => filter).Evaluate(value)
4649
, Is.EqualTo(expected));
4750

4851
[Test]
4952
[TestCase("12345678", "284", "248")]
5053
[TestCase("12314561789", "214", "12141")]
5154
[TestCase("(null)", "214", "(null)")]
55+
[TestCase(null, "214", "(null)")]
5256
[TestCase("(empty)", "214", "(empty)")]
5357
[TestCase("(blank)", "214", "(blank)")]
5458
[TestCase("(blank)", "214", "(blank)")]
55-
public void FilterChars_String_Valid(string value, string filter, string expected)
59+
public void FilterChars_String_Valid(string? value, string filter, string expected)
5660
=> Assert.That(new FilterChars(() => filter).Evaluate(value)
5761
, Is.EqualTo(expected));
62+
63+
[Test]
64+
[TestCase("foo", "foo")]
65+
[TestCase("foo bar", "foo bar")]
66+
[TestCase("foo bar", "foo bar")]
67+
[TestCase("foo\tbar", "foo\tbar")]
68+
[TestCase("foo\t bar", "foo\tbar")]
69+
[TestCase("foo\r\nbar", "foo\r\nbar")]
70+
[TestCase("\t\t\tfoo\t\tbar\t\t\t", "foo\tbar")]
71+
[TestCase("(null)", "(null)")]
72+
[TestCase(null, "(null)")]
73+
[TestCase("(empty)", "(empty)")]
74+
[TestCase("(blank)", "(empty)")]
75+
public void CollapseWhitespace_Value_Valid(string? value, string expected)
76+
=> Assert.That(new CollapseWhitespace().Evaluate(value)
77+
, Is.EqualTo(expected));
78+
79+
[Test]
80+
[TestCase("foo", "foo")]
81+
[TestCase("foo bar", "foo bar")]
82+
[TestCase("foo bar", "foo bar")]
83+
[TestCase("foo\tbar", "foo bar")]
84+
[TestCase("foo\t bar", "foo bar")]
85+
[TestCase("foo\r\nbar", "foo bar")]
86+
[TestCase("foo\rbar\n", "foo bar ")]
87+
[TestCase("foo\r\n\r\nbar", "foo bar")]
88+
[TestCase("\t\t\tfoo\t\tbar\t\t\t", " foo bar ")]
89+
[TestCase("(null)", "(null)")]
90+
[TestCase(null, "(null)")]
91+
[TestCase("(empty)", "(empty)")]
92+
[TestCase("(blank)", "(blank)")]
93+
public void CleanWhitespace_Value_Valid(string? value, string expected)
94+
=> Assert.That(new CleanWhitespace().Evaluate(value)
95+
, Is.EqualTo(expected));
5896
}

Expressif/Functions/Text/CharFunctions.cs

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class RemoveChars : BaseTextFunction
1818
public RemoveChars(Func<char> charToRemove)
1919
=> CharToRemove = charToRemove;
2020

21-
protected override object EvaluateString(string value)
21+
protected override object? EvaluateString(string value)
2222
{
2323
var stringBuilder = new StringBuilder();
2424
foreach (var c in value)
@@ -27,7 +27,7 @@ protected override object EvaluateString(string value)
2727
return stringBuilder.ToString();
2828
}
2929

30-
protected override object EvaluateBlank()
30+
protected override object? EvaluateBlank()
3131
{
3232
if (char.IsWhiteSpace(CharToRemove.Invoke()))
3333
return new Empty().Keyword;
@@ -49,7 +49,7 @@ public class ReplaceChars : BaseTextFunction
4949
public ReplaceChars(Func<char> charToReplace, Func<char> charReplacing)
5050
=> (CharToReplace, CharReplacing) = (charToReplace, charReplacing);
5151

52-
protected override object EvaluateString(string value)
52+
protected override object? EvaluateString(string value)
5353
{
5454
var charToReplace = CharToReplace.Invoke();
5555
var charReplacing = CharReplacing.Invoke();
@@ -63,7 +63,7 @@ protected override object EvaluateString(string value)
6363
return stringBuilder.ToString();
6464
}
6565

66-
protected override object EvaluateBlank()
66+
protected override object? EvaluateBlank()
6767
=> new Whitespace().Keyword;
6868
}
6969

@@ -86,7 +86,7 @@ public FilterChars(Func<string> filter)
8686
Filter = toCharArray(filter.Invoke());
8787
}
8888

89-
protected override object EvaluateString(string value)
89+
protected override object? EvaluateString(string value)
9090
{
9191
var filter = Filter.Invoke();
9292

@@ -97,6 +97,52 @@ protected override object EvaluateString(string value)
9797
return stringBuilder.ToString();
9898
}
9999

100-
protected override object EvaluateBlank()
100+
protected override object? EvaluateBlank()
101+
=> new Whitespace().Keyword;
102+
}
103+
104+
/// <summary>
105+
/// returns the argument with any two or more consecutive whitespaces replaced by the first whitespace in the sequence and trimming the result. `\r\n` is considered as a single character.
106+
/// </summary>
107+
public class CollapseWhitespace : BaseTextFunction
108+
{
109+
protected override object? EvaluateString(string value)
110+
{
111+
char? previousWithespace = null;
112+
var stringBuilder = new StringBuilder();
113+
foreach (var c in value)
114+
{
115+
if (previousWithespace == '\r' && c == '\n')
116+
previousWithespace = null;
117+
if (previousWithespace is null || !char.IsWhiteSpace(c))
118+
stringBuilder.Append(c);
119+
previousWithespace = char.IsWhiteSpace(c) ? c : null;
120+
}
121+
return stringBuilder.ToString().Trim();
122+
}
123+
124+
protected override object? EvaluateBlank()
125+
=> new Empty().Keyword;
126+
}
127+
128+
/// <summary>
129+
/// returns the argument with any whitespace replaced by a space character. `\r\n` is considered as a single character.
130+
/// </summary>
131+
public class CleanWhitespace : BaseTextFunction
132+
{
133+
protected override object? EvaluateString(string value)
134+
{
135+
char? previousWithespace = null;
136+
var stringBuilder = new StringBuilder();
137+
foreach (var c in value)
138+
{
139+
if (!(previousWithespace == '\r' && c == '\n'))
140+
stringBuilder.Append(char.IsWhiteSpace(c) ? ' ' : c);
141+
previousWithespace = char.IsWhiteSpace(c) ? c : null;
142+
}
143+
144+
return stringBuilder.ToString();
145+
}
146+
protected override object? EvaluateBlank()
101147
=> new Whitespace().Keyword;
102148
}

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ Install-Package Expressif
289289
|Text | append-new-line | text-to-append-new-line |
290290
|Text | append-space | text-to-append-space |
291291
|Text | before-substring | text-to-before-substring |
292+
|Text | clean-whitespace | text-to-clean-whitespace |
293+
|Text | collapse-whitespace | text-to-collapse-whitespace |
292294
|Text | count-distinct-chars | text-to-count-distinct-chars |
293295
|Text | count-substring | text-to-count-substring |
294296
|Text | empty-to-null | |

0 commit comments

Comments
 (0)