RubyでANSIカラーシーケンスを学ぼう!
ブログを下記に移転しました。デザイン変更により移転先では記事が一層読みやすくなっていますので、よろしければ移動をお願い致します。
RubyでANSIカラーシーケンスを学ぼう! : melborne.github.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
CUIの世界は地味な世界です
真っ黒なターミナル画面に単一色の文字列
それが却って落ち着くという向きもありますが
今となってはその地味さは際立っています
ターミナルで色を使う方法を学ぶことで
新しい世界が開けるかも知れません
ようこそANSIカラーの世界へ
エスケープシーケンス
ターミナルで色を使うためには
エスケープシーケンスというものを利用します
エスケープシーケンスはターミナル上で色を含む特定の制御を
実現するための特殊な文字列です
print "\e[31mhello\e[0m"
これによりターミナル上に青文字で「hello」と出力されます
この"\e[31m" "\e[0m"の部分がエスケープシーケンスです
"\e[31m"はそれ以降を青文字で出力する制御命令
"\e[0m"はそれ以降を初期状態へリセットする制御命令です
シーケンス中の数字において
30~37は文字色 40~47は背景色
0~9は文字装飾に割り振られています
Text attributes 0 All attributes off 1 Bold on 4 Underscore (on monochrome display adapter only) 5 Blink on 7 Reverse video on 8 Concealed on Foreground colors 30 Black 31 Red 32 Green 33 Yellow 34 Blue 35 Magenta 36 Cyan 37 White Background colors 40 Black 41 Red 42 Green 43 Yellow 44 Blue 45 Magenta 46 Cyan 47 White
ASCII Table - ANSI Escape sequences
1つの文字列に複数のシーケンスを適用することもできます
print "\e[31m\e[43m\e[5mhello\e[0m"
これで黄色の背景色上で赤いhelloが点滅します
セミコロンで区切って
複数のシーケンスコードを適用することもできます
これは上のシーケンスと等価です
print "\e[31;43;5mhello\e[0m"
エスケープシーケンスは端末依存で
端末によって使えないものもあります
ターミナルカラー・ライブラリ
Rubyでカラーシーケンスを使う場合
そのままでは扱いづらいので
定数などへのマッピングが必要になるでしょう
また文字列終端での復帰にも対応しなければいけません
自作する手もありますが
Rubyには既に便利なライブラリがいくつかあります
HighLine
HighLineはターミナルの入出力を支援するツール群です
その中にカラーシーケンスを扱うHighLine#colorがあります
gem install highlineでインストールして
以下のように使います
require 'highline' h = HighLine.new puts h.color("hello", :green)
色属性として複数の引数を取ることもできます
puts h.color("Ruby World", :red, :on_cyan, :underline)
TermColor
TermColorは文字列中のカラータグを
エスケープシーケンスに変換するライブラリです
gem install termcolorでインストールして
以下のように使います
require 'termcolor' puts TermColor.parse("<green>hello</green>") puts TermColor.parse("<red><on_white><blink>ruby is fun!</blink></on_white></red>")
色指定は1つしかできませんが以下のように使うこともできます
puts TermColor.colorize("hello", :green)
またString#termcolorが用意されているので
以下のようにもできます
puts "<red><bold>Ruby is red!</bold></red>".termcolor
TermColorはTermtterのjugyoさん作で
Termtterでのカラー表示に使われています
Rainbow
RainbowはStringクラスに
color(foreground), background,bright, blink, inverseなどの
エスケープシーケンスに対応したメソッドを追加します
gem install rainbowでインストールして
以下のように使います
require 'rainbow' puts "hello".color(:red) puts "hello".color(255, 0, 0) puts "hello".color(:red).background(:green) puts "hello".bright.background(:blue).blink
Term-ANSIColor
Term-ANSIColorは多様な使い方ができるライブラリで
エスケープシーケンスをモジュール関数化したり
Stringクラスのインスタンスメソッドにしたりできます
gem install term-ansicolorでインストールして
以下のように使います
まずはクラスメソッドとして
require 'term/ansicolor' class Color extend Term::ANSIColor end print Color.red, Color.bold, "No Namespace cluttering:", Color.clear, "\n" print Color.green + "green" + Color.clear, "\n" print Color.on_red(Color.green("green")), "\n" print Color.yellow { Color.on_black { "yellow on_black" } }, "\n\n"
次にTerm::ANSIColorのインスタンスメソッドとして
c = Term::ANSIColor print c.red, c.bold, "No Namespace cluttering (alternative):", c.clear, "\n" print c.green + "green" + c.clear, "\n" print c.on_red(c.green("green")), "\n" print c.yellow { c.on_black { "yellow on_black" } }, "\n\n"
関数的に
include Term::ANSIColor print red, bold, "Usage as constants:", reset, "\n" print red("red"), on_red("on_red"), "\n" print red { bold { "Usage as block forms:" } }, "\n"
Stringのメソッドとして
class String include Term::ANSIColor end print "Usage as String Mixins:".red.bold, "\n" print "Hello, World\n".blue.on_yellow.blink
Wirble
Wirbleはirb(Interactive Ruby)の支援ツールで
Rubyのシンタックスに合わせたカラーリングすなわち
Syntax Highlightingを実現します
ライブラリとして使う場合は以下のようにします
require "wirble" w = Wirble::Colorize puts w.colorize_string("Hello, Ruby", :light_cyan) puts w.colorize("hello, :hello, [1, 2, 3], {:a => 1, :b => 2}")
colorizeメソッドでRubyのオブジェクトに応じた
カラーリングが実現できているのが分かります
なおirbで使う場合は.irbrcで以下のように指定します
require 'wirble' Wirble.init Wirble.colorize
Coderay
CodeRayは複数の言語に対応したSyntax Highlightingライブラリです
Rubyのコードをターミナルでカラーリングする場合は
以下のようにします
require "coderay" puts CodeRay.scan("5.times do\n puts 'hello, ruby'\nend", :ruby).term
ファイルから読込んでHTML出力するようなこともできます
puts CodeRay.scan_file("code.rb").div(:line_numbers => :table)
素晴らしいですね!
Paint
Paintはライブラリでの使い勝手と拡張性を売りにした
非常にユニークな使い方ができるライブラリです
gem install paintでインストールして
以下のように使います
まずはPaint.[]クラスメソッドを使う例です
require 'paint' Paint['Ruby', :red] #=> "\e[31mRuby\e[0m" Paint['Ruby', :red, :bright, :underline] #=> "\e[31;1;4mRuby\e[0m" Paint['Ruby', :red, :blue] #=> "\e[31;44mRuby\e[0m"
第3引数以降に現れるカラーは背景色用です
色の指定は多様な方法でできます
Paint['Ruby', [100, 255, 5]] #=> "\e[38;5;118mRuby\e[0m" Paint['Ruby', "gold", "snow"] #=> "\e[38;5;226;48;5;231mRuby\e[0m" Paint['Ruby', "#123456"] #=> "\e[38;5;24mRuby\e[0m" Paint['Ruby', "fff"] #=> "\e[38;5;231mRuby\e[0m"
第2引数以下を省略すると色指定がランダムになり
:inverseをしていすると前景色と背景色を入れ替えます
Paint['Ruby'] #=> "\e[37mRuby\e[0m" Paint['Ruby', :inverse] #=> "\e[7mRuby\e[0m"
PaintがユニークなのはPaint::SHORTCUTSを使った
ユーザカラー定義です
Paint::SHORTCUTS[:mycolor] = { :white => Paint.color(:black), :red => Paint.color(:red, :bright), :title => Paint.color(:underline) } #=> {:white=>"\e[30m", :red=>"\e[31;1m", :title=>"\e[4m"}
上のように登録することで
Paint::Mycolorの名前空間で
white red titleの各クラスメソッドが有効になります
Paint::Mycolor.red "Ruby" #=> "\e[31;1mRuby\e[0m" Paint::Mycolor.white #=> "\e[30m" Paint::Mycolor.title "Ruby" #=> "\e[4mRuby\e[0m" include Paint::Mycolor #=> Object red "Ruby" #=> "\e[31;1mRuby\e[0m" white "Ruby" #=> "\e[30mRuby\e[0m"
それだけでなく
Paint::Mycolor::Stringモジュールをincludeすることにより
あらゆるオブジェクトをユーザ定義に従い
色つき文字列化することもできます
include Paint::Mycolor::String #=> Object "Ruby".red #=> "\e[1;31mRuby\e[0m" "Ruby".title #=> "\e[4mRuby\e[0m" 5.red #=> "\e[31;1m5\e[0m" [1, 2].red #=> "\e[31;1m[1, 2]\e[0m"
ちょっとやり過ぎな気もしますが..
グローバルな名前空間が汚染されることを避けたいなら
プレフィクスとして任意のメソッド名を指定することもできます
include Paint::Mycolor::Prefix::C #=> Object "Ruby".c(:red) #=> "\e[31;1mRuby\e[0m" "Ruby".c(:title) #=> "\e[4mRuby\e[0m" [1, 2].c(:red) #=> "\e[31;1m[1, 2]\e[0m"
なんかスゴイですね!
ご想像のとおりPaintモジュールの内部は
メタプログラミングばりばりです:)
IRC(Interactive Colors)
最後に上のライブラリを使って
ターミナル上でインタラクティブにカラーチェックができる
irc.rbという簡単なツールを作りました
Term-ANSIColorライブラリを使っています
ruby irc.rbで立上げると
welcomeメッセージに続きirbのようにpromptモードになります
red on_greenなどの色属性をタイプすると
その属性に制御された文字列が表示されます
文字列をリセットしたい場合は
'='に続いて文字列をタイプします
入力できる属性はhelp(h, colors, attrs)で確認できます
終了はexit(q, quit, bye)です
使ってくれる人がいたらうれしいです
(追記:2010-11-8) rainbow commandを追加しました。GNU Readlineに対応しました。
(追記:2010-11-12) WirbleとCodeRayライブラリの記載を追加しました。
(追記:2011-7-20) Paintライブラリの記載を追加しました。