On 10/23/2012 03:51 AM, Jens Mueller wrote:
Chad J wrote:
On 10/22/2012 03:47 AM, Jens Mueller wrote:
Chad J wrote:
There is no weakness to this. The only shred of a counterargument I
can think of is that it makes the format strings more difficult to
learn. Other than that, it is possible to detect the destination of
the formatter, so color codes will never end up in places where they
shouldn't. A conservative approach to this should handle most
desires and never interfere with all the people with no interest in
color.
On the upshot are the things I've mentioned:
- A format specifier is potentially more discoverable.
- A format specifier is more concise. This keeps your lines from
wrapping. They are probably too long already.
Do you consider this
writecf(Color.red, "something %s", "here")
concise as well?
The case is too easy. You're formatting an entire line.
Am I? I think it's not a line. But I see your point.
You mean something like
writec(Color.red, "red")
writec(Color.blue, "blue")
writec(Color.green, "green")
is too verbose.
You want something like
writef("%CFred(red%)%CFblue(blue%)%CFgreeng(reen%)");
Right?
- To cement the previous point: nesting requires a few extra
characters with a format specifier, rather than a couple extra
/lines/ for extra function calls.
Don't understand this point. Can you give an example?
Option A:
auto save = getConsoleState();
scope (exit) setConsoleState(save);
setConsoleColors(Fg.red, Bg.blue);
writeln("Red text on blue background.");
Option B:
writefln("%CFredBblu(Red text on blue background.%)");
I see. Though I find the last line difficult to decipher (because there
are no spaces).
- Calls to stateful console functions allow people to write bugs
like saving console state and then forgetting to restore it (or
throwing an exception and neglecting to restore from within a scope
guard). Format specifiers do not have this problem.
The same holds for
writecf(Color.red, "something %s", "here")
See my above example. In that case the formatter no longer requires
even using the scope feature because there are no resources to clean
up. The library handles that mess.
Also statefulness is a pain to deal with. Stack-like operation with
push/pop or bracketing constructs is usually much less troublesome
for this sort of thing.
It'll be nice then if you can built something using format specifiers on
top of a basic library.
- etc (I'm sure I'm forgetting one or two.)
These are the reasons why my ideal language has color formatting
built into its I/O routines.
Just wanted to point out that instead of that you can add writec*
functions. I think the only thing is that these are less discoverable
but they also work without formatting, e.g.
writec(Color.red, "my text");
The thing I found very difficult with other color formatting APIs
was formatting individual words or characters. Entire lines are
easy-peasy stuff in any API. Solving the entire-lines case won't
impress me. ;)
I see your point now. But we should keep it simple.
Here's my more typical use case:
writefln("The %CFred(widgetometer%) is a device for measuring");
writefln("widget effectiveness. It is possible to ");
writefln("reconcile transcendental properties by hitting");
writefln("%CFblu(B%) for blue coefficients, %CFgrn(G%) for green");
writefln("coefficients, or %CFyel(Y%) for yellow coefficients.");
writefln("Here is a correspondence table:");
writefln(" %CFnue( %) | %CFblu( B %) %CFgrn( G %) %CFyel( Y %) ");
writefln(" %CFnue(-%)-+-%CFnue(---%)-%CFnue(---%)-%CFnue(---%)-");
writefln(" %CFblu(B%) | %CFblu(200%) %CFwht(330%) %CFwht(303%) ");
writefln(" %CFgrn(G%) | %CFwht(110%) %CFgrn(020%) %CFwht(033%) ");
writefln(" %CFyel(Y%) | %CFwht(101%) %CFwht(011%) %CFyel(002%) ");
I realized that I wanted a "nue" color that has no effect but allows
me to align things effectively ;)
Anyhow, please try to write the above example using any other style.
Interleaved function calls are particularly "fun"<g>
I'm convinced. But I find that it difficult to read. Though that's a
problem I usually have with format strings. Can these format strings be
made easier to read. I mean
writefln("The %CF(red)(widgetometer) is a device for measuring");
or
writefln("The %c(red,white)(widgetometer) is a device for measuring"); // for
writing red on white
is already easier to my eyes.
I'd be happy to see it built on top.
Jens
That's a reasonable suggestion. The only thing that can't be solved is
the trailing ) enclosing the text to be formatted. That needs a %
before it to prevent ambiguity with parentheses in the text itself. So
I could make your example:
> writefln("The %c(red,white)(widgetometer%) is a device
formeasuring"); // for writing red on white
I was also considering the possibility of separating layout and style by
allowing some kind of style specification before the printing, with a
limited formatting spec for using the styles:
stdout.addTermTextStyle("id=myStyle, fg=red, bg=white, dark, underline");
writefln("The %c(myStyle)(widgetometer%) is a device for measuring");