lib/ougai/formatters/colors/configuration.rb
# frozen_string_literal: true
require 'ougai/formatters/colors'
module Ougai
module Formatters
module Colors
# Handle the colorization of output, mainly aimed at console formatting.
# The configuration,split by subject such as +level+, +msg+,
# or +datetime+ is basically a Hash: +config+ with the subject as key
# and values. Values can be have three types:
#
# - +String+: the color escape sequence for the subject
# - +Hash+: the color escape sequence per severity. If not all severities
# are defined, a +:default+ value must be defined
# - +Symbol+: refers to another key and same coloring is applied
class Configuration
class << self
# list default color configuration
# @note 'any' severity label decided in
# +Ougai::Logging::Severity#to_label+
# @note values are copied from +Ougai::Formatters::Readable+ coloring
# values
# @return [Hash] default color configuration is severities only
def default_configuration
{
severity: {
trace: Ougai::Formatters::Colors::BLUE,
debug: Ougai::Formatters::Colors::WHITE,
info: Ougai::Formatters::Colors::CYAN,
warn: Ougai::Formatters::Colors::YELLOW,
error: Ougai::Formatters::Colors::RED,
fatal: Ougai::Formatters::Colors::PURPLE,
any: Ougai::Formatters::Colors::GREEN
}
}
end
end
# Configuration accept following keys:
# - +:load_default_config+ If true, then default configuration
# values is fetched to fill missing value from the provided
# configuration. Default is true.
# - any remaining key is considered to be color-related and is translated
# into a *subject => color rule* mapping
#
# @param [Hash] configuration color configuration. Cannot be nil
def initialize(configuration = {})
# check if loading or not from default configuration
if configuration.fetch(:load_default_config) { true }
@config = Configuration.default_configuration
else
@config = {}
end
configuration.each do |key, val|
default_val = @config[key]
# default value is a Hash AND input value is a Hash => merge
if val.is_a?(Hash) && default_val.is_a?(Hash)
@config[key] = default_val.merge(val)
# Input value is assigned because one of the follow
# 1) input value is not defined in default configuration
# 2) input value is not a Hash which overrides the default value
# 3) default value is not a Hash and input is a Hash => Arbitrary
else
@config[key] = val
end
end
end
# Convenience method to color a subject for a given log severity
#
# @param [Symbol] subject_key to fetch the color to color the text
# @param [String] text to be colored text
# @param [Symbol] severity log level
#
# @return [String] a colored text depending on the subject
def color(subject_key, text, severity)
color = get_color_for(subject_key, severity)
Ougai::Formatters::Colors.color_text(color, text)
end
# Return the color for a given suject and a given severity. This color
# can then be applied to any text via
# +Ougai::Formatters::Colors.color_text+
#
# +get_color_for+ handles color inheritance: if a subject inherit color
# from another subject, subject value is the symbol refering to the
# other subject.
#
# @note !!WARNING!!: Circular references are not checked and lead to infinite
# loop
#
# @param [Symbol] subject_key to define the color to color the text
# @param [Symbol] severity log level
#
# @return [String,nil] requested color String value or +nil+ if not colored
def get_color_for(subject_key, severity)
# no colorization
return nil unless @config.key?(subject_key)
# no severity dependence nor inheritance
color = @config[subject_key]
return color if color.is_a? String
# inheritance from another subject
return get_color_for(color, severity) if color.is_a? Symbol
# severity dependent but not inherited value or return +nil+ if
# configuration is incorrect
severity = severity.downcase.to_sym
color.fetch(severity) { color[:default] }
end
end
end
end
end