Skip to content

Commit f630d6f

Browse files
committed
Merge pull request #3 from p0nce/master
Add Windows Support
2 parents b4a23ba + 4c6aba2 commit f630d6f

File tree

5 files changed

+251
-1
lines changed

5 files changed

+251
-1
lines changed

dub.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
"description": "A port of Ruby's colorize library to D.",
44
"license": "MIT",
55
"copyright": "Copyright © 2014, Pedro Tacla Yamada",
6+
"importPaths": ["source"],
7+
"sourcePaths": ["source"],
68
"authors": [
7-
"Pedro Tacla Yamada"
9+
"Pedro Tacla Yamada",
10+
"ponce"
811
]
912
}

source/colorize.d renamed to source/colorize/colorize.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* License: Licensed under the MIT license. See LICENSE for more information
55
* Version: 0.1.0
66
*/
7+
module colorize.colorize;
78

89
import std.string : format;
910

source/colorize/cwrite.d

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* Authors: ponce
3+
* Date: July 28, 2014
4+
* License: Licensed under the MIT license. See LICENSE for more information
5+
* Version: 0.1.0
6+
*/
7+
module colorize.cwrite;
8+
9+
import std.stdio : File, stdout;
10+
11+
import colorize.winterm;
12+
13+
/// Coloured write.
14+
void cwrite(T...)(T args) if (!is(T[0] : File))
15+
{
16+
stdout.cwrite(args);
17+
}
18+
19+
/// Coloured writef.
20+
void cwritef(T...)(T args)
21+
{
22+
stdout.cwritef(args);
23+
}
24+
25+
/// Coloured writefln.
26+
void cwritefln(T...)(T args)
27+
{
28+
stdout.cwritef(args, "\n");
29+
}
30+
31+
/// Coloured writeln.
32+
void cwriteln(T...)(T args)
33+
{
34+
// Most general instance
35+
stdout.cwrite(args, '\n');
36+
}
37+
38+
/// Coloured writef to a File.
39+
void cwritef(Char, A...)(File f, in Char[] fmt, A args)
40+
{
41+
auto s = format(fmt, args);
42+
f.cwrite(s);
43+
}
44+
45+
/// Coloured writef to a File.
46+
void cwrite(S...)(File f, S args)
47+
{
48+
import std.conv : to;
49+
50+
string s = "";
51+
foreach(arg; args)
52+
s ~= to!string(arg);
53+
54+
version(Windows)
55+
{
56+
WinTermEmulation winterm;
57+
winterm.initialize();
58+
foreach(dchar c ; s)
59+
{
60+
auto charAction = winterm.feed(c);
61+
final switch(charAction) with (WinTermEmulation.CharAction)
62+
{
63+
case drop: break;
64+
case write: f.write(c); break;
65+
case flush: f.flush(); break;
66+
}
67+
}
68+
}
69+
else
70+
{
71+
f.write(s);
72+
}
73+
}
74+

source/colorize/package.d

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Authors: ponce
3+
* Date: July 28, 2014
4+
* License: Licensed under the MIT license. See LICENSE for more information
5+
* Version: 0.1.0
6+
*/
7+
module colorize;
8+
9+
public import colorize.colorize;
10+
public import colorize.cwrite;

source/colorize/winterm.d

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/**
2+
* Authors: ponce
3+
* Date: July 28, 2014
4+
* License: Licensed under the MIT license. See LICENSE for more information
5+
* Version: 0.1.0
6+
*/
7+
module colorize.winterm;
8+
9+
10+
version(Windows)
11+
{
12+
import core.sys.windows.windows;
13+
14+
// This is a state machine to enable terminal colors on Windows.
15+
// Parses and interpret ANSI/VT100 Terminal Control Escape Sequences.
16+
// Only supports colour sequences, will output char incorrectly on invalid input.
17+
struct WinTermEmulation
18+
{
19+
public:
20+
@nogc void initialize() nothrow
21+
{
22+
// saves console attributes
23+
_console = GetStdHandle(STD_OUTPUT_HANDLE);
24+
_savedInitialColor = (0 != GetConsoleScreenBufferInfo(_console, &consoleInfo));
25+
_state = State.initial;
26+
}
27+
28+
@nogc ~this() nothrow
29+
{
30+
// Restore initial text attributes on release
31+
if (_savedInitialColor)
32+
{
33+
SetConsoleTextAttribute(_console, consoleInfo.wAttributes);
34+
_savedInitialColor = false;
35+
}
36+
}
37+
38+
enum CharAction
39+
{
40+
write,
41+
drop,
42+
flush
43+
}
44+
45+
// Eat one character and update color state accordingly.
46+
// Returns what to do with the fed character.
47+
@nogc CharAction feed(dchar d) nothrow
48+
{
49+
final switch(_state) with (State)
50+
{
51+
case initial:
52+
if (d == '\x1B')
53+
{
54+
_state = escaped;
55+
return CharAction.flush;
56+
}
57+
break;
58+
59+
case escaped:
60+
if (d == '[')
61+
{
62+
_state = readingAttribute;
63+
_parsedAttr = 0;
64+
return CharAction.drop;
65+
}
66+
break;
67+
68+
69+
case readingAttribute:
70+
if (d >= '0' && d <= '9')
71+
{
72+
_parsedAttr = _parsedAttr * 10 + (d - '0');
73+
return CharAction.drop;
74+
}
75+
else if (d == ';')
76+
{
77+
executeAttribute(_parsedAttr);
78+
_parsedAttr = 0;
79+
return CharAction.drop;
80+
}
81+
else if (d == 'm')
82+
{
83+
executeAttribute(_parsedAttr);
84+
_state = State.initial;
85+
return CharAction.drop;
86+
}
87+
break;
88+
}
89+
return CharAction.write;
90+
}
91+
92+
private:
93+
HANDLE _console;
94+
bool _savedInitialColor;
95+
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
96+
State _state;
97+
WORD _currentAttr;
98+
int _parsedAttr;
99+
100+
enum State
101+
{
102+
initial,
103+
escaped,
104+
readingAttribute
105+
}
106+
107+
@nogc void setForegroundColor(WORD fgFlags) nothrow
108+
{
109+
_currentAttr = _currentAttr & ~(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
110+
_currentAttr = _currentAttr | fgFlags;
111+
SetConsoleTextAttribute(_console, _currentAttr);
112+
}
113+
114+
@nogc void setBackgroundColor(WORD bgFlags) nothrow
115+
{
116+
_currentAttr = _currentAttr & ~(BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY);
117+
_currentAttr = _currentAttr | bgFlags;
118+
SetConsoleTextAttribute(_console, _currentAttr);
119+
}
120+
121+
@nogc void executeAttribute(int attr) nothrow
122+
{
123+
switch (attr)
124+
{
125+
case 0:
126+
// reset all attributes
127+
SetConsoleTextAttribute(_console, consoleInfo.wAttributes);
128+
break;
129+
130+
default:
131+
if ( (30 <= attr && attr <= 37) || (90 <= attr && attr <= 97) )
132+
{
133+
WORD color = 0;
134+
if (90 <= attr && attr <= 97)
135+
{
136+
color = FOREGROUND_INTENSITY;
137+
attr -= 60;
138+
}
139+
attr -= 30;
140+
color |= (attr & 1 ? FOREGROUND_RED : 0) | (attr & 2 ? FOREGROUND_GREEN : 0) | (attr & 4 ? FOREGROUND_BLUE : 0);
141+
setForegroundColor(color);
142+
}
143+
144+
if ( (40 <= attr && attr <= 47) || (100 <= attr && attr <= 107) )
145+
{
146+
WORD color = 0;
147+
if (100 <= attr && attr <= 107)
148+
{
149+
color = BACKGROUND_INTENSITY;
150+
attr -= 60;
151+
}
152+
attr -= 40;
153+
color |= (attr & 1 ? BACKGROUND_RED : 0) | (attr & 2 ? BACKGROUND_GREEN : 0) | (attr & 4 ? BACKGROUND_BLUE : 0);
154+
setBackgroundColor(color);
155+
}
156+
}
157+
}
158+
}
159+
}
160+
161+
162+

0 commit comments

Comments
 (0)