Programmer's Note

コード読み書きの備忘録。

エスケープシーケンスでカーソル移動を使ってみる(Ruby)

ちょい前にエスケープシーケンスで文字装飾を試した。(エスケープシーケンスの文字装飾を試す - Programmer's Dialy

さて、今回はカーソル移動を試してみたい。 (ちょっと文字列処理が入るのでRubyで)

Kernighan先生の「Software Tools」の中で、フィルタープログラムの章があって そこでは、スペースをタブに変えていたりしていたが、 ここでは空白で区切られたレコード(文字列)をきれいに並べて、ターミナルに出力させてみたい。

例えば、

TYPE NAME AGE MONEY
Human Hurry.Potter 12 1200
Dwarf Dongland 200 20

を受けて、以下のように出力する。

TYPE  NAME         AGE MONEY
Human Hurry.Potter 12  1200
Dwarf Dongland     200 20

実行方法

$ cat data.txt | ./align.rb

という感じ。

さて、ソースコード(align.rb):

#!/usr/bin/ruby

def puts_rcd(dat, maxlen)
    pad = 1
    for i in 0...dat.length
        print "\e[#{pad}G"
        print dat[i]
        pad += maxlen[i]+1
    end
    puts ""
end

$maxlen = []
$lines = []
while line = STDIN.gets
    rcds =  line.split(' ')
    for i in 0...rcds.length do
        len = rcds[i].length
        $maxlen[i] = len if $maxlen[i]==nil || len > $maxlen[i]
    end
    $lines << rcds
end

$lines.each do |rcd|
    puts_rcd(rcd,$maxlen)
end

エスケープシーケンスのところは、

print "\e[#{pad}G"

のところだけ。カーソルの水平位置を指定しているだけ。 エスケープシーケンス結構ラクだし楽しいね。

しかしまあ、普通に整形して出すなら、たぶんスペースを埋めた方が無難だし汎用的だ。

たとえば、出力をlessに食わせると

$ cat data.txt | ./align.rb | less 

以下になってしまう。

ESC[1GTYPEESC[7GNAMEESC[20GAGEESC[24GMONEY
ESC[1GHumanESC[7GHurry.PotterESC[20G12ESC[24G1200
ESC[1GDwarfESC[7GDonglandESC[20G200ESC[24G20

出力に制御コード入れてるからねえ。(当然だ)