私が歌川です

@utgwkk が書いている

現状の癖を反映した .perltidyrc

はじめに

これは Perl Advent Calendar 2020 - Qiita 19日目の記事です。枠が空いていたので飛び入りです。

昨日は nanto_vi さんで Perl の Test2::V0 でオブジェクトの基底クラスを確認する: Days on the Moon でした。 isaをテストしたくなることはけっこうある*1ので、かなりありがたい新機能ですね。

perltidyはPerlのコードフォーマッタです。 設定ファイルがコマンドライン引数を書き下したような形式になっていて、けっこうコツが要ります。

GNU Coding StandardsにもPerl Best Practicesにもそこまで納得感がないので自分で設定を作っていきます。納得感がなくても設定があって自動で適用できるなら従うままだと思うけど、既存コードの書き方からはできるだけ離れないように設定してみました。 Twitter-Textで試しながら調整しました。

.perltidyrc

--add-newlines
--add-semicolons
--add-whitespace
--break-at-old-comma-breakpoints
--character-encoding=utf8
--comma-arrow-breakpoints=1
--continuation-indentation=4
--cuddled-else
--indent-block-comments
--indent-columns=4
--logical-padding
--long-block-line-count=1
--maximum-line-length=0
--no-blanks-before-comments
--no-indent-closing-brace
--no-opening-sub-brace-on-new-line
--no-space-for-semicolon
--paren-tightness=2
--quiet
--trim-qw

設定項目

--add-newlines

perltidyが改行を入れてもよいことにする。

--add-semicolons

perltidyがセミコロンを入れてもよいことにする。

--add-whitespace

perltidyが空白を入れてもよいことにする。

--block-brace-tightness=0

1行のコードブロック {} の内側には必ずスペースを入れる。 map {$_->name} @users よりも map { $_->name } @users がよい。

--brace-tightness=1

コードブロックでない中括弧 {} のうち、最も外側にあるものの内側にスペースを入れる。

--break-at-old-comma-breakpoints

カンマ区切りのリストがフォーマットされないようにする。普通に書いてて破滅しないのでこうしてる。

--character-encoding=utf8

エンコーディングをutf8に指定する。それはそう。

--comma-arrow-breakpoints=1

1行のリストでない限り、ファットコンマの後ろで改行する。

--continuation-indentation=4

文を改行したあとのインデントはスペース4つ。

--cuddled-else

elseelsif の直前で改行しない。デフォルトは --no-cuddled-else だけど、この書き方が手に馴染んでるのでこうしてる。

# --cuddled-else
if ($a) {
    print('a');
} elsif ($b) {
    print('b');
} else {
    print('else');
}

# --no-cuddled-else
if ($a) {
    print('a');
}
elsif ($b) {
    print('b');
}
else {
    print('else');
}

--indent-block-comments

コメントと文のインデントを揃える。

    # --indent-block-comments
    if ($a) { print('a'); }

# --no-indent-block-comments
    if ($a) { print('a'); }

--indent-columns=4

インデントはスペース4つ。

--logical-padding

複数行の論理演算があるときインデントをいい感じに揃える。そこまで長い式を書いてないので効果があるかは不明。

--long-block-line-count=1

制御構造ごと? に改行を入れるようperltidyに指示する。

--maximum-line-length=0

1行あたりの文字数上限を取っ払う。現代で1行80文字は短すぎると思う。とはいえちょうどよい上限も見つかってない。ふつうに書いてて1行にいろいろ詰め込むことはないので困ってない。

--no-blanks-before-comments

1行コメントの直前で改行しないようにする。バスバス改行しなくてもよいでしょう。

--no-indent-closing-brace

閉じ括弧の前でインデントしないようにする。

--no-opening-sub-brace-on-new-line

サブルーチン名と括弧の間で改行しないようにする。

--no-space-for-semicolon

C言語形式の for ループのセミコロンの前にスペースを入れない。滅多にC言語形式の for ループを書かないのであまり気にしてないけど書くことがあったら気になる。

--paren-tightness=2

括弧 () の内側にスペースを入れない。

--quiet

エラーメッセージを出力しない。VSCodeからはKaktus.perltidy-moreを使っていて、エラーログを見ることがない。

--trim-qw

複数行の qw クォートの周りのスペースを取り除いていい感じにインデントする。

(2021/9/11 追記) うまくいってない点

調整したけどうまくいかなかった点もある。 誰かうまい設定方法を知ってたら教えてください! この記事を書いた時点ではうまくいっていなかったけど、この記事の.perltidyrcと最新のperltidyだとうまく閉じ括弧のインデントが下げられるようになった。perltidy v20210111で確認したので、ちょうどこの記事から1ヶ月の間に修正されたのだろう。

github.com

複数行の qw クォートの閉じ括弧がインデントされる

# こうなってほしい
my @a = (
    qw(
        foo
        bar
        baz
    ),
    qw(
        hoge
        fuga
        piyo
    ),
);

# こうなる
my @a = (
    qw(
        foo
        bar
        baz
        ),
    qw(
        hoge
        fuga
        piyo
        ),
);

おわりに

perlcriticが比較的柔軟に設定できることと比べると、なんかもうちょっと設定を書きやすくできるとよい気がしますね。

明日は teckl さんです。

*1:Test::DeepからTest2::V0に移行するときはとくに