List::TableMark 0.01 を coderepos に入れました
前から少しずつ考えていた、リストをテーブル風に扱うモジュールのプロトタイプをcodereposに入れました。
http://coderepos.org/share/changeset/13035
なんでこんなものを作ったかといいますと、テーブル的なレイアウトを扱う局面ってすごくあって、HTMLのtableタグとかもそうですが、ul, li の構造でliの要素数が固定の場合とか、カレンダーの表示とか、「特定の要素数で折り返して且つ行の最後まで行く」という仕組みが欲しいなと思っていました。
# あと Class::InsideOut を使ってみたかった
SYNOPSIS 丸コピーですが、使い方的には以下のような感じです。
my $list = List::TableMark−>new(col => 7); $list−>push(undef(), undef()); $list−>push(1..31); $list−>finish(); my $bar = "−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−\n"; my $output = ""; foreach my $num (@$list) { $output .= $bar if $num−>is_table_start; $output .= sprintf("week %d | ", $num−>row) if $num−>is_row_start; $output .= $num−>is_empty ? ’−−|’ : sprintf("%2d|", ($num−>value || 0)) ; $output .= "\n" if $num−>is_row_end; $output .= $bar if $num−>is_table_end; } print $output; # output # −−−−−−−−−−−−−−−−−−−−−−−−−−−−−− # week 1 | −−|−−| 1| 2| 3| 4| 5| # week 2 | 6| 7| 8| 9|10|11|12| # week 3 | 13|14|15|16|17|18|19| # week 4 | 20|21|22|23|24|25|26| # week 5 | 27|28|29|30|31|−−|−−| # −−−−−−−−−−−−−−−−−−−−−−−−−−−−−− # you can also push reference to the list my $fruit = List::TableMark−>new(col => 3); $fruit−>push( { name => ’banana’ color => ’yellow’ }, { name => ’apple’ color => ’red’ }, { name => ’lemmon’ color => ’yellow’ }, { name => ’grape’ color => ’purple’ }, ); $fruit−>finish(); # push undef value to rest of the table foreach my $data (@$list) { my $ref = $data−>value; # get pushed refernce if (!$ref−>is_empty) { print $ref−>{name} . ’ ’; } else { print "−−− "; } print "\n" if $ref−>is_line_end; } # output: # banana apple lemmon # grape −−− −−−
横幅を指定してlistを作成してそこにデータをpushしていくと、特定の区切りでマークが付く、って感じです。配列のリファレンスを bless しているので、@$list で中身(List::TableMark−::Element の配列)が取れます。
データを取り出した後に、$data->value とかやらなくてもスカラーコンテキストで評価された時点で元の値として評価される、っていうのがかっこいいかなと思ったのですが、元のオブジェクトを取り出しづらくなりそうだし、豪快なoverloadは僕の手に負えない可能性大なので見送りました。
$list->push されたデータは List::TableMark−::Element にマークとともに入れられて保存されます。取り出したあとは is_* 系のメソッドでフラグの確認ができるのですが、hashで一気にとれるようにもなっています(markhash())。これはテンプレートエンジンに渡す際に簡単に書けるようにそうしてみました。
my (@loop); foreach my $data (@$list) { my %temp = $data->markhash(); $temp{value} = $data->value; push @loop, \%temp; } $template->param(loop => \@loop);
結構探して確認したのですが、似たようなモジュールが既にあったら誰かツッコミお願いします!
今日一日他の方のコードを結構見ていたのですが、すごい勉強になりますね。特にテストの書き方とか僕はすごく未熟だなと、Test::More 全然使いこなせてないなと、いやむしろテスト書いてないなと反省しました>< perlcritic が入っていればそのチェックもするっていうのは素敵ですね、真似しよう。