この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
コンソールアプリで表を出力しよう
■ この記事について
メンテナンスや日々の確認のために
ちょっとしたスクリプトを書くことがあります。
データなどを確認したい場面では
タブ区切りでのテキストを出力していましたが
データ量が大きくなると視認性が悪くなります。
そこでコンソール上でも表を出力したい!
となります。
※記事内でソースコードを変更する箇所がありますが、利用する場合は自己責任でお願いします。
■ formatador
rubygemsでインストールができる
を使うこととします。
簡単な使い方は以下の通りです。
#-*- coding: utf-8 -*-
require "rubygems"
require "formatador"
data = [
{:name => "taro", :age => 30},
{:name => "hanako", :age => 25}
]
Formatador.display_compact_table(data, [:name, :age])
#第2引数で列順を指定
+--------+-----+
| name | age |
+--------+-----+
| taro | 30 |
| hanako | 25 |
+--------+-----+
実行すると上記のように表が出力されます。
■ 日本語表示でずれる
スクリプト上のdataを以下のように変更して出力してみます。
data = [
{:name => "太郎", :age => 30},
{:name => "花子", :age => 25}
]
+------+-----+
| name | age |
+------+-----+
| 太郎 | 30 |
| 花子 | 25 |
+------+-----+
ずれました。
マルチバイト文字に対応させてみます。
formatador-0.2.4/lib/formatador/table.rb
を以下のように修正しました。
--- table.rb.org
+++ table.rb
@@ -1,3 +1,9 @@
+class String
+ def width
+ chars.inject(0){|s,c| s += c.bytesize > 1 ? 2 : 1}
+ end
+end
+
class Formatador
def display_table(hashes, keys = nil, &block)
new_hashes = hashes.inject([]) do |accum,item|
@@ -14,7 +20,7 @@
# Calculate Widths
if hashes.empty? && keys
keys.each do |key|
- widths[key] = key.to_s.length
+ widths[key] = key.to_s.width
end
else
hashes.each do |hash|
@@ -52,7 +58,7 @@
# Display data row
columns = []
headers.each do |header|
- columns << "[bold]#{header}[/]#{' ' * (widths[header] - header.to_s.length)}"
+ columns << "[bold]#{header}[/]#{' ' * (widths[header] - header.to_s.width)}"
end
display_line("| #{columns.join(' | ')} |")
display_line(split)
@@ -80,7 +86,7 @@
private
def length(value)
- value.to_s.gsub(PARSE_REGEX, '').length
+ value.to_s.gsub(PARSE_REGEX, '').width
end
def calculate_datum(header, hash)
再度出力してみます。
+------+-----+
| name | age |
+------+-----+
| 太郎 | 30 |
| 花子 | 25 |
+------+-----+
ずれなくなりました!
環境
ruby 1.9.3p484
formatador 0.2.4