概要
ここ最近はNim離れしていたので、リハビリ&思い出しながら、書いてみました。
2次元配列の(文字列)データを、テキスト表形式で出力します。
ソース
import strutils,sequtils
import unicode,nre,options
proc display_length( text: string) : int =
let rune_text = text.toRunes
let text_len = rune_text.len
for i in 0..<text_len:
let c = $rune_text[i]
# by http://orange-factory.com/sample/utf8/code3/ef.html#HalfwidthandFullwidthForms
if c.match(re"(*U)[ヲ-゚]").isSome:
result += 1
elif c.match(re"^[^\x01-\x7E\xA1-\xDF]").isSome :
result += 2
else:
result += 1
proc out_table( rows: openArray[seq[string]]) : string =
assert( rows.len >= 2 )
assert( rows[0].len > 0 )
# 各カラムの長さを計算
var col_len_max: seq[int] = repeat(0, rows[0].len)
for cols in rows:
for i in 0..<cols.len:
let col_len = cols[i].display_length
if col_len > col_len_max[i]:
col_len_max[i] = col_len
# カラムの幅を+1する
col_len_max.apply( proc (len: var int) = len += 1)
# 水平の線を作成
var horizon_line: seq[string] = @["+"]
for i in 0..<rows[0].len:
horizon_line.add(repeat("-",col_len_max[i]).join(""))
horizon_line.add("+")
let horizon = horizon_line.join("")
# 結果格納用
var newTable: seq[string] = @[ horizon ]
# 1行ずつ出力する
var row_num = 0
for cols in rows:
var newCols: seq[string] = @[""]
for i in 0..<cols.len:
let len_max = col_len_max[i]
let col_len = cols[i].display_length
newCols.add (cols[i] & repeat(" ", len_max - col_len).join(""))
newCols.add("")
newTable.add( newCols.join("|") )
# 1行目出力後に、横線を追加する
if row_num == 0:
newTable.add( horizon )
row_num += 1
newTable.add( horizon )
result = newTable.join("\n")
let text = """
abc,abcd
def,defff
ghi,ghiiiji
あいう,あいうえお
かきく,かきくけこ
さしす,サシスセソ"""
let lines = text.splitLines()
var table: seq[seq[string]] = @[]
for line in lines:
let row: seq[string] = line.split(",")
table.add( row )
echo out_table( table )