🔧

VSCode と Rust で快適に AtCoder をするためのプラグインを作った

2022/10/23に公開

TL;DR

https://youtu.be/dRF3Uc83Igw

https://github.com/himkt/cargo-atcoder-vscode

Visual Studio Code (VSCode) と Rust を使った AtCoder 生活をちょっと快適にするプラグインを作ったのでよかったら使ってください。いい感じだと思っていただけたらスターもなにとぞ。

Rust と AtCoder

AtCoder はさまざまなプログラミング言語をサポートしており、 Rust も利用できます。利用できる言語はコンテストごとにルールページで列挙されていて、例えば ABC274 は こんな感じ です。(どのコンテストも共通な気もしますが、未確認です。古いコンテストとか有志コンテストだとサポートされている言語が違ったりするのかもしれません)。

cargo-atcoder

Rust で AtCoder をするときに便利なツールとして、 cargo-atcoder があります。他にもいくつかツールはありますが、私は cargo-atcoder を愛用しています。
https://github.com/tanakh/cargo-atcoder

cargo-atcoder はカレントディレクトリにコンテスト用のフォルダを作ったり、解答を AtCoder のジャッジサーバに提出したり、提出した問題のステータスを見たり...といったことができる便利なツールです。 cargo-atcoder は CLI アプリなので、 VSCode でコード書くユーザは VSCode とは別にターミナルアプリを起動したり、必要なタイミングで VSCode の Integrated Terminal を起動したりして利用することになります。

課題感: ターミナルと VSCode 行ったり来たり問題

ターミナルを別に起動して VSCode を cargo-atcoder を併用する方式でも十分快適だったのですが、だんだん VSCode とターミナルを行き来するのが少し面倒に感じるようになってきました。自分のメインの開発環境が NeoVim から VSCode にだんだん遷移していき、開発中にターミナルを開く習慣が無くなってきたのが要因だと思います。

VSCode のプラグインを作成すれば VSCode のコマンドパレットから直接 cargo-atcoder を起動できるようになり、 VSCode 上の AtCoder 生活がより快適になりそうです。 VSCode の extention API は公式ドキュメントも充実しているので、プラグインを作ってみることにしました。プラグインは TypeScript で書けて、 VSCode 上でデバッグができて開発体験がよいです。詳しくは公式ドキュメントをご覧ください。

cargo-atcoder-vscode

というわけで以下の機能を要件としてプラグインの実装を始めました。 cargo-atcoder の一部コマンドしかサポートしていませんが、私はこのあたりのコマンドしか使っておらず、ひとまず自分が必要なものだけ実装することにしました。

  • コンテスト用フォルダの作成 (cargo atcoder new {contest})
  • 問題ページをブラウザで確認 (対応コマンドは cargo-atcoder に存在しない)
  • 手元でプログラムを実行 (cargo run)
  • 手元でのテスト実行 (cargo atcoder test {problem})
  • 解答の提出 (cargo atcoder submit {problem})
  • 提出状況の確認 (cargo atcoder status)

https://github.com/himkt/cargo-atcoder-vscode

できたものが cargo-atcoder-vscode です。 VSCode の marketplace にはアップロードしていない(Azure アカウントを作るのをめんどくさがっている)のでインストールするためには README にあるように code --install-extension を実行する必要があります。

上に記載した要件を満たす形で以下のコマンドが提供されています。

  • cargo-atcoder-vscode.new
  • cargo-atcoder-vscode.open
  • cargo-atcoder-vscode.run
  • cargo-atcoder-vscode.test
  • cargo-atcoder-vscode.test-debug
  • cargo-atcoder-vscode.submit
  • cargo-atcoder-vscode.submit-force
  • cargo-atcoder-vscode.status

デモ

機能のデモ動画を紹介します。

cargo-atcoder-vscode.new

https://youtu.be/SX9WZxW85J4

cargo atcoder new を実行してコンテストフォルダを作成します。作成完了後、 VSCode は自動的に作成したフォルダを開きます。

フォルダを作成するディレクトリはデフォルトで /tmp になっていますが、 settings.json で変更できます。 cargo-atcoder-vscode.rootDir を変更してください。私は自分の競技プログラミング用リポジトリrootDir にして運用しています。

生成されるソースコードは cargo-atcoder の設定ファイルの template セクションで変更できます。私は以下のようなテンプレートを使っています。

https://github.com/himkt/dotfiles/blob/cb3cee0b409574626f5ff85800ef3bb560552f7e/cargo-atcoder/config/cargo-atcoder.toml

cargo-atcoder-vscode.open

https://youtu.be/0S0wokwJtN8

エディタで開いているファイルの問題ページをブラウザで開きます。内部的には当該のコンテストの問題一覧ページを取得し、テーブルタグをパースして問題ページのリンクを特定しています。

AtCoder の問題ページは /contests/{contest}/tasks/{contest}_{problem} というルーティング規則で提供されています。ファイル名から直接リンクを生成すれば良いのではと思う方もいらっしゃるかもしれません。わざわざ問題一覧ページを取得するという周りくどい方法をとっている理由は、過去のコンテストは ABC/ARC で問題が共有されていたことがあり、ファイル名と問題 ID が一致しないことがあるためです。

例えば、 ARC069cargo atcoder new すると src/binc.rsd.rse.rsf.rs というファイルが出力されます。 /contests/arc069/tasks/arc069_c は E 問題へのリンクなので、ファイル名を信じて /contests/arc069/tasks/arc069_c を開くとおかしなことになります。

問題一覧ページを取得し、ファイル名と問題 ID を照合してリンクを生成することで、 c.rs から対応する問題のページ (今回の場合は /contests/arc069/tasks/arc069_a) へ遷移できるようになっています。

cargo-atcoder-vscode.run

https://youtu.be/LmyCJww8Rl0

cargo run --bin {problem} を実行します。 VSCode のタスクとして実行し,
Integrated Terminal が開かれます。タスクとして実行しているので、プログラム実行終了時はエンターキーを入力するとペインが閉じられるようになっています。

cargo-atcoder-vscode.test{,-debug}

https://youtu.be/dRF3Uc83Igw

cargo atcoder test {problem} を実行します。 test はリリースモード、 test-debug はデバッグモードでコードをコンパイルします。

以下に示すようなマクロを用いることで、手元でデバッグするときだけ標準エラー出力に文字列を表示できます。これと test-debug コマンドを利用することで、サンプルケースでデバッグをするのが容易になります。万一デバッグコードを消し忘れてコードを提出してしまっても、ジャッジサーバ上では無視されるので安心です。

#[macro_export]
macro_rules! debug {
    () => {
        #[cfg(debug_assertions)]
        println!();
    };
    ($($arg:tt)*) => {
        #[cfg(debug_assertions)]
        println!($($arg)*);
    };
}

cargo-atcoder-vscode.submit{,-force}

https://youtu.be/g7xYTWs_d4w

cargo atcoder submit コマンドを実行してジャッジサーバに解答を提出します。 submit コマンドは提出前にサンプルケースで実行結果を検証し、結果が一致しない場合はジャッジサーバへの提出を中止します。例えば構築問題などでサンプルと結果が一致しなくても正答となるケースがあります。そのような場合のために cargo-atcoder は submit コマンドで --force オプションを提供しています。 submit-force はこのオプションを有効にして cargo atcoder submit コマンドを実行します。

cargo-atcoder-vscode.status

https://youtu.be/G4R1mez-Bks

cargo atcoder status を実行します。タスクが起動して Integrated Terminal に現在の提出状況が表示されます。

まとめ

本稿では cargo-atcoder を VSCode で快適に利用するためのプラグイン cargo-atcoder-vscode を紹介しました。 VSCode と cargo-atcoder を使って AtCoder をしているみなさんの体験をちょっと快適にできたら嬉しいです。

https://github.com/himkt/cargo-atcoder-vscode

cargo-atcoder は非常に便利なツールです。 cargo-atcoder-vscode は cargo-atcoder の一部機能しか利用していません。 cargo-atcoder について詳しく知りたい方は cargo-atcoder リポジトリの README をご覧ください。

https://github.com/tanakh/cargo-atcoder

Discussion