Sets up initial project structure
Initializes the project with core files including: - Editor configuration (.editorconfig, .gitattributes, .gitignore, .vscode/settings.json) - Log.gd addon for enhanced debugging - Loggie addon for advanced logging - Project assets folder
This commit is contained in:
parent
f8140c83ff
commit
02b3be35b0
144 changed files with 7399 additions and 0 deletions
621
addons/log/log.gd
Normal file
621
addons/log/log.gd
Normal file
|
|
@ -0,0 +1,621 @@
|
|||
## Log.gd - colorized pretty printing functions
|
||||
##
|
||||
## [code]Log.pr(...)[/code] and [code]Log.prn(...)[/code] are drop-in replacements for [code]print(...)[/code].
|
||||
##
|
||||
## [br][br]
|
||||
## You can also [code]Log.warn(...)[/code] or [code]Log.error(...)[/code] to both print and push_warn/push_error.
|
||||
##
|
||||
## [br][br]
|
||||
## Custom object output is supported by implementing [code]to_pretty()[/code] on the object.
|
||||
##
|
||||
## [br][br]
|
||||
## For objects you don't own (built-ins or addons you don't want to edit),
|
||||
## there is a [code]register_type_overwrite(key, handler)[/code] helper.
|
||||
##
|
||||
## [br][br]
|
||||
## You can find up to date docs and examples in the Log.gd repo and docs site:
|
||||
## [br]
|
||||
## - https://github.com/russmatney/log.gd
|
||||
## [br]
|
||||
## - https://russmatney.github.io/log.gd
|
||||
##
|
||||
|
||||
@tool
|
||||
extends Object
|
||||
class_name Log
|
||||
|
||||
# helpers ####################################
|
||||
|
||||
static func assoc(opts: Dictionary, key: String, val):
|
||||
var _opts = opts.duplicate(true)
|
||||
_opts[key] = val
|
||||
return _opts
|
||||
|
||||
# config ####################################
|
||||
|
||||
const KEY_PREFIX = "log_gd/config"
|
||||
static var is_config_setup = false
|
||||
|
||||
const KEY_COLOR_THEME = "%s/color_theme" % KEY_PREFIX
|
||||
const KEY_DISABLE_COLORS = "%s/disable_colors" % KEY_PREFIX
|
||||
const KEY_MAX_ARRAY_SIZE = "%s/max_array_size" % KEY_PREFIX
|
||||
const KEY_SKIP_KEYS = "%s/dictionary_skip_keys" % KEY_PREFIX
|
||||
|
||||
static func setup_config(opts={}):
|
||||
var keys = opts.get("keys", [
|
||||
KEY_COLOR_THEME,
|
||||
KEY_DISABLE_COLORS,
|
||||
KEY_MAX_ARRAY_SIZE,
|
||||
KEY_SKIP_KEYS,
|
||||
])
|
||||
|
||||
for key in keys:
|
||||
if ProjectSettings.has_setting(key):
|
||||
Log.config[key] = ProjectSettings.get_setting(key)
|
||||
else:
|
||||
var val = Log.config[key]
|
||||
if val != null:
|
||||
ProjectSettings.set_setting(key, val)
|
||||
ProjectSettings.set_initial_value(key, val)
|
||||
|
||||
Log.is_config_setup = true
|
||||
|
||||
static var config = {
|
||||
KEY_COLOR_THEME: LOG_THEME_TERMSAFE,
|
||||
KEY_DISABLE_COLORS: false,
|
||||
KEY_MAX_ARRAY_SIZE: 20,
|
||||
KEY_SKIP_KEYS: [
|
||||
"layer_0/tile_data", # skip huge tilemap arrays
|
||||
],
|
||||
}
|
||||
|
||||
# config getters ###################################################################
|
||||
|
||||
static func get_max_array_size():
|
||||
return Log.config.get(KEY_MAX_ARRAY_SIZE, 20)
|
||||
|
||||
static func get_dictionary_skip_keys():
|
||||
return Log.config.get(KEY_SKIP_KEYS, [])
|
||||
|
||||
static func get_disable_colors():
|
||||
return Log.config.get(KEY_DISABLE_COLORS, false)
|
||||
|
||||
static func get_config_color_theme():
|
||||
var theme_id = Log.config.get(KEY_COLOR_THEME, LOG_THEME_TERMSAFE)
|
||||
match theme_id:
|
||||
LOG_THEME_TERMSAFE:
|
||||
return Log.COLORS_TERMINAL_SAFE
|
||||
LOG_THEME_PRETTY_V1:
|
||||
return Log.COLORS_PRETTY_V1
|
||||
_:
|
||||
print("Unknown LOG_THEME '%s', using fallback" % theme_id)
|
||||
return Log.COLORS_TERMINAL_SAFE
|
||||
|
||||
# config setters ###################################################################
|
||||
|
||||
## Disable color-wrapping output.
|
||||
##
|
||||
## [br][br]
|
||||
## Useful to declutter the output if the environment does not support colors.
|
||||
## Note that some environments support only a subset of colors - you may prefer
|
||||
## [code]set_colors_termsafe()[/code] or otherwise setting the theme to 'TERMSAFE'.
|
||||
static func disable_colors():
|
||||
Log.config[KEY_DISABLE_COLORS] = true
|
||||
|
||||
## Re-enable color-wrapping output.
|
||||
static func enable_colors():
|
||||
Log.config[KEY_DISABLE_COLORS] = false
|
||||
|
||||
## DEPRECATED
|
||||
static func set_color_scheme(theme):
|
||||
set_color_theme(theme)
|
||||
|
||||
static func set_color_theme(theme):
|
||||
Log.config[KEY_COLOR_THEME] = theme
|
||||
|
||||
## colors ###########################################################################
|
||||
|
||||
# terminal safe colors:
|
||||
# - black
|
||||
# - red
|
||||
# - green
|
||||
# - yellow
|
||||
# - blue
|
||||
# - magenta
|
||||
# - pink
|
||||
# - purple
|
||||
# - cyan
|
||||
# - white
|
||||
# - orange
|
||||
# - gray
|
||||
|
||||
const LOG_THEME_TERMSAFE = "TERMSAFE"
|
||||
const LOG_THEME_PRETTY_V1 = "PRETTY_V1"
|
||||
|
||||
static var COLORS_TERMINAL_SAFE = {
|
||||
"SRC": "cyan",
|
||||
"ADDONS": "red",
|
||||
"TEST": "green",
|
||||
",": "red",
|
||||
"(": "red",
|
||||
")": "red",
|
||||
"[": "red",
|
||||
"]": "red",
|
||||
"{": "red",
|
||||
"}": "red",
|
||||
"&": "orange",
|
||||
"^": "orange",
|
||||
"dict_key": "magenta",
|
||||
"vector_value": "green",
|
||||
"class_name": "magenta",
|
||||
TYPE_NIL: "pink",
|
||||
TYPE_BOOL: "pink",
|
||||
TYPE_INT: "green",
|
||||
TYPE_FLOAT: "green",
|
||||
TYPE_STRING: "pink",
|
||||
TYPE_VECTOR2: "green",
|
||||
TYPE_VECTOR2I: "green",
|
||||
TYPE_RECT2: "green",
|
||||
TYPE_RECT2I: "green",
|
||||
TYPE_VECTOR3: "green",
|
||||
TYPE_VECTOR3I: "green",
|
||||
TYPE_TRANSFORM2D: "pink",
|
||||
TYPE_VECTOR4: "green",
|
||||
TYPE_VECTOR4I: "green",
|
||||
TYPE_PLANE: "pink",
|
||||
TYPE_QUATERNION: "pink",
|
||||
TYPE_AABB: "pink",
|
||||
TYPE_BASIS: "pink",
|
||||
TYPE_TRANSFORM3D: "pink",
|
||||
TYPE_PROJECTION: "pink",
|
||||
TYPE_COLOR: "pink",
|
||||
TYPE_STRING_NAME: "pink",
|
||||
TYPE_NODE_PATH: "pink",
|
||||
TYPE_RID: "pink",
|
||||
TYPE_OBJECT: "pink",
|
||||
TYPE_CALLABLE: "pink",
|
||||
TYPE_SIGNAL: "pink",
|
||||
TYPE_DICTIONARY: "pink",
|
||||
TYPE_ARRAY: "pink",
|
||||
TYPE_PACKED_BYTE_ARRAY: "pink",
|
||||
TYPE_PACKED_INT32_ARRAY: "pink",
|
||||
TYPE_PACKED_INT64_ARRAY: "pink",
|
||||
TYPE_PACKED_FLOAT32_ARRAY: "pink",
|
||||
TYPE_PACKED_FLOAT64_ARRAY: "pink",
|
||||
TYPE_PACKED_STRING_ARRAY: "pink",
|
||||
TYPE_PACKED_VECTOR2_ARRAY: "pink",
|
||||
TYPE_PACKED_VECTOR3_ARRAY: "pink",
|
||||
TYPE_PACKED_COLOR_ARRAY: "pink",
|
||||
TYPE_MAX: "pink",
|
||||
}
|
||||
|
||||
static var COLORS_PRETTY_V1 = {
|
||||
"SRC": "aquamarine",
|
||||
"ADDONS": "peru",
|
||||
"TEST": "green_yellow",
|
||||
",": "crimson",
|
||||
"(": "crimson",
|
||||
")": "crimson",
|
||||
"[": "crimson",
|
||||
"]": "crimson",
|
||||
"{": "crimson",
|
||||
"}": "crimson",
|
||||
"&": "coral",
|
||||
"^": "coral",
|
||||
"dict_key": "cadet_blue",
|
||||
"vector_value": "cornflower_blue",
|
||||
"class_name": "cadet_blue",
|
||||
TYPE_NIL: "coral",
|
||||
TYPE_BOOL: "pink",
|
||||
TYPE_INT: "cornflower_blue",
|
||||
TYPE_FLOAT: "cornflower_blue",
|
||||
TYPE_STRING: "dark_gray",
|
||||
TYPE_VECTOR2: "cornflower_blue",
|
||||
TYPE_VECTOR2I: "cornflower_blue",
|
||||
TYPE_RECT2: "cornflower_blue",
|
||||
TYPE_RECT2I: "cornflower_blue",
|
||||
TYPE_VECTOR3: "cornflower_blue",
|
||||
TYPE_VECTOR3I: "cornflower_blue",
|
||||
TYPE_TRANSFORM2D: "pink",
|
||||
TYPE_VECTOR4: "cornflower_blue",
|
||||
TYPE_VECTOR4I: "cornflower_blue",
|
||||
TYPE_PLANE: "pink",
|
||||
TYPE_QUATERNION: "pink",
|
||||
TYPE_AABB: "pink",
|
||||
TYPE_BASIS: "pink",
|
||||
TYPE_TRANSFORM3D: "pink",
|
||||
TYPE_PROJECTION: "pink",
|
||||
TYPE_COLOR: "pink",
|
||||
TYPE_STRING_NAME: "pink",
|
||||
TYPE_NODE_PATH: "pink",
|
||||
TYPE_RID: "pink",
|
||||
TYPE_OBJECT: "pink",
|
||||
TYPE_CALLABLE: "pink",
|
||||
TYPE_SIGNAL: "pink",
|
||||
TYPE_DICTIONARY: "pink",
|
||||
TYPE_ARRAY: "pink",
|
||||
TYPE_PACKED_BYTE_ARRAY: "pink",
|
||||
TYPE_PACKED_INT32_ARRAY: "pink",
|
||||
TYPE_PACKED_INT64_ARRAY: "pink",
|
||||
TYPE_PACKED_FLOAT32_ARRAY: "pink",
|
||||
TYPE_PACKED_FLOAT64_ARRAY: "pink",
|
||||
TYPE_PACKED_STRING_ARRAY: "pink",
|
||||
TYPE_PACKED_VECTOR2_ARRAY: "pink",
|
||||
TYPE_PACKED_VECTOR3_ARRAY: "pink",
|
||||
TYPE_PACKED_COLOR_ARRAY: "pink",
|
||||
TYPE_MAX: "pink",
|
||||
}
|
||||
|
||||
## set color theme ####################################
|
||||
|
||||
## Use the terminal safe color scheme, which should handle colors in most tty-like environments.
|
||||
static func set_colors_termsafe():
|
||||
set_color_theme(LOG_THEME_TERMSAFE)
|
||||
|
||||
## Use prettier colors - looks nice in most dark godot themes.
|
||||
##
|
||||
## [br][br]
|
||||
## Hopefully we'll support more themes (including light themes) soon!
|
||||
static func set_colors_pretty():
|
||||
set_color_theme(LOG_THEME_PRETTY_V1)
|
||||
|
||||
static var theme_overwrites = {}
|
||||
|
||||
## Merge per type color adjustments.
|
||||
##
|
||||
## [br][br]
|
||||
## Expects a Dictionary from [code]{typeof(obj): Color}[/code].
|
||||
## See [code]COLORS_TERMINAL_SAFE[/code] for an example.
|
||||
static func merge_theme_overwrites(colors):
|
||||
theme_overwrites.merge(colors, true)
|
||||
|
||||
static func clear_theme_overwrites():
|
||||
theme_overwrites = {}
|
||||
|
||||
static func get_color_theme(opts={}):
|
||||
var theme = opts.get("color_theme", {})
|
||||
# fill in any missing vals with the set theme, then the term-safe fallbacks
|
||||
theme.merge(Log.theme_overwrites)
|
||||
theme.merge(Log.get_config_color_theme())
|
||||
theme.merge(Log.COLORS_TERMINAL_SAFE)
|
||||
return theme
|
||||
|
||||
static func should_use_color(opts={}):
|
||||
if Log.get_disable_colors():
|
||||
return false
|
||||
# supports per-print color skipping
|
||||
if opts.get("disable_colors", false):
|
||||
return false
|
||||
return true
|
||||
|
||||
static func color_wrap(s, opts={}):
|
||||
# don't rebuild the theme every time
|
||||
var colors = opts.get("built_color_theme", get_color_theme(opts))
|
||||
|
||||
if not should_use_color(opts):
|
||||
return str(s)
|
||||
|
||||
var color = opts.get("color")
|
||||
if not color:
|
||||
var s_type = opts.get("typeof", typeof(s))
|
||||
if s_type is String:
|
||||
# type overwrites
|
||||
color = colors.get(s_type)
|
||||
elif s_type is int and s_type == TYPE_STRING:
|
||||
# specific strings/punctuation
|
||||
var s_trimmed = s.strip_edges()
|
||||
if s_trimmed in colors:
|
||||
color = colors.get(s_trimmed)
|
||||
else:
|
||||
# fallback string color
|
||||
color = colors.get(s_type)
|
||||
else:
|
||||
# all other types
|
||||
color = colors.get(s_type)
|
||||
|
||||
if color == null:
|
||||
print("Log.gd could not determine color for object: %s type: (%s)" % [str(s), typeof(s)])
|
||||
|
||||
return "[color=%s]%s[/color]" % [color, s]
|
||||
|
||||
## overwrites ###########################################################################
|
||||
|
||||
static var type_overwrites = {}
|
||||
|
||||
## Register a single type overwrite.
|
||||
##
|
||||
## [br][br]
|
||||
## The key should be either obj.get_class() or typeof(var). (Note that using typeof(var) may overwrite more broadly than expected).
|
||||
##
|
||||
## [br][br]
|
||||
## The handler is called with the object and an options dict.
|
||||
## [code]func(obj, _opts): return {name=obj.name}[/code]
|
||||
static func register_type_overwrite(key, handler):
|
||||
# TODO warning on key exists? support multiple handlers for same type?
|
||||
# validate the key/handler somehow?
|
||||
type_overwrites[key] = handler
|
||||
|
||||
## Register a dictionary of type overwrite.
|
||||
##
|
||||
## [br][br]
|
||||
## Expects a Dictionary like [code]{obj.get_class(): func(obj, opts): return {key=obj.get_key()}}[/code].
|
||||
##
|
||||
## [br][br]
|
||||
## It depends on [code]obj.get_class()[/code] then [code]typeof(obj)[/code] for the key.
|
||||
## The handler is called with the object and an options dict (e.g. [code]func(obj, _opts): return {name=obj.name}[/code]).
|
||||
static func register_type_overwrites(overwrites):
|
||||
type_overwrites.merge(overwrites, true)
|
||||
|
||||
static func clear_type_overwrites(overwrites):
|
||||
type_overwrites = {}
|
||||
|
||||
## to_pretty ###########################################################################
|
||||
|
||||
## Returns the passed object as a bb-colorized string.
|
||||
##
|
||||
## [br][br]
|
||||
## Useful for feeding directly into a RichTextLabel, but also the core
|
||||
## of Log.gd's functionality.
|
||||
static func to_pretty(msg, opts={}) -> String:
|
||||
var newlines = opts.get("newlines", false)
|
||||
var indent_level = opts.get("indent_level", 0)
|
||||
if not "indent_level" in opts:
|
||||
opts["indent_level"] = indent_level
|
||||
|
||||
var theme = opts.get("built_color_theme", get_color_theme(opts))
|
||||
if not "built_color_theme" in opts:
|
||||
opts["built_color_theme"] = theme
|
||||
|
||||
if not is_instance_valid(msg) and typeof(msg) == TYPE_OBJECT:
|
||||
return str("invalid instance: ", msg)
|
||||
|
||||
if msg == null:
|
||||
return Log.color_wrap(msg, opts)
|
||||
|
||||
if msg is Object and msg.get_class() in type_overwrites:
|
||||
# TODO support single arity (no opts) impls?
|
||||
return type_overwrites.get(msg.get_class()).call(msg, opts)
|
||||
elif typeof(msg) in type_overwrites:
|
||||
return type_overwrites.get(typeof(msg)).call(msg, opts)
|
||||
|
||||
# objects
|
||||
if msg is Object and msg.has_method("to_pretty"):
|
||||
return Log.to_pretty(msg.to_pretty(), opts)
|
||||
if msg is Object and msg.has_method("data"):
|
||||
return Log.to_pretty(msg.data(), opts)
|
||||
# DEPRECATED
|
||||
if msg is Object and msg.has_method("to_printable"):
|
||||
return Log.to_pretty(msg.to_printable(), opts)
|
||||
|
||||
# arrays
|
||||
if msg is Array or msg is PackedStringArray:
|
||||
if len(msg) > Log.get_max_array_size():
|
||||
pr("[DEBUG]: truncating large array. total:", len(msg))
|
||||
msg = msg.slice(0, Log.get_max_array_size() - 1)
|
||||
if newlines:
|
||||
msg.append("...")
|
||||
|
||||
var tmp = Log.color_wrap("[ ", opts)
|
||||
var last = len(msg) - 1
|
||||
for i in range(len(msg)):
|
||||
if newlines and last > 1:
|
||||
tmp += "\n\t"
|
||||
tmp += Log.to_pretty(msg[i],
|
||||
# duplicate here to prevent indenting-per-msg
|
||||
# e.g. when printing an array of dictionaries
|
||||
opts.duplicate(true))
|
||||
if i != last:
|
||||
tmp += Log.color_wrap(", ", opts)
|
||||
tmp += Log.color_wrap(" ]", opts)
|
||||
return tmp
|
||||
|
||||
# dictionary
|
||||
elif msg is Dictionary:
|
||||
var tmp = Log.color_wrap("{ ", opts)
|
||||
var ct = len(msg)
|
||||
var last
|
||||
if len(msg) > 0:
|
||||
last = msg.keys()[-1]
|
||||
for k in msg.keys():
|
||||
var val
|
||||
if k in Log.get_dictionary_skip_keys():
|
||||
val = "..."
|
||||
else:
|
||||
opts.indent_level += 1
|
||||
val = Log.to_pretty(msg[k], opts)
|
||||
if newlines and ct > 1:
|
||||
tmp += "\n\t" \
|
||||
+ range(indent_level)\
|
||||
.map(func(_i): return "\t")\
|
||||
.reduce(func(a, b): return str(a, b), "")
|
||||
var key = Log.color_wrap('"%s"' % k, Log.assoc(opts, "typeof", "dict_key"))
|
||||
tmp += "%s: %s" % [key, val]
|
||||
if last and str(k) != str(last):
|
||||
tmp += Log.color_wrap(", ", opts)
|
||||
tmp += Log.color_wrap(" }", opts)
|
||||
return tmp
|
||||
|
||||
# strings
|
||||
elif msg is String:
|
||||
if msg == "":
|
||||
return '""'
|
||||
if "[color=" in msg and "[/color]" in msg:
|
||||
# assumes the string is already colorized
|
||||
# NOT PERFECT! could use a regex for something more robust
|
||||
return msg
|
||||
return Log.color_wrap(msg, opts)
|
||||
elif msg is StringName:
|
||||
return str(Log.color_wrap("&", opts), '"%s"' % msg)
|
||||
elif msg is NodePath:
|
||||
return str(Log.color_wrap("^", opts), '"%s"' % msg)
|
||||
|
||||
# vectors
|
||||
elif msg is Vector2 or msg is Vector2i:
|
||||
return '%s%s%s%s%s' % [
|
||||
Log.color_wrap("(", opts),
|
||||
Log.color_wrap(msg.x, Log.assoc(opts, "typeof", "vector_value")),
|
||||
Log.color_wrap(",", opts),
|
||||
Log.color_wrap(msg.y, Log.assoc(opts, "typeof", "vector_value")),
|
||||
Log.color_wrap(")", opts),
|
||||
]
|
||||
|
||||
elif msg is Vector3 or msg is Vector3i:
|
||||
return '%s%s%s%s%s%s%s' % [
|
||||
Log.color_wrap("(", opts),
|
||||
Log.color_wrap(msg.x, Log.assoc(opts, "typeof", "vector_value")),
|
||||
Log.color_wrap(",", opts),
|
||||
Log.color_wrap(msg.y, Log.assoc(opts, "typeof", "vector_value")),
|
||||
Log.color_wrap(",", opts),
|
||||
Log.color_wrap(msg.z, Log.assoc(opts, "typeof", "vector_value")),
|
||||
Log.color_wrap(")", opts),
|
||||
]
|
||||
elif msg is Vector4 or msg is Vector4i:
|
||||
return '%s%s%s%s%s%s%s%s%s' % [
|
||||
Log.color_wrap("(", opts),
|
||||
Log.color_wrap(msg.x, Log.assoc(opts, "typeof", "vector_value")),
|
||||
Log.color_wrap(",", opts),
|
||||
Log.color_wrap(msg.y, Log.assoc(opts, "typeof", "vector_value")),
|
||||
Log.color_wrap(",", opts),
|
||||
Log.color_wrap(msg.z, Log.assoc(opts, "typeof", "vector_value")),
|
||||
Log.color_wrap(",", opts),
|
||||
Log.color_wrap(msg.w, Log.assoc(opts, "typeof", "vector_value")),
|
||||
Log.color_wrap(")", opts),
|
||||
]
|
||||
|
||||
# packed scene
|
||||
elif msg is PackedScene:
|
||||
if msg.resource_path != "":
|
||||
return str(Log.color_wrap("PackedScene:", opts), '%s' % msg.resource_path.get_file())
|
||||
elif msg.get_script() != null and msg.get_script().resource_path != "":
|
||||
return Log.color_wrap(msg.get_script().resource_path.get_file(), Log.assoc(opts, "typeof", "class_name"))
|
||||
else:
|
||||
return Log.color_wrap(msg, opts)
|
||||
|
||||
# resource
|
||||
elif msg is Resource:
|
||||
if msg.get_script() != null and msg.get_script().resource_path != "":
|
||||
return Log.color_wrap(msg.get_script().resource_path.get_file(), Log.assoc(opts, "typeof", "class_name"))
|
||||
elif msg.resource_path != "":
|
||||
return str(Log.color_wrap("Resource:", opts), '%s' % msg.resource_path.get_file())
|
||||
else:
|
||||
return Log.color_wrap(msg, opts)
|
||||
|
||||
# refcounted
|
||||
elif msg is RefCounted:
|
||||
if msg.get_script() != null and msg.get_script().resource_path != "":
|
||||
return Log.color_wrap(msg.get_script().resource_path.get_file(), Log.assoc(opts, "typeof", "class_name"))
|
||||
else:
|
||||
return Log.color_wrap(msg.get_class(), Log.assoc(opts, "typeof", "class_name"))
|
||||
|
||||
# fallback to primitive-type lookup
|
||||
else:
|
||||
return Log.color_wrap(msg, opts)
|
||||
|
||||
## to_printable ###########################################################################
|
||||
|
||||
static func log_prefix(stack) -> String:
|
||||
if len(stack) > 1:
|
||||
var call_site = stack[1]
|
||||
var basename = call_site["source"].get_file().get_basename()
|
||||
var line_num = str(call_site.get("line", 0))
|
||||
if call_site["source"].match("*/test/*"):
|
||||
return "{" + basename + ":" + line_num + "}: "
|
||||
elif call_site["source"].match("*/addons/*"):
|
||||
return "<" + basename + ":" + line_num + ">: "
|
||||
else:
|
||||
return "[" + basename + ":" + line_num + "]: "
|
||||
return ""
|
||||
|
||||
static func to_printable(msgs, opts={}) -> String:
|
||||
if not Log.is_config_setup:
|
||||
setup_config()
|
||||
|
||||
if not msgs is Array:
|
||||
msgs = [msgs]
|
||||
var stack = opts.get("stack", [])
|
||||
var pretty = opts.get("pretty", true)
|
||||
var newlines = opts.get("newlines", false)
|
||||
var m = ""
|
||||
if len(stack) > 0:
|
||||
var prefix = Log.log_prefix(stack)
|
||||
var prefix_type
|
||||
if prefix != null and prefix[0] == "[":
|
||||
prefix_type = "SRC"
|
||||
elif prefix != null and prefix[0] == "{":
|
||||
prefix_type = "TEST"
|
||||
elif prefix != null and prefix[0] == "<":
|
||||
prefix_type = "ADDONS"
|
||||
if pretty:
|
||||
m += Log.color_wrap(prefix, Log.assoc(opts, "typeof", prefix_type))
|
||||
else:
|
||||
m += prefix
|
||||
for msg in msgs:
|
||||
# add a space between msgs
|
||||
if pretty:
|
||||
m += "%s " % Log.to_pretty(msg, opts)
|
||||
else:
|
||||
m += "%s " % str(msg)
|
||||
return m.trim_suffix(" ")
|
||||
|
||||
## public print fns ###########################################################################
|
||||
|
||||
static func is_not_default(v) -> bool:
|
||||
return not v is String or (v is String and v != "ZZZDEF")
|
||||
|
||||
## Pretty-print the passed arguments in a single line.
|
||||
static func pr(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
|
||||
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
|
||||
msgs = msgs.filter(Log.is_not_default)
|
||||
var m = Log.to_printable(msgs, {stack=get_stack()})
|
||||
print_rich(m)
|
||||
|
||||
## Pretty-print the passed arguments in a single line.
|
||||
static func info(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
|
||||
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
|
||||
msgs = msgs.filter(Log.is_not_default)
|
||||
var m = Log.to_printable(msgs, {stack=get_stack()})
|
||||
print_rich(m)
|
||||
|
||||
## Pretty-print the passed arguments in a single line.
|
||||
static func log(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
|
||||
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
|
||||
msgs = msgs.filter(Log.is_not_default)
|
||||
var m = Log.to_printable(msgs, {stack=get_stack()})
|
||||
print_rich(m)
|
||||
|
||||
## Pretty-print the passed arguments, expanding dictionaries and arrays with newlines and indentation.
|
||||
static func prn(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
|
||||
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
|
||||
msgs = msgs.filter(Log.is_not_default)
|
||||
var m = Log.to_printable(msgs, {stack=get_stack(), newlines=true})
|
||||
print_rich(m)
|
||||
|
||||
## Like [code]Log.prn()[/code], but also calls push_warning() with the pretty string.
|
||||
static func warn(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
|
||||
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
|
||||
msgs = msgs.filter(Log.is_not_default)
|
||||
var rich_msgs = msgs.duplicate()
|
||||
rich_msgs.push_front("[color=yellow][WARN][/color]")
|
||||
print_rich(Log.to_printable(rich_msgs, {stack=get_stack(), newlines=true}))
|
||||
var m = Log.to_printable(msgs, {stack=get_stack(), newlines=true, pretty=false})
|
||||
push_warning(m)
|
||||
|
||||
## Like [code]Log.prn()[/code], but also calls push_error() with the pretty string.
|
||||
static func err(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
|
||||
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
|
||||
msgs = msgs.filter(Log.is_not_default)
|
||||
var rich_msgs = msgs.duplicate()
|
||||
rich_msgs.push_front("[color=red][ERR][/color]")
|
||||
print_rich(Log.to_printable(rich_msgs, {stack=get_stack(), newlines=true}))
|
||||
var m = Log.to_printable(msgs, {stack=get_stack(), newlines=true, pretty=false})
|
||||
push_error(m)
|
||||
|
||||
## Like [code]Log.prn()[/code], but also calls push_error() with the pretty string.
|
||||
static func error(msg, msg2="ZZZDEF", msg3="ZZZDEF", msg4="ZZZDEF", msg5="ZZZDEF", msg6="ZZZDEF", msg7="ZZZDEF"):
|
||||
var msgs = [msg, msg2, msg3, msg4, msg5, msg6, msg7]
|
||||
msgs = msgs.filter(Log.is_not_default)
|
||||
var rich_msgs = msgs.duplicate()
|
||||
rich_msgs.push_front("[color=red][ERR][/color]")
|
||||
print_rich(Log.to_printable(rich_msgs, {stack=get_stack(), newlines=true}))
|
||||
var m = Log.to_printable(msgs, {stack=get_stack(), newlines=true, pretty=false})
|
||||
push_error(m)
|
||||
Loading…
Add table
Add a link
Reference in a new issue