コンテンツへスキップ

rust-fmt v0.1.13 - 空行はそのまま、範囲整形が動作、Vim 向け1行インストール

注: rust-fmt v0.1.13 は 2026年10月9日 にリリースされました。

今回のリリースのテーマは「信頼できること」です。フォーマッタは頼んでいない差分を出すべきではなく、バッファを失わせるべきでもなく、macro_rules! の中身も外側と同じように整形すべきです。

ざっくりまとめ

  • 空行はデフォルトでそのまま残ります。以前のコンパクトな出力はオプトインの設定になりました。
  • Format Selection が安定版 rustfmt でも動作し、選択した行だけを変更します。
  • Vim / Neovim 向けの rust-fmt-mf が Linux・macOS・Windows でコマンド1つでインストールできます。
  • rust-fmt-mf は整形に失敗してもクラッシュしても、バッファを空にしません。
  • マクロ整形の修正が多数。ファイル全体の整形を止めていた単一アームのマクロの問題も含みます。

変更: 空行はそのまま残ります

0.1.13 より前は、波括弧の内側、構造体フィールドの間、属性の後にある空行がすべて削除されていました。そのため、普通のファイルを初めて整形すると、マクロとは無関係の巨大な差分が出ていました。

現在は空行がデフォルトで保持されます。以前のコンパクトな出力が好みなら、次の設定で元に戻せます:

{
  "rustfmt.compactBlankLines": true
}

スタンドアロンバイナリにも同じスイッチ --compact-blank-lines があります。

追加

  • rustfmt.compactBlankLines 設定と --compact-blank-lines フラグ。デフォルトはオフ。オンにすると波括弧の内側の空行を削除し、大きなファイルを短く保ちます。

  • スタンドアロンバイナリに --rustfmt-arg を追加。すべての rustfmt 呼び出しに追加の引数を1つ渡します。引数ごとに繰り返して指定します:

    rust-fmt-mf --rustfmt-arg=--config --rustfmt-arg=max_width=80
  • Vim / Neovim 向けの1行インストール。 3つの OS 共通の1つのスクリプトで、Python 3.8 以上が必要です。

    Linux と macOS:

    curl -fsSL https://raw.githubusercontent.com/vremyavnikuda/rust-fmt/main/install.py | python3 -

    Windows(PowerShell):

    irm https://raw.githubusercontent.com/vremyavnikuda/rust-fmt/main/install.py | python -

    rust-fmt-mf を ~/.local/bin に配置し、SHA-256 をリリースのものと照合します。Linux と macOS ではシェル設定に追加する行を表示し、Windows ではそのディレクトリをユーザーの PATH に追加します。RUSTFMT_MF_VERSION でリリースを固定し、RUSTFMT_MF_BIN_DIR で別の場所にインストールできます。

修正

エディタ連携

  • Vim / Neovim でバッファが空にならなくなりました。 エディタは終了ステータスに関係なく、フォーマッタが出力した内容で対象行を置き換えます。整形に失敗した場合、rust-fmt-mf は受け取ったソースをそのまま出力してエラーで終了するようになりました。整形は子プロセスで実行されるため、子プロセスがパニック、スタックオーバーフロー、強制終了した場合も親プロセスが同じように振る舞います。深くネストした $( ... )* の繰り返しは、スタックオーバーフローを起こす入力の一例でした。
  • Format Selection が動作します。 安定版 rustfmt でも動作し、マクロ本体もドキュメント全体の整形と同じように整形します。以前は --file-lines に依存していましたが、これは安定版 rustfmt には存在せず、nightly でも --unstable-features 付きでしか受け付けないため、どこでも失敗していました。ネイティブフォーマッタが有効な場合は、代わりにファイル全体を整形し直していました。現在はファイルを通常どおり整形し、選択した行に関わる変更だけを残します。選択範囲の境界をまたぐ変更はまるごと適用されます。rustfmt が別の場所へ移動させる import のように、選択範囲を他と切り離して整形できない場合は何も変更せず、その理由をログに出力します。
  • ネイティブフォーマッタ有効時(デフォルト)にも rustfmt.extraArgs が適用されます。 以前は黙って無視されていました。そこに指定した --edition や --config-path は自動検出された値を置き換え、rustfmt に二重に渡されて拒否されることはなくなりました。
  • ワークスペースのエディションを尊重します。 edition.workspace = true でエディションを継承するクレートは、ワークスペースのエディションで整形されます。以前はマクロフォーマッタが 2021 を仮定し、素の rustfmt にはエディションが渡されていませんでした。また、エディションは edition を最初に含むテーブルではなく、[package] からのみ読み取るようになりました。
  • 大きなファイルの非 ASCII 文字が � にならなくなりました。 出力をチャンクごとにデコードしていたため、2回のパイプ読み取りにまたがった文字が壊れていました。
  • rust-fmt: Open Logs にログが再び表示されます。 0.1.12 では VS Code のログレベルを手動で変更しない限り空でした。現在はすべての行が表示され、実際に実行されたフォーマッタのバイナリも記録されます。

マクロ整形

  • 最後のアームに ; がない macro_rules! がファイル全体の整形を止めなくなりました。 rustfmt はその ; を追加しますが、安全性チェックがその追加をコードの破損と判断していました。そのため、こうしたマクロを含むファイルは VS Code では素の rustfmt にフォールバックし、Vim では整形されないままでした。これは単一アームのマクロの一般的な書き方です:

    macro_rules! square {
        ($x:expr) => {
            $x * $x
        }
    }
  • マクロ本体内のコードが、外側のコードと同じようにレイアウトされます。 アイテム間に空行が入り、fn f() {} は2行に分割されず1行のまま残ります。

  • macro_rules! 本体内の空行も、他の場所と同様に保持されます。 以前は rustfmt.compactBlankLines がオフでも削除されていました。オンの場合は引き続き削除されます。

  • アーム間のコメントでマクロが SKIPPED にならなくなりました。 2つのアームの間、または開き波括弧の直後にあるコメントは元の位置に残ります。

  • マクロ内で生成される構造体のフィールドが個別の行に保たれます。 where 句が単独の行にあり、{ fields } がさらに下の行にある場合、本体が { $(pub $field: $ty),+ } のように1行にくっついていました。

  • 2つのブロックを持つトランスクライバ {{ a }; { b }} が、途中に余分な }; { を含む1つの {{ .. }} ブロックとしてレイアウトされなくなりました。

  • ジェネリクスの閉じ > の後に = が続く場合、スペースが保たれます。 マクロ本体内の pub type Alias<T> = Vec<T> が Vec<T>= ... となり、演算子 >= として解釈され、再度整形しても直りませんでした。

アップグレード

VS Code 拡張は自動で更新されます。Vim / Neovim では、インストールコマンドをもう一度実行すると最新リリースを取得します。

アップグレード後の最初の整形で差分が以前より少なく見えるのは想定どおりです。空行が削除されなくなったためです。

リンク