diff --git a/README.md b/README.md index d2dd262..9685d74 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,11 @@ You can take a look at the `Client` API documentation on [DUB](https://birchwood More standards will be added within the next month or so, mostly relating to new response codes that just need to be added. +## Credits + +* [supremestdoggo](https://github.com/supremestdoggo) + * Adding IRC message formatting code (`267f8886150dbd40eb5c2fecb9d7e3a4c8dfd71f`) + ## License See [LICENSE](LICENSE). diff --git a/source/birchwood/client/client.d b/source/birchwood/client/client.d index 9d1da4f..06400bd 100644 --- a/source/birchwood/client/client.d +++ b/source/birchwood/client/client.d @@ -1098,6 +1098,35 @@ public class Client : Thread client.directMessage("(3) Message to myself (multi)", ["birchwood", "birchwood"]); + /** + * Test formatting of text + */ + import birchwood.protocol.formatting; + string formattedTextBold = bold("Hello in bold!"); + string formattedTextItalics = italics("Hello in italics!"); + string formattedTextUnderline = underline("Hello in underline!"); + string formattedTextMonospace = monospace("Hello in monospace!"); + string formattedTextStrikthrough = strikethrough("Hello in strikethrough!"); + client.channelMessage(formattedTextBold, "#birchwood"); + client.channelMessage(formattedTextItalics, "#birchwood"); + client.channelMessage(formattedTextUnderline, "#birchwood"); + client.channelMessage(formattedTextMonospace, "#birchwood"); + client.channelMessage(formattedTextStrikthrough, "#birchwood"); + + string combination = bold(italics("Italiano Boldino")); + client.channelMessage(combination, "#birchwood"); + + string foregroundRedtext = setForeground(SimpleColor.RED)~"This is red text"; + client.channelMessage(foregroundRedtext, "#birchwood"); + + string alternatePattern = setForeground(SimpleColor.RED)~"This "~setForeground(SimpleColor.WHITE)~"is "~setForeground(SimpleColor.BLUE)~"America!"; + client.channelMessage(alternatePattern, "#birchwood"); + + string backgroundText = setForegroundBackground(SimpleColor.RED, SimpleColor.CYAN)~"Birchwood"; + client.channelMessage(backgroundText, "#birchwood"); + + string combined = combination~foregroundRedtext~resetForegroundBackground()~backgroundText~resetForegroundBackground()~alternatePattern; + client.channelMessage(combined, "#birchwood"); /** diff --git a/source/birchwood/client/exceptions.d b/source/birchwood/client/exceptions.d index a66e412..0556e5a 100644 --- a/source/birchwood/client/exceptions.d +++ b/source/birchwood/client/exceptions.d @@ -76,7 +76,13 @@ public enum ErrorType * If the final encoded IRC message * is too long to send to the server */ - COMMAND_TOO_LONG + COMMAND_TOO_LONG, + + /** + * If invalid parameters are passed + * to any of the text formatting functions + */ + INVALID_FORMATTING } /** diff --git a/source/birchwood/protocol/formatting.d b/source/birchwood/protocol/formatting.d index a3fb7b7..2219a00 100644 --- a/source/birchwood/protocol/formatting.d +++ b/source/birchwood/protocol/formatting.d @@ -1,24 +1,69 @@ +/** + * Message formatting utilities + */ module birchwood.protocol.formatting; -import std.string; +import birchwood.client.exceptions; -// Reset character; resets all formatting -enum reset_code = '\x0F'; +/** + * Control codes + * + * TODO: Document each member + */ +public enum ControlCode: char +{ + /** + * Reset styling + */ + Reset = '\x0F', -// Toggle characters -enum bold_code = '\x02'; -enum italic_code = '\x1D'; -enum underline_code = '\x1F'; -enum strikethrough_code = '\x1E'; -enum monospace_code = '\x11'; -enum reverse_colors_code = '\x16'; // NOT UNIVERSALLY SUPPORTED + /** + * Bold text styling + */ + Bolden = '\x02', -// Color characters -enum ascii_color_code = '\x03'; -enum hex_color_code = '\x04'; + /** + * Italic text styling + */ + Italic = '\x1D', -// Simple color codes -enum simpleColor: string { + /** + * Underlined text styling + */ + Underline = '\x1F', + + /** + * Strikethough text styling + */ + Strikethrough = '\x1E', + + /** + * Monospace text styling + */ + Monospace = '\x11', + + /** + * Reverse colors (NOTE: not universally supported) + */ + ReverseColors = '\x16', + + /** + * ASCII color encoding scheme + */ + AsciiColor = '\x03', + + /** + * Hex color encoding scheme + */ + HexColor = '\x04' +} + + +/** + * Simple color codes + */ +public enum SimpleColor: string +{ WHITE = "00", BLACK = "01", BLUE = "02", @@ -38,75 +83,198 @@ enum simpleColor: string { DEFAULT = "99" // NOT UNIVERSALLY SUPPORTED } -// Return the hex control character if color is a hexadecimal color code, the ASCII control character if color is two ASCII digits, and throw an exception if it's neither -// This function might be useless now that set_fg and set_fg_bg have been changed, but I'll keep it in case it's needed later. -char generate_color_control_char(string color) { - if (color.length == 6) { - return hex_color_code; - } else if (color.length == 2) { - return ascii_color_code; - } else { - throw new StringException("Invalid color code (must be either two ASCII digits or a hexadecimal code of the form RRGGBB)"); +/** + * Return the hex control character if color is a hexadecimal color code, + * the ASCII control character if color is two ASCII digits, and throw an + * exception if it's neither. + * + * This function might be useless now that set_fg and set_fg_bg have been + * changed, but I'll keep it in case it's needed later. + * + * Params: + * color = the color to check for + * + * Returns: the color control type + */ +private char generateColorControlChar(string color) +{ + if(color.length == 6) + { + return ControlCode.HexColor; + } + else if(color.length == 2) + { + return ControlCode.AsciiColor; + } + else + { + throw new BirchwoodException(ErrorType.INVALID_FORMATTING, "Invalid color code (must be either two ASCII digits or a hexadecimal code of the form RRGGBB)"); } } -// Generates a string that changes the foreground color -string set_foreground(string color) { +/** + * Generates a string that changes the foreground color + * + * Params: + * color = the foreground color + * + * Returns: the color control sequence + */ +public string setForeground(string color) +{ char[1] control_char; - if (color.length == 6) { - control_char[0] = hex_color_code; - } else if (color.length == 2) { - control_char[0] = ascii_color_code; - } else { - throw new StringException("Invalid color code (must be either two ASCII digits or a hexadecimal code of the form RRGGBB)"); + + if(color.length == 6) + { + control_char[0] = ControlCode.HexColor; } - return control_char.idup ~ color; + else if(color.length == 2) + { + control_char[0] = ControlCode.AsciiColor; + } + else + { + throw new BirchwoodException(ErrorType.INVALID_FORMATTING, "Invalid color code (must be either two ASCII digits or a hexadecimal code of the form RRGGBB)"); + } + + return cast(string)control_char~color; } -// Generate a string that sets the foreground and background color -string set_foreground_background(string fg, string bg) { +/** + * Generate a string that sets the foreground and background color + * + * Params: + * fg = foreground color in hex code or ASCII color code + * bg = background color + * + * Returns: the control sequence to set the style + */ +public string setForegroundBackground(string fg, string bg) +{ char[1] control_char; - if (fg.length != bg.length) { - throw new StringException("Invalid color code (cannot mix hex and ASCII)"); + + if(fg.length != bg.length) + { + throw new BirchwoodException(ErrorType.INVALID_FORMATTING, "Invalid color code (cannot mix hex and ASCII)"); } - if (fg.length == 6) { - control_char[0] = hex_color_code; - } else if (fg.length == 2) { - control_char[0] = ascii_color_code; - } else { - throw new StringException("Invalid color code (must be either two ASCII digits or a hexadecimal code of the form RRGGBB)"); + + if(fg.length == 6) + { + control_char[0] = ControlCode.HexColor; } - return control_char.idup ~ fg ~ "," ~ bg; + else if(fg.length == 2) + { + control_char[0] = ControlCode.AsciiColor; + } + else + { + throw new BirchwoodException(ErrorType.INVALID_FORMATTING, "Invalid color code (must be either two ASCII digits or a hexadecimal code of the form RRGGBB)"); + } + + return cast(string)control_char~fg~","~bg; } -// Generates a string that changes the foreground color (except enum) -pragma(inline) -string set_foreground(simpleColor color) { - return ascii_color_code ~ color; +/** + * Generates a string that changes the foreground color (except enum) + * + * Params: + * color = the foreground color + * + * Returns: the control sequence + */ +public string setForeground(SimpleColor color) +{ + return ControlCode.AsciiColor~color; } -// Generate a string that sets the foreground and background color (except enum) -pragma(inline) -string set_foreground_background(simpleColor fg, simpleColor bg) { - return ascii_color_code ~ fg ~ "," ~ bg; +/** + * Generate a string that sets the foreground and background color (except enum) + * + * Params: + * fg = the foreground color + * bg = the background color + * + * Returns: thecolor control sequence + */ +public string setForegroundBackground(SimpleColor fg, SimpleColor bg) +{ + return ControlCode.AsciiColor~fg~","~bg; } -// Generate a string that resets the foreground and background colors -pragma(inline) -string reset_fg_bg() {return [ascii_color_code].idup;} +/** + * Generate a string that resets the foreground + * and background colors + * + * Returns: The control string + */ +public string resetForegroundBackground() +{ + return [ControlCode.AsciiColor]; +} -// Format strings with functions -pragma(inline) -string bold(string text) {return bold_code~text~bold_code;} +// Format strings with functions (TODO: remove comment) -pragma(inline) -string italics(string text) {return italic_code~text~italic_code;} +/** + * Formats the provided text as bold + * + * Params: + * text = the text to bolden + * + * Returns: the boldened text + */ +public string bold(string text) +{ + return ControlCode.Bolden~text~ControlCode.Bolden; +} -pragma(inline) -string underline(string text) {return underline_code~text~underline_code;} +/** + * Formats the provided text in italics + * + * Params: + * text = the text to italicize + * + * Returns: the italicized text + */ +public string italics(string text) +{ + return ControlCode.Italic~text~ControlCode.Italic; +} -pragma(inline) -string strikethrough(string text) {return strikethrough_code~text~strikethrough_code;} +/** + * Formats the text as underlined + * + * Params: + * text = the text to underline + * + * Returns: the underlined text + */ +public string underline(string text) +{ + return ControlCode.Underline~text~ControlCode.Underline; +} -pragma(inline) -string monospace(string text) {return monospace_code~text~monospace_code;} \ No newline at end of file +/** + * Formats the text as strikethroughed + * + * Params: + * text = the text to strikethrough + * + * Returns: the strikethroughed text + */ +public string strikethrough(string text) +{ + return ControlCode.Strikethrough~text~ControlCode.Strikethrough; +} + +/** + * Formats the text as monospaced + * + * Params: + * text = the text to monospace + * + * Returns: the monospaced text + */ +public string monospace(string text) +{ + return ControlCode.Monospace~text~ControlCode.Monospace; +} \ No newline at end of file