เอาต์พุต Ruby Colorized ไปยังเทอร์มินัล [ปิด]


273

ใช้ Ruby ฉันจะทำ colorization พื้นหลังและพื้นหน้าข้อความสำหรับการส่งออกใน terminal ได้อย่างไร

ฉันจำได้ว่าเมื่อการเขียนโปรแกรม Pascal เราทุกคนเคยเขียน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 Terminal หรือไม่? ฉันพยายามเรียกใช้โค้ดด้านบนใน Cygwin แต่มันออกมาโดยไม่มีสี ..
jj_

5
สิ่งนี้จะทำงานได้ดีใน Windows Command Prompt หากคุณติดตั้งwin32consolegem และrequire 'win32console'หลังจากcolorizeนั้น
Ben

2
@Ben ฉันไม่ได้ลองเป็นการส่วนตัว แต่ตั้งแต่ Ruby 2.0 คุณไม่ควรต้องการwin32consoleอัญมณีอีกต่อไป github.com/luislavena/win32console/issues/…
Dennis

1
มีวิธีใดบ้างที่จะใช้งานได้กับ Sumblime Text console
นิปปอน

6
อัญมณีนี้ได้รับอนุญาตภายใต้ GPL ดังนั้น (ฉันคิดว่า) ไม่สามารถใช้ในซอฟต์แวร์ที่เป็นกรรมสิทธิ์ได้ jonathannen.com/2013/07/07/license-your-gems.html
Andrei Botalov

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

อ่าแก้ไขได้ดีมาก Nick ใช่แน่นอนไม่จำเป็นต้องผ่านตัวเอง ฉันเหนื่อยเมื่อฉันเขียนสิ่งนี้ :)
Erik Skoglund

จะใช้งานได้ใน windows ด้วยหรือไม่
Alp

มันทำงานได้ในหน้าต่างถ้าคุณใช้ConEmu
Mike Glenn

1
ฉันชอบสิ่งนี้ดีกว่า colorize เพราะจะเปลี่ยนเฉพาะสีพื้นหน้าเท่านั้น colorize ดูเหมือนจะเปลี่ยนสีพื้นหลังเสมอ
jlyonsmith

1
ฉันรู้ว่าฉันมางานปาร์ตี้สาย แต่จะดีกว่าไหมถ้าใช้การปิดที่นี่?

215

ในฐานะที่เป็นวิธีการเรียน String (ยูนิกซ์เท่านั้น):

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
Kanat Bolazar

@KanatBolazar บางระบบสนับสนุน21 แต่ฉันเปลี่ยนเป็น 22 เพื่อความสามารถ ขอบคุณ
Ivan Black

1
นี่ยอดเยี่ยมมากฉันใส่ไว้ใน initializer ในแอปพลิเคชั่น Rails ของฉัน ทำงานเหมือนจับใจ!

เคล็ดลับที่ยอดเยี่ยม ง่ายและไม่ต้องพึ่งพา ทำได้ดีมากมาก!
mraxus

1
ใน Windows 10 cmd.exe, puts "\e[0"ไม่ทำงานให้เป็นรูปแบบที่ชัดเจน puts "\e[0m"ต้องใช้
พฤศจิกายน

41

ฉันเขียนวิธีการเล็กน้อยเพื่อทดสอบโหมดสีพื้นฐานโดยยึดตามคำตอบของ Erik Skoglund และผู้อื่น

#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 escape sequences เพื่อทำสิ่งนี้บนคอนโซล ฉันรู้ว่าใช้งานได้กับ 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

จากนั้นคุณสามารถสืบค้นฐานข้อมูลเช่นนี้ (ดูหน้าterminfoสำหรับรายการรหัสที่มีให้):

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

นี่คือคลาส wrapper เล็กน้อยที่ฉันรวบรวมเข้าด้วยกันเพื่อทำให้สิ่งต่าง ๆ ใช้ง่ายขึ้นเล็กน้อย

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ช่วยฉัน
Pierce

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; 38mHello World \ e [0m"

ฉันทดสอบด้วยputs, printและ, อัญมณี Logger, และมันใช้ได้ดี


ฉันดีขึ้นนี้และทำระดับเพื่อให้colorsและbgColorsมีค่าคงที่การเรียนและcolorizeเป็นวิธีการเรียน:

แก้ไข: สไตล์โค้ดที่ดีขึ้นค่าคงที่ที่กำหนดไว้แทนตัวแปรคลาสโดยใช้สัญลักษณ์แทนสตริงเพิ่มตัวเลือกเพิ่มเติมเช่นตัวหนาตัวเอียงและอื่น ๆ

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
ออสการ์ Godson

มีการพิมพ์ผิดในตัวหนีแรก: ควรจะ"\e(...)"แทน"e\(...)"
arthropod

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" เพื่อเปิดใช้งานการรองรับสี

นอกจากนี้บทความColorizing console เอาต์พุต Ruby-scriptมีประโยชน์ถ้าคุณต้องการสร้างอัญมณีของคุณเอง มันอธิบายถึงวิธีการเพิ่มการระบายสี 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" }

ฉันหวังว่ามันจะช่วย!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.