🖋️

JuliaFormatter.jl でコードを整えるお話

2022/02/05に公開
3

本日は

JuliaFormatter.jl の紹介です.
自分のプロジェクト単位だったり特定のファイルを整形することができます.

一般にソースコードは書く時間よりも読む/読まれる時間の方が多いです.他人(=Nヶ月後の未来の自分自身も含む)が読む際に書いてある事柄を正確に把握してもらうことは非常に重要です. 記述に一貫性がある・なしでは雲泥の差があります. ある種の一貫性を単一のファイルだけでなく,プロジェクト単位で保つのは手動では大変です.そこでツールを使って自動化してもらいましょう. JuliaFormatter.jl はその一つです.

使い方

まずは下記のようにしてパッケージをインストールします. Julia の REPL を開いて -e の後ろの文字列を実行するでもOKです.

$ julia -e 'using Pkg; Pkg.add("JuliaFormatter")'

次に整形するファイルがある場所まで移動します.例えば Git などで管理しているパッケージの直下などです.そのあとは下記のようにするとパッケージ src, test ディレクトリ以下の .jl ファイルたちが整形されます.

$ julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.7.1 (2021-12-22)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> using JuliaFormatter
julia> format(".") # 現在作業しているディレクトリを指定している.
  • 特定のファイルを指定する場合は format_file("yourfile.jl")
  • ソースコードを文字列としてとってきたときには format_text("<ソースコード>")
    のような関数があります.

整形ルールの調整

好みの問題ではありますが, 私は Python での開発は black フォーマッタを採用しています. Julia でもそれに近いものが欲しいと思っていました.設定ファイル .JuliaFormatter.toml (ファイル名が . 始まりに注意)をプロジェクトの直下においておくと設定ファイルのルールに従って整形することができます. 例えば下記のようにします.

remove_extra_newlines=true
join_lines_based_on_source=true
whitespace_in_kwargs=false
short_to_long_function_def=true
always_for_in=true
verbose=true
margin=92

2022/02/05 の時点では Julia 1.6 で上記の設定はうまくいきませんでしたが 2023/12/15 の時点では動作しました. 🎉

julia> uisng PkgVersion
julia> PkgVersion.Version(JuliaFormatter)
v"1.0.43"

雛形を使う

上の設定はオレオレ設定感がありますよね.以前は margin = 88 をしてましたが, 狭すぎると感じる方もいらっしゃったようなので SciML のスタイルガイドに従って margin = 92 にしています.実際,SciML では下記のように取り決めしているようです.

Use 4 spaces per indentation level, no tabs.
Try to adhere to a 92 character line length limit.

See https://github.com/SciML/SciMLStyle?tab=readme-ov-file#specific-rules

文字 SciML のスタイルガイドに準拠したい場合は .JuliaFormatter.toml に下記の内容を書けばOKです:

.JuliaFormatter.toml
style = "sciml"

もちろん上記に微小な変更を加えることもできます. style = "sciml" を指定することで得られる効果は

SciML Style
でも確認できます.

他にも下記のようなスタイルもサポートしています.

ちょっと試しに Blue Style を試してみたいなーって場合は format 関数にスタイルオブジェクトを渡し実行することができます.

julia> using JuliaFormatter; format(".", BlueStyle())

特定のファイル,ディレクトリを無視したい場合

下記のドキュメントそのままですが ignore に指定することができます.

https://domluna.github.io/JuliaFormatter.jl/dev/config/#ignore

.JuliaFormatter.toml
ignore = ["file.jl", "directory", "file_*.jl"]

またコメントに #! format: off などを加えておくことで特定のコードブロックに対する整形作業を無視することができます.

https://domluna.github.io/JuliaFormatter.jl/dev/skipping_formatting/

応用

Pull Request のお供にも(2022-05-22 の時点)

GitHub Actions と連携し PR がきた際にファイルたちがちゃんと整形されているかを確認することもできます.

https://github.com/AtelierArith/Replay.jl/blob/main/.github/workflows/FormatCheck.yml

また,Flux3D.jl の場合はPRは広く受け入れて masterブランチの取り込み後に機械的に整形してくれるPRを発行する仕組みを採用しています.

https://github.com/FluxML/Flux3D.jl/blob/master/.github/workflows/format_pr.yml

Pull Request のお供にも(2023-12-15 の時点)

割とタイムリーな話なのですが,GitHub Actions でフォーマットをチェックするアクションが整備されたようです.

何を整えたのか?
全部!

とのこと.

これらついての解説は今月の Julia Tokai での

https://juliatokai.connpass.com/event/304201/

Hyrodium さんの発表で julia-formatを
整えた話と質問

知ることができます.

一般人は下記のように使えばOK(ありがたや):

# 参考: https://hackmd.io/@hyrodium/Hk1zPiMIp#/3
name: Format suggestions
on:
  pull_request:
jobs:
  code-style:
    runs-on: ubuntu-latest
    steps:
      - uses: julia-actions/julia-format@v2

GitHub Actions はこちら https://github.com/julia-actions/julia-format

PkgTemplates.jl

PkgTemplates.jl (v"0.7.46") ではパッケージのテンプレートを作るときに .JuliaFormatter.toml を生成してくれる機能がサポートされていました.

help?> Formatter
search: Formatter JuliaFormatter format_text

  Formatter(;
      file="~/.julia/packages/PkgTemplates/BFleG/templates/.JuliaFormatter.toml",
      style="nostyle"
  )

  Create a .JuliaFormatter.toml file, used by JuliaFormatter.jl
  (https://github.com/domluna/JuliaFormatter.jl) and the Julia VSCode extension to
  configure automatic code formatting.

  This file can be entirely customized by the user, see the JuliaFormatter.jl docs
  (https://domluna.github.io/JuliaFormatter.jl/stable/).

  Keyword Arguments
  ===================

    •  file::String: Template file for .JuliaFormatter.toml.

    •  style::String: Style name, defaults to "nostyle" for an empty style but
       can also be one of ("sciml", "blue", "yas") for a fully preconfigured
       style.

おまけ

まー.いつか誰かやらなきゃなー.自分やるかー手が回ってないって思ってたところで Hyrodium さんがコントリビューションをされたようなので GitHub 上でワンタイムスポンサーを私のポケットマネーでしました.

まとめ

Julia でのコードを整形するツールを紹介しました.

GitHubで編集を提案

Discussion

HyrodiumHyrodium

AtelierArith/Replay.jl/.github/workflows/FormatCheck.ymlhttps://github.com/julia-actions/julia-format/blob/master/workflows/format_check.yml を参考に作られたのでしょうか?
format_check.ymlはJuliaFormatter.jlの公式ドキュメントから参照されていますが、Julia v1.3 を参照しているので適切にメンテされてなさそうです。

Julia Slackで聞いたところ、JuliaFormatter自体が公式に推奨して(かつメンテされて)いるGitHub Actionsの設定は現段階で無さそうでした。

ChainRulesCore.jlのformat.ymlはreview dogが動いていて便利そうでした。例: https://github.com/JuliaDiff/ChainRulesCore.jl/pull/570

ごまふあざらしごまふあざらし

AtelierArith/Replay.jl/.github/workflows/FormatCheck.ymlは https://github.com/julia-actions/julia-format/blob/master/workflows/format_check.yml を参考に作られたのでしょうか?

その通りです.確か「古い Julia のバージョンを使われているなぁ・・・」という背景があったので既存の Action に依存しない形でフォーマットチェックの確認する方法を理解をしておきたかったモチベーションがありこの記事が存在しています.

review dog 良さそうなので遊んでみますペコペコ