Keluaran Ruby berwarna ke terminal [ditutup]


273

Menggunakan Ruby, bagaimana saya bisa melakukan pewarnaan teks latar dan latar depan untuk output di terminal?

Saya ingat, ketika memprogram Pascal kita semua biasa menulis textcolor(…)prosedur kita sendiri untuk membuat program pendidikan kecil kita terlihat lebih cantik dan presentasional.

Bagaimana saya bisa mengkode yang setara dengan itu di Ruby?


Jadi tidak mungkin untuk mendapatkan warna "oranye" sebagai contoh?
Matrix

Jawaban:


379

Mewarnai adalah permata favorit saya! :-)

Saksikan berikut ini:

https://github.com/fazibear/colorize

Instalasi:

gem install colorize

Pemakaian:

require 'colorize'

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

2
Bisakah seseorang memberi tahu saya jika Colorize berfungsi di Terminal Cygwin? Saya mencoba menjalankan kode di atas dalam Cygwin tetapi keluar tanpa warna ..
jj_

5
Ini akan bekerja dengan baik di Prompt Perintah Windows jika Anda menginstal win32consolepermata dan require 'win32console'setelahnya colorize.
Ben

2
@Ben Saya belum mencobanya secara pribadi, tetapi sejak Ruby 2.0 Anda tidak perlu lagi win32consolepermata itu. github.com/luislavena/win32console/issues/…
Dennis

1
Adakah cara untuk membuat ini bekerja dengan Sumblime Text console?
nipponese

6
Permata ini dilisensikan di bawah GPL sehingga (saya pikir) itu tidak dapat digunakan dalam perangkat lunak berpemilik. jonathannen.com/2013/07/07/license-your-gems.html
Andrei Botalov

249

Menggabungkan jawaban di atas, Anda dapat menerapkan sesuatu yang berfungsi seperti permata berwarna tanpa perlu ketergantungan lain.

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, edit Nick yang bagus. Ya tentu saja tidak perlu melewati diri sendiri. Saya lelah ketika saya menulis ini :)
Erik Skoglund

Apakah ini akan bekerja di windows juga?
Alp

Ini bekerja di windows jika Anda menggunakan ConEmu
Mike Glenn

1
Saya suka ini lebih baik daripada mewarnai karena ini hanya mengubah warna latar depan. warna sepertinya selalu mengubah warna latar belakang.
jlyonsmith

1
Saya tahu saya terlambat ke pesta, tapi bukankah lebih baik menggunakan penutupan di sini?

215

Sebagai metode kelas String (hanya 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

dan penggunaan:

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

di konsol saya:

masukkan deskripsi gambar di sini

tambahan:

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

menghapus karakter pemformatan

Catatan

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

Bold off harus menggunakan kode melarikan diri 22 bukan 21:def bold; "\e[1m#{self}\e[22m" end
Kanat Bolazar

@ KanatBolazar, Beberapa sistem mendukung 21 . Tapi saya mengubahnya ke 22 untuk kemampuan. Terima kasih.
Ivan Black

1
Ini bagus, saya taruh di inisialisasi di aplikasi Rails saya. Bekerja seperti pesona!

Kiat yang fantastis. Sangat mudah dan tidak ada ketergantungan. Dilakukan dengan sangat baik!
mraxus

1
Di Windows 10 cmd.exe, puts "\e[0"tidak berfungsi untuk menghapus format; puts "\e[0m"harus digunakan
Nnnes

41

Saya menulis sedikit metode untuk menguji mode warna dasar, berdasarkan jawaban oleh Erik Skoglund dan lainnya.

#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

contoh output: ruby colortest


37

Anda dapat menggunakan urutan pelarian ANSI untuk melakukan ini di konsol. Saya tahu ini berfungsi di Linux dan OSX, saya tidak yakin apakah konsol Windows (cmd) mendukung ANSI.

Saya melakukannya di Jawa, tetapi idenya sama.

//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
Ini berfungsi dan memiliki keuntungan karena tidak memerlukan permata, yang mungkin mengganggu sebagian orang.
ThomasW

3
Konsol Windows memang mendukung kode ANSI.
Ben

16

Sementara jawaban lain akan melakukan pekerjaan dengan baik untuk kebanyakan orang, cara Unix yang "benar" untuk melakukan ini harus disebutkan. Karena semua jenis terminal teks tidak mendukung urutan ini, Anda dapat meminta database terminfo , sebuah abstraksi atas kapabilitas dari berbagai terminal teks. Hal ini mungkin tampak sebagian besar dari kepentingan sejarah - terminal software yang digunakan saat ini umumnya mendukung urutan ANSI - tetapi memiliki (setidaknya) satu efek praktis: kadang-kadang berguna untuk dapat mengatur variabel lingkungan TERMuntuk dumbmenghindari semua styling seperti, misalnya saat menyimpan output ke file teks. Juga, rasanya menyenangkan melakukan hal-hal yang benar . :-)

Anda dapat menggunakan permata ruby-terminfo . Perlu beberapa kompilasi C untuk menginstal; Saya dapat menginstalnya di sistem Ubuntu 14.10 saya dengan:

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

Kemudian Anda dapat meminta basis data seperti ini (lihat halaman manual terminfo untuk mengetahui daftar kode apa yang tersedia):

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

Inilah kelas pembungkus kecil yang saya kumpulkan untuk membuat segala sesuatunya menjadi lebih mudah digunakan.

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

Pemakaian:

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

Output dari skrip Ruby di atas

(sunting) Akhirnya, jika Anda lebih suka tidak memerlukan permata, Anda dapat mengandalkan tputprogram, seperti dijelaskan di sini - Contoh Ruby:

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

4
Mayor, +1 utama untuk penggunaan tput. Bahkan tidak bisa mengartikulasikan betapa rambut rontok tputtelah menyelamatkan saya.
Pierce

14

Saya membuat metode ini yang bisa membantu. Ini bukan masalah besar tapi berhasil:

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

Berikut cara menggunakannya:

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

Kemungkinan peningkatan bisa:

  • colorsdan bgColorssedang didefinisikan setiap kali metode dipanggil dan mereka tidak berubah.
  • Menambahkan opsi lain seperti bold, underline, dim, dll

Metode ini tidak berfungsi untuk p, seperti phalnya inspectuntuk argumennya. Sebagai contoh:

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

akan menampilkan "\ e [0; 38mHello World \ e [0m"

Saya mengujinya dengan puts,, printdan permata Logger, dan itu berfungsi dengan baik.


Saya meningkatkan ini dan membuat kelas jadi colorsdan bgColorsmerupakan konstanta kelas dan colorizemerupakan metode kelas:

EDIT: Gaya kode yang lebih baik, konstanta yang didefinisikan alih-alih variabel kelas, menggunakan simbol alih-alih string, menambahkan lebih banyak opsi seperti, tebal, miring, dll.

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

Anda dapat menggunakannya dengan melakukan:

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

Inilah yang saya lakukan untuk membuatnya bekerja tanpa membutuhkan permata:

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

Maka hanya teks dalam tanda kutip yang berwarna, dan Anda kembali ke program yang dijadwalkan secara rutin.


3
Tidak bekerja untuk saya. Saya mendapatkan, tepatnya:e[32mSOMETEXT
Oscar Godson

ada kesalahan ketik dalam karakter pelarian pertama: harus "\e(...)"bukannya"e\(...)"
arthropod

12

Saya menemukan beberapa:

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

Contoh:

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

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

Contoh:

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

http://github.com/sickill/rainbow

Contoh:

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

Jika Anda menggunakan Windows, Anda mungkin perlu melakukan "permata instal win32console" untuk mengaktifkan dukungan warna.

Juga artikel Pewarnaan konsol Naskah Ruby-script berguna jika Anda perlu membuat permata Anda sendiri. Ini menjelaskan cara menambahkan pewarnaan ANSI ke string. Anda dapat menggunakan pengetahuan ini untuk membungkusnya dalam beberapa kelas yang memperluas string atau sesuatu.



3

Saya menemukan jawaban di atas berguna tetapi tidak sesuai dengan tagihan jika saya ingin mewarnai sesuatu seperti keluaran log tanpa menggunakan perpustakaan pihak ketiga. Berikut ini yang memecahkan masalah bagi saya:

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

Saya harap ini membantu!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.