如何使用 Ruby 将文本输出着色到终端? [关闭]
Posted
技术标签:
【中文标题】如何使用 Ruby 将文本输出着色到终端? [关闭]【英文标题】:How can I use Ruby to colorize the text output to a terminal? [closed] 【发布时间】:2010-12-02 03:07:21 【问题描述】:使用 Ruby,如何在终端中为输出执行背景和前景文本着色?
我记得,在编写 Pascal 时,我们都曾经编写自己的 textcolor(…)
程序,以使我们的小型教育程序看起来更漂亮和更具表现力。
我将如何在 Ruby 中编写等价的代码?核心库中是否有任何内置支持可以做到这一点?如果没有,添加它的惯用方式是什么?
【问题讨论】:
那么例如不可能得到“橙色”颜色? 结帐github.com/kigster/colored2 【参考方案1】:着色是我最喜欢的宝石! :-)
检查一下:
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
【讨论】:
有人能告诉我 Colorize 在 Cygwin Terminal 中是否有效吗?我尝试在 Cygwin 中运行上面的代码,但它没有颜色.. 如果您在colorize
之后安装win32console
gem 和require 'win32console'
,这将在Windows 命令提示符中正常工作。
@Ben 我没有亲自尝试过,但是从 Ruby 2.0 开始,您应该不再需要 win32console
gem。 github.com/luislavena/win32console/issues/…
有什么方法可以使用 Sumblime Text 控制台进行这项工作?
这个 gem 是在 GPL 下授权的,所以(我认为)它不能在专有软件中使用。 jonathannen.com/2013/07/07/license-your-gems.html【参考方案2】:
结合上面的答案,您可以实现类似于 gem colorize 的功能,而无需其他依赖项。
class String
# colorization
def colorize(color_code)
"\e[#color_codem#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
【讨论】:
啊,很好的编辑尼克。是的,当然没有必要传递 self 。写这个的时候我累了:) 这也适用于 Windows 吗? 如果你使用ConEmu,它可以在windows中工作 我比着色更喜欢这个,因为它只会改变前景色。 colorize 似乎总是改变背景颜色。 我知道我迟到了,但在这里使用闭包不是更好吗?【参考方案3】:作为 String 类方法(仅限 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
及用法:
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
@KanatBolazar,一些系统支持21。但我将其更改为 22 以获取能力。谢谢。
这很好,我把它放在我的 Rails 应用程序的初始化程序中。像魅力一样工作!
绝妙的技巧。如此简单,没有依赖关系。做得很好!
在 Windows 10 中 cmd.exe
, puts "\e[0"
无法清除格式;必须使用puts "\e[0m"
【参考方案4】:
根据 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
示例输出:
【讨论】:
【参考方案5】:您可以在控制台中使用 ANSI 转义序列来执行此操作。我知道这适用于 Linux 和 Mac OS X,但我不确定 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 characters
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";
【讨论】:
这很有效,并且具有不需要宝石的优点,这可能会惹恼一些人。 Windows 控制台确实支持 ANSI 代码。【参考方案6】:虽然其他答案对大多数人来说都很好,但应该提到“正确”的 Unix 方法。由于所有类型的文本终端都不支持这些序列,您可以查询 terminfo 数据库,这是对各种文本终端功能的抽象。这似乎主要是历史上的兴趣——今天使用的软件终端通常支持 ANSI 序列——但它确实(至少)有一个实际效果:能够将环境变量 TERM
设置为 dumb
有时很有用避免所有此类样式,例如将输出保存到文本文件时。此外,做事正确感觉很好。 :-)
您可以使用ruby-terminfo gem。它需要一些C编译才能安装;我能够在我的 Ubuntu 14.10 系统下安装它:
$ sudo apt-get install libncurses5-dev
$ gem install ruby-terminfo --user-install
然后您可以像这样查询数据库(请参阅terminfo man page 以获取可用代码列表):
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 = %wblack 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.redWarning:#C this is #c.boldway#C #c.bg_redtoo much #c.cyan + c.understyling#C!"
puts "#c.dim(Don't you think?)#C"
(编辑)最后,如果您不想使用 gem,可以依赖 tput
程序,as described here – Ruby 示例:
puts "Hi! " + `tput setaf 1` + "This is red!" + `tput sgr0`
【讨论】:
专业,专业 +1 供tput
使用。甚至无法表达tput
拯救了我多少脱发。【参考方案7】:
我做了这个可以帮助的方法。这没什么大不了的,但它确实有效:
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_codem#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 gem 对其进行了测试,它运行良好。
我对此进行了改进并创建了一个类,所以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_codem#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
【讨论】:
【参考方案8】:这是我在不需要任何宝石的情况下使其工作的方法:
def red(mytext) ; "\e[31m#mytext\e[0m" ; end
puts red("hello world")
然后只有引号中的文本是彩色的,然后您将返回到您的定期计划。
【讨论】:
对我不起作用。我明白了:e[32mSOMETEXT
第一个转义字符有错字:应该是"\e(...)"
而不是"e\(...)"
【参考方案9】:
我找到了一些:
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,文章 Colorizing console Ruby-script output 也很有用。它解释了如何为字符串添加 ANSI 着色。您可以使用这些知识将其包装在一些扩展字符串或其他东西的类中。
【讨论】:
【参考方案10】:这可能会对您有所帮助:Colorized ruby output
【讨论】:
并改进此链接上的示例,您可以扩展 String 类以使其更易于使用(“Hello”.red):class String; def red; colorize(self, "\033[31m"); end; end
【参考方案11】:
我发现以前的答案很有用。但是,如果我想在不使用任何第三方库的情况下 对日志输出等内容进行着色,则它们不符合要求。以下为我解决了这个问题:
red = 31
green = 32
blue = 34
def color (color=blue)
printf "\033[#colorm";
yield
printf "\033[0m"
end
color puts "this is blue"
color(red) logger.info "and this is red"
【讨论】:
以上是关于如何使用 Ruby 将文本输出着色到终端? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何将所有终端输出记录/协议到python中的文本文件中[重复]