1 /** 2 * Message formatting utilities 3 */ 4 module birchwood.protocol.formatting; 5 6 import birchwood.client.exceptions; 7 8 /** 9 * Control codes 10 */ 11 public enum ControlCode: char 12 { 13 /** 14 * Reset styling 15 */ 16 Reset = '\x0F', 17 18 /** 19 * Bold text styling 20 */ 21 Bolden = '\x02', 22 23 /** 24 * Italic text styling 25 */ 26 Italic = '\x1D', 27 28 /** 29 * Underlined text styling 30 */ 31 Underline = '\x1F', 32 33 /** 34 * Strikethough text styling 35 */ 36 Strikethrough = '\x1E', 37 38 /** 39 * Monospace text styling 40 */ 41 Monospace = '\x11', 42 43 /** 44 * Reverse colors (NOTE: not universally supported) 45 */ 46 ReverseColors = '\x16', 47 48 /** 49 * ASCII color encoding scheme 50 */ 51 AsciiColor = '\x03', 52 53 /** 54 * Hex color encoding scheme 55 */ 56 HexColor = '\x04' 57 } 58 59 60 /** 61 * Simple color codes 62 */ 63 public enum SimpleColor: string 64 { 65 WHITE = "00", 66 BLACK = "01", 67 BLUE = "02", 68 GREEN = "03", 69 RED = "04", 70 BROWN = "05", 71 MAGENTA = "06", 72 ORANGE = "07", 73 YELLOW = "08", 74 LIGHT_GREEN = "09", 75 CYAN = "10", 76 LIGHT_CYAN = "11", 77 LIGHT_BLUE = "12", 78 PINK = "13", 79 GREY = "14", 80 LIGHT_GREY = "15", 81 DEFAULT = "99" // NOT UNIVERSALLY SUPPORTED 82 } 83 84 /** 85 * Return the hex control character if color is a hexadecimal color code, 86 * the ASCII control character if color is two ASCII digits, and throw an 87 * exception if it's neither. 88 * 89 * This function might be useless now that set_fg and set_fg_bg have been 90 * changed, but I'll keep it in case it's needed later. 91 * 92 * Params: 93 * color = the color to check for 94 * 95 * Returns: the color control type 96 */ 97 private char generateColorControlChar(string color) 98 { 99 if(color.length == 6) 100 { 101 return ControlCode.HexColor; 102 } 103 else if(color.length == 2) 104 { 105 return ControlCode.AsciiColor; 106 } 107 else 108 { 109 throw new BirchwoodException(ErrorType.INVALID_FORMATTING, "Invalid color code (must be either two ASCII digits or a hexadecimal code of the form RRGGBB)"); 110 } 111 } 112 113 /** 114 * Generates a string that changes the foreground color 115 * 116 * Params: 117 * color = the foreground color 118 * 119 * Returns: the color control sequence 120 */ 121 public string setForeground(string color) 122 { 123 char[1] control_char; 124 125 if(color.length == 6) 126 { 127 control_char[0] = ControlCode.HexColor; 128 } 129 else if(color.length == 2) 130 { 131 control_char[0] = ControlCode.AsciiColor; 132 } 133 else 134 { 135 throw new BirchwoodException(ErrorType.INVALID_FORMATTING, "Invalid color code (must be either two ASCII digits or a hexadecimal code of the form RRGGBB)"); 136 } 137 138 return cast(string)control_char~color; 139 } 140 141 /** 142 * Generate a string that sets the foreground and background color 143 * 144 * Params: 145 * fg = foreground color in hex code or ASCII color code 146 * bg = background color 147 * 148 * Returns: the control sequence to set the style 149 */ 150 public string setForegroundBackground(string fg, string bg) 151 { 152 char[1] control_char; 153 154 if(fg.length != bg.length) 155 { 156 throw new BirchwoodException(ErrorType.INVALID_FORMATTING, "Invalid color code (cannot mix hex and ASCII)"); 157 } 158 159 if(fg.length == 6) 160 { 161 control_char[0] = ControlCode.HexColor; 162 } 163 else if(fg.length == 2) 164 { 165 control_char[0] = ControlCode.AsciiColor; 166 } 167 else 168 { 169 throw new BirchwoodException(ErrorType.INVALID_FORMATTING, "Invalid color code (must be either two ASCII digits or a hexadecimal code of the form RRGGBB)"); 170 } 171 172 return cast(string)control_char~fg~","~bg; 173 } 174 175 /** 176 * Generates a string that changes the foreground color (except enum) 177 * 178 * Params: 179 * color = the foreground color 180 * 181 * Returns: the control sequence 182 */ 183 public string setForeground(SimpleColor color) 184 { 185 return ControlCode.AsciiColor~color; 186 } 187 188 /** 189 * Generate a string that sets the foreground and background color (except enum) 190 * 191 * Params: 192 * fg = the foreground color 193 * bg = the background color 194 * 195 * Returns: thecolor control sequence 196 */ 197 public string setForegroundBackground(SimpleColor fg, SimpleColor bg) 198 { 199 return ControlCode.AsciiColor~fg~","~bg; 200 } 201 202 /** 203 * Generate a string that resets the foreground 204 * and background colors 205 * 206 * Returns: The control string 207 */ 208 public string resetForegroundBackground() 209 { 210 return [ControlCode.AsciiColor]; 211 } 212 213 // Format strings with functions (TODO: remove comment) 214 215 /** 216 * Formats the provided text as bold 217 * 218 * Params: 219 * text = the text to bolden 220 * 221 * Returns: the boldened text 222 */ 223 public string bold(string text) 224 { 225 return ControlCode.Bolden~text~ControlCode.Bolden; 226 } 227 228 /** 229 * Formats the provided text in italics 230 * 231 * Params: 232 * text = the text to italicize 233 * 234 * Returns: the italicized text 235 */ 236 public string italics(string text) 237 { 238 return ControlCode.Italic~text~ControlCode.Italic; 239 } 240 241 /** 242 * Formats the text as underlined 243 * 244 * Params: 245 * text = the text to underline 246 * 247 * Returns: the underlined text 248 */ 249 public string underline(string text) 250 { 251 return ControlCode.Underline~text~ControlCode.Underline; 252 } 253 254 /** 255 * Formats the text as strikethroughed 256 * 257 * Params: 258 * text = the text to strikethrough 259 * 260 * Returns: the strikethroughed text 261 */ 262 public string strikethrough(string text) 263 { 264 return ControlCode.Strikethrough~text~ControlCode.Strikethrough; 265 } 266 267 /** 268 * Formats the text as monospaced 269 * 270 * Params: 271 * text = the text to monospace 272 * 273 * Returns: the monospaced text 274 */ 275 public string monospace(string text) 276 { 277 return ControlCode.Monospace~text~ControlCode.Monospace; 278 }