Visual Studio Codeで競プロ環境構築(実践編)

## 追記(2019/03/27)
訳あってC++の環境構築についても書きました。「これから競プロ始めるぞ！」って人は、以下の記事から読んでください。
Visual Studio Codeで競プロ環境構築(導入編)
https://qiita.com/AokabiC/items/e9312856f588dd9303ed

---
[Visual Studio Code Advent Calendar 2017](https://qiita.com/advent-calendar/2017/vscode)の19日目の記事です。

## はじめに
みなさん、競プロやってますか？私はまわりの強い人を見ながらちまちまやってます。
競技プログラミングってなんぞやって人は、以下の記事を読んでみてください。
[競プロ初心者が書く｢標準入出力からはじめる競プロ入門｣ - Qiita](https://qiita.com/blackcurrant/items/312ea2471900132fbd6a)

何回かコンテストに出た経験のある人ならわかると思いますが、競プロでは素早いコーディング力がアルゴリズムと並んで重要な要素になっています。解法を短時間で正確にコードに落とし込むことが要求されます。
今日はそういった要求を満たせるようなVSCodeの使い方を紹介しようと思います。

#### 環境
Windows 10 Home 64bit
(MacやLinuxでも大丈夫です、多分)

## 覚えておきたいショートカット
ある程度覚えておくと便利なキーボードショートカットがあります(Windows)。
#### カーソル移動、選択系
| 必須 | コマンド | 動作 |
| :-: |:-:|:-:|
|☆|  Shift + 十字キー | 選択  |
|☆|  Ctrl + 十字キー |  単語区切りでの移動 |
|☆| Ctrl + Shift + 十字キー  | 単語区切りでの選択  |
|| Ctrl + Shift + \ | 対応する括弧に移動 |
|| Ctrl + K -> Ctrl + 0 | コードを折りたたむ |

 
#### 編集
| 必須 | コマンド | 動作 |
|:-:|:-:|:-:|
| ☆ | Ctrl + (Shift +) Enter  |  下(上)に行追加 |
| ☆ | Ctrl + X  | 選択範囲or行を切り取りコピー  |
| ☆ | Ctrl + C  |  選択範囲or行をコピー |
| ☆ | Ctrl + Shift + K  | 行を削除  |
| ☆ | (Shift +) Tab  | 選択範囲のインデントを深く(浅く)する  |
| ☆ |  Ctrl + / |  選択範囲をコメントアウト/アンコメント |
|   |  Alt + 十字キー | 行を上下に移動  |
|   |  Alt + Shift + 十字キー | 行を上下にコピー  |
|   | Ctrl + Shift + L | 選択範囲のマッチを全選択 |


#### エディター/ウインドウ操作
| 必須 | コマンド | 動作 |
|:-:|:-:|:-:|
| ☆ | Ctrl + @ | 統合ターミナルを開閉 |
| | Ctrl + B | サイドバーを開閉 |
|  | Ctrl + Tab | エディタータブの切り替え |

Visual Studioとコマンドがちょいちょい違うのでなんとかしたい…

## コードスニペット(Code Snippet)でタイプ量を減らす
呪文(prefix)を唱えてtabキーを押すと、予め書いておいたコードスニペット(短いコード片)が挿入されます。タブストップが設定できるので、配列名を打つ -> tabで遷移 -> 長さを打つ といったことが可能になります。

```json:cpp.json(ユーザースニペットの設定ファイル)
	"cin_vector_int":{
		"prefix": "cvi",
		"body":[
			"vector<int> $1($2);",
			"REP(i, $2) cin >> $1[i];",
			"$3"
		],
		"description": "vector<int>の受取"
	}

```

エディタ上で "cvi" と打ってtabを押すと、\$1 の部分にカーソルが移った状態でスニペットが挿入されます。複数ある \$1 は連動するので、例えばVと入力すれば2行目のREPマクロ内の \$1 にも Vが入力されるわけです。
tabキーを更に押すと次のタブストップ($2)に遷移します。
[独自のスニペットを作成 | Visual Studio Code Docs](https://vscode-doc-jp.github.io/docs/userguide/userdefinedsnippets.html)

入力受け取りの部分を書く際にめちゃめちゃ重宝します。
何でもかんでもマクロにする競プロerもいますが、適度に使い分けたほうがコードは読みやすい気がします。私はマクロの方はREPとlong longのエイリアスを使う程度に留めて、他はコードスニペットを使ってます。

#### quicksuggestionを切る
スニペットを入力する際、intellisenseが邪魔だなあと感じるときもあります。そんな方は設定で `"editor.quickSuggestions": false` と書くとOKです。intellisenseを呼び出す際はCtrl+Spaceです。

[Customizing IntelliSense](https://code.visualstudio.com/docs/editor/intellisense#_customizing-intellisense)

## あると便利かもしれない拡張機能
VSCodeをフル活用するには拡張機能をインストールしましょう。
といっても、このへんは個人差があると思うので自分で探してみるのが一番いいです。
以下に、私が競プロをやる上で便利だと思ったやつや、気になったやつを紹介していこうと思います。

#### [Indentation Level Movement](https://marketplace.visualstudio.com/items?itemName=kaiwood.indentation-level-movement)
同じインデントレベルの行に飛びます。先述した括弧移動のショートカットよりよっぽど使い勝手がいいです。

#### [jumpy](https://marketplace.visualstudio.com/items?itemName=wmaurer.vscode-jumpy)
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f37363734302f33343364613035642d386263312d343731642d356237372d6333353366363733623662332e676966.gif](https://qiita-image-store.s3.amazonaws.com/0/152770/1314b345-6a3d-5fc2-beb5-5fec79138555.gif)

一発でコードの好きな場所に移動できる拡張です。vimでいうeasymotionです。ショートカットをあんまり覚えられない人はこれが便利かも(行移動なんかは備え付けのよりも使い勝手がいい)。

#### [Meta-snippet for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=wmontalvo.vsc-meta-snippet)

ユーザースニペットを作るスニペットです。  
  

こんなもんでしょうか。あとは各人の好みに応じて表示などをいじる拡張を入れるといいと思います。

## 自動でサンプルケースを検証する

問題を解く上で必ず行うプロセスとして、サンプルケースの検証があります。何度もコピペしては実行する羽目になりますから、できれば楽をしたいものです。
そうして調べていくと、ある便利なツールにたどり着きました。
[競技プログラミングのための補助ツールを作った · うさぎ小屋](https://kimiyuki.net/blog/2017/01/19/pr-online-judge-tools/)

このツール、一体なにをしてくれるのかといいますと、主要なコンテストサイトの問題のサンプルケースをスクレイピングし、一括でテストしてくれるのです(!)。これ、使ってみたらめちゃくちゃ便利だったので紹介しておきます。
Windowsの人はBash on Ubuntu on Windowsなどを利用する必要があります。

`$ oj dl [問題のURL]` でサンプルケースをDLし、`$ oj test` でテストしてくれるようです。
ということで、ソースのコンパイル->サンプルのDL->検証 をサクッとやってくれるスクリプトを書きました。

```sh:cptest_atcoder.sh
#!/bin/bash
problemname=$1
oj dl "https://${problemname:0:6}.contest.atcoder.jp/tasks/${problemname:0:8}"
g++ -Wall -std=c++14 ./$1.cpp
oj test
rm -f a.out
rm -rf test 
```

AtCoder限定ですが、こいつに適当なエイリアスを設定してやると `$ cptest arc087_b` みたいな感じで検証させられます。
試した問題はこちら -> [D: FT Robot - AtCoder Regular Condest 087](https://arc087.contest.atcoder.jp/tasks/arc087_b)

```
$ cptest arc087_b
[x] problem recognized: <onlinejudge.atcoder.AtCoderProblem object at 0x7fedf2096860>: https://arc087.contest.atcoder.jp/tasks/arc087_b
[*] load cookie from: /home/AokabiC/.local/share/onlinejudge/cookie.jar
[x] GET: http://arc087.contest.atcoder.jp/tasks/arc087_b
[x] 200 OK
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Input 1
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Output 1
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Input 2
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Output 2
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Input 3
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Output 3
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Input 4
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Output 4
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Input 5
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Output 5
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Input 6
[*] skipped due to language: current one is lang-ja, not lang-en: Sample Output 6
[*] save cookie to: /home/AokabiC/.local/share/onlinejudge/cookie.jar

[*] sample 0
[x] input: 入力例 1
FTFFTFFF
4 2
[+] saved to: test/sample-1.in
[x] output: 出力例 1
Yes
[+] saved to: test/sample-1.out

[*] sample 1
[x] input: 入力例 2
FTFFTFFF
-2 -2
[+] saved to: test/sample-2.in
[x] output: 出力例 2
Yes
[+] saved to: test/sample-2.out

[*] sample 2
[x] input: 入力例 3
FF
1 0
[+] saved to: test/sample-3.in
[x] output: 出力例 3
No
[+] saved to: test/sample-3.out

[*] sample 3
[x] input: 入力例 4
TF
1 0
[+] saved to: test/sample-4.in
[x] output: 出力例 4
No
[+] saved to: test/sample-4.out

[*] sample 4
[x] input: 入力例 5
FFTTFF
0 0
[+] saved to: test/sample-5.in
[x] output: 出力例 5
Yes
[+] saved to: test/sample-5.out

[*] sample 5
[x] input: 入力例 6
TTTT
1 0
[+] saved to: test/sample-6.in
[x] output: 出力例 6
No
[+] saved to: test/sample-6.out
[*] 6 cases found

[*] sample-1
[x] time: 0.132533 sec
[+] AC

[*] sample-2
[x] time: 0.137352 sec
[+] AC

[*] sample-3
[x] time: 0.142059 sec
[+] AC

[*] sample-4
[x] time: 0.131833 sec
[+] AC

[*] sample-5
[x] time: 0.131379 sec
[+] AC

[*] sample-6
[x] time: 0.171815 sec
[+] AC

[x] slowest: 0.171815 sec  (for sample-6)
[+] test success: 6 cases
```


## デバッグツール
VSCodeにはVisual Studioばりの強力なデバッグツールがついているので、RE出たらとりあえず使ってみるのもありだと思います。
[VSCodeでC++デバッグ(Windows) - Qiita](https://qiita.com/bigengelt/items/e4c6f08003fe15988b7d)
[Visual Studio CodeとBoWでC++をデバッグする - My Reference Blog](http://www.myrefblog.com/archives/1971)

## 最後に
VSCode、軽量で統合ターミナルなんかが非常に優秀なので、Visual Studioで競プロしていた各位やエディタに悩んでいる競プロerの方にぜひおすすめしたいです。