VSCode と Rust で快適に AtCoder をするためのプラグインを作った
TL;DR
Visual Studio Code (VSCode) と Rust を使った AtCoder 生活をちょっと快適にするプラグインを作ったのでよかったら使ってください。いい感じだと思っていただけたらスターもなにとぞ。
Rust と AtCoder
AtCoder はさまざまなプログラミング言語をサポートしており、 Rust も利用できます。利用できる言語はコンテストごとにルールページで列挙されていて、例えば ABC274 は こんな感じ です。(どのコンテストも共通な気もしますが、未確認です。古いコンテストとか有志コンテストだとサポートされている言語が違ったりするのかもしれません)。
cargo-atcoder
Rust で AtCoder をするときに便利なツールとして、 cargo-atcoder があります。他にもいくつかツールはありますが、私は 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
)
できたものが 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
cargo atcoder new
を実行してコンテストフォルダを作成します。作成完了後、 VSCode は自動的に作成したフォルダを開きます。
フォルダを作成するディレクトリはデフォルトで /tmp
になっていますが、 settings.json
で変更できます。 cargo-atcoder-vscode.rootDir
を変更してください。私は自分の競技プログラミング用リポジトリを rootDir
にして運用しています。
生成されるソースコードは cargo-atcoder の設定ファイルの template
セクションで変更できます。私は以下のようなテンプレートを使っています。
cargo-atcoder-vscode.open
エディタで開いているファイルの問題ページをブラウザで開きます。内部的には当該のコンテストの問題一覧ページを取得し、テーブルタグをパースして問題ページのリンクを特定しています。
AtCoder の問題ページは /contests/{contest}/tasks/{contest}_{problem}
というルーティング規則で提供されています。ファイル名から直接リンクを生成すれば良いのではと思う方もいらっしゃるかもしれません。わざわざ問題一覧ページを取得するという周りくどい方法をとっている理由は、過去のコンテストは ABC/ARC で問題が共有されていたことがあり、ファイル名と問題 ID が一致しないことがあるためです。
例えば、 ARC069 は cargo atcoder new
すると src/bin
に c.rs
、d.rs
、e.rs
、f.rs
というファイルが出力されます。 /contests/arc069/tasks/arc069_c
は E 問題へのリンクなので、ファイル名を信じて /contests/arc069/tasks/arc069_c
を開くとおかしなことになります。
問題一覧ページを取得し、ファイル名と問題 ID を照合してリンクを生成することで、 c.rs
から対応する問題のページ (今回の場合は /contests/arc069/tasks/arc069_a
) へ遷移できるようになっています。
cargo-atcoder-vscode.run
cargo run --bin {problem}
を実行します。 VSCode のタスクとして実行し,
Integrated Terminal が開かれます。タスクとして実行しているので、プログラム実行終了時はエンターキーを入力するとペインが閉じられるようになっています。
cargo-atcoder-vscode.test{,-debug}
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}
cargo atcoder submit
コマンドを実行してジャッジサーバに解答を提出します。 submit
コマンドは提出前にサンプルケースで実行結果を検証し、結果が一致しない場合はジャッジサーバへの提出を中止します。例えば構築問題などでサンプルと結果が一致しなくても正答となるケースがあります。そのような場合のために cargo-atcoder は submit
コマンドで --force
オプションを提供しています。 submit-force
はこのオプションを有効にして cargo atcoder submit
コマンドを実行します。
cargo-atcoder-vscode.status
cargo atcoder status
を実行します。タスクが起動して Integrated Terminal に現在の提出状況が表示されます。
まとめ
本稿では cargo-atcoder を VSCode で快適に利用するためのプラグイン cargo-atcoder-vscode
を紹介しました。 VSCode と cargo-atcoder を使って AtCoder をしているみなさんの体験をちょっと快適にできたら嬉しいです。
cargo-atcoder は非常に便利なツールです。 cargo-atcoder-vscode は cargo-atcoder の一部機能しか利用していません。 cargo-atcoder について詳しく知りたい方は cargo-atcoder リポジトリの README をご覧ください。
Discussion