📚

vimでAtCoderするときに楽したい

2023/10/06に公開2

vimってめちゃめちゃ速くコードをかけるということを最近実感しました。というのも、授業の一環で行われたペアプログラミングで、vimを使ってるつよつよerの人が謎コマンドを大量に駆使して高速でコードを書いていたからです。
そこで僕は、これを競技プログラミングに取り入れたらとても高速に問題をACできるのではないだろうか、と考えました。しかし、それには弊害も伴うのでそれらを解決していこう というのが今回の記事の内容です。

vimにしたことで不便になったこと

元々僕はIntellJ系のIDEであるCLionを学割で使用していました。それと比べてvimで不便になったなと思うことは

  • ビルド&実行が1クリック or 1コマンドで実行できない
  • 標準入力をテキストファイルから取ることができない
  • ファイル全体のコピペがめんどくさい

などが挙げられます。そこで今回は、これらを解決していきます。

その前に:vimでできるようになったこと

今までIntellJでは「自分自身をincludeすることにより、テンプレファイルを下に持っていく」というテクニックをすると、警告が出てしまうので使えませんでした。
しかし、vimにしたことによりこれらはなくなりました。そこでまずはそれの導入を行います。

#if !__INCLUDE_LEVEL__
#include __FILE__
void solve(){
	
}

ファイルの先頭はこのようにしました。つまり、初回読み込み時は#include __FILE__で自分自身をincludeした後に、solve関数を定義するということです。
mainではなくsolve関数を用意した理由は下で説明しますが、この関数内で処理を実行していきます。

#else
#include <bits/stdc++.h>

//中略

void solve();
int main(){
   	cin.tie(0); ios::sync_with_stdio(0);
	solve();
	return 0;
}
#endif

先程の分岐により、コンパイラ側ではelseの先がこちら側がファイルの一番先頭であると認識されるため、いつも書いてるテンプレをそのまま書いた上で、solve関数をプロトタイプ宣言します。。
その後main関数を実行した上で、cin/coutが速くなるおまじないをします。このように、毎回main関数で実行するコードもテンプレ化できるようにするために、solve関数を使用しました。

これでら、3行目からコーディングしながら、テンプレも使うことができるようになります。

ビルド&実行が1クリックでできない

この問題を解決するのは非常に簡単です。今回は、makefileにコンパイルオプションを書いた上で、makeコマンド→実行 をshファイルに記述しました。

1.makefileを書く

GNUmakefileというファイルを作り、中にこんな感じに書きます。

atcoder:AtCoder.cpp
	g++ -Wall -std=c++20 -D LOCAL  AtCoder.cpp

-D LOCALとすることにより、ローカル環境のみ動くコードというものが作れるようになっています。これはこの後重要になります。

2.shファイルを書く

先程はビルド先ファイルを指定していないので、./a.outに生成されるはずです。よって、makeコマンドと合わせて

make
./a.out

とすれば良いです。僕は予測変換が効きやすようにmake_and_start.shという名前をつけましたが、好きな名前でいいです。

標準入力をテキストファイルから受け取れない

元々僕はIDEの機能を使って入力をinput.txtから受け取っていました。しかしその方法はvimではできないので、別の方法を使用することにしました。
./a.out < input.txtでも確かにできますが、それだとビルドせずに単体で実行したい場合は不便です(という理由をつけただけで、忘れてました)。
そこで、C++ファイル内で読み込むようにするために、main関数を以下のように変更します。

#include <fstream> //こいつも追記

int main(){
	#ifdef LOCAL
    	    ifstream inputFile("input.txt");
    	    cin.rdbuf(inputFile.rdbuf());
	#else
    	    cin.tie(0);
    	    ios::sync_with_stdio(0);
	#endif

	solve();
	return 0;	
}

AtCoderのオンラインジャッジでもinput.txtから読み込むのはまずいですから、#ifdef LOCALを使うことによってローカルのみにしています。ifstreamで読み込んで、rdbufでcinの入力受け取りを標準入力から変更しています。
ただし残念なことに、高速化するおまじないとは競合してしまうので、高速化はオンラインジャッジのみとしました。これにより、input.txtからcinできるようになります。

ファイル全体のコピペがめんどくさい

vimで全部をコピーする簡単な方法があったらぜひ教えてください。分からなかったので、ターミナルでファイルの内容をコピーできるようにしたいと思って調べたら、以下の情報が出てきました。

pbcopy < AtCoder.cpp

しかし、僕が普段使ってるArchにpbcopyはなく、かわりにxclipというものが使えるというのがわかったので、xclipを使って

xclip -selection clipboard < AtCoder.cpp

というコマンドをshファイルに追加しました。これで、ビルド時に自動でクリップボードにコピーしてくれるので、後は成功したら提出欄に貼り付けるだけですみます。非常にスマートです。

終わりに

vimを便利に使えるようにするために、周辺環境を整えてみました。肝心のvimはまだあまり慣れていないので、これから使いこなせるように練習していきます。

参考文献

GitHubで編集を提案

Discussion

serna37serna37

vimでファイル全体をコピーするには、vimのコマンドである
:%y
を使用するとよいです!
vimでヤンク時にレジスタだけでなく、OSのクリップボードにも値を入れるために
vimrcに
set clipeboard+=unnamed
を記載する必要があります

kokastarkokastar

なるほど、そんな設定があるのですね。ありがとうございます!