1 module sily.tui.render;
2 
3 version (Have_speedy_stdio) static import stdio = speedy.stdio;
4 else static import stdio = std.stdio;
5 
6 import std.string: format;
7 import std.conv: to;
8 
9 import sily.color;
10 import sily.bashfmt;
11 import sily.vector;
12 
13 private dstring _screenBuffer = "";
14 
15 /**
16 Escapes color into bash sequence according to selected color mode
17 Params:
18     c = Color
19     b = Is color background
20     m = ColorMode (ansi8, ansi256, truecolor)
21 Returns: Escaped color
22 */
23 string escape(Color c, bool b, ColorMode m) {
24     switch (m) {
25         case ColorMode.truecolor: return c.toTrueColorString(b);
26         case ColorMode.ansi256: return c.toAnsiString(b);
27         case ColorMode.ansi8:
28         default: return c.toAnsi8String(b);
29     }
30 }
31 
32 /// Ditto
33 string escape(Color c, bool b) {
34     return escape(c, b, colorMode);
35 }
36 
37 /// Render color mode
38 enum ColorMode {
39     ansi8, ansi256, truecolor
40 }
41 
42 private ColorMode _colorMode = ColorMode.truecolor;
43 
44 /// Returns current color mode
45 ColorMode colorMode() {
46     return _colorMode;
47 }
48 
49 /// Sets color mode
50 void colorMode(ColorMode c) {
51     _colorMode = c;
52 }
53 
54 /// Returns screen buffer contents
55 dstring readBuffer() {
56     return _screenBuffer;
57 }
58 
59 /// Clears screen buffer
60 void clearBuffer() {
61     _screenBuffer = "";
62 }
63 
64 size_t sizeofBuffer() {
65     return _screenBuffer.length;
66 }
67 
68 /// Writes buffer into stdout and flushes stdout
69 void flushBuffer() {
70     // stdout.write(_screenBuffer);
71     // stdout.flush(); // Eliminates flickering if used instead of no buffer
72     stdio.write(_screenBuffer);
73     // version (Have_speedy_stdio) // unsafe_stdout_flush();
74     version(Have_speedy_stdio) {} else stdio.stdout.flush(); // Eliminates flickering if used instead of no buffer
75 }
76 
77 /// Replaces buffer contents with `content`
78 void writeBuffer(dstring content) {
79     _screenBuffer = content;
80 }
81 
82 /// Formatted writes `args into buffer. Slow
83 void writef(A...)(A args) if (args.length > 0) {
84     _screenBuffer ~= format(args).to!dstring;
85 }
86 
87 /// Writes `args into buffer
88 void write(A...)(A args) if (args.length > 0) {
89     foreach (arg; args) {
90         _screenBuffer ~= arg.to!dstring;
91     }
92 }
93 
94 /// Clears terminal screen
95 void screenClearOnly() {
96     write("\033[2J");
97 }
98 /// Moves cursor in terminal to `{0, 0}`
99 void cursorMoveHome() {
100     write("\033[H");
101 }
102 
103 /**
104 Moves cursor to pos. Allows for chaining
105 Example:
106 ---
107 Render.at(12, 15).write("My pretty text");
108 ---
109 */
110 void cursorMoveTo(uint x, uint y) {
111     write("\033[", y + 1, ";", x + 1, "f");
112 }
113 /// Ditto
114 void cursorMoveTo(uvec2 pos) {
115     cursorMoveTo(pos.x, pos.y);
116 }
117 /// Ditto
118 void cursorMoveTo(ivec2 pos) {
119     cursorMoveTo(cast(uint) pos.x, cast(uint) pos.y);
120 }
121 
122 // TODO:
123 void clearRect(uvec2 pos, uvec2 size) {
124     assert(0, "clearRect not yet implemented");
125 }
126 
127