Text::XslateでCソースを吐くときにケツカンマを防止する方法
この記事はPerl Advent Calendar 2016の17日目の記事です。
YAPC::Hokkaido 2016 SAPPOROの前夜祭で言い忘れたのですが、
楽器アプリを作る工程の半分以上はPerlを書いていて、
基本的にパラメータテーブルはText::Xslate
で出力しています。
ただ、個人的にケツカンマは好きじゃないので、
レンダリング前に処理する必要があって、これ面倒だなーって思ってたので、
metacpanのText::Xslateでドキュメントを漁ってたら、あっさり解決しました。
use v5.16; use strict; use warnings; use Text::Xslate; # 出力したいパラメータ my @params = map { $_ - 8; } 0..15; my $template = join( '', <DATA> ); my $tx = Text::Xslate->new(); print $tx->render_string( $template, { src1 => format_as_int(\@params, 8), src2 => format_as_hex(\@params, 4), } ); sub format_as_int { my ( $params, $n ) = @_; my @tmp = @{$params}; my @ret = (); while ( @tmp ) { my @items = map { sprintf( '%3d', $_ ); } splice(@tmp, 0, $n); push @ret, \@items; } return \@ret; } sub format_as_hex { my ( $params, $n ) = @_; my @tmp = @{$params}; my @ret = (); while ( @tmp ) { my @items = map { # 負の数を許容するややこしい書き方 my $str = sprintf( '%04X', $_ ); $str = substr($str, -4) if 4 < length($str); "0x${str}"; } splice(@tmp, 0, $n); push @ret, \@items; } return \@ret; } __DATA__ static const int16_t foo[] = { : for $src1 -> $item { <: $item.join(', ') :><: if not $~item.is_last { ',' } :> : } }; static const int16_t bar[] = { : for $src2 -> $item { <: $item.join(', ') :><: if not $~item.is_last { ',' } :> : } };
$ perl aaa.pl static const int16_t foo[] = { -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 }; static const int16_t bar[] = { 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007 };
ポイントは、 <: if not $~item.is_last { ',' } :>
ですね。
最後の要素じゃないときのみ、カンマを付加するようにしています。
それと、カンマ区切りで出力するのに使ってる、
<: $item.join(', ') :>
も、すっごい便利。
おしまい。
Leave a Comment