class Console::Filter

def self.[] **levels

def self.[] **levels
	klass = Class.new(self)
	minimum_level, maximum_level = levels.values.minmax
	
	klass.instance_exec do
		const_set(:LEVELS, levels.freeze)
		const_set(:MINIMUM_LEVEL, minimum_level)
		const_set(:MAXIMUM_LEVEL, maximum_level)
		
		levels.each do |name, level|
			const_set(name.to_s.upcase, level)
			
			define_immutable_method(name) do |subject = nil, *arguments, **options, &block|
				if self.enabled?(subject, level)
					@output.call(subject, *arguments, severity: name, **@options, **options, &block)
				end
			end
			
			define_immutable_method("#{name}!") do
				@level = level
			end
			
			define_immutable_method("#{name}?") do
				@level <= level
			end
		end
	end
	
	return klass
end

def self.define_immutable_method(name, &block)

def self.define_immutable_method(name, &block)
	block = Ractor.make_shareable(block)
	self.define_method(name, &block)
end

def self.define_immutable_method(name, &block)

def self.define_immutable_method(name, &block)
	define_method(name, &block)
end

def all!

def all!
	@level = self.class::MINIMUM_LEVEL - 1
end

def call(subject, *arguments, **options, &block)

def call(subject, *arguments, **options, &block)
	severity = options[:severity] || UNKNOWN
	level = self.class::LEVELS[severity]
	
	if self.enabled?(subject, level)
		@output.call(subject, *arguments, **options, &block)
	end
end

def clear(subject)

@parameter name [Module] The class to disable.
Clear any specific filters for the given class.
def clear(subject)
	unless subject.is_a?(Module)
		raise ArgumentError, "Expected a class, got #{subject.inspect}"
	end
	
	@subjects.delete(subject)
end

def disable(subject)

def disable(subject)
	# Set the filter level of the logging for a given subject which filters all log messages:
	filter(subject, self.class::MAXIMUM_LEVEL + 1)
end

def enable(subject, level = self.class::MINIMUM_LEVEL)

@parameter name [Module] The class to enable.
Enable specific log level for the given class.
def enable(subject, level = self.class::MINIMUM_LEVEL)
	# Set the filter level of logging for a given subject which passes all log messages:
	filter(subject, level)
end

def enabled?(subject, level = self.class::MINIMUM_LEVEL)

Parameters:
  • subject (Object) -- the subject to check.
def enabled?(subject, level = self.class::MINIMUM_LEVEL)
	subject = subject.class unless subject.is_a?(Module)
	
	if specific_level = @subjects[subject]
		return level >= specific_level
	end
	
	if level >= @level
		return true
	end
end

def filter(subject, level)

def filter(subject, level)
	unless subject.is_a?(Module)
		raise ArgumentError, "Expected a class, got #{subject.inspect}"
	end
	
	@subjects[subject] = level
end

def initialize(output, verbose: true, level: self.class::DEFAULT_LEVEL, **options)

def initialize(output, verbose: true, level: self.class::DEFAULT_LEVEL, **options)
	@output = output
	@verbose = verbose
	@level = level
	
	@subjects = {}
	
	@options = options
end

def level= level

def level= level
	if level.is_a? Symbol
		@level = self.class::LEVELS[level]
	else
		@level = level
	end
end

def off!

def off!
	@level = self.class::MAXIMUM_LEVEL + 1
end

def verbose!(value = true)

def verbose!(value = true)
	@verbose = value
	@output.verbose!(value)
end

def with(level: @level, verbose: @verbose, **options)

def with(level: @level, verbose: @verbose, **options)
	dup.tap do |logger|
		logger.level = level
		logger.verbose! if verbose
		logger.options = @options.merge(options)
	end
end