Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce allocations in Styling API #134

Merged
merged 2 commits into from
Dec 1, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 45 additions & 23 deletions source/argparse/ansi.d
Original file line number Diff line number Diff line change
Expand Up @@ -52,38 +52,47 @@ private enum Color

package struct TextStyle
{
private ubyte[] style;
private string style = prefix;

private this(return scope inout(ubyte)[] st) scope inout nothrow pure @safe @nogc
private this(const(ubyte)[] st...) scope inout nothrow pure @safe
{
style = st;
}
private this(ubyte st) scope inout nothrow pure @safe
{
if(st != 0)
style = [st];
import std.algorithm.iteration: joiner, map;
import std.array: appender;
import std.conv: toChars;
import std.utf: byCodeUnit;

auto a = appender(prefix);
a ~= st.map!(_ => uint(_).toChars).joiner(separator.byCodeUnit);
style = a[];
}

private auto opBinary(string op : "~")(ubyte other) inout
private ref opOpAssign(string op : "~")(ubyte other)
{
return other != 0 ? inout TextStyle(style ~ other) : this;
import std.array: appender;
import std.conv: toChars;

if(other != 0)
{
auto a = appender(style);
if(style.length != prefix.length)
a ~= separator;
a ~= uint(other).toChars;
style = a[];
}
return this;
}

public auto opCall(string str) const
{
import std.conv: text, to;
import std.algorithm: joiner, map;
import std.utf: byCodeUnit;

if(style.length == 0 || str.length == 0)
if(str.length == 0 || style.length == prefix.length)
return str;

return text(prefix, style.map!(_ => _.to!string.byCodeUnit).joiner(separator.byCodeUnit), suffix, str, reset);
return style ~ suffix ~ str ~ reset;
}
}

nothrow pure @safe unittest
{
assert(TextStyle.init("foo") == "foo");
assert(TextStyle([])("foo") == "foo");
assert(TextStyle([Font.bold])("foo") == "\033[1mfoo\033[m");
assert(TextStyle([Font.bold, Font.italic])("foo") == "\033[1;3mfoo\033[m");
Expand All @@ -107,6 +116,7 @@ package struct StyledText
{
return toString() ~ rhs;
}

// lhs ~ this
string opBinaryRight(string op : "~")(string lhs) const
{
Expand All @@ -122,27 +132,33 @@ nothrow pure @safe unittest
const ubyte[1] data = [Font.bold];
scope c = const TextStyle(data);
assert((const StyledText(c, "foo")).toString() == c("foo"));

immutable foo = StyledText(s, "foo");
assert(foo ~ "bar" == s("foo") ~ "bar");
assert("bar" ~ foo == "bar" ~ s("foo"));
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package template StyleImpl(ubyte styleCode)
{
public auto StyleImpl()
immutable style = TextStyle(styleCode);

public TextStyle StyleImpl()
{
return TextStyle(styleCode);
return style;
}
public auto StyleImpl(TextStyle otherStyle)
{
return otherStyle ~ styleCode;
return otherStyle ~= styleCode;
}
public auto StyleImpl(string text)
{
return StyledText(TextStyle(styleCode), text);
return StyledText(style, text);
}
public auto StyleImpl(TextStyle otherStyle, string text)
{
return StyledText(otherStyle ~ styleCode, text);
return StyledText(otherStyle ~= styleCode, text);
}
}

Expand Down Expand Up @@ -199,6 +215,12 @@ nothrow pure @safe unittest
assert(bold.italic.red.onWhite("foo").toString() == "\033[1;3;31;107mfoo\033[m");
}

nothrow pure @safe @nogc unittest
{
auto style = bold;
style = italic; // Should be able to reassign.
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public auto getUnstyledText(string text)
Expand All @@ -217,7 +239,7 @@ package size_t getUnstyledTextLength(string text)

package size_t getUnstyledTextLength(StyledText text)
{
return getUnstyledTextLength(text.toString());
return getUnstyledTextLength(text.text);
}

unittest
Expand Down