Uscita Ruby colorata al terminale [chiuso]


273

Utilizzando Ruby, come posso eseguire la colorazione del testo in background e in primo piano per l'output nel terminale?

Ricordo che durante la programmazione di Pascal eravamo tutti soliti scrivere le nostre textcolor(…)procedure per rendere i nostri piccoli programmi educativi più belli e presentativi.

Come potrei fare per codificare un equivalente di quello in Ruby?


Quindi è impossibile ottenere il colore "arancione" per esempio?
Matrix,

Risposte:


379

Colorize è la mia gemma preferita! :-)

Controlla:

https://github.com/fazibear/colorize

Installazione:

gem install colorize

Uso:

require 'colorize'

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

2
Qualcuno potrebbe dirmi se Colorize funziona nel terminale Cygwin? Ho provato a eseguire il codice sopra in Cygwin ma viene fuori senza colori ..
jj_

5
Funzionerà perfettamente in un prompt dei comandi di Windows se si installa win32consolegem e require 'win32console'successivamente colorize.
Ben

2
@ Ben non l'ho provato personalmente, ma da Ruby 2.0 non dovresti più aver bisogno della win32consolegemma. github.com/luislavena/win32console/issues/…
Dennis

1
Un modo per farlo funzionare con la console di Sumblime Text?
nipponese,

6
Questa gemma è sotto licenza GPL, quindi (penso) non può essere utilizzata in software proprietario. jonathannen.com/2013/07/07/license-your-gems.html
Andrei Botalov

249

Combinando le risposte sopra, è possibile implementare qualcosa che funziona come la gemma colorize senza bisogno di un'altra dipendenza.

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

ah, bella modifica Nick. Sì, certo, non è necessario passare da soli. Ero stanco quando ho scritto questo :)
Erik Skoglund,

funzionerà anche su Windows?
Alp

Funziona su Windows se stai usando ConEmu
Mike Glenn il

1
Mi piace di più che colorare. Questo cambia solo il colore di primo piano. colorize sembra cambiare sempre il colore di sfondo.
jlyonsmith l'

1
So di essere in ritardo alla festa, ma non sarebbe meglio usare una chiusura qui?

215

Come metodi della classe String (solo 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

e utilizzo:

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

sulla mia console:

inserisci qui la descrizione dell'immagine

supplementari:

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

rimuove i caratteri di formattazione

Nota

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

Il grassetto dovrebbe usare il codice di escape 22 non 21:def bold; "\e[1m#{self}\e[22m" end
Kanat Bolazar,

@KanatBolazar, Alcuni sistemi supportano 21 . Ma lo cambio a 22 per capacità. Grazie.
Ivan Black,

1
È fantastico, l'ho messo in un inizializzatore nella mia applicazione Rails. Funziona come un fascino!

Suggerimenti fantastici. Così facile e senza dipendenze. Molto ben fatto!
mraxus,

1
In Windows 10 cmd.exe, puts "\e[0"non funziona per cancellare il formato; puts "\e[0m"deve essere usato
Nnnes il

41

Ho scritto un piccolo metodo per testare le modalità colore di base, basato sulle risposte di Erik Skoglund e altri.

#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

esempio di output: ruby colortest


37

È possibile utilizzare le sequenze di escape ANSI per eseguire ciò sulla console. So che funziona su Linux e OSX, non sono sicuro che la console di Windows (cmd) supporti ANSI.

L'ho fatto in Java, ma le idee sono le stesse.

//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
Funziona e ha il vantaggio di non richiedere una gemma, che potrebbe infastidire alcune persone.
ThomasW,

3
La console di Windows supporta infatti i codici ANSI.
Ben

16

Mentre le altre risposte faranno il lavoro bene per la maggior parte delle persone, dovrebbe essere menzionato il modo "corretto" di Unix per farlo. Poiché tutti i tipi di terminali di testo non supportano queste sequenze, è possibile eseguire una query sul database terminfo , un'astrazione sulle capacità di vari terminali di testo. Questo potrebbe sembrare per lo più di interesse storico - terminali software in uso oggi generalmente supportare le sequenze ANSI - ma non hanno (almeno) un effetto pratico: a volte è utile essere in grado di impostare la variabile d'ambiente TERMper dumbevitare tutti questi styling, ad esempio quando si salva l'output in un file di testo. Inoltre, è bello fare le cose nel modo giusto . :-)

Puoi usare la gemma rubino-terminfo . Ha bisogno di un po 'di compilazione C per l'installazione; Sono stato in grado di installarlo sul mio sistema Ubuntu 14.10 con:

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

Quindi è possibile eseguire una query sul database in questo modo (consultare la pagina man terminfo per un elenco di quali codici sono disponibili):

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

Ecco una piccola classe di wrapper che ho messo insieme per rendere le cose un po 'più semplici da usare.

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

Uso:

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

Uscita dello script Ruby sopra

(modifica) Infine, se preferisci non richiedere un gioiello, puoi fare affidamento sul tputprogramma, come descritto qui - Esempio di Ruby:

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

4
Maggiore, maggiore +1 per l'uso di tput. Non riesco nemmeno a capire quanta perdita di capelli tputmi ha salvato.
Pierce,

14

Ho fatto questo metodo che potrebbe aiutare. Non è un grosso problema ma funziona:

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

Ecco come usarlo:

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

I possibili miglioramenti potrebbero essere:

  • colorse bgColorsvengono definiti ogni volta che viene chiamato il metodo e non cambiano.
  • Aggiungere altre opzioni come bold, underline, dim, etc.

Questo metodo non funziona per p, come pfa un inspectal suo argomento. Per esempio:

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

mostrerà "\ e [0; 38mHello World \ e [0m"

L'ho provato con puts, printe la gemma Logger, e funziona benissimo.


Ho migliorato questo, ho creato una classe colorse bgColorssono costanti di classe ed colorizeè un metodo di classe:

EDIT: migliore stile del codice, definizione di costanti anziché variabili di classe, utilizzo di simboli anziché stringhe, aggiunta di altre opzioni come grassetto, corsivo, ecc.

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

Puoi usarlo facendo:

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

Ecco cosa ho fatto per farlo funzionare senza bisogno di gemme:

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

Quindi solo il testo tra virgolette è colorato e si torna al programma regolarmente programmato.


3
Non funziona per me. Ricevo esattamente:e[32mSOMETEXT
Oscar Godson

c'era un errore di battitura nel primo personaggio di escape: dovrebbe essere "\e(...)"invece di"e\(...)"
artropodi il

12

Ne ho trovati alcuni:

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

Esempi:

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

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

Esempi:

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

http://github.com/sickill/rainbow

Esempio:

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

Se utilizzi Windows, potrebbe essere necessario eseguire una "gem install win32console" per abilitare il supporto per i colori.

Anche l'articolo L' output di Ruby-script della console di colorazione è utile se devi creare il tuo gioiello. Spiega come aggiungere la colorazione ANSI alle stringhe. Puoi usare questa conoscenza per racchiuderla in una classe che estende la stringa o qualcosa del genere.



3

Ho trovato utili le risposte di cui sopra ma non mi andava bene se volevo colorare qualcosa come l'output del log senza usare librerie di terze parti. Quanto segue ha risolto il problema per me:

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

Spero possa essere d'aiuto!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.