From 5caf15bd46fd65db75ccf16fb7f8962546b180b7 Mon Sep 17 00:00:00 2001 From: ponce Date: Mon, 28 Jul 2014 22:54:08 +0200 Subject: [PATCH 1/9] Reorganize package as to split in several files (colourize, Windows term emulation, and cprintf functions). --- dub.json | 2 ++ source/{ => colorize}/colorize.d | 1 + source/colorize/package.d | 10 ++++++++++ source/colorize/winterm.d | 7 +++++++ 4 files changed, 20 insertions(+) rename source/{ => colorize}/colorize.d (99%) create mode 100644 source/colorize/package.d create mode 100644 source/colorize/winterm.d diff --git a/dub.json b/dub.json index 2d72e33..3aef623 100644 --- a/dub.json +++ b/dub.json @@ -3,6 +3,8 @@ "description": "A port of Ruby's colorize library to D.", "license": "MIT", "copyright": "Copyright © 2014, Pedro Tacla Yamada", + "importPaths": ["source"], + "sourcePaths": ["source"], "authors": [ "Pedro Tacla Yamada" ] diff --git a/source/colorize.d b/source/colorize/colorize.d similarity index 99% rename from source/colorize.d rename to source/colorize/colorize.d index ae707c6..49628d8 100644 --- a/source/colorize.d +++ b/source/colorize/colorize.d @@ -4,6 +4,7 @@ * License: Licensed under the MIT license. See LICENSE for more information * Version: 0.1.0 */ +module colorize.colorize; import std.string : format; diff --git a/source/colorize/package.d b/source/colorize/package.d new file mode 100644 index 0000000..0669be1 --- /dev/null +++ b/source/colorize/package.d @@ -0,0 +1,10 @@ +/** + * Authors: ponce + * Date: July 28, 2014 + * License: Licensed under the MIT license. See LICENSE for more information + * Version: 0.1.0 + */ +module colorize; + +public import colorize.colorize; +public import colorize.winterm; \ No newline at end of file diff --git a/source/colorize/winterm.d b/source/colorize/winterm.d new file mode 100644 index 0000000..93030d7 --- /dev/null +++ b/source/colorize/winterm.d @@ -0,0 +1,7 @@ +/** + * Authors: ponce + * Date: July 28, 2014 + * License: Licensed under the MIT license. See LICENSE for more information + * Version: 0.1.0 + */ +module colorize.winterm; \ No newline at end of file From 1361fca5d8f4ae2b12c1a5f36151d61209c1221e Mon Sep 17 00:00:00 2001 From: ponce Date: Mon, 28 Jul 2014 23:55:16 +0200 Subject: [PATCH 2/9] Partially implement coloured write/writef/... Partially implement windows terminal emulation. --- source/colorize/cwrite.d | 56 +++++++++++++++++++++++++++++++++++++++ source/colorize/package.d | 2 +- source/colorize/winterm.d | 46 +++++++++++++++++++++++++++++++- 3 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 source/colorize/cwrite.d diff --git a/source/colorize/cwrite.d b/source/colorize/cwrite.d new file mode 100644 index 0000000..5550a29 --- /dev/null +++ b/source/colorize/cwrite.d @@ -0,0 +1,56 @@ +/** + * Authors: ponce + * Date: July 28, 2014 + * License: Licensed under the MIT license. See LICENSE for more information + * Version: 0.1.0 + */ +module colorize.cwrite; + +import std.stdio : File, stdout; + +import colorize.winterm; + +/// Coloured write. +void cwrite(T...)(T args) if (!is(T[0] : File)) +{ + stdout.cwrite(args); +} + +/// Coloured writef. +void cwritef(T...)(T args) +{ + stdout.cwritef(args); +} + +/// Coloured writefln. +void cwritefln(T...)(T args) +{ + stdout.cwritefln(args); +} + +/// Coloured writeln. +void cwriteln(T...)(T args) +{ + // Most general instance + stdout.cwrite(args, '\n'); +} + +/// Coloured writef to a File. +void cwritef(File f, Char, A...)(in Char[] fmt, A args) +{ + auto s = format(fmt, args); + f.write(s); // TODO support colours +} + +/// Coloured writef to a File. +void cwrite(S...)(File f, S args) +{ + import std.conv : to; + + string s = ""; + foreach(arg; args) + s ~= to!string(arg); + + f.write(s); +} + diff --git a/source/colorize/package.d b/source/colorize/package.d index 0669be1..c4c07f5 100644 --- a/source/colorize/package.d +++ b/source/colorize/package.d @@ -7,4 +7,4 @@ module colorize; public import colorize.colorize; -public import colorize.winterm; \ No newline at end of file +public import colorize.cwrite; \ No newline at end of file diff --git a/source/colorize/winterm.d b/source/colorize/winterm.d index 93030d7..c0d76aa 100644 --- a/source/colorize/winterm.d +++ b/source/colorize/winterm.d @@ -4,4 +4,48 @@ * License: Licensed under the MIT license. See LICENSE for more information * Version: 0.1.0 */ -module colorize.winterm; \ No newline at end of file +module colorize.winterm; + + +version(Windows) +{ + import core.sys.windows.windows; + + // This is a state machine to enable terminal colors on Windows. + // Parses and interpret ANSI/VT100 Terminal Control Escape Sequences. + // Only supports fg and bg colors. + struct WinTermEmulation + { + public: + this(bool workardound = true) nothrow + { + _console = GetStdHandle(STD_OUTPUT_HANDLE); + + // saves console attributes + _savedInitialColor = (0 != GetConsoleScreenBufferInfo(_console, &consoleInfo)); + + } + + ~this() + { + if (_savedInitialColor) + { + SetConsoleTextAttribute(_console, consoleInfo.wAttributes); + _savedInitialColor = false; + } + } + + void feed(dchar d) nothrow + { + + } + + private: + HANDLE _console; + bool _savedInitialColor; + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + } +} + + + From 48444a6fb680eccdaf46ba6a87516a97b09526f6 Mon Sep 17 00:00:00 2001 From: ponce Date: Tue, 29 Jul 2014 00:20:33 +0200 Subject: [PATCH 3/9] Coloured write now uses WinTermEmulation on Windows. Basic state machine for parsing ANSI VT100 subset. --- source/colorize/cwrite.d | 15 ++++-- source/colorize/winterm.d | 106 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 8 deletions(-) diff --git a/source/colorize/cwrite.d b/source/colorize/cwrite.d index 5550a29..3917e8a 100644 --- a/source/colorize/cwrite.d +++ b/source/colorize/cwrite.d @@ -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); + } } diff --git a/source/colorize/winterm.d b/source/colorize/winterm.d index c0d76aa..e989045 100644 --- a/source/colorize/winterm.d +++ b/source/colorize/winterm.d @@ -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: + } + } } } From 30f4576db5bd06d563aa2d9e44ad716419682ceb Mon Sep 17 00:00:00 2001 From: ponce Date: Tue, 29 Jul 2014 00:41:50 +0200 Subject: [PATCH 4/9] Implement colour changing, still not working. --- source/colorize/cwrite.d | 5 ++- source/colorize/winterm.d | 84 +++++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/source/colorize/cwrite.d b/source/colorize/cwrite.d index 3917e8a..5ccfe36 100644 --- a/source/colorize/cwrite.d +++ b/source/colorize/cwrite.d @@ -55,7 +55,10 @@ void cwrite(S...)(File f, S args) { auto winterm = WinTermEmulation(); foreach(c ; s) - winterm.feed(c); + { + if (winterm.feed(c)) + f.write(c); + } } else { diff --git a/source/colorize/winterm.d b/source/colorize/winterm.d index e989045..a2c7479 100644 --- a/source/colorize/winterm.d +++ b/source/colorize/winterm.d @@ -13,7 +13,7 @@ version(Windows) // This is a state machine to enable terminal colors on Windows. // Parses and interpret ANSI/VT100 Terminal Control Escape Sequences. - // Only supports fg and bg colors. + // Only supports colour sequences, will output char incorrectly on invalid input. struct WinTermEmulation { public: @@ -53,7 +53,7 @@ version(Windows) if (d == '[') { _state = readingAttribute; - _currentAttr = 0; + _parsedAttr = 0; return false; } break; @@ -62,16 +62,18 @@ version(Windows) case readingAttribute: if (d >= '0' && d <= '9') { - _parsedAttr = _parsedAttr * 10 + (_parsedAttr - '0'); + _parsedAttr = _parsedAttr * 10 + (d - '0'); return false; } else if (d == ';') { executeAttribute(_parsedAttr); + _parsedAttr = 0; return false; } else if (d == 'm') { + executeAttribute(_parsedAttr); _state = State.initial; return false; } @@ -95,49 +97,55 @@ version(Windows) readingAttribute } + void setForegroundColor(WORD fgFlags) nothrow @nogc + { + _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); + _currentAttr = _currentAttr | fgFlags; + SetConsoleTextAttribute(_console, _currentAttr); + } + + void setBackgroundColor(WORD bgFlags) nothrow @nogc + { + _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); + _currentAttr = _currentAttr | bgFlags; + SetConsoleTextAttribute(_console, _currentAttr); + } + void executeAttribute(int attr) nothrow @nogc { switch (attr) { - /+ case 0: - if (_savedInitialColor) - SetConsoleTextAttribute(_console, consoleInfo.wAttributes); + case 0: + // reset all attributes + SetConsoleTextAttribute(_console, consoleInfo.wAttributes); break; default: + if ( (30 <= attr && attr <= 37) || (90 <= attr && attr <= 97) ) + { + WORD color = 0; + if (90 <= attr && attr <= 97) + { + color = FOREGROUND_INTENSITY; + attr -= 60; + } + attr -= 30; + color |= (attr & 1 ? FOREGROUND_RED : 0) | (attr & 2 ? FOREGROUND_GREEN : 0) | (attr & 4 ? FOREGROUND_BLUE : 0); + setForegroundColor(color); + } - 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: + if ( (40 <= attr && attr <= 47) || (100 <= attr && attr <= 107) ) + { + WORD color = 0; + if (100 <= attr && attr <= 107) + { + color = BACKGROUND_INTENSITY; + attr -= 60; + } + attr -= 40; + color |= (attr & 1 ? BACKGROUND_RED : 0) | (attr & 2 ? BACKGROUND_GREEN : 0) | (attr & 4 ? BACKGROUND_BLUE : 0); + setBackgroundColor(color); + } } } } From 8ff025230e7e25b3bb1566844c2482a7fa01df90 Mon Sep 17 00:00:00 2001 From: ponce Date: Tue, 29 Jul 2014 23:36:46 +0200 Subject: [PATCH 5/9] fg and bg colours working. There was a problem with changing colors before stdout was ever flushed. --- source/colorize/cwrite.d | 21 +++++++++++++++++---- source/colorize/winterm.d | 26 +++++++++++++++++--------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/source/colorize/cwrite.d b/source/colorize/cwrite.d index 5ccfe36..cd4e7fb 100644 --- a/source/colorize/cwrite.d +++ b/source/colorize/cwrite.d @@ -53,11 +53,24 @@ void cwrite(S...)(File f, S args) version(Windows) { - auto winterm = WinTermEmulation(); - foreach(c ; s) + WinTermEmulation winterm; + winterm.initialize(); + foreach(dchar c ; s) { - if (winterm.feed(c)) - f.write(c); + auto charAction = winterm.feed(c); + final switch(charAction) with (WinTermEmulation.CharAction) + { + case drop: + break; + + case write: + f.write(c); + break; + + case flush: + f.flush(); + break; + } } } else diff --git a/source/colorize/winterm.d b/source/colorize/winterm.d index a2c7479..7406d1a 100644 --- a/source/colorize/winterm.d +++ b/source/colorize/winterm.d @@ -17,7 +17,7 @@ version(Windows) struct WinTermEmulation { public: - this(bool workardound = true) nothrow @nogc + void initialize() nothrow @nogc { // saves console attributes _console = GetStdHandle(STD_OUTPUT_HANDLE); @@ -36,8 +36,16 @@ version(Windows) } } - // Eat one character and update color state accordingly. Return true if this character should be displayed. - bool feed(dchar d) nothrow @nogc + enum CharAction + { + write, + drop, + flush + } + + // Eat one character and update color state accordingly. + // What to do with the fed character. + CharAction feed(dchar d) nothrow @nogc { final switch(_state) with (State) { @@ -45,7 +53,7 @@ version(Windows) if (d == '\x1B') { _state = escaped; - return false; + return CharAction.flush; } break; @@ -54,7 +62,7 @@ version(Windows) { _state = readingAttribute; _parsedAttr = 0; - return false; + return CharAction.drop; } break; @@ -63,23 +71,23 @@ version(Windows) if (d >= '0' && d <= '9') { _parsedAttr = _parsedAttr * 10 + (d - '0'); - return false; + return CharAction.drop; } else if (d == ';') { executeAttribute(_parsedAttr); _parsedAttr = 0; - return false; + return CharAction.drop; } else if (d == 'm') { executeAttribute(_parsedAttr); _state = State.initial; - return false; + return CharAction.drop; } break; } - return true; + return CharAction.write; } private: From 4d98f3f9d373a1f246d4e2051599c79720e5aea2 Mon Sep 17 00:00:00 2001 From: ponce on vps Date: Tue, 29 Jul 2014 23:49:38 +0200 Subject: [PATCH 6/9] Fix compatibility with linux and 2.065 --- source/colorize/cwrite.d | 2 +- source/colorize/winterm.d | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/colorize/cwrite.d b/source/colorize/cwrite.d index cd4e7fb..9b67ffa 100644 --- a/source/colorize/cwrite.d +++ b/source/colorize/cwrite.d @@ -36,7 +36,7 @@ void cwriteln(T...)(T args) } /// Coloured writef to a File. -void cwritef(File f, Char, A...)(in Char[] fmt, A args) +void cwritef(Char, A...)(File f, in Char[] fmt, A args) { auto s = format(fmt, args); f.cwrite(s); diff --git a/source/colorize/winterm.d b/source/colorize/winterm.d index 7406d1a..d24b294 100644 --- a/source/colorize/winterm.d +++ b/source/colorize/winterm.d @@ -17,7 +17,7 @@ version(Windows) struct WinTermEmulation { public: - void initialize() nothrow @nogc + @nogc void initialize() nothrow { // saves console attributes _console = GetStdHandle(STD_OUTPUT_HANDLE); @@ -26,7 +26,7 @@ version(Windows) _state = State.initial; } - ~this() nothrow @nogc + @nogc ~this() nothrow { // Restore initial text attributes on release if (_savedInitialColor) @@ -45,7 +45,7 @@ version(Windows) // Eat one character and update color state accordingly. // What to do with the fed character. - CharAction feed(dchar d) nothrow @nogc + @nogc CharAction feed(dchar d) nothrow { final switch(_state) with (State) { @@ -105,21 +105,21 @@ version(Windows) readingAttribute } - void setForegroundColor(WORD fgFlags) nothrow @nogc + @nogc void setForegroundColor(WORD fgFlags) nothrow { _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); _currentAttr = _currentAttr | fgFlags; SetConsoleTextAttribute(_console, _currentAttr); } - void setBackgroundColor(WORD bgFlags) nothrow @nogc + @nogc void setBackgroundColor(WORD bgFlags) nothrow { _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); _currentAttr = _currentAttr | bgFlags; SetConsoleTextAttribute(_console, _currentAttr); } - void executeAttribute(int attr) nothrow @nogc + @nogc void executeAttribute(int attr) nothrow { switch (attr) { From 183ee21692ab631df572bc5fd60181453dc59966 Mon Sep 17 00:00:00 2001 From: ponce Date: Tue, 29 Jul 2014 23:53:59 +0200 Subject: [PATCH 7/9] Whitespace tweak. --- source/colorize/winterm.d | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/colorize/winterm.d b/source/colorize/winterm.d index d24b294..916fef8 100644 --- a/source/colorize/winterm.d +++ b/source/colorize/winterm.d @@ -107,14 +107,14 @@ version(Windows) @nogc void setForegroundColor(WORD fgFlags) nothrow { - _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); + _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); _currentAttr = _currentAttr | fgFlags; SetConsoleTextAttribute(_console, _currentAttr); } @nogc void setBackgroundColor(WORD bgFlags) nothrow { - _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); + _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); _currentAttr = _currentAttr | bgFlags; SetConsoleTextAttribute(_console, _currentAttr); } @@ -138,7 +138,7 @@ version(Windows) attr -= 60; } attr -= 30; - color |= (attr & 1 ? FOREGROUND_RED : 0) | (attr & 2 ? FOREGROUND_GREEN : 0) | (attr & 4 ? FOREGROUND_BLUE : 0); + color |= (attr & 1 ? FOREGROUND_RED : 0) | (attr & 2 ? FOREGROUND_GREEN : 0) | (attr & 4 ? FOREGROUND_BLUE : 0); setForegroundColor(color); } @@ -151,7 +151,7 @@ version(Windows) attr -= 60; } attr -= 40; - color |= (attr & 1 ? BACKGROUND_RED : 0) | (attr & 2 ? BACKGROUND_GREEN : 0) | (attr & 4 ? BACKGROUND_BLUE : 0); + color |= (attr & 1 ? BACKGROUND_RED : 0) | (attr & 2 ? BACKGROUND_GREEN : 0) | (attr & 4 ? BACKGROUND_BLUE : 0); setBackgroundColor(color); } } From 57605758d25d289782ea4ff502d2d24d4b34a5e1 Mon Sep 17 00:00:00 2001 From: ponce Date: Wed, 30 Jul 2014 00:29:05 +0200 Subject: [PATCH 8/9] 2-space indent --- source/colorize/cwrite.d | 63 ++++----- source/colorize/winterm.d | 289 +++++++++++++++++++------------------- 2 files changed, 172 insertions(+), 180 deletions(-) diff --git a/source/colorize/cwrite.d b/source/colorize/cwrite.d index 9b67ffa..f5e5857 100644 --- a/source/colorize/cwrite.d +++ b/source/colorize/cwrite.d @@ -13,69 +13,62 @@ import colorize.winterm; /// Coloured write. void cwrite(T...)(T args) if (!is(T[0] : File)) { - stdout.cwrite(args); + stdout.cwrite(args); } /// Coloured writef. void cwritef(T...)(T args) { - stdout.cwritef(args); + stdout.cwritef(args); } /// Coloured writefln. void cwritefln(T...)(T args) { - stdout.cwritef(args, "\n"); + stdout.cwritef(args, "\n"); } /// Coloured writeln. void cwriteln(T...)(T args) { - // Most general instance - stdout.cwrite(args, '\n'); + // Most general instance + stdout.cwrite(args, '\n'); } /// Coloured writef to a File. void cwritef(Char, A...)(File f, in Char[] fmt, A args) { - auto s = format(fmt, args); - f.cwrite(s); + auto s = format(fmt, args); + f.cwrite(s); } /// Coloured writef to a File. void cwrite(S...)(File f, S args) { - import std.conv : to; + import std.conv : to; - string s = ""; - foreach(arg; args) - s ~= to!string(arg); + string s = ""; + foreach(arg; args) + s ~= to!string(arg); - version(Windows) + version(Windows) + { + WinTermEmulation winterm; + winterm.initialize(); + foreach(dchar c ; s) { - WinTermEmulation winterm; - winterm.initialize(); - foreach(dchar c ; s) - { - auto charAction = winterm.feed(c); - final switch(charAction) with (WinTermEmulation.CharAction) - { - case drop: - break; - - case write: - f.write(c); - break; - - case flush: - f.flush(); - break; - } - } - } - else - { - f.write(s); + auto charAction = winterm.feed(c); + final switch(charAction) with (WinTermEmulation.CharAction) + { + case drop: break; + case write: f.write(c); break; + case flush: f.flush(); break; + } } + } + else + { + f.write(s); + } } diff --git a/source/colorize/winterm.d b/source/colorize/winterm.d index 916fef8..a10e731 100644 --- a/source/colorize/winterm.d +++ b/source/colorize/winterm.d @@ -9,154 +9,153 @@ module colorize.winterm; version(Windows) { - import core.sys.windows.windows; + import core.sys.windows.windows; - // This is a state machine to enable terminal colors on Windows. - // Parses and interpret ANSI/VT100 Terminal Control Escape Sequences. - // Only supports colour sequences, will output char incorrectly on invalid input. - struct WinTermEmulation + // This is a state machine to enable terminal colors on Windows. + // Parses and interpret ANSI/VT100 Terminal Control Escape Sequences. + // Only supports colour sequences, will output char incorrectly on invalid input. + struct WinTermEmulation + { + public: + @nogc void initialize() nothrow { - public: - @nogc void initialize() nothrow - { - // saves console attributes - _console = GetStdHandle(STD_OUTPUT_HANDLE); - _savedInitialColor = (0 != GetConsoleScreenBufferInfo(_console, &consoleInfo)); - - _state = State.initial; - } - - @nogc ~this() nothrow - { - // Restore initial text attributes on release - if (_savedInitialColor) - { - SetConsoleTextAttribute(_console, consoleInfo.wAttributes); - _savedInitialColor = false; - } - } - - enum CharAction - { - write, - drop, - flush - } - - // Eat one character and update color state accordingly. - // What to do with the fed character. - @nogc CharAction feed(dchar d) nothrow - { - final switch(_state) with (State) - { - case initial: - if (d == '\x1B') - { - _state = escaped; - return CharAction.flush; - } - break; - - case escaped: - if (d == '[') - { - _state = readingAttribute; - _parsedAttr = 0; - return CharAction.drop; - } - break; - - - case readingAttribute: - if (d >= '0' && d <= '9') - { - _parsedAttr = _parsedAttr * 10 + (d - '0'); - return CharAction.drop; - } - else if (d == ';') - { - executeAttribute(_parsedAttr); - _parsedAttr = 0; - return CharAction.drop; - } - else if (d == 'm') - { - executeAttribute(_parsedAttr); - _state = State.initial; - return CharAction.drop; - } - break; - } - return CharAction.write; - } - - private: - HANDLE _console; - bool _savedInitialColor; - CONSOLE_SCREEN_BUFFER_INFO consoleInfo; - State _state; - WORD _currentAttr; - int _parsedAttr; - - enum State - { - initial, - escaped, - readingAttribute - } - - @nogc void setForegroundColor(WORD fgFlags) nothrow - { - _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); - _currentAttr = _currentAttr | fgFlags; - SetConsoleTextAttribute(_console, _currentAttr); - } - - @nogc void setBackgroundColor(WORD bgFlags) nothrow - { - _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); - _currentAttr = _currentAttr | bgFlags; - SetConsoleTextAttribute(_console, _currentAttr); - } - - @nogc void executeAttribute(int attr) nothrow - { - switch (attr) - { - case 0: - // reset all attributes - SetConsoleTextAttribute(_console, consoleInfo.wAttributes); - break; - - default: - if ( (30 <= attr && attr <= 37) || (90 <= attr && attr <= 97) ) - { - WORD color = 0; - if (90 <= attr && attr <= 97) - { - color = FOREGROUND_INTENSITY; - attr -= 60; - } - attr -= 30; - color |= (attr & 1 ? FOREGROUND_RED : 0) | (attr & 2 ? FOREGROUND_GREEN : 0) | (attr & 4 ? FOREGROUND_BLUE : 0); - setForegroundColor(color); - } - - if ( (40 <= attr && attr <= 47) || (100 <= attr && attr <= 107) ) - { - WORD color = 0; - if (100 <= attr && attr <= 107) - { - color = BACKGROUND_INTENSITY; - attr -= 60; - } - attr -= 40; - color |= (attr & 1 ? BACKGROUND_RED : 0) | (attr & 2 ? BACKGROUND_GREEN : 0) | (attr & 4 ? BACKGROUND_BLUE : 0); - setBackgroundColor(color); - } - } - } + // saves console attributes + _console = GetStdHandle(STD_OUTPUT_HANDLE); + _savedInitialColor = (0 != GetConsoleScreenBufferInfo(_console, &consoleInfo)); + _state = State.initial; } + + @nogc ~this() nothrow + { + // Restore initial text attributes on release + if (_savedInitialColor) + { + SetConsoleTextAttribute(_console, consoleInfo.wAttributes); + _savedInitialColor = false; + } + } + + enum CharAction + { + write, + drop, + flush + } + + // Eat one character and update color state accordingly. + // Returns what to do with the fed character. + @nogc CharAction feed(dchar d) nothrow + { + final switch(_state) with (State) + { + case initial: + if (d == '\x1B') + { + _state = escaped; + return CharAction.flush; + } + break; + + case escaped: + if (d == '[') + { + _state = readingAttribute; + _parsedAttr = 0; + return CharAction.drop; + } + break; + + + case readingAttribute: + if (d >= '0' && d <= '9') + { + _parsedAttr = _parsedAttr * 10 + (d - '0'); + return CharAction.drop; + } + else if (d == ';') + { + executeAttribute(_parsedAttr); + _parsedAttr = 0; + return CharAction.drop; + } + else if (d == 'm') + { + executeAttribute(_parsedAttr); + _state = State.initial; + return CharAction.drop; + } + break; + } + return CharAction.write; + } + + private: + HANDLE _console; + bool _savedInitialColor; + CONSOLE_SCREEN_BUFFER_INFO consoleInfo; + State _state; + WORD _currentAttr; + int _parsedAttr; + + enum State + { + initial, + escaped, + readingAttribute + } + + @nogc void setForegroundColor(WORD fgFlags) nothrow + { + _currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); + _currentAttr = _currentAttr | fgFlags; + SetConsoleTextAttribute(_console, _currentAttr); + } + + @nogc void setBackgroundColor(WORD bgFlags) nothrow + { + _currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY); + _currentAttr = _currentAttr | bgFlags; + SetConsoleTextAttribute(_console, _currentAttr); + } + + @nogc void executeAttribute(int attr) nothrow + { + switch (attr) + { + case 0: + // reset all attributes + SetConsoleTextAttribute(_console, consoleInfo.wAttributes); + break; + + default: + if ( (30 <= attr && attr <= 37) || (90 <= attr && attr <= 97) ) + { + WORD color = 0; + if (90 <= attr && attr <= 97) + { + color = FOREGROUND_INTENSITY; + attr -= 60; + } + attr -= 30; + color |= (attr & 1 ? FOREGROUND_RED : 0) | (attr & 2 ? FOREGROUND_GREEN : 0) | (attr & 4 ? FOREGROUND_BLUE : 0); + setForegroundColor(color); + } + + if ( (40 <= attr && attr <= 47) || (100 <= attr && attr <= 107) ) + { + WORD color = 0; + if (100 <= attr && attr <= 107) + { + color = BACKGROUND_INTENSITY; + attr -= 60; + } + attr -= 40; + color |= (attr & 1 ? BACKGROUND_RED : 0) | (attr & 2 ? BACKGROUND_GREEN : 0) | (attr & 4 ? BACKGROUND_BLUE : 0); + setBackgroundColor(color); + } + } + } + } } From 4c6aba25be59061b5565619fa9a73c5b50ee1b82 Mon Sep 17 00:00:00 2001 From: ponce Date: Wed, 30 Jul 2014 00:29:55 +0200 Subject: [PATCH 9/9] Add myself as author. I do not wish to retain copyright so LICENSE can stay as is. --- dub.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dub.json b/dub.json index 3aef623..547b549 100644 --- a/dub.json +++ b/dub.json @@ -6,6 +6,7 @@ "importPaths": ["source"], "sourcePaths": ["source"], "authors": [ - "Pedro Tacla Yamada" + "Pedro Tacla Yamada", + "ponce" ] }