New ExpandTabs feature w/ tests

This commit is contained in:
Scott Bilas 2018-02-15 13:01:20 +01:00
Родитель d7eb93f1eb
Коммит d252809c8d
2 изменённых файлов: 66 добавлений и 0 удалений

Просмотреть файл

@ -136,5 +136,35 @@ namespace Unity.Core.Tests
enumerable.StringJoin(Selector, " ** ").ShouldBe("String ** Int32 ** (null) ** ValueTuple`2");
enumerable.StringJoin(Selector, '?').ShouldBe("String?Int32?(null)?ValueTuple`2");
}
[Test]
public void ExpandTabs_WithEmpty_Returns_Empty()
{
"".ExpandTabs(4).ShouldBeEmpty();
}
[Test]
public void ExpandTabs_WithNoTabs_Returns_IdenticalString() // i.e. no allocs
{
const string text = "abc def ghijkl";
ReferenceEquals(text, text.ExpandTabs(4)).ShouldBeTrue();
}
[Test]
public void ExpandTabs_WithInvalidTabWidth_Throws()
{
Should.Throw<ArgumentException>(() => "".ExpandTabs(-123));
Should.Throw<ArgumentException>(() => "abc".ExpandTabs(-1));
}
[Test]
public void ExpandTabs_BasicScenarios_ExpandsProperly()
{
"a\tbc\t\td".ExpandTabs(4).ShouldBe("a bc d");
"a\tbc\t\td".ExpandTabs(3).ShouldBe("a bc d");
"a\tbc\t\td".ExpandTabs(2).ShouldBe("a bc d");
"a\tbc\t\td".ExpandTabs(1).ShouldBe("a bc d");
"a\tbc\t\td".ExpandTabs(0).ShouldBe("abcd");
}
}
}

Просмотреть файл

@ -2,6 +2,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
namespace Unity.Core
@ -60,5 +61,40 @@ namespace Unity.Core
[NotNull]
public static string StringJoin<T, TSelected>([NotNull] this IEnumerable<T> @this, [NotNull] Func<T, TSelected> selector, char separator)
=> string.Join(new string(separator, 1), @this.Select(selector));
[NotNull]
public static string ExpandTabs([NotNull] this string @this, int tabWidth, StringBuilder buffer = null)
{
if (tabWidth < 0)
throw new ArgumentException("tabWidth must be >= 0", nameof(tabWidth));
var tabCount = @this.Count(c => c == '\t');
// early out if nothing to do
if (tabCount == 0)
return @this;
// more early-out and a bit silly scenarios, but why not..
if (tabWidth == 0)
return @this.Replace("\t", "");
if (tabWidth == 1)
return @this.Replace('\t', ' ');
var capacity = @this.Length + tabCount * (tabWidth - 1);
if (buffer != null)
buffer.EnsureCapacity(capacity);
else
buffer = new StringBuilder(capacity);
foreach (var c in @this)
{
if (c != '\t')
buffer.Append(c);
else
buffer.Append(' ', tabWidth - buffer.Length % tabWidth);
}
return buffer.ToString();
}
}
}