1 /++
2 	D wrappers for the C functions
3 
4 	Authors: Matthew Soucy, msoucy@csh.rit.edu
5 	License: Subject to the terms of the MIT license, as written in the included LICENSE file.
6 +/
7 module fabd.dfab;
8 
9 import cfab = fabd.fab;
10 import fabd.fab : Color, rgb_t;
11 
12 import std.string : toStringz;
13 import std.conv : to;
14 import std.traits : isSomeString;
15 
16 private string takeown(char* cptr)
17 {
18 	import core.stdc.string : strlen;
19 	import core.stdc.stdlib : free;
20 	// When fromStringz is in default repos (IE ldc on Fedora)
21 	// it should be used instead of manually reimplementing it
22 	auto dstr = cptr[0 .. strlen(cptr)].idup;
23 	free(cptr);
24 	return dstr;
25 }
26 
27 /++
28 	Applies the color $(D c) to $(D text).
29 
30 	Returns the string created as a result
31 +/
32 string apply_color(String)(String text, Color c)
33 	if(isSomeString!String)
34 {
35 	return cfab.apply_color(c, text.toStringz).takeown;
36 }
37 
38 /++
39 	Applies the $(D c) to the foreground of $(D text)
40 +/
41 string foreground_256(String)(String text, rgb_t c)
42 	if(isSomeString!String)
43 {
44 	return cfab.foreground_256(c, text.toStringz).takeown;
45 }
46 
47 /++
48 	Applies the $(D c) to the background of $(D text)
49 +/
50 string background_256(String)(String text, rgb_t c)
51 	if(isSomeString!String)
52 {
53 	return cfab.background_256(c, text.toStringz).takeown;
54 }
55 
56 /++
57 	Highlights $(D text) with the color $(D c)
58 +/
59 string highlight_256(String)(String text, rgb_t c)
60 	if(isSomeString!String)
61 {
62 	return cfab.highlight_256(c, text.toStringz).takeown;
63 }
64 
65 /++
66 	Converts an xterm color number into an RGB value
67 +/
68 rgb_t xterm_to_rgb(int xcolor)
69 {
70 	auto res = cfab.xterm_to_rgb_i(xcolor);
71 	return cfab.rgb_t(
72 		(res>>16) & 0xFF,
73 		(res>>8) & 0xFF,
74 		res & 0xFF
75 	);
76 }
77 
78 /++
79 	Create an $(D rgb_t)
80 	Params:
81 		r = The amount of red
82 		g = The amount of green
83 		b = The amount of blue
84 +/
85 auto rgb(ubyte r, ubyte g, ubyte b) {
86 	return rgb_t(r, g, b);
87 }
88 
89 ///Stores converted image data
90 struct Image
91 {
92 public:
93 	/++
94 		Load an image
95 		Params:
96 			path = The name of the file to load the image from
97 	+/
98 	this(string path)
99 	{
100 		auto xti = cfab.image_to_xterm(path.toStringz);
101 		scope(exit) cfab.xcolor_image_free(xti);
102 		image = cfab.image_to_string(xti).takeown;
103 	}
104 	/// Prints the image
105 	void toString(scope void delegate(const(char)[]) sink) const
106 	{
107 		sink(image);
108 	}
109 private:
110 	@disable this();
111 
112 	string image;
113 }
114 
115 unittest {
116 	// Test styles
117 	import std.algorithm : equal;
118 	import std.range : chain;
119 	enum T = "Hello There";
120 	auto test_generic(Color c, string prefix, string suffix)
121 	{
122 		return equal(T.apply_color(c).to!string, chain(prefix, T, suffix));
123 	}
124 	with(Color) {
125 		assert(test_generic(BOLD, "\x1b[1m", "\x1b[22m"));
126 		assert(test_generic(ITALIC, "\x1b[3m", "\x1b[23m"));
127 		assert(test_generic(UNDER, "\x1b[4m", "\x1b[24m"));
128 		assert(test_generic(UNDER2, "\x1b[21m", "\x1b[24m"));
129 		assert(test_generic(STRIKE, "\x1b[9m", "\x1b[29m"));
130 		assert(test_generic(BLINK, "\x1b[5m", "\x1b[25m"));
131 		assert(test_generic(FLIP, "\x1b[7m", "\x1b[27m"));
132 	}
133 }
134 
135 unittest {
136 	// Test colors
137 	import std.algorithm : equal;
138 	import std.range : chain;
139 	enum T = "Hello There";
140 	auto test_color(Color c, string prefix)
141 	{
142 		return equal(T.apply_color(c).to!string, chain(prefix, T, "\x1b[39m"));
143 	}
144 	with(Color) {
145 		assert(test_color(BLACK, "\x1b[30m"));
146 		assert(test_color(RED, "\x1b[31m"));
147 		assert(test_color(GREEN, "\x1b[32m"));
148 		assert(test_color(YELLOW, "\x1b[33m"));
149 		assert(test_color(BLUE, "\x1b[34m"));
150 		assert(test_color(MAGENTA, "\x1b[35m"));
151 		assert(test_color(CYAN, "\x1b[36m"));
152 		assert(test_color(WHITE, "\x1b[37m"));
153 	}
154 }
155