Кольоровий вихід Ruby до терміналу [закрито]


273

Використовуючи Ruby, як я можу виконати кольоровість тексту фонового та переднього плану для виводу в термінал?

Пам’ятаю, під час програмування Паскаля ми всі писали власні 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, але він виходить без кольорів ..
jj_

5
Це буде добре працювати в командному рядку Windows, якщо встановити win32consoleдорогоцінний камінь і require 'win32console'після colorize.
Бен

2
@Ben я особисто не пробував цього, але оскільки Ruby 2.0 вам більше не потрібен win32consoleдорогоцінний камінь. github.com/luislavena/win32console/isissue/…
Dennis

1
Будь-який спосіб зробити цю роботу за допомогою текстової консолі Sumblime?
nipponese

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?
Альп

Він працює у Windows, якщо ви використовуєте ConEmu
Mike Glenn

1
Мені це подобається краще, ніж розфарбувати, оскільки це лише змінює колір переднього плану. кольоровий колір, здається, завжди змінює колір фону.
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. Працює як шарм!

Фантастичні поради. Так легко і без залежностей. Дуже дуже добре зроблено!
mraxus

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 . Для встановлення потрібен певний компілюючий C; Мені вдалося встановити його в моїй системі Ubuntu 14.10 за допомогою:

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

Тоді ви можете запитувати подібну базу даних (див. Сторінку manfo для переліку доступних кодів):

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

(редагувати) Нарешті, якщо вам не потрібен дорогоцінний камінь, ви можете покластися на 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; 38mСвіт привіт \ e [0m"

Я протестував це з puts, printі драгоценним каменем Logger, і він чудово працює.


Я вдосконалив це і створив клас таким чином, colorsі bgColorsце константи класу іcolorize це метод класу:

EDIT: Кращий стиль коду, визначені константи замість змінних класів, використання символів замість рядків, додано більше параметрів, таких як, жирний шрифт, курсив тощо.

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", щоб увімкнути підтримку кольорів.

Також стаття Розфарбовування консолі 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.