Coloured write now uses WinTermEmulation on Windows.

Basic state machine for parsing ANSI VT100 subset.
This commit is contained in:
ponce 2014-07-29 00:20:33 +02:00
parent 1361fca5d8
commit 48444a6fb6
2 changed files with 113 additions and 8 deletions

View file

@ -25,7 +25,7 @@ void cwritef(T...)(T args)
/// Coloured writefln.
void cwritefln(T...)(T args)
{
stdout.cwritefln(args);
stdout.cwritef(args, "\n");
}
/// Coloured writeln.
@ -39,7 +39,7 @@ void cwriteln(T...)(T args)
void cwritef(File f, Char, A...)(in Char[] fmt, A args)
{
auto s = format(fmt, args);
f.write(s); // TODO support colours
f.cwrite(s);
}
/// Coloured writef to a File.
@ -51,6 +51,15 @@ void cwrite(S...)(File f, S args)
foreach(arg; args)
s ~= to!string(arg);
f.write(s);
version(Windows)
{
auto winterm = WinTermEmulation();
foreach(c ; s)
winterm.feed(c);
}
else
{
f.write(s);
}
}

View file

@ -17,17 +17,18 @@ version(Windows)
struct WinTermEmulation
{
public:
this(bool workardound = true) nothrow
this(bool workardound = true) nothrow @nogc
{
_console = GetStdHandle(STD_OUTPUT_HANDLE);
// saves console attributes
_console = GetStdHandle(STD_OUTPUT_HANDLE);
_savedInitialColor = (0 != GetConsoleScreenBufferInfo(_console, &consoleInfo));
_state = State.initial;
}
~this()
~this() nothrow @nogc
{
// Restore initial text attributes on release
if (_savedInitialColor)
{
SetConsoleTextAttribute(_console, consoleInfo.wAttributes);
@ -35,15 +36,110 @@ version(Windows)
}
}
void feed(dchar d) nothrow
// Eat one character and update color state accordingly. Return true if this character should be displayed.
bool feed(dchar d) nothrow @nogc
{
final switch(_state) with (State)
{
case initial:
if (d == '\x1B')
{
_state = escaped;
return false;
}
break;
case escaped:
if (d == '[')
{
_state = readingAttribute;
_currentAttr = 0;
return false;
}
break;
case readingAttribute:
if (d >= '0' && d <= '9')
{
_parsedAttr = _parsedAttr * 10 + (_parsedAttr - '0');
return false;
}
else if (d == ';')
{
executeAttribute(_parsedAttr);
return false;
}
else if (d == 'm')
{
_state = State.initial;
return false;
}
break;
}
return true;
}
private:
HANDLE _console;
bool _savedInitialColor;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
State _state;
WORD _currentAttr;
int _parsedAttr;
enum State
{
initial,
escaped,
readingAttribute
}
void executeAttribute(int attr) nothrow @nogc
{
switch (attr)
{
/+ case 0:
if (_savedInitialColor)
SetConsoleTextAttribute(_console, consoleInfo.wAttributes);
break;
default:
if (30 <= attr && attr <= 37)
}
0 Reset all attributes
1 Bright
2 Dim
4 Underscore
5 Blink
7 Reverse
8 Hidden
Foreground Colours
30 Black
31 Red
32 Green
33 Yellow
34 Blue
35 Magenta
36 Cyan
37 White
Background Colours
40 Black
41 Red
42 Green
43 Yellow
44 Blue
45 Magenta
46 Cyan
47 White
+/
default:
}
}
}
}