diff --git a/dub.json b/dub.json index aa9acc6..6a066bf 100644 --- a/dub.json +++ b/dub.json @@ -5,10 +5,10 @@ ], "copyright": "Copyright © 2023, Tristan B. Kildaire", "dependencies": { - "dlog": ">=0.3.19" + "dlog": ">=0.4.0" }, "description": "Simple VT100 colourised pretty-printing logger", "license": "LGPL 3.0", "name": "gogga", "targetType": "library" -} \ No newline at end of file +} diff --git a/source/gogga/context.d b/source/gogga/context.d deleted file mode 100644 index 4b4f6d1..0000000 --- a/source/gogga/context.d +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Custom context for gogga logging - */ -module gogga.context; - -import dlog; - -/** - * Pass in a custom context to be used for gogga - */ -public final class GoggaContext : Context -{ - // TODO: Put more advanced stuff here -} \ No newline at end of file diff --git a/source/gogga/core.d b/source/gogga/core.d index 5af7545..551329b 100644 --- a/source/gogga/core.d +++ b/source/gogga/core.d @@ -1,62 +1,318 @@ /** - * Logging facilities + * Core routines and types + * + * Authors: Tristan Brice Velloza Kildaire (deavmi) */ module gogga.core; -import dlog; +import dlog.core; +import dlog.basic; +import std.conv : to; import dlog.utilities : flatten; import std.array : join; -import gogga.transform; -import gogga.context; +/** + * The gogga styles supported + */ +public enum GoggaMode +{ + /** + * TwoKTwenty3 is: `[] (:) ` + */ + TwoKTwenty3, + + /** + * Simple mode is just: `[] ` + */ + SIMPLE, + + /** + * Rustacean mode is: `[] (/:) ` + */ + RUSTACEAN, + + /** + * Simple rustacean mode is: `[] (:) ` + */ + RUSTACEAN_SIMPLE +} + +/** + * Information obtained during compilation time (if any) + */ +private struct GoggaCompInfo +{ + /** + * compile time usage file + */ + public string fullFilePath; + + /** + * compile time usage file (relative) + */ + public string file; + + /** + * compile time usage line number + */ + public ulong line; + + /** + * compile time usage module + */ + public string moduleName; + + /** + * compile time usage function + */ + public string functionName; + + /** + * compile time usage function (pretty) + */ + public string prettyFunctionName; + + /** + * Constructs the compilation information with the provided + * parameters + * + * Params: + * __FILE_FULL_PATH__ = compile time usage file + * __FILE__ = compile time usage file (relative) + * __LINE__ = compile time usage line number + * __MODULE__ = compile time usage module + * __FUNCTION__ = compile time usage function + * __PRETTY_FUNCTION__ = compile time usage function (pretty) + */ + this(string fullFilePath, string file, ulong line, string moduleName, string functionName, string prettyFunctionName) + { + this.fullFilePath = fullFilePath; + this.file = file; + this.line = line; + this.moduleName = moduleName; + this.functionName = functionName; + this.prettyFunctionName = prettyFunctionName; + } + + /** + * Flattens the known compile-time information into a string array + * + * Returns: a string[] + */ + public string[] toArray() + { + return [fullFilePath, file, to!(string)(line), moduleName, functionName, prettyFunctionName]; + } +} /** - * The logging class which provides the logging print - * calls, controlling of style and whether to debug or - * not + * A `GoggaMessage` which comprises + * of a `GoggaCompInfo` for context */ -public class GoggaLogger : Logger +private class GoggaMessage : BasicMessage { - /** - * The custom transformer - */ - private GoggaTransform gTransform = new GoggaTransform(); + /** + * The line information + */ + private GoggaCompInfo ctx; - /** + /** + * Sets the context + * + * Params: + * ctx = the context + */ + public void setContext(GoggaCompInfo ctx) + { + this.ctx = ctx; + } + + /** + * Returns the context + * + * Returns: the context + */ + public GoggaCompInfo getContext() + { + return this.ctx; + } +} + +/** + * The Gogga transformer which + * applies stylization to + * incoming `GoggaMessage`(s) + */ +private class GoggaTransform : Transform +{ + /** + * Mode to use for stylization + */ + private GoggaMode mode; + + /** + * Sets the stylization to + * use when transforming + * the message's text + * + * Params: + * mode = the `GoggaMode` + */ + public void setMode(GoggaMode mode) + { + this.mode = mode; + } + + /** + * Transforms the incoming message + * to use the Gogga stylization. This + * will be a no-op if the incoming + * message is not a `GoggaMessage`. + * + * Params: + * message = the message to transform + * Returns: the transformed message, + * else the same exact one + */ + public Message transform(Message message) + { + // Only handle GoggaMessage(s) + GoggaMessage goggaMesg = cast(GoggaMessage)message; + if(goggaMesg is null) + { + return null; + } + + /* The generated output string */ + string finalOutput; + + + + /* Extract the Level */ + Level level = goggaMesg.getLevel(); + + /* Extract the text */ + string text = goggaMesg.getText(); + + /* get the context data */ + string[] context = goggaMesg.getContext().toArray(); + + + /** + * Simple mode is just: `[] ` + */ + if(this.mode == GoggaMode.SIMPLE) + { + finalOutput = cast(string)debugColor("["~to!(string)(level)~"] ", level); + + finalOutput ~= text~"\n"; + } + /** + * TwoKTwenty3 is: `[] (:) ` + */ + else if(this.mode == GoggaMode.TwoKTwenty3) + { + /* Module information (and status debugColoring) */ + string moduleInfo = cast(string)debugColor("["~context[1]~"]", level); + + /* Function and line number info */ + string funcInfo = cast(string)(colorSrc("("~context[4]~":"~context[2]~")")); + + finalOutput = moduleInfo~" "~funcInfo~" "~text~"\n"; + } + /** + * Rustacean mode is: `[] (/:) ` + */ + else if(this.mode == GoggaMode.RUSTACEAN) + { + finalOutput = cast(string)debugColor(to!(string)(level)~"\t", level); + finalOutput ~= cast(string)(colorSrc(context[1]~"/"~context[4]~":"~context[2]~" ")); + finalOutput ~= text~"\n"; + } + /** + * Simple rustacean mode is: `[] (:) ` + */ + else if(this.mode == GoggaMode.RUSTACEAN_SIMPLE) + { + finalOutput = cast(string)debugColor(to!(string)(level)~"\t", level); + finalOutput ~= cast(string)(colorSrc(context[4]~":"~context[2]~" ")); + finalOutput ~= text~"\n"; + } + + goggaMesg.setText(finalOutput); + return message; + } +} + +/** + * A `GoggaLogger` + */ +public final class GoggaLogger : BasicLogger +{ + /** + * The Gogga text transformer + */ + private GoggaTransform gogTrans; + + /** * Whether debug prints are enabled or not */ private bool debugEnabled = false; - /** - * Constructs a new GoggaLOgger - */ + /** + * Constructs a new `GoggaLogger` + */ this() { - super(gTransform); - } - - /** - * Our underlying logging implementation - * - * Params: - * text = the text to write - */ - public override void logImpl(string text) - { - import std.stdio : write; - write(text); + super(); + this.gogTrans = new GoggaTransform(); + addTransform(this.gogTrans); } - /** - * Set the style of print outs - * - * Params: - * mode = the GoggaMode wanted - */ - public void mode(GoggaMode mode) - { - gTransform.setMode(mode); - } + /** + * Sets the style of logging + * to use + * + * Params: + * mode = the `GoggaMode` + */ + public void mode(GoggaMode mode) + { + this.gogTrans.setMode(mode); + } + + /** + * Performs the actual logging + * by packing up everything before + * sending it to the `log(Message)` + * method + * + * Params: + * segments = the compile-time segments + * info = the context + * level = the log level to use + */ + private void doLog(TextType...)(TextType segments, GoggaCompInfo info, Level level) + { + /* Create a new GoggaMessage */ + GoggaMessage message = new GoggaMessage(); + + /* Set context to the line information */ + message.setContext(info); + + /* Set the level */ + message.setLevel(level); + + /** + * Grab all compile-time arguments and make them + * into an array, then join them together and + * set that text as the message's text + */ + message.setText(join(flatten(segments), " ")); + + /* Log this message */ + log(message); + } /** * Logs using the default context an arbitrary amount of arguments @@ -77,28 +333,7 @@ public class GoggaLogger : Logger string c4 = __MODULE__, string c5 = __FUNCTION__, string c6 = __PRETTY_FUNCTION__) { - /* Use the context `GoggaContext` */ - GoggaContext defaultContext = new GoggaContext(); - - /* Build up the line information */ - CompilationInfo compilationInfo = CompilationInfo(c1, c2, c3, c4, c5, c6); - - /* Set the line information in the context */ - defaultContext.setLineInfo(compilationInfo); - - /* Set the level to ERROR */ - defaultContext.setLevel(Level.ERROR); - - /** - * Grab at compile-time all arguments and generate runtime code to add them to `components` - */ - string[] components = flatten(segments); - - /* Join all `components` into a single string */ - string messageOut = join(components, multiArgJoiner); - - /* Call the log */ - logc(defaultContext, messageOut, c1, c2, c3, c4, c5, c6); + doLog(segments, GoggaCompInfo(c1, c2, c3, c4, c5, c6), Level.ERROR); } /** @@ -120,28 +355,7 @@ public class GoggaLogger : Logger string c4 = __MODULE__, string c5 = __FUNCTION__, string c6 = __PRETTY_FUNCTION__) { - /* Use the context `GoggaContext` */ - GoggaContext defaultContext = new GoggaContext(); - - /* Build up the line information */ - CompilationInfo compilationInfo = CompilationInfo(c1, c2, c3, c4, c5, c6); - - /* Set the line information in the context */ - defaultContext.setLineInfo(compilationInfo); - - /* Set the level to INFO */ - defaultContext.setLevel(Level.INFO); - - /** - * Grab at compile-time all arguments and generate runtime code to add them to `components` - */ - string[] components = flatten(segments); - - /* Join all `components` into a single string */ - string messageOut = join(components, multiArgJoiner); - - /* Call the log */ - logc(defaultContext, messageOut, c1, c2, c3, c4, c5, c6); + doLog(segments, GoggaCompInfo(c1, c2, c3, c4, c5, c6), Level.INFO); } /** @@ -163,28 +377,7 @@ public class GoggaLogger : Logger string c4 = __MODULE__, string c5 = __FUNCTION__, string c6 = __PRETTY_FUNCTION__) { - /* Use the context `GoggaContext` */ - GoggaContext defaultContext = new GoggaContext(); - - /* Build up the line information */ - CompilationInfo compilationInfo = CompilationInfo(c1, c2, c3, c4, c5, c6); - - /* Set the line information in the context */ - defaultContext.setLineInfo(compilationInfo); - - /* Set the level to WARN */ - defaultContext.setLevel(Level.WARN); - - /** - * Grab at compile-time all arguments and generate runtime code to add them to `components` - */ - string[] components = flatten(segments); - - /* Join all `components` into a single string */ - string messageOut = join(components, multiArgJoiner); - - /* Call the log */ - logc(defaultContext, messageOut, c1, c2, c3, c4, c5, c6); + doLog(segments, GoggaCompInfo(c1, c2, c3, c4, c5, c6), Level.WARN); } /** @@ -206,65 +399,101 @@ public class GoggaLogger : Logger string c2 = __FILE__, ulong c3 = __LINE__, string c4 = __MODULE__, string c5 = __FUNCTION__, string c6 = __PRETTY_FUNCTION__) - { - /* Only debug if debugging is enabled */ - if(debugEnabled) - { - /* Use the context `GoggaContext` */ - GoggaContext defaultContext = new GoggaContext(); - - /* Build up the line information */ - CompilationInfo compilationInfo = CompilationInfo(c1, c2, c3, c4, c5, c6); - - /* Set the line information in the context */ - defaultContext.setLineInfo(compilationInfo); - - /* Set the level to DEBUG */ - defaultContext.setLevel(Level.DEBUG); - - /** - * Grab at compile-time all arguments and generate runtime code to add them to `components` - */ - string[] components = flatten(segments); - - /* Join all `components` into a single string */ - string messageOut = join(components, multiArgJoiner); - - /* Call the log */ - logc(defaultContext, messageOut, c1, c2, c3, c4, c5, c6); - } + { + doLog(segments, GoggaCompInfo(c1, c2, c3, c4, c5, c6), Level.DEBUG); } - /** + /** * Alias for debug_ */ public alias dbg = debug_; +} - /** - * Enables debug prints - */ - public void enableDebug() - { - this.debugEnabled = true; - } +/** + * Colorise the text provided accoridng to the level and then + * reset the colors at the end + * + * Params: + * text = the text to colorise + * level = the color to use + * Returns: the byte sequence of characters and controls + */ +private byte[] debugColor(string text, Level level) +{ + /* The generated message */ + byte[] messageBytes; - /** - * Disables debug prints - */ - public void disableDebug() + /* If INFO, set green */ + if(level == Level.INFO) { - this.debugEnabled = false; + messageBytes = cast(byte[])[27, '[','3','2','m']; } + /* If WARN, set yellow */ + else if(level == Level.WARN) + { + messageBytes = cast(byte[])[27, '[','3','1', ';', '9', '3', 'm']; + } + /* If ERROR, set red */ + else if(level == Level.ERROR) + { + messageBytes = cast(byte[])[27, '[','3','1','m']; + } + /* If DEBUG, set pink */ + else + { + messageBytes = cast(byte[])[27, '[','3','5','m']; + } + + /* Add the message */ + messageBytes ~= cast(byte[])text; + + /* Switch back debugColor */ + messageBytes ~= cast(byte[])[27, '[', '3', '9', 'm']; + + /* Reset coloring */ + messageBytes ~= [27, '[', 'm']; + + return messageBytes; +} + +/** + * Colors the provided text in a gray fashion and then + * resets back to normal + * + * Params: + * text = the text to gray color + * Returns: the byte sequence of characters and controls + */ +private byte[] colorSrc(string text) +{ + /* The generated message */ + byte[] messageBytes; + + /* Reset coloring */ + messageBytes ~= [27, '[', 'm']; + + /* Color gray */ + messageBytes ~= [27, '[', '3', '9', ';', '2', 'm']; + + /* Append the message */ + messageBytes ~= text; + + /* Reset coloring */ + messageBytes ~= [27, '[', 'm']; + + return messageBytes; } version(unittest) { - import std.stdio : writeln; + import std.stdio : writeln, stdout; } unittest { GoggaLogger gLogger = new GoggaLogger(); + gLogger.addHandler(new FileHandler(stdout)); + gLogger.setLevel(Level.INFO); // Test the normal modes gLogger.info("This is an info message"); @@ -275,7 +504,7 @@ unittest gLogger.dbg("This is a debug which is hidden", 1); // Now enable debugging and you should see it - gLogger.enableDebug(); + gLogger.setLevel(Level.DEBUG); gLogger.dbg("This is a VISIBLE debug", true); // Make space between unit tests @@ -285,6 +514,9 @@ unittest unittest { GoggaLogger gLogger = new GoggaLogger(); + gLogger.addHandler(new FileHandler(stdout)); + gLogger.setLevel(Level.INFO); + gLogger.mode(GoggaMode.TwoKTwenty3); // Test the normal modes @@ -296,7 +528,7 @@ unittest gLogger.dbg("This is a debug which is hidden", 1); // Now enable debugging and you should see it - gLogger.enableDebug(); + gLogger.setLevel(Level.DEBUG); gLogger.dbg("This is a VISIBLE debug", true); // Make space between unit tests @@ -306,6 +538,9 @@ unittest unittest { GoggaLogger gLogger = new GoggaLogger(); + gLogger.addHandler(new FileHandler(stdout)); + gLogger.setLevel(Level.INFO); + gLogger.mode(GoggaMode.SIMPLE); // Test the normal modes @@ -317,7 +552,7 @@ unittest gLogger.dbg("This is a debug which is hidden", 1); // Now enable debugging and you should see it - gLogger.enableDebug(); + gLogger.setLevel(Level.DEBUG); gLogger.dbg("This is a VISIBLE debug", true); // Make space between unit tests @@ -327,6 +562,9 @@ unittest unittest { GoggaLogger gLogger = new GoggaLogger(); + gLogger.addHandler(new FileHandler(stdout)); + gLogger.setLevel(Level.INFO); + gLogger.mode(GoggaMode.RUSTACEAN); // Test the normal modes @@ -338,7 +576,7 @@ unittest gLogger.dbg("This is a debug which is hidden", 1); // Now enable debugging and you should see it - gLogger.enableDebug(); + gLogger.setLevel(Level.DEBUG); gLogger.dbg("This is a VISIBLE debug", true); // Make space between unit tests @@ -348,6 +586,9 @@ unittest unittest { GoggaLogger gLogger = new GoggaLogger(); + gLogger.addHandler(new FileHandler(stdout)); + gLogger.setLevel(Level.INFO); + gLogger.mode(GoggaMode.RUSTACEAN_SIMPLE); // Test the normal modes @@ -359,7 +600,7 @@ unittest gLogger.dbg("This is a debug which is hidden", 1); // Now enable debugging and you should see it - gLogger.enableDebug(); + gLogger.setLevel(Level.DEBUG); gLogger.dbg("This is a VISIBLE debug", true); // Make space between unit tests diff --git a/source/gogga/package.d b/source/gogga/package.d index 9371e8b..d1a9d66 100644 --- a/source/gogga/package.d +++ b/source/gogga/package.d @@ -1,16 +1,14 @@ /** * Gogga logging facilities */ +/** + * The Gogga logging library + * + * Authors: Tristan Brice Velloza Kildaire (deavmi) + */ module gogga; -/** - * The logging class which provides the logging print - * calls, controlling of style and whether to debug or - * not +/** + * Core routines and types */ -public import gogga.core : GoggaLogger; - -/** - * The gogga styles supported - */ -public import gogga.transform : GoggaMode; \ No newline at end of file +public import gogga.core; \ No newline at end of file diff --git a/source/gogga/transform.d b/source/gogga/transform.d deleted file mode 100644 index a744d75..0000000 --- a/source/gogga/transform.d +++ /dev/null @@ -1,201 +0,0 @@ -/** - * The custom text transformer that implements the gogga-stylised - * logging messages - */ -module gogga.transform; - -import dlog; -import gogga.context; -import std.conv : to; - -/** - * The gogga styles supported - */ -public enum GoggaMode -{ - /** - * TwoKTwenty3 is: `[] (:) ` - */ - TwoKTwenty3, - - /** - * Simple mode is just: `[] ` - */ - SIMPLE, - - /** - * Rustacean mode is: `[] (/:) ` - */ - RUSTACEAN, - - /** - * Simple rustacean mode is: `[] (:) ` - */ - RUSTACEAN_SIMPLE -} - -/** - * The custom gogga text transformer - */ -public class GoggaTransform : MessageTransform -{ - /** - * Current style - */ - private GoggaMode mode; - - /** - * Transforms the provided text - * - * Params: - * text = text to transform - * ctx = the context passed in - * Returns: a string of transformed text - */ - public override string transform(string text, Context ctx) - { - /* The generated output string */ - string finalOutput; - - - /* Get the GoggaContext */ - GoggaContext gCtx = cast(GoggaContext)ctx; - - /* Extract the line information */ - CompilationInfo compInfo = gCtx.getLineInfo(); - string[] context = compInfo.toArray(); - - /* Extract the Level */ - Level level = gCtx.getLevel(); - - - /** - * Simple mode is just: `[] ` - */ - if(mode == GoggaMode.SIMPLE) - { - finalOutput = cast(string)debugColor("["~to!(string)(level)~"] ", level); - - finalOutput ~= text~"\n"; - } - /** - * TwoKTwenty3 is: `[] (:) ` - */ - else if(mode == GoggaMode.TwoKTwenty3) - { - /* Module information (and status debugColoring) */ - string moduleInfo = cast(string)debugColor("["~context[1]~"]", level); - - /* Function and line number info */ - string funcInfo = cast(string)(colorSrc("("~context[4]~":"~context[2]~")")); - - finalOutput = moduleInfo~" "~funcInfo~" "~text~"\n"; - } - /** - * Rustacean mode is: `[] (/:) ` - */ - else if(mode == GoggaMode.RUSTACEAN) - { - finalOutput = cast(string)debugColor(to!(string)(level)~"\t", level); - finalOutput ~= cast(string)(colorSrc(context[1]~"/"~context[4]~":"~context[2]~" ")); - finalOutput ~= text~"\n"; - } - /** - * Simple rustacean mode is: `[] (:) ` - */ - else if(mode == GoggaMode.RUSTACEAN_SIMPLE) - { - finalOutput = cast(string)debugColor(to!(string)(level)~"\t", level); - finalOutput ~= cast(string)(colorSrc(context[4]~":"~context[2]~" ")); - finalOutput ~= text~"\n"; - } - - return finalOutput; - } - - /** - * Set the gogga style - * - * Params: - * mode = the GoggaMode to use - */ - public void setMode(GoggaMode mode) - { - this.mode = mode; - } -} - -/** - * Colorise the text provided accoridng to the level and then - * reset the colors at the end - * - * Params: - * text = the text to colorise - * level = the color to use - * Returns: the byte sequence of characters and controls - */ -private byte[] debugColor(string text, Level level) -{ - /* The generated message */ - byte[] messageBytes; - - /* If INFO, set green */ - if(level == Level.INFO) - { - messageBytes = cast(byte[])[27, '[','3','2','m']; - } - /* If WARN, set yellow */ - else if(level == Level.WARN) - { - messageBytes = cast(byte[])[27, '[','3','1', ';', '9', '3', 'm']; - } - /* If ERROR, set red */ - else if(level == Level.ERROR) - { - messageBytes = cast(byte[])[27, '[','3','1','m']; - } - /* If DEBUG, set pink */ - else - { - messageBytes = cast(byte[])[27, '[','3','5','m']; - } - - /* Add the message */ - messageBytes ~= cast(byte[])text; - - /* Switch back debugColor */ - messageBytes ~= cast(byte[])[27, '[', '3', '9', 'm']; - - /* Reset coloring */ - messageBytes ~= [27, '[', 'm']; - - return messageBytes; -} - -/** - * Colors the provided text in a gray fashion and then - * resets back to normal - * - * Params: - * text = the text to gray color - * Returns: the byte sequence of characters and controls - */ -private byte[] colorSrc(string text) -{ - /* The generated message */ - byte[] messageBytes; - - /* Reset coloring */ - messageBytes ~= [27, '[', 'm']; - - /* Color gray */ - messageBytes ~= [27, '[', '3', '9', ';', '2', 'm']; - - /* Append the message */ - messageBytes ~= text; - - /* Reset coloring */ - messageBytes ~= [27, '[', 'm']; - - return messageBytes; -} \ No newline at end of file