digitalmars.D.learn - Template/mixin ideas?
- Chris Katko (32/32) Oct 03 2018 I've got this simple task but I'm trying to perfect it as best I
- Sebastiaan Koppe (24/57) Oct 03 2018 A combination of static introspection with string mixins does the
- Chris Katko (6/31) Oct 03 2018 The mixin part wouldn't be slowed by strings, right? So the
- Sebastiaan Koppe (6/10) Oct 05 2018 During the concatenation phase you'll use an Appender. Afterwards
- Stanislav Blinov (4/5) Oct 05 2018 Since the purpose is terminal output, you could just make a
- Anonymouse (4/27) Oct 05 2018 https://run.dlang.io/gist/run-dlang/e0d0bcebe6c4edcc3cd0c2858183357d?com...
I've got this simple task but I'm trying to perfect it as best I
can to learn something in the process.
I have Linux terminal ASCII codes for coloring terminal output.
string red(string) { /* ... */ }
"Hello world".red => "\033[31mHello World\033[0m"
which translates to "[red]Hello World[reset to normal text]".
I have to do some slight trickery so I can chain them. But it all
works fine. __The function is the same__ no matter what kind of
color, bold, etc attribute I want. The only difference is the
tag/prefix string.
So I have a table (or enum):
enum colors{
reset = "\033[0m",
red = "\033[31m",
bold = "\033[1m" //...
}
Absolute perfection would be some way to add a single line to
that enum (or table) and magically get a new function. I add
"blue" with its prefix code to the enum and immediately I can do:
"hello world".blue
Add yellow = "\033..." and I can do:
"hello world".bold.yellow
It's an interesting problem. Right now, I made a generic version
that accepts the prefix code string directly called "color()" and
red() translates to a call to color with the red string. blue()
does the same. And so on. But it's still plenty of boiler plate.
I do that so I don't have 80+ functions all a half-page
long--which would be a nightmare to verify.
It's surely nothing mission critical. But I wonder if I can
distill this simple problem down further, I may be able to learn
some tricks for later problems.
Thanks.
Oct 03 2018
On Wednesday, 3 October 2018 at 11:01:53 UTC, Chris Katko wrote:
I've got this simple task but I'm trying to perfect it as best
I can to learn something in the process.
I have Linux terminal ASCII codes for coloring terminal output.
string red(string) { /* ... */ }
"Hello world".red => "\033[31mHello World\033[0m"
which translates to "[red]Hello World[reset to normal text]".
I have to do some slight trickery so I can chain them. But it
all works fine. __The function is the same__ no matter what
kind of color, bold, etc attribute I want. The only difference
is the tag/prefix string.
So I have a table (or enum):
enum colors{
reset = "\033[0m",
red = "\033[31m",
bold = "\033[1m" //...
}
Absolute perfection would be some way to add a single line to
that enum (or table) and magically get a new function. I add
"blue" with its prefix code to the enum and immediately I can
do:
"hello world".blue
Add yellow = "\033..." and I can do:
"hello world".bold.yellow
It's an interesting problem. Right now, I made a generic
version that accepts the prefix code string directly called
"color()" and red() translates to a call to color with the red
string. blue() does the same. And so on. But it's still plenty
of boiler plate. I do that so I don't have 80+ functions all a
half-page long--which would be a nightmare to verify.
It's surely nothing mission critical. But I wonder if I can
distill this simple problem down further, I may be able to
learn some tricks for later problems.
Thanks.
A combination of static introspection with string mixins does the
trick:
---
enum colors {
reset = "\033[0m",
red = "\033[31m"
}
auto GenerateColorFuncs() {
string result;
static foreach(c; __traits(allMembers, colors))
result ~= "auto "~c~"(string str) { return colors."~c~" ~
str ~ colors.reset; }";
return result;
}
mixin(GenerateColorFuncs());
void main()
{
import std.stdio;
writeln("bla".red);
}
---
Although you might want to replace the string concatenation with
something more performant if used a lot.
Oct 03 2018
On Wednesday, 3 October 2018 at 11:51:01 UTC, Sebastiaan Koppe wrote:On Wednesday, 3 October 2018 at 11:01:53 UTC, Chris Katko wrote:The mixin part wouldn't be slowed by strings, right? So the "slowness" is the invokation part which changes strings and forces GC allocations, I guess? What's the alternative to using strings... for strings?[...]A combination of static introspection with string mixins does the trick: --- enum colors { reset = "\033[0m", red = "\033[31m" } auto GenerateColorFuncs() { string result; static foreach(c; __traits(allMembers, colors)) result ~= "auto "~c~"(string str) { return colors."~c~" ~ str ~ colors.reset; }"; return result; } mixin(GenerateColorFuncs()); void main() { import std.stdio; writeln("bla".red); } --- Although you might want to replace the string concatenation with something more performant if used a lot.
Oct 03 2018
On Thursday, 4 October 2018 at 01:12:04 UTC, Chris Katko wrote:The mixin part wouldn't be slowed by strings, right? So the "slowness" is the invokation part which changes strings and forces GC allocations, I guess?Yep, that is right.What's the alternative to using strings... for strings?During the concatenation phase you'll use an Appender. Afterwards you retrieve the resulting string from the appender. It is very similar to a StringBuilder in other languages. See std.array.appender
Oct 05 2018
On Thursday, 4 October 2018 at 01:12:04 UTC, Chris Katko wrote:What's the alternative to using strings... for strings?Since the purpose is terminal output, you could just make a custom formatter, something like this: https://run.dlang.io/is/F51UCZ
Oct 05 2018
On Wednesday, 3 October 2018 at 11:01:53 UTC, Chris Katko wrote:
I've got this simple task but I'm trying to perfect it as best
I can to learn something in the process.
I have Linux terminal ASCII codes for coloring terminal output.
string red(string) { /* ... */ }
"Hello world".red => "\033[31mHello World\033[0m"
which translates to "[red]Hello World[reset to normal text]".
I have to do some slight trickery so I can chain them. But it
all works fine. __The function is the same__ no matter what
kind of color, bold, etc attribute I want. The only difference
is the tag/prefix string.
So I have a table (or enum):
enum colors{
reset = "\033[0m",
red = "\033[31m",
bold = "\033[1m" //...
}
Absolute perfection would be some way to add a single line to
that enum (or table) and magically get a new function. I add
"blue" with its prefix code to the enum and immediately I can
do:
"hello world".blue
Add yellow = "\033..." and I can do:
"hello world".bold.yellow
https://run.dlang.io/gist/run-dlang/e0d0bcebe6c4edcc3cd0c2858183357d?compiler=dmd
https://issues.dlang.org/show_bug.cgi?id=19286 prevents us from
using static foreaches to declare the aliases.
Oct 05 2018









Sebastiaan Koppe <mail skoppe.eu> 