Есть ли способ исправить строку, чтобы […] он по умолчанию вызывал метод colourize?
Это плохая идея. Строки являются фундаментальными для Ruby, как массивы, хэши и символы. Помещение цветовых кодов в каждую созданную строку, несмотря ни на что, скорее всего что-то сломает.
Вы должны добавлять цветовые коды только при фактической печати строки (и, вероятно, только при печати на tty).
Это подводит нас к puts
. Он записывает данные объекты в стандартный формат, преобразовывая их в строки при необходимости. К сожалению, строка не нуждается ни в каком преобразовании, поэтому вызов to_s
пропускается, и у нас нет метода для подключения.
Но вместо исправления String
мы могли бы исправить верхний уровень puts
:
(я использую upcase
в демонстрационных целях, потому что здесь я не могу отобразить escape-последовательности ANSI)
def puts(*args)
Kernel.puts(*args.map { |a| a.is_a?(String) ? a.upcase : a })
end
puts 'hello'
Выход:
HELLO
Поскольку исправление основных классов - грязное дело, давайте посмотрим, сможем ли мы найти более чистый подход. Документация для Kernel.puts
гласит:
Эквивалент $stdout.puts(obj, ...)
Это звучит многообещающе: $stdout
как глобальная переменная может быть легко изменена. Все, что нам нужно, это объект, который предоставляет собственный метод puts
и делегирует любой другой метод исходному стандартному выводу. Вот для чего SimpleDelegator
:
class OutputDecorator < SimpleDelegator
def puts(*args)
super *args.map { |a| a.is_a?(String) ? a.upcase : a }
end
end
Давайте попробуем:
puts 'before'
$stdout = OutputDecorator.new($stdout)
puts 'within'
$stdout = $stdout.__getobj__
puts 'after'
Выход:
before
WITHIN
after