Đầu ra Ruby được tô màu cho thiết bị đầu cuối [đóng]


273

Sử dụng Ruby, làm cách nào tôi có thể thực hiện tô màu văn bản nền và tiền cảnh cho đầu ra trong thiết bị đầu cuối?

Tôi nhớ, khi lập trình Pascal, tất cả chúng ta thường viết các textcolor(…)quy trình của riêng mình để làm cho các chương trình giáo dục nhỏ của chúng ta trông đẹp hơn và mang tính trình bày.

Làm thế nào tôi có thể viết về một mã tương đương với Ruby?


Vì vậy, nó có thể có được màu "cam" cho mẫu?
Ma trận

Câu trả lời:


379

Colorize là đá quý yêu thích của tôi! :-)

Kiểm tra xem nó:

https://github.com/fazibear/colorize

Cài đặt:

gem install colorize

Sử dụng:

require 'colorize'

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

2
Ai đó có thể cho tôi biết nếu Colorize không hoạt động trong Cygwin Terminal? Tôi đã thử chạy đoạn mã trên trong Cygwin nhưng nó không có màu ..
jj_

5
Điều này sẽ hoạt động tốt trong Windows Command Prompt nếu bạn cài đặt win32consolegem và require 'win32console'sau đó colorize.
Bến

2
@Ben cá nhân tôi đã không thử nó, nhưng vì Ruby 2.0 nên bạn không còn cần win32consoleđá quý nữa. github.com/luislavena/win32console/issues/ Kẻ
Dennis

1
Bất kỳ cách nào để làm cho điều này hoạt động với bảng điều khiển Sumblime Text?
nipponese

6
Viên ngọc này được cấp phép theo GPL vì vậy (tôi nghĩ) nó không thể được sử dụng trong phần mềm độc quyền. jonathannen.com/2013/07/07/license-your-gems.html
Andrei Botalov

249

Kết hợp các câu trả lời ở trên, bạn có thể thực hiện một cái gì đó hoạt động như đá quý tô màu mà không cần phụ thuộc khác.

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, chỉnh sửa tốt đẹp Nick. Vâng tất nhiên không cần phải vượt qua chính mình. Tôi đã mệt mỏi khi tôi viết bài này :)
Erik Skoglund

cái này cũng sẽ hoạt động trong windows chứ?
Alp

Nó hoạt động trong windows nếu bạn đang sử dụng ConEmu
Mike Glenn

1
Tôi thích điều này hơn là tô màu vì điều này chỉ thay đổi màu nền trước. colorize dường như luôn luôn thay đổi màu nền.
jlyonsmith

1
Tôi biết tôi đến bữa tiệc muộn, nhưng sẽ tốt hơn nếu sử dụng việc đóng cửa ở đây?

215

Như các phương thức lớp String (chỉ 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

và cách sử dụng:

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

trên bảng điều khiển của tôi:

nhập mô tả hình ảnh ở đây

bổ sung:

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

xóa định dạng ký tự

Ghi chú

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

In đậm nên sử dụng mã thoát 22 không phải 21:def bold; "\e[1m#{self}\e[22m" end
Kanat Bolazar

@KanatBolazar, Một số hệ thống hỗ trợ 21 . Nhưng tôi thay đổi nó thành 22 cho khả năng. Cảm ơn.
Ivan Black

1
Điều này thật tuyệt, tôi đã đặt nó trong một trình khởi tạo trong ứng dụng Rails của mình. Hoạt động như một lá bùa!

Lời khuyên tuyệt vời. Vì vậy, dễ dàng và không phụ thuộc. Rất rất tốt được thực hiện!
mraxus

1
Trong Windows 10 cmd.exe, puts "\e[0"không hoạt động để xóa định dạng; puts "\e[0m"phải được sử dụng
Nnnes

41

Tôi đã viết một phương pháp nhỏ để kiểm tra các chế độ màu cơ bản, dựa trên câu trả lời của Erik Skoglund và những người khác.

#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

đầu ra ví dụ: đá ruby


37

Bạn có thể sử dụng các chuỗi thoát ANSI để làm điều này trên bàn điều khiển. Tôi biết điều này hoạt động trên Linux và OSX, tôi không chắc liệu bảng điều khiển Windows (cmd) có hỗ trợ ANSI hay không.

Tôi đã làm nó trong Java, nhưng các ý tưởng là như nhau.

//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
Điều này hoạt động và có lợi thế là không yêu cầu đá quý, có thể gây khó chịu cho một số người.
ThomasW

3
Bảng điều khiển Windows thực sự hỗ trợ mã ANSI.
Bến

16

Trong khi các câu trả lời khác sẽ làm tốt công việc của hầu hết mọi người, thì cách "chính xác" của Unix làm điều này nên được đề cập. Vì tất cả các loại thiết bị đầu cuối văn bản không hỗ trợ các trình tự này, bạn có thể truy vấn cơ sở dữ liệu terminfo , một sự trừu tượng hóa về khả năng của các thiết bị đầu cuối văn bản khác nhau. Điều này có vẻ chủ yếu là di tích lịch sử - thiết bị đầu cuối phần mềm sử dụng ngày nay thường hỗ trợ các chuỗi ANSI - nhưng nó không có (ít nhất) một hiệu quả thiết thực: đó là đôi khi hữu ích để có thể thiết lập các biến môi trường TERMđể dumbtránh tất cả các phong cách như vậy, ví dụ khi lưu đầu ra vào một tệp văn bản. Ngoài ra, nó cảm thấy tốt để làm những điều đúng . :-)

Bạn có thể sử dụng đá quý ruby-terminfo . Nó cần một số biên dịch C để cài đặt; Tôi đã có thể cài đặt nó trong hệ thống Ubuntu 14.10 của mình với:

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

Sau đó, bạn có thể truy vấn cơ sở dữ liệu như thế này (xem trang man terminfo để biết danh sách các mã có sẵn):

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

Đây là một lớp bao bọc nhỏ mà tôi kết hợp để làm cho mọi thứ đơn giản hơn để sử dụng.

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

Sử dụng:

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

Đầu ra của tập lệnh Ruby ở trên

(chỉnh sửa) Cuối cùng, nếu bạn không cần đá quý, bạn có thể dựa vào tputchương trình, như được mô tả ở đây - Ví dụ về Ruby:

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

4
Chính, +1 chính để sử dụng tput. Thậm chí không thể nói rõ rụng tóc tputđã cứu tôi được bao nhiêu .
Xỏ

14

Tôi đã thực hiện phương pháp này có thể giúp đỡ. Nó không phải là một vấn đề lớn nhưng nó hoạt động:

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

Đây là cách sử dụng nó:

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

Những cải tiến có thể là:

  • colorsbgColorsđang được xác định mỗi khi phương thức được gọi và chúng không thay đổi.
  • Thêm tùy chọn khác như bold, underline, dimvv

Phương pháp này không làm việc cho p, như plàm một inspectlập luận của mình. Ví dụ:

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

sẽ hiển thị "\ e [0; 38mHello World \ e [0m"

Tôi đã thử nó với puts, printvà đá quý Logger, và nó hoạt động tốt.


Tôi đã cải thiện điều này và tạo ra một lớp như vậy colorsbgColorslà hằng số lớp và colorizelà một phương thức lớp:

EDIT: Kiểu mã tốt hơn, các hằng số được xác định thay vì các biến lớp, sử dụng các ký hiệu thay vì chuỗi, thêm nhiều tùy chọn như, in đậm, in nghiêng, v.v.

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

Bạn có thể sử dụng nó bằng cách làm:

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

Đây là những gì tôi đã làm để làm cho nó hoạt động mà không cần bất kỳ đá quý nào:

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

Sau đó, chỉ có văn bản trong dấu ngoặc kép được tô màu và bạn sẽ trở lại chương trình được lên lịch thường xuyên của mình.


3
Không làm việc cho tôi. Tôi nhận được, chính xác:e[32mSOMETEXT
Oscar Godson

có một lỗi đánh máy trong ký tự thoát đầu tiên: nên "\e(...)"thay vì"e\(...)"
arthropod

12

Tôi tìm thấy một vài:

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

Ví dụ:

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

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

Ví dụ:

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

http://github.com/sickill/rainbow

Thí dụ:

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

Nếu bạn đang ở trên Windows, bạn có thể cần phải thực hiện "cài đặt gem win32console" để hỗ trợ màu sắc.

Ngoài ra, bài viết Colorizing console Ruby-script rất hữu ích nếu bạn cần tạo gem của riêng mình. Nó giải thích làm thế nào để thêm màu ANSI vào chuỗi. Bạn có thể sử dụng kiến ​​thức này để bọc nó trong một số lớp mở rộng chuỗi hoặc một cái gì đó.



3

Tôi thấy các câu trả lời ở trên là hữu ích tuy nhiên không phù hợp với hóa đơn nếu tôi muốn tô màu thứ gì đó như đầu ra nhật ký mà không sử dụng bất kỳ thư viện bên thứ ba nào. Sau đây đã giải quyết vấn đề cho tôi:

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

Tôi hy vọng nó sẽ giúp!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.