Цветной выход Ruby на терминал [закрыт]


273

Используя Ruby, как я могу выполнить цвет фона и текста переднего плана для вывода в терминал?

Я помню, когда мы программировали на Pascal, мы все писали свои собственные textcolor(…)процедуры, чтобы наши маленькие образовательные программы выглядели более симпатично и представительно.

Как мне написать код, эквивалентный этому в Ruby?


То есть невозможно получить «оранжевый» цвет для примера?
Матрица

Ответы:


379

Colorize - мой любимый драгоценный камень! :-)

Проверьте это:

https://github.com/fazibear/colorize

Монтаж:

gem install colorize

Использование:

require 'colorize'

puts "I am now red".red
puts "I am now blue".blue
puts "Testing".yellow

2
Может кто-нибудь сказать мне, если Colorize работает в терминале Cygwin? Я попытался запустить приведенный выше код в Cygwin, но он выходит без цветов ..
JJ_

5
Это будет хорошо работать в командной строке Windows, если вы установите win32consoleгем и require 'win32console'после colorize.
Бен

2
@Ben Я лично не пробовал это, но начиная с Ruby 2.0 вам больше не нужен win32consoleдрагоценный камень. github.com/luislavena/win32console/issues/…
Деннис

1
Есть ли способ заставить это работать с консолью Sumblime Text?
Ниппонский

6
Этот драгоценный камень лицензирован под лицензией GPL, поэтому (я думаю) его нельзя использовать в проприетарном программном обеспечении. jonathannen.com/2013/07/07/license-your-gems.html
Андрей Боталов

249

Комбинируя ответы выше, вы можете реализовать что-то, что работает как раскраска драгоценного камня, не нуждаясь в другой зависимости.

class String
  # colorization
  def colorize(color_code)
    "\e[#{color_code}m#{self}\e[0m"
  end

  def red
    colorize(31)
  end

  def green
    colorize(32)
  end

  def yellow
    colorize(33)
  end

  def blue
    colorize(34)
  end

  def pink
    colorize(35)
  end

  def light_blue
    colorize(36)
  end
end

ах, приятно редактировать Ник. Да, конечно, нет нужды раздавать себя. Я устал, когда писал это :)
Эрик Скоглунд,

это будет работать в Windows тоже?
Alp

Он работает в Windows, если вы используете ConEmu
Майк Гленн

1
Мне нравится это лучше, чем colorize, поскольку это только меняет цвет переднего плана. colorize, кажется, всегда меняет цвет фона.
Jlyonsmith

1
Я знаю, что опаздываю на вечеринку, но не лучше ли использовать здесь затвор?

215

Как методы класса String (только для Unix):

class String
def black;          "\e[30m#{self}\e[0m" end
def red;            "\e[31m#{self}\e[0m" end
def green;          "\e[32m#{self}\e[0m" end
def brown;          "\e[33m#{self}\e[0m" end
def blue;           "\e[34m#{self}\e[0m" end
def magenta;        "\e[35m#{self}\e[0m" end
def cyan;           "\e[36m#{self}\e[0m" end
def gray;           "\e[37m#{self}\e[0m" end

def bg_black;       "\e[40m#{self}\e[0m" end
def bg_red;         "\e[41m#{self}\e[0m" end
def bg_green;       "\e[42m#{self}\e[0m" end
def bg_brown;       "\e[43m#{self}\e[0m" end
def bg_blue;        "\e[44m#{self}\e[0m" end
def bg_magenta;     "\e[45m#{self}\e[0m" end
def bg_cyan;        "\e[46m#{self}\e[0m" end
def bg_gray;        "\e[47m#{self}\e[0m" end

def bold;           "\e[1m#{self}\e[22m" end
def italic;         "\e[3m#{self}\e[23m" end
def underline;      "\e[4m#{self}\e[24m" end
def blink;          "\e[5m#{self}\e[25m" end
def reverse_color;  "\e[7m#{self}\e[27m" end
end

и использование:

puts "I'm back green".bg_green
puts "I'm red and back cyan".red.bg_cyan
puts "I'm bold and green and backround red".bold.green.bg_red

на моей консоли:

введите описание изображения здесь

дополнительно:

def no_colors
  self.gsub /\e\[\d+m/, ""
end

удаляет символы форматирования

Заметка

puts "\e[31m" # set format (red foreground)
puts "\e[0m"   # clear format
puts "green-#{"red".red}-green".green # will be green-red-normal, because of \e[0

Выделенные должны использовать код выхода 22, а не 21:def bold; "\e[1m#{self}\e[22m" end
Канат Болазар

@KanatBolazar, некоторые системы поддерживают 21 . Но я изменяю это на 22 для возможности. Спасибо.
Иван Блэк

1
Это здорово, я поместил его в инициализатор в своем приложении Rails. Работает как шарм!

Фантастические советы. Так просто и без зависимостей. Очень, очень хорошо сделано!
Мраксус

1
В Windows 10 cmd.exe, puts "\e[0"не работает в четкой форме; puts "\e[0m"должен быть использован
Nnnes

41

Я написал небольшой метод для проверки основных цветовых режимов, основанный на ответах Эрика Скоглунда и других.

#outputs color table to console, regular and bold modes
def colortable
  names = %w(black red green yellow blue pink cyan white default)
  fgcodes = (30..39).to_a - [38]

  s = ''
  reg  = "\e[%d;%dm%s\e[0m"
  bold = "\e[1;%d;%dm%s\e[0m"
  puts '                       color table with these background codes:'
  puts '          40       41       42       43       44       45       46       47       49'
  names.zip(fgcodes).each {|name,fg|
    s = "#{fg}"
    puts "%7s "%name + "#{reg}  #{bold}   "*9 % [fg,40,s,fg,40,s,  fg,41,s,fg,41,s,  fg,42,s,fg,42,s,  fg,43,s,fg,43,s,  
      fg,44,s,fg,44,s,  fg,45,s,fg,45,s,  fg,46,s,fg,46,s,  fg,47,s,fg,47,s,  fg,49,s,fg,49,s ]
  }
end

пример вывода: рубиновый цвет


37

Вы можете использовать управляющие последовательности ANSI, чтобы сделать это на консоли. Я знаю, что это работает на Linux и OSX, я не уверен, поддерживает ли консоль Windows (cmd) ANSI.

Я сделал это на Java, но идеи те же.

//foreground color
public static final String BLACK_TEXT()   { return "\033[30m";}
public static final String RED_TEXT()     { return "\033[31m";}
public static final String GREEN_TEXT()   { return "\033[32m";}
public static final String BROWN_TEXT()   { return "\033[33m";}
public static final String BLUE_TEXT()    { return "\033[34m";}
public static final String MAGENTA_TEXT() { return "\033[35m";}
public static final String CYAN_TEXT()    { return "\033[36m";}
public static final String GRAY_TEXT()    { return "\033[37m";}

//background color
public static final String BLACK_BACK()   { return "\033[40m";}
public static final String RED_BACK()     { return "\033[41m";}
public static final String GREEN_BACK()   { return "\033[42m";}
public static final String BROWN_BACK()   { return "\033[43m";}
public static final String BLUE_BACK()    { return "\033[44m";}
public static final String MAGENTA_BACK() { return "\033[45m";}
public static final String CYAN_BACK()    { return "\033[46m";}
public static final String WHITE_BACK()   { return "\033[47m";}

//ANSI control chars
public static final String RESET_COLORS() { return "\033[0m";}
public static final String BOLD_ON()      { return "\033[1m";}
public static final String BLINK_ON()     { return "\033[5m";}
public static final String REVERSE_ON()   { return "\033[7m";}
public static final String BOLD_OFF()     { return "\033[22m";}
public static final String BLINK_OFF()    { return "\033[25m";}
public static final String REVERSE_OFF()  { return "\033[27m";}

7
Это работает и имеет то преимущество, что не требует драгоценного камня, который может раздражать некоторых людей.
ThomasW

3
Консоль Windows действительно поддерживает коды ANSI.
Бен

16

В то время как другие ответы отлично подойдут для большинства людей, следует упомянуть «правильный» способ Unix сделать это. Поскольку все типы текстовых терминалов не поддерживают эти последовательности, вы можете запросить базу данных terminfo , абстракцию над возможностями различных текстовых терминалов. Это может показаться в основном исторический интерес - программного обеспечения терминалов, используемых сегодня в целом поддерживают ANSI последовательности - но у него есть (по крайней мере) один практический эффект: иногда полезно , чтобы иметь возможность установить переменную окружения , TERMчтобы dumbизбежать всех таких стиль, например, при сохранении вывода в текстовый файл. Кроме того, приятно делать все правильно . :-)

Вы можете использовать гем ruby-terminfo . Для установки требуется компиляция Си; Я смог установить его под свою систему Ubuntu 14.10 с помощью:

$ sudo apt-get install libncurses5-dev
$ gem install ruby-terminfo --user-install

Затем вы можете запросить базу данных следующим образом (см. Справочную страницу terminfo для получения списка доступных кодов):

require 'terminfo' 
TermInfo.control("bold")
puts "Bold text"
TermInfo.control("sgr0")
puts "Back to normal."
puts "And now some " + TermInfo.control_string("setaf", 1) + 
     "red" + TermInfo.control_string("sgr0") + " text."

Вот небольшой класс-обертка, который я собрал, чтобы сделать его немного более простым в использовании.

require 'terminfo'

class Style
  def self.style() 
    @@singleton ||= Style.new
  end

  colors = %w{black red green yellow blue magenta cyan white}
  colors.each_with_index do |color, index|
    define_method(color) { get("setaf", index) }
    define_method("bg_" + color) { get("setab", index) }
  end

  def bold()  get("bold")  end
  def under() get("smul")  end
  def dim()   get("dim")   end
  def clear() get("sgr0")  end

  def get(*args)
    begin
      TermInfo.control_string(*args)
    rescue TermInfo::TermInfoError
      ""
    end
  end
end

Использование:

c = Style.style
C = c.clear
puts "#{c.red}Warning:#{C} this is #{c.bold}way#{C} #{c.bg_red}too much #{c.cyan + c.under}styling#{C}!"
puts "#{c.dim}(Don't you think?)#{C}"

Вывод вышеуказанного скрипта Ruby

(edit) Наконец, если вы не хотите использовать гем, вы можете положиться на tputпрограмму, как описано здесь - пример Ruby:

puts "Hi! " + `tput setaf 1` + "This is red!" + `tput sgr0`

4
Майор, майор +1 для использования tput. Даже не могу сказать, сколько выпадение волос tputспасло меня.
Пирс

14

Я сделал этот метод, который мог бы помочь. Это не имеет большого значения, но это работает:

def colorize(text, color = "default", bgColor = "default")
    colors = {"default" => "38","black" => "30","red" => "31","green" => "32","brown" => "33", "blue" => "34", "purple" => "35",
     "cyan" => "36", "gray" => "37", "dark gray" => "1;30", "light red" => "1;31", "light green" => "1;32", "yellow" => "1;33",
      "light blue" => "1;34", "light purple" => "1;35", "light cyan" => "1;36", "white" => "1;37"}
    bgColors = {"default" => "0", "black" => "40", "red" => "41", "green" => "42", "brown" => "43", "blue" => "44",
     "purple" => "45", "cyan" => "46", "gray" => "47", "dark gray" => "100", "light red" => "101", "light green" => "102",
     "yellow" => "103", "light blue" => "104", "light purple" => "105", "light cyan" => "106", "white" => "107"}
    color_code = colors[color]
    bgColor_code = bgColors[bgColor]
    return "\033[#{bgColor_code};#{color_code}m#{text}\033[0m"
end

Вот как это использовать:

puts "#{colorize("Hello World")}"
puts "#{colorize("Hello World", "yellow")}"
puts "#{colorize("Hello World", "white","light red")}"

Возможные улучшения могут быть:

  • colorsи bgColorsопределяются каждый раз, когда вызывается метод, и они не меняются.
  • Добавьте другие варианты , как bold, underline, dimи т.д.

Этот метод не работает p, как pи inspectего аргумент. Например:

p "#{colorize("Hello World")}"

покажет "\ e [0; 38mHello World \ e [0m"

Я тестировал его puts, printи камень Logger, и он работает отлично.


Я улучшил это и сделал класс так, colorsи он bgColorsявляется константой класса и colorizeявляется методом класса:

РЕДАКТИРОВАТЬ: улучшенный стиль кода, определенные константы вместо переменных класса, использование символов вместо строк, добавлены дополнительные параметры, такие как полужирный шрифт, курсив и т. Д.

class Colorizator
    COLOURS = { default: '38', black: '30', red: '31', green: '32', brown: '33', blue: '34', purple: '35',
                cyan: '36', gray: '37', dark_gray: '1;30', light_red: '1;31', light_green: '1;32', yellow: '1;33',
                light_blue: '1;34', light_purple: '1;35', light_cyan: '1;36', white: '1;37' }.freeze
    BG_COLOURS = { default: '0', black: '40', red: '41', green: '42', brown: '43', blue: '44',
                   purple: '45', cyan: '46', gray: '47', dark_gray: '100', light_red: '101', light_green: '102',
                   yellow: '103', light_blue: '104', light_purple: '105', light_cyan: '106', white: '107' }.freeze

    FONT_OPTIONS = { bold: '1', dim: '2', italic: '3', underline: '4', reverse: '7', hidden: '8' }.freeze

    def self.colorize(text, colour = :default, bg_colour = :default, **options)
        colour_code = COLOURS[colour]
        bg_colour_code = BG_COLOURS[bg_colour]
        font_options = options.select { |k, v| v && FONT_OPTIONS.key?(k) }.keys
        font_options = font_options.map { |e| FONT_OPTIONS[e] }.join(';').squeeze
        return "\e[#{bg_colour_code};#{font_options};#{colour_code}m#{text}\e[0m".squeeze(';')
    end
end

Вы можете использовать его, выполнив:

Colorizator.colorize "Hello World", :gray, :white
Colorizator.colorize "Hello World", :light_blue, bold: true
Colorizator.colorize "Hello World", :light_blue, :white, bold: true, underline: true

13

Вот что я сделал, чтобы он работал без каких-либо драгоценных камней:

def red(mytext) ; "\e[31m#{mytext}\e[0m" ; end
puts red("hello world")

Тогда только текст в кавычках там раскрашен, и вы возвращаетесь в свою регулярно запланированную программу.


3
Не работает для меня Я получаю, точно:e[32mSOMETEXT
Оскар Годсон

там была опечатка в первом экранирующего символа: должна быть "\e(...)"вместо"e\(...)"
членистоногих

12

Я нашел несколько:

http://github.com/ssoroka/ansi/tree/master

Примеры:

puts ANSI.color(:red) { "hello there" }
puts ANSI.color(:green) + "Everything is green now" + ANSI.no_color

http://flori.github.com/term-ansicolor/

Примеры:

print red, bold, "red bold", reset, "\n"
print red(bold("red bold")), "\n"
print red { bold { "red bold" } }, "\n"

http://github.com/sickill/rainbow

Пример:

puts "this is red".foreground(:red) + " and " + "this on yellow bg".background(:yellow) + " and " + "even bright underlined!".underline.bright

Если вы работаете в Windows, вам может потребоваться установить gem install win32console, чтобы включить поддержку цветов.

Также статья Colorizing console Вывод Ruby-скрипта полезен, если вам нужно создать свой собственный гем. В нем объясняется, как добавить ANSI-раскраску в строки. Вы можете использовать это знание, чтобы обернуть его в некоторый класс, который расширяет строку или что-то еще.



3

Я нашел ответы выше, чтобы быть полезным, но не отвечал всем требованиям, если я хотел раскрасить что-то вроде вывода журнала без использования сторонних библиотек. Следующее решило проблему для меня:

red = 31
green = 32
blue = 34

def color (color=blue)
  printf "\033[#{color}m";
  yield
  printf "\033[0m"
end

color { puts "this is blue" }
color(red) { logger.info "and this is red" }

Я надеюсь, что это помогает!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.