使用Ruby,我如何在终端中为输出执行背景和前景文本着色?
我记得,在编程Pascal时,我们都习惯编写自己的textcolor(…)程序,以使我们的小教育程序看起来更漂亮、更有表现力。
我该如何在Ruby中编写类似的代码呢?核心库中是否有任何内置的支持来实现这一点?如果不是,什么是添加它的惯用方式?
使用Ruby,我如何在终端中为输出执行背景和前景文本着色?
我记得,在编程Pascal时,我们都习惯编写自己的textcolor(…)程序,以使我们的小教育程序看起来更漂亮、更有表现力。
我该如何在Ruby中编写类似的代码呢?核心库中是否有任何内置的支持来实现这一点?如果不是,什么是添加它的惯用方式?
当前回答
我发现前面的答案很有用。但是,如果我想在不使用任何第三方库的情况下对日志输出等内容进行着色,那么它们就不适合。下面的方法帮我解决了这个问题:
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" }
其他回答
以下是我不需要任何宝石就能让它工作的方法:
def red(mytext) ; "\e[31m#{mytext}\e[0m" ; end
puts red("hello world")
然后,只有引号中的文本是有颜色的,您将返回到定期安排的节目。
结合上面的答案,您可以实现一些类似于gem colorize的东西,而不需要另一个依赖项。
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
While the other answers will do the job fine for most people, the "correct" Unix way of doing this should be mentioned. Since all types of text terminals do not support these sequences, you can query the terminfo database, an abstraction over the capabilites of various text terminals. This might seem mostly of historical interest – software terminals in use today generally support the ANSI sequences – but it does have (at least) one practical effect: it is sometimes useful to be able to set the environment variable TERM to dumb to avoid all such styling, for example when saving the output to a text file. Also, it feels good to do things right. :-)
你可以使用红宝石终端宝石。它需要一些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."
这里有一个小的包装器类,我把它放在一起使事情更容易使用。
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}"
(编辑)最后,如果你不想要一个gem,你可以依赖tput程序,如下所述- Ruby示例:
puts "Hi! " + `tput setaf 1` + "This is red!" + `tput sgr0`
我发现了一些:
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”来启用对颜色的支持。
另外,如果您需要创建自己的gem,为控制台Ruby-script输出着色这篇文章也很有用。它解释了如何向字符串添加ANSI着色。你可以用这个知识把它包装在一些类中,这些类扩展了字符串或其他东西。
根据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
示例输出: