1 /* 2 * Copyright (c) 2018-2020 sel-project 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in all 12 * copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 * 22 */ 23 /** 24 * Copyright: Copyright (c) 2018-2020 sel-project 25 * License: MIT 26 * Authors: Kripth 27 * Source: $(HTTP github.com/sel-project/sel-util/terminal/sel/terminal.d, sel/terminal.d) 28 */ 29 module sel.terminal; 30 31 import std.string : indexOf; 32 33 import sel.format; 34 35 import terminal : Terminal, Color, Foreground; 36 37 private Terminal _terminal; 38 39 static this() { 40 _terminal = new Terminal(); 41 } 42 43 void write(Terminal terminal, string message) { 44 synchronized writeImpl(terminal, message); 45 } 46 47 void write(string message) { 48 write(_terminal, message); 49 } 50 51 void writeln(Terminal terminal, string message) { 52 write(terminal, message); 53 terminal.reset(); 54 terminal.write("\n"); 55 } 56 57 void writeln(string message) { 58 writeln(_terminal, message); 59 } 60 61 void writeImpl(Terminal terminal, string message) { 62 immutable i = message.indexOf('§'); 63 if(i != -1 && i < message.length - 2) { 64 immutable c = message[i+2]; 65 if(c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'k' && c <= 'o' || c == 'r') { 66 terminal.write(message[0..i]); 67 applyFormat(terminal, c); 68 writeImpl(terminal, message[i+3..$]); 69 } else { 70 terminal.write(message[0..i+1]); 71 writeImpl(terminal, message[i+2..$]); 72 } 73 } else { 74 terminal.write(message); 75 } 76 } 77 78 enum char charOf(string code) = code[2]; 79 80 private __gshared Foreground[char] __table; 81 82 shared static this() { 83 84 import std.process : environment; 85 86 if(environment.get("TERM").indexOf("256") != -1) { 87 88 // should support 24-bit colours 89 90 Foreground rgb(uint num) { 91 return Foreground((num >> 16) & 0xFF, (num >> 8) & 0xFF, num & 0xFF); 92 } 93 94 with(Format) { 95 96 __table[charOf!black] = rgb(0x000000); 97 __table[charOf!darkBlue] = rgb(0x0000AA); 98 __table[charOf!darkGreen] = rgb(0x00AA00); 99 __table[charOf!darkAqua] = rgb(0x00AAAA); 100 __table[charOf!darkRed] = rgb(0xAA0000); 101 __table[charOf!darkPurple] = rgb(0xAA00AA); 102 __table[charOf!gold] = rgb(0xFFAA00); 103 __table[charOf!gray] = rgb(0xAAAAAA); 104 __table[charOf!darkGray] = rgb(0x555555); 105 __table[charOf!blue] = rgb(0x5555FF); 106 __table[charOf!green] = rgb(0x55FF55); 107 __table[charOf!aqua] = rgb(0x55FFFF); 108 __table[charOf!red] = rgb(0xFF5555); 109 __table[charOf!lightPurple] = rgb(0xFF55FF); 110 __table[charOf!yellow] = rgb(0xFFFF55); 111 __table[charOf!white] = rgb(0xFFFFFF); 112 113 } 114 115 } else { 116 117 with(Format) { 118 119 __table[charOf!black] = Color.black; 120 __table[charOf!darkBlue] = Color.blue; 121 __table[charOf!darkGreen] = Color.green; 122 __table[charOf!darkAqua] = Color.cyan; 123 __table[charOf!darkRed] = Color.red; 124 __table[charOf!darkPurple] = Color.magenta; 125 __table[charOf!gold] = Color.yellow; 126 __table[charOf!gray] = Color.lightGray; 127 __table[charOf!darkGray] = Color.gray; 128 __table[charOf!blue] = Color.brightBlue; 129 __table[charOf!green] = Color.brightGreen; 130 __table[charOf!aqua] = Color.brightCyan; 131 __table[charOf!red] = Color.brightRed; 132 __table[charOf!lightPurple] = Color.brightMagenta; 133 __table[charOf!yellow] = Color.brightYellow; 134 __table[charOf!white] = Color.white; 135 136 } 137 138 } 139 140 } 141 142 private void applyFormat(Terminal terminal, char c) { 143 switch(c) with(Format) { 144 case charOf!obfuscated: break; // not supported 145 case charOf!bold: 146 terminal.bold = true; 147 break; 148 case charOf!strikethrough: 149 terminal.strikethrough = true; 150 break; 151 case charOf!underlined: 152 terminal.underlined = true; 153 break; 154 case charOf!italic: 155 terminal.italic = true; 156 break; 157 case charOf!reset: 158 terminal.reset(); 159 break; 160 default: 161 terminal.foreground = __table[c]; 162 break; 163 } 164 } 165 166 unittest { 167 168 foreach(immutable member ; __traits(allMembers, Format)) { 169 with(Format) writeln(mixin(member) ~ member); 170 } 171 172 foreach(immutable member ; __traits(allMembers, Format)) { 173 with(Format) write(mixin(member) ~ "#"); 174 } 175 176 _terminal.writeln(); 177 178 }