Sortie Ruby colorisée vers le terminal [fermé]

273

À l'aide de Ruby, comment puis-je effectuer la colorisation du texte d'arrière-plan et de premier plan pour la sortie dans le terminal?

Je me souviens, lors de la programmation de Pascal, nous écrivions tous nos propres textcolor(…)procédures pour rendre nos petits programmes éducatifs plus jolis et plus présentationnels.

Comment pourrais-je procéder pour coder un équivalent de cela dans Ruby?

gmile
la source
Il est donc impossible d'obtenir une couleur "orange" par exemple?
Matrix
Commander github.com/kigster/colored2
Konstantin Gredeskoul

Réponses:

379

Coloriser est mon joyau préféré! :-)

Vérifiez-le:

https://github.com/fazibear/colorize

Installation:

gem install colorize

Usage:

require 'colorize'

puts "I am now red".red
puts "I am now blue".blue
puts "Testing".yellow
jaredmdobson
la source
2
Quelqu'un pourrait-il me dire si Colorize fonctionne dans Cygwin Terminal? J'ai essayé d'exécuter le code ci-dessus dans Cygwin mais il sort sans couleurs ..
jj_
5
Cela fonctionnera bien dans une invite de commande Windows si vous installez la win32consolegemme et require 'win32console'après colorize.
Ben
2
@Ben Je ne l'ai pas essayé personnellement, mais depuis Ruby 2.0, vous ne devriez plus avoir besoin de la win32consolegemme. github.com/luislavena/win32console/issues/…
Dennis
1
Est-il possible de faire fonctionner cela avec la console Sumblime Text?
nipponese
6
Ce bijou est sous licence GPL donc (je pense) il ne peut pas être utilisé dans un logiciel propriétaire. jonathannen.com/2013/07/07/license-your-gems.html
Andrei Botalov
249

En combinant les réponses ci-dessus, vous pouvez implémenter quelque chose qui fonctionne comme la gemme à colorier sans avoir besoin d'une autre dépendance.

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
Erik Skoglund
la source
ah, belle retouche Nick. Oui, bien sûr, il n'est pas nécessaire de se faire passer. J'étais fatigué quand j'ai écrit ça :)
Erik Skoglund
cela fonctionnera-t-il également sous Windows?
Alp
Cela fonctionne dans les fenêtres si vous utilisez ConEmu
Mike Glenn
1
J'aime mieux que coloriser car cela ne change que la couleur de premier plan. colorize semble toujours changer la couleur de fond.
jlyonsmith
1
Je sais que je suis en retard à la fête, mais ne serait-il pas préférable d'utiliser une fermeture ici?
215

En tant que méthodes de classe String (Unix uniquement):

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

et utilisation:

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

sur ma console:

entrez la description de l'image ici

Additionnel:

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

supprime les caractères de formatage

Remarque

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
Ivan Black
la source
Les caractères gras doivent utiliser le code d'échappement 22 et non 21:def bold; "\e[1m#{self}\e[22m" end
Kanat Bolazar
@KanatBolazar, Certains systèmes prennent en charge 21 . Mais je le change en 22 pour la capacité. Merci.
Ivan Black
1
C'est super, je l'ai mis dans un initialiseur dans mon application Rails. Fonctionne comme un charme!
Conseils fantastiques. Si facile et sans dépendances. Très très bien fait!
mraxus
1
Dans Windows 10 cmd.exe, puts "\e[0"ne fonctionne pas pour effacer le format; puts "\e[0m"doit être utilisé
Nnnes
41

J'ai écrit une petite méthode pour tester les modes de couleur de base, basée sur les réponses d'Erik Skoglund et d'autres.

#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

exemple de sortie: ruby colortest

glacé
la source
37

Vous pouvez utiliser des séquences d'échappement ANSI pour ce faire sur la console. Je sais que cela fonctionne sur Linux et OSX, je ne sais pas si la console Windows (cmd) prend en charge ANSI.

Je l'ai fait à Java, mais les idées sont les mêmes.

//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";}
Ryan Michela
la source
7
Cela fonctionne et a l'avantage de ne pas nécessiter de gemme, ce qui pourrait ennuyer certaines personnes.
ThomasW
3
La console Windows prend en charge les codes ANSI.
Ben
16

Alors que les autres réponses feront l'affaire pour la plupart des gens, la manière Unix "correcte" de le faire doit être mentionnée. Étant donné que tous les types de terminaux de texte ne prennent pas en charge ces séquences, vous pouvez interroger la base de données terminfo , une abstraction sur les capacités de divers terminaux de texte. Cela peut sembler la plupart du temps d'intérêt historique - terminaux logiciels utilisés aujourd'hui supportent en général les séquences ANSI - mais il ne possède (au moins) un effet pratique: il est parfois utile de pouvoir définir la variable d'environnement TERMpour dumbéviter tout ce style, par exemple lors de l'enregistrement de la sortie dans un fichier texte. En outre, il est bon de faire les choses à droite . :-)

Vous pouvez utiliser la gemme ruby-terminfo . Il a besoin d'être compilé en C pour être installé; J'ai pu l'installer sous mon système Ubuntu 14.10 avec:

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

Ensuite, vous pouvez interroger la base de données comme ceci (voir la page de manuel terminfo pour une liste des codes disponibles):

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."

Voici une petite classe wrapper que j'ai réunie pour rendre les choses un peu plus simples à utiliser.

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

Usage:

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}"

Sortie du script Ruby ci-dessus

(modifier) ​​Enfin, si vous préférez ne pas avoir besoin d'une gemme, vous pouvez vous fier au tputprogramme, comme décrit ici - exemple Ruby:

puts "Hi! " + `tput setaf 1` + "This is red!" + `tput sgr0`
skagedal
la source
4
Majeur, majeur +1 pour l'utilisation de tput. Je ne peux même pas dire combien la perte de cheveux tputm'a sauvé.
Pierce
14

J'ai fait cette méthode qui pourrait aider. Ce n'est pas grave mais ça marche:

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

Voici comment l'utiliser:

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

Les améliorations possibles pourraient être:

  • colorset bgColorssont définis à chaque appel de la méthode et ne changent pas.
  • Ajouter d' autres options comme bold, underline, dim, etc.

Cette méthode ne fonctionne pas pour p, tout comme pun inspectpour son argument. Par exemple:

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

affichera "\ e [0; 38mHello World \ e [0m"

Je l'ai testé avec puts, printet le bijou Logger, et cela fonctionne très bien.


J'ai amélioré cela et fait une classe ainsi colorset bgColorssont des constantes de classe etcolorize est une méthode de classe:

EDIT: meilleur style de code, constantes définies au lieu de variables de classe, utilisation de symboles au lieu de chaînes, ajout d'options supplémentaires comme, gras, italique, etc.

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

Vous pouvez l'utiliser en faisant:

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
Redithion
la source
13

Voici ce que j'ai fait pour le faire fonctionner sans avoir besoin de gemmes:

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

Ensuite, seul le texte entre guillemets est coloré et vous revenez à votre programme régulier.

suzyQ
la source
3
Ça ne marche pas pour moi. Je reçois, exactement:e[32mSOMETEXT
Oscar Godson
il y avait une faute de frappe dans le premier caractère d'échappement: devrait être "\e(...)"au lieu de"e\(...)"
arthropode
12

J'en ai trouvé quelques-uns:

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

Exemples:

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

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

Exemples:

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

http://github.com/sickill/rainbow

Exemple:

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

Si vous êtes sous Windows, vous devrez peut-être faire une "gem install win32console" pour activer la prise en charge des couleurs.

De plus, l'article Colorizing console Ruby-script output est utile si vous devez créer votre propre bijou. Il explique comment ajouter une coloration ANSI aux chaînes. Vous pouvez utiliser ces connaissances pour l'envelopper dans une classe qui étend la chaîne ou quelque chose.

Petros
la source
8

Cela peut vous aider: Sortie rubis colorisée

ennuikiller
la source
1
Et en améliorant l'exemple sur ce lien, vous pouvez étendre la classe String pour la rendre plus facile à utiliser ("Hello" .red):class String; def red; colorize(self, "\033[31m"); end; end
Adriano P
3

J'ai trouvé les réponses ci-dessus utiles, mais cela ne convenait pas si je voulais coloriser quelque chose comme la sortie du journal sans utiliser de bibliothèques tierces. Les éléments suivants ont résolu le problème pour moi:

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" }

J'espère que ça aide!

pmyjavec
la source