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