class Console::Output::Sensitive

Redact sensitive information from output.

def call(subject = nil, *arguments, sensitive: true, **options, &block)

@parameter block [Proc] An optional block to pass to the output.
@parameter options [Hash] Additional options to pass to the output.
@parameter sensitive [Boolean | Filter | Hash] Whether to filter sensitive information.
@parameter arguments [Array] The arguments to output.
@parameter subject [String] The subject of the message.

Write a message to the output, filtering sensitive information if necessary.
def call(subject = nil, *arguments, sensitive: true, **options, &block)
	if sensitive
		if sensitive.respond_to?(:call)
			filter = sensitive
		elsif sensitive.is_a?(Hash)
			filter = Filter.new(sensitive)
		end
		
		subject = redact(subject, filter)
		arguments = redact_array(arguments, filter)
	end
	
	super(subject, *arguments, **options)
end

def initialize(output, redact: REDACT, **options)

@parameter options [Hash] Additional options to pass to the output.
@parameter redact [Regexp] The pattern to redact.
@parameter output [Console::Output] The output to wrap.

Create a new sensitive output wrapper.
def initialize(output, redact: REDACT, **options)
	super(output, **options)
	
	@redact = redact
end

def redact(argument, filter)

@returns [String | Array | Hash] The redacted argument.
@parameter filter [Proc] An optional filter to apply to redacted text.
@parameter argument [String | Array | Hash] The argument to redact.

Redact sensitive information from the given argument.
def redact(argument, filter)
	case argument
	when String
		if filter
			filter.call(argument)
		elsif redact?(argument)
			"[REDACTED]"
		else
			argument
		end
	when Array
		redact_array(argument, filter)
	when Hash
		redact_hash(argument, filter)
	else
		redact(argument.to_s, filter)
	end
end

def redact?(text)

@returns [Boolean] Whether the text should be redacted.
@parameter text [String] The text to check.

Check if the given text should be redacted.
def redact?(text)
	text.match?(@redact)
end

def redact_array(array, filter)

@returns [Array] The redacted array.
@parameter filter [Proc] An optional filter to apply to redacted text.
@parameter array [Array] The array to redact.

Redact sensitive information from an array.
def redact_array(array, filter)
	array.map do |value|
		redact(value, filter)
	end
end

def redact_hash(arguments, filter)

@returns [Hash] The redacted hash.
@parameter filter [Proc] An optional filter to apply to redacted text.
@parameter arguments [Hash] The hash to redact.

Redact sensitive information from a hash.
def redact_hash(arguments, filter)
	arguments.transform_values do |value|
		redact(value, filter)
	end
end