Skip to content

Commit

Permalink
Merge pull request #1 from Shiva-Shadowsong/v1.1-dev
Browse files Browse the repository at this point in the history
V1.1
  • Loading branch information
Shiva-Shadowsong authored Oct 3, 2024
2 parents b927ea6 + bf05185 commit a5c6264
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 111 deletions.
1 change: 1 addition & 0 deletions addons/loggie/custom_settings.gd.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ func load():

self.terminal_mode = LoggieTools.TerminalMode.BBCODE
self.log_level = LoggieTools.LogLevel.INFO
self.show_loggie_specs = true
self.show_system_specs = true
self.output_message_domain = true
self.print_errors_to_console = true
Expand Down
24 changes: 14 additions & 10 deletions addons/loggie/loggie.gd
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
@tool

## Loggie is a basic logging utility for those who need common minor improvements and helpers around the basic [method print], [method print_rich]
## and other default Godot printing functions. Loggie creates instances of [LoggieMsg], which are a wrapper around a string that needs to manipulated,
## then uses them to properly format, arrange and present them in the console and .log files. Loggie uses the default Godot logging mechanism under the hood.
extends Node

## Stores a string describing the current version of Loggie.
const VERSION : String = "v1.0"
const VERSION : String = "v1.1"

## A reference to the settings of this Loggie. Read more about [LoggieSettings].
var settings : LoggieSettings
Expand Down Expand Up @@ -42,16 +43,17 @@ func _ready() -> void:
push_error("Loggie loaded neither a custom nor a default settings file. This will break the plugin. Make sure that a valid loggie_settings.gd is in the same directory where loggie.gd is.")
return

var bootMsg = msg("[color=orange]👀 Loggie {version} booted.[/color]".format({"version" : self.VERSION})).header().nl()
bootMsg.append("[b]Terminal Mode:[/b]", LoggieTools.TerminalMode.keys()[settings.terminal_mode]).suffix(" - ")
bootMsg.append("[b]Log Level:[/b]", LoggieTools.LogLevel.keys()[settings.log_level]).suffix(" - ")
bootMsg.append("[b]Is in Production:[/b]", self.is_in_production()).suffix(" - ")
bootMsg.append("[b]Box Characters Mode:[/b]", LoggieTools.BoxCharactersMode.keys()[settings.box_characters_mode]).nl()
bootMsg.append("[b]Using Custom Settings File:[/b]", !uses_original_settings_file).nl()
bootMsg.preprocessed(false).info()
msg("👀 Loggie {version} booted.".format({"version" : self.VERSION})).color(Color.ORANGE).header().nl().info()

if settings.show_loggie_specs:
var loggieSpecsMsg = LoggieSystemSpecsMsg.new().useLogger(self)
loggieSpecsMsg.embed_logger_specs()
loggieSpecsMsg.add(msg("Using Custom Settings File: ").bold(), !uses_original_settings_file).nl()
loggieSpecsMsg.preprocessed(false).info()

if settings.show_system_specs:
LoggieSystemSpecsMsg.new().embed_specs().preprocessed(false).info()
var systemSpecsMsg = LoggieSystemSpecsMsg.new().useLogger(self)
systemSpecsMsg.embed_specs().preprocessed(false).info()

## Attempts to instantiate a LoggieSettings object from the script at the given [param path].
## Returns true if successful, otherwise false and prints an error.
Expand Down Expand Up @@ -97,5 +99,7 @@ func is_domain_enabled(domain_name : String) -> bool:
## You may continue to modify the [LoggieMsg] with additional functions from that class, then when you are ready to output it, use methods like:
## [method LoggieMsg.info], [method LoggieMsg.warn], etc.
func msg(msg = "", arg1 = null, arg2 = null, arg3 = null, arg4 = null, arg5 = null) -> LoggieMsg:
return LoggieMsg.new(msg, arg1, arg2, arg3, arg4, arg5)
var loggieMsg = LoggieMsg.new(msg, arg1, arg2, arg3, arg4, arg5)
loggieMsg.useLogger(self)
return loggieMsg

88 changes: 55 additions & 33 deletions addons/loggie/loggie_message.gd
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@tool

## LoggieMsg represents a mutable object that holds a string message ([member content]), its original unmutated form ([member original_content]), and
## a bunch of helper methods that make it easy to manipulate the content and chain together additions and changes to it.
## [br][br]For example:
Expand Down Expand Up @@ -29,53 +31,74 @@ var domain_name : String = ""
## Whether this message should be preprocessed and modified during [method output].
var preprocess : bool = true

## Stores a reference to the logger that generated this message, from which we need to read settings and other data.
var _logger : Variant

func _init(msg = "", arg1 = null, arg2 = null, arg3 = null, arg4 = null, arg5 = null) -> void:
self.content = LoggieTools.concatenate_msg_and_args(msg, arg1, arg2, arg3, arg4, arg5)
self.original_content = self.content

## Returns a reference to the logger object that created this message.
## If the currently stored reference is null, an attempt will be made to automatically obtain the reference
## for an autoloaded singleton named 'Loggie'.
func getLogger() -> Variant:
return self._logger

## Sets this message to use the given [param logger] as the logger from which it will be reading
## settings. The given logger should be of class [Loggie] or an extension of it.
func useLogger(logger_to_use : Variant) -> LoggieMsg:
self._logger = logger_to_use
return self

## Outputs the given string [param msg] at the given output level to the standard output using either [method print_rich] or [method print].
## It also does a number of changes to the given [param msg] based on various Loggie settings.
## Designed to be called internally. You should consider using [method info], [method error], [method warn], [method notice], [method debug] instead.
func output(level : LoggieTools.LogLevel, msg : String, domain : String = "") -> void:
var loggie = getLogger()

if loggie == null:
push_error("Attempt to log output with an invalid _logger. Make sure to call LoggieMsg.useLogger to set the appropriate logger before working with the message.")
return

# We don't output the message if the settings dictate that messages of that level shouldn't be outputted.
if level > Loggie.settings.log_level:
if level > loggie.settings.log_level:
return

# We don't output the message if the domain from which it comes is not enabled.
if not Loggie.is_domain_enabled(domain):
if not loggie.is_domain_enabled(domain):
return

if self.preprocess:
# We append the name of the domain if that setting is enabled.
if !domain.is_empty() and Loggie.settings.output_message_domain == true:
msg = Loggie.settings.format_domain_prefix % [domain, msg]
if !domain.is_empty() and loggie.settings.output_message_domain == true:
msg = loggie.settings.format_domain_prefix % [domain, msg]

# We prepend the name of the class that called the function which resulted in this output being generated
# (if Loggie settings are configured to do so).
if Loggie.settings.derive_and_show_class_names == true and OS.has_feature("debug"):
if loggie.settings.derive_and_show_class_names == true and OS.has_feature("debug"):
var stack_frame : Dictionary = LoggieTools.get_current_stack_frame_data()
var _class_name : String

var scriptPath = stack_frame.source
if Loggie.class_names.has(scriptPath):
_class_name = Loggie.class_names[scriptPath]
if loggie.class_names.has(scriptPath):
_class_name = loggie.class_names[scriptPath]
else:
_class_name = LoggieTools.extract_class_name_from_gd_script(scriptPath)
Loggie.class_names[scriptPath] = _class_name
loggie.class_names[scriptPath] = _class_name

msg = "[b]({class_name})[/b] {msg}".format({
"class_name" : _class_name,
"msg" : msg
})

# We prepend a timestamp to the message (if Loggie settings are configured to do so).
if Loggie.settings.show_timestamps == true:
if loggie.settings.show_timestamps == true:
msg = "{timestamp} {msg}".format({
"timestamp" : Time.get_datetime_string_from_system(Loggie.settings.timestamps_use_utc, true),
"timestamp" : Time.get_datetime_string_from_system(loggie.settings.timestamps_use_utc, true),
"msg" : msg
})

var usedTerminalMode = LoggieTools.TerminalMode.PLAIN if Loggie.is_in_production() else Loggie.settings.terminal_mode
var usedTerminalMode = LoggieTools.TerminalMode.PLAIN if loggie.is_in_production() else loggie.settings.terminal_mode
match usedTerminalMode:
LoggieTools.TerminalMode.ANSI:
# We put the message through the rich_to_ANSI converted which takes care of converting BBCode
Expand All @@ -95,41 +118,46 @@ func output(level : LoggieTools.LogLevel, msg : String, domain : String = "") ->
## Outputs this message from Loggie as an Error type message.
## The [Loggie.settings.log_level] must be equal to or higher to the ERROR level for this to work.
func error() -> LoggieMsg:
var msg = Loggie.settings.format_error_msg % [self.content]
var loggie = getLogger()
var msg = loggie.settings.format_error_msg % [self.content]
output(LoggieTools.LogLevel.ERROR, msg, self.domain_name)
if Loggie.settings.print_errors_to_console and Loggie.settings.log_level >= LoggieTools.LogLevel.ERROR:
if loggie.settings.print_errors_to_console and loggie.settings.log_level >= LoggieTools.LogLevel.ERROR:
push_error(self.string())
return self

## Outputs this message from Loggie as an Warning type message.
## The [Loggie.settings.log_level] must be equal to or higher to the WARN level for this to work.
func warn() -> LoggieMsg:
var msg = Loggie.settings.format_warning_msg % [self.content]
var loggie = getLogger()
var msg = loggie.settings.format_warning_msg % [self.content]
output(LoggieTools.LogLevel.WARN, msg, self.domain_name)
if Loggie.settings.print_warnings_to_console and Loggie.settings.log_level >= LoggieTools.LogLevel.WARN:
if loggie.settings.print_warnings_to_console and loggie.settings.log_level >= LoggieTools.LogLevel.WARN:
push_warning(self.string())
return self

## Outputs this message from Loggie as an Notice type message.
## The [Loggie.settings.log_level] must be equal to or higher to the NOTICE level for this to work.
func notice() -> LoggieMsg:
var msg = Loggie.settings.format_notice_msg % [self.content]
var loggie = getLogger()
var msg = loggie.settings.format_notice_msg % [self.content]
output(LoggieTools.LogLevel.NOTICE, msg, self.domain_name)
return self

## Outputs this message from Loggie as an Info type message.
## The [Loggie.settings.log_level] must be equal to or higher to the INFO level for this to work.
func info() -> LoggieMsg:
var msg = Loggie.settings.format_info_msg % [self.content]
var loggie = getLogger()
var msg = loggie.settings.format_info_msg % [self.content]
output(LoggieTools.LogLevel.INFO, msg, self.domain_name)
return self

## Outputs this message from Loggie as a Debug type message.
## The [Loggie.settings.log_level] must be equal to or higher to the DEBUG level for this to work.
func debug() -> LoggieMsg:
var msg = Loggie.settings.format_debug_msg % [self.content]
var loggie = getLogger()
var msg = loggie.settings.format_debug_msg % [self.content]
output(LoggieTools.LogLevel.DEBUG, msg, self.domain_name)
if Loggie.settings.use_print_debug_for_debug_msg and Loggie.settings.log_level >= LoggieTools.LogLevel.DEBUG:
if loggie.settings.use_print_debug_for_debug_msg and loggie.settings.log_level >= LoggieTools.LogLevel.DEBUG:
print_debug(self.string())
return self

Expand Down Expand Up @@ -177,17 +205,19 @@ func italic() -> LoggieMsg:

## Stylizes the current content of this message as a header.
func header() -> LoggieMsg:
self.content = Loggie.settings.format_header % self.content
var loggie = getLogger()
self.content = loggie.settings.format_header % self.content
return self

## Constructs a decorative box with the given horizontal padding around the current content
## of this message. Messages containing a box are not going to be preprocessed, so they are best
## used only as a special header or decoration.
func box(h_padding : int = 4):
var loggie = getLogger()
var stripped_content = LoggieTools.remove_BBCode(self.content).strip_edges(true, true)
var content_length = stripped_content.length()
var h_fill_length = content_length + (h_padding * 2)
var box_character_source = Loggie.settings.box_symbols_compatible if Loggie.settings.box_characters_mode == LoggieTools.BoxCharactersMode.COMPATIBLE else Loggie.settings.box_symbols_pretty
var box_character_source = loggie.settings.box_symbols_compatible if loggie.settings.box_characters_mode == LoggieTools.BoxCharactersMode.COMPATIBLE else loggie.settings.box_symbols_pretty

var top_row_design = "{top_left_corner}{h_fill}{top_right_corner}".format({
"top_left_corner" : box_character_source.top_left,
Expand Down Expand Up @@ -217,18 +247,9 @@ func box(h_padding : int = 4):
self.preprocessed(false)

return self

## Concatenates the content of another [LoggieMsg] to the end of this message (optionally with a separator string between them).
func add(logmsg : LoggieMsg, separator : String = "") -> LoggieMsg:
self.content = "{msg}{separator}{newContent}".format({
"msg" : self.content,
"separator" : separator,
"newContent" : logmsg.content
})
return self

## Appends a new message to the end of this message.
func append(msg : String, arg1 = null, arg2 = null, arg3 = null, arg4 = null, arg5 = null) -> LoggieMsg:
## Appends additional content to this message at the end of the current content and its stylings.
func add(msg : Variant = null, arg1 : Variant = null, arg2 : Variant = null, arg3 : Variant = null, arg4 : Variant = null, arg5 : Variant = null) -> LoggieMsg:
self.content = self.content + LoggieTools.concatenate_msg_and_args(msg, arg1, arg2, arg3, arg4, arg5)
return self

Expand Down Expand Up @@ -269,7 +290,8 @@ func suffix(suffix : String, separator : String = "") -> LoggieMsg:
## Appends a horizontal separator with the given length to the message.
## If [param alternative_symbol] is provided, it should be a String, and it will be used as the symbol for the separator instead of the default one.
func hseparator(size : int = 16, alternative_symbol : Variant = null) -> LoggieMsg:
var symbol = Loggie.settings.h_separator_symbol if alternative_symbol == null else str(alternative_symbol)
var loggie = getLogger()
var symbol = loggie.settings.h_separator_symbol if alternative_symbol == null else str(alternative_symbol)
self.content += (symbol.repeat(size))
return self

Expand Down
19 changes: 19 additions & 0 deletions addons/loggie/loggie_settings.gd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@tool

## Defines a set of variables through which all the relevant settings of Loggie can have their
## values set, read and documented. An instance of this class is found in [member Loggie.settings], and that's where Loggie
## ultimately reads from when it's asking for the value of a setting. For user convenience, settings are (by default) exported
Expand All @@ -9,6 +10,12 @@
## Loggie calls [method load] on this class during its [method _ready] function.
class_name LoggieSettings extends Node

## The name that will be used for the singleton referring to Loggie.
## [br][br][i][b]Note:[/b] You may change this to something you're more used to, such as "log" or "logger".[/i]
## When doing so, make sure to either do it while the Plugin is enabled, then disable and re-enable the plugin,
## or that you manually clear out the previously created autoload (should be called "Loggie") in Project Settings -> Autoloads.
static var loggie_singleton_name = "Loggie"

## The dictionary which is used to grab the defaults and other values associated with each setting
## relevant to Loggie, particularly important for the default way of loading [LoggieSettings] and
## setting up Godot Project Settings related to Loggie.
Expand Down Expand Up @@ -37,6 +44,14 @@ const project_settings = {
"hint_string" : "",
"doc" : "Should Loggie log the system and device specs of the user as soon as it is booted?",
},
"show_loggie_specs" = {
"path": "loggie/general/show_loggie_specs",
"default_value" : true,
"type" : TYPE_BOOL,
"hint" : PROPERTY_HINT_NONE,
"hint_string" : "",
"doc" : "Should Loggie log its own specs when it is booted?",
},
"output_timestamps" = {
"path": "loggie/timestamps/output_timestamps",
"default_value" : false,
Expand Down Expand Up @@ -116,6 +131,9 @@ var terminal_mode : LoggieTools.TerminalMode
## Set this using [method setLogLevel].
var log_level : LoggieTools.LogLevel

## Whether or not Loggie should log the loggie specs on ready.
var show_loggie_specs : bool

## Whether or not Loggie should log the system specs on ready.
var show_system_specs : bool

Expand Down Expand Up @@ -218,6 +236,7 @@ var box_symbols_pretty = {
func load():
terminal_mode = ProjectSettings.get_setting(project_settings.terminal_mode.path, project_settings.terminal_mode.default_value)
log_level = ProjectSettings.get_setting(project_settings.log_level.path, project_settings.log_level.default_value)
show_loggie_specs = ProjectSettings.get_setting(project_settings.show_loggie_specs.path, project_settings.show_loggie_specs.default_value)
show_system_specs = ProjectSettings.get_setting(project_settings.show_system_specs.path, project_settings.show_system_specs.default_value)
show_timestamps = ProjectSettings.get_setting(project_settings.output_timestamps.path, project_settings.output_timestamps.default_value)
timestamps_use_utc = ProjectSettings.get_setting(project_settings.timestamps_use_utc.path, project_settings.timestamps_use_utc.default_value)
Expand Down
2 changes: 1 addition & 1 deletion addons/loggie/plugin.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
name="Loggie"
description="Simple functional stylish logger for your basic logging needs."
author="Shiva Shadowsong"
version="1.0"
version="1.1"
script="plugin.gd"
4 changes: 2 additions & 2 deletions addons/loggie/plugin.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
class_name LoggieEditorPlugin extends EditorPlugin

func _enter_tree():
add_autoload_singleton("Loggie", "res://addons/loggie/loggie.gd")
add_autoload_singleton(LoggieSettings.loggie_singleton_name, "res://addons/loggie/loggie.gd")
add_loggie_project_settings()

func _exit_tree() -> void:
remove_loggie_project_setings()
remove_autoload_singleton("Loggie")
remove_autoload_singleton(LoggieSettings.loggie_singleton_name)

## Adds new Loggie related ProjectSettings to Godot.
func add_loggie_project_settings():
Expand Down
Loading

0 comments on commit a5c6264

Please sign in to comment.