Vim Advent Calendar 2012 の 173 日目の記事です。
今回は C# を書くのに便利な OmniSharp と言うツールを紹介します。これさえあれば、エディタとしての Visual Studio はもう必要ありません!
経緯
(興味ない人はここは飛ばしてインストールのところから読むと良いです)
先日、OmniSharp なるものの存在を教えてもらいました。
2013-05-09 23:47:26 via YoruFukurou to @thinca
@mizchi お、面白そうですね!私は知らなかったです。明日あたり見てみますー。ありがとうございます。
2013-05-09 23:51:36 via tweetvim to @mizchi
と言うわけで調査してみることにしました。
様々な罠にかかりつつ、ソースコードにちょろちょろ手を入れて試していくと…
動く、動くぞ!
これは素晴らしい。が、Vim script の部分とかあちこちイケてない…。
[速報] OmniSharp のおかげで C# で Visual Studio 捨てられそうな予感。 URL TODO: Vim script 部分がクソすぎるので直して pull req しまくる。
と言うわけで pull req を投げまくることに。
このことについて Lingr の Vim 部屋 で宣伝したところ…
日本人 Vimmer 達がものすごい勢いで pull request を投げ始めました。以下一部抜粋。これで全てではありません。
- Move autoload functions to the right location by thinca · Pull Request #26 · OmniSharp/omnisharp-vim · GitHub
- Add syntax check options. by osyo-manga · Pull Request #36 · OmniSharp/omnisharp-vim · GitHub
- Fix issue #33 by DeaR · Pull Request #37 · OmniSharp/omnisharp-vim · GitHub
- Show connect error by mattn · Pull Request #43 · OmniSharp/omnisharp-vim · GitHub
- Add command by osyo-manga · Pull Request #46 · OmniSharp/omnisharp-vim · GitHub
- Check the MD5 of title as type GUID by thinca · Pull Request #47 · OmniSharp/omnisharp-vim · GitHub
- Add '-complete=file' to OmniSharpStartServerSolution by osyo-manga · Pull Request #55 · OmniSharp/omnisharp-vim · GitHub
と言うわけで、精力的に Pull Request を取り込んでくれている作者の nosami さんのおかげもあって、発見時点からかなり改良されています*1。
インストール
このプラグインは、サーバクライアント方式で動作します。ローカルにサーバを立てて、Vim とそのサーバで通信をして各種機能を提供します。
Vim
そのためまず、クライアントとなる Vim は +python が有効になった Vim が必要になります。Vim 内で以下のコマンドを実行すると、+python が有効かどうか確認できます。
:echo has('python')
1 が表示されたら、+python が使えます。0 だったら使えないので、何とかして使える Vim を調達してください。
ちなみに、現在 +python に依存しないようにする Pull Request が投げられています。代わりに curl か wget に依存しますが、場合によっては +python よりも用意しやすいでしょう。
プラグイン
このプラグインはサーバが C# で書かれているため、これをビルドする必要があります。Windows では Visual Studio、Mac や Linux では Mono が必要です。
サーバをビルドする必要があるので、インストールにはビルド機能もある neobundle をお勧めします。neobundle を使う場合、以下のように設定すればインストールと一緒にビルドも自動で行われます。*2
NeoBundleLazy 'nosami/Omnisharp', { \ 'autoload': {'filetypes': ['cs']}, \ 'build': { \ 'windows': 'MSBuild.exe server/OmniSharp.sln /p:Platform="Any CPU"', \ 'mac': 'xbuild server/OmniSharp.sln', \ 'unix': 'xbuild server/OmniSharp.sln', \ } \ }
手動インストール
以下は、それ以外の方法(Vundle や pathogen、もっと古典的な手法など)で手動でインストールする手順です。
まずは通常のプラグインと同じようにインストールします。この辺りは割愛します。
サーバ
まず、サーバは submodule になっているので、更新する必要があります。
cd path/to/Omnisharp git submodule update --init
その後、環境に応じて以下のようにサーバをビルドします。
Visual Studio
cd server MSBuild.exe /p:Platform="Any CPU"
通常は MSBuild.exe だけでいけるようですが、私の環境では /p を指定する必要がありました。
Windows Vista 以降の人は、サーバやVimを管理者権限で動かすのでなければ、以下の設定が必要です。
管理者権限のコマンドプロンプトで実行します。(参考: https://subtech.g.hatena.ne.jp/motemen/20101125/1290694952 )
netsh http add urlacl url=http://+:2000/ user=thinca
ユーザ名は適時読み替えてください。ポート番号は OmniSharp がデフォルトで使うものです。
Mono
cd server xbuild
server/OmniSharp/bin/Debug/OmniSharp.exe が生成されていれば成功です。
使い方
サーバの起動
まずはサーバを起動します。サーバは起動する際にプロジェクトの .sln ファイルを指定する必要があります。
path/to/OmniSharp/server/OmniSharp/bin/Debug/OmniSharp.exe -s path/to/project.sln
mono を使っている場合は mono 経由で起動する必要があります。
mono path/to/OmniSharp/server/OmniSharp/bin/Debug/OmniSharp.exe -s path/to/project.sln
Vim 内から起動することも可能です。C# のソースコードを開いているファイル*3で、以下のようにします。
:OmniSharpStartServer " もしくは :OmniSharpStartServerSolution foo.sln
前者の場合は現在開いているファイルの位置から .sln ファイルを自動的に探して開きます。
また、.sln に存在しないファイル名を与えてもとりあえずは動くようです。この場合でも標準的なライブラリ周りの補完は可能のようです。
コード補完
オムニ補完が利用可能です。コードの任意の場所で、
[ gifアニメーション提供: id:osyo-manga ]
neocomplcache を使うことで、自動補完も可能です。以下は設定例です。
if !exists('g:neocomplcache_force_omni_patterns') let g:neocomplcache_force_omni_patterns = {} endif let g:neocomplcache_force_omni_patterns.cs = '[^.]\.\%(\u\{2,}\)\?'
コマンド
C# を編集しているバッファで以下のコマンドが使えます。私自身全ての機能を試したわけではないので、私がよくわかっていない部分については備考に書いておきました。コマンドはほぼ全て、現在のカーソル位置に対して動作します。
コマンド | 説明 | 備考 |
---|---|---|
:OmniSharpGotoDefinition | コードの定義へジャンプします。 | 超便利。 |
:OmniSharpFindUsages | コードの参照元を検索します。 | quickfix に出る。超便利。 |
:OmniSharpFindImplementations | 型を実装している型を検索します。 | インターフェース上で実行すると、インターフェースを実装している型のリストが出たりする。 |
:OmniSharpFindSyntaxErrors | 簡易構文チェックを実行します。 | 構文チェックであり、ビルドエラーは出ない。デフォルトだと保存時に自動される。 |
:OmniSharpGetCodeActions | カーソル位置に応じた様々なアクションを実行します。 | Visual Studio でおなじみの、using 補完や using 並び換えなど。 |
:OmniSharpTypeLookup | 型情報をメッセージ領域に表示します。 | コマンド打つ領域のこと。 |
:OmniSharpBuild | ビルドします。 | ビルドエラーが quickfix で出るようになってるらしいけど私の環境だとうまく出ない。 |
:OmniSharpRename | 変数等をリネームします。 | 微妙にうまく動かず。 |
:OmniSharpReloadSolution | ソリューションをリロードします。 | 編集していて、ジャンプがずれたりうまくいかなくなってきたら実行してみると良いかも。 |
:OmniSharpCodeFormat | コードフォーマットします。 | 動作未確認。 |
:OmniSharpStartServer | サーバを実行します。 | dispatch.vim に依存。 vimprocが使えるようにする pull req あり。 |
:OmniSharpStopServer | サーバを停止します。 | |
:OmniSharpAddToProject | ファイルをプロジェクトに追加します。 | 動作未確認。 |
特によく使うものに関してはキーマッピングしておくと良いでしょう。例えば Visual Studio 風にするには以下のような感じです。*4
" Windowsの場合は ~/vimfiles/after/ftplugin/cs.vim に、 " それ以外では ~/.vim/after/ftplugin/cs.vim に書く nnoremap <silent> <buffer> <F12> :OmniSharpGotoDefinition<CR> nnoremap <silent> <buffer> <S-F12> :OmniSharpFindUsages<CR>
私はとりあえず一通りって感じで以下のようにしています。
nnoremap <silent> <buffer> ma :OmniSharpAddToProject<CR> nnoremap <silent> <buffer> mb :OmniSharpBuild<CR> nnoremap <silent> <buffer> mc :OmniSharpFindSyntaxErrors<CR> nnoremap <silent> <buffer> mf :OmniSharpCodeFormat<CR> nnoremap <silent> <buffer> mj :OmniSharpGotoDefinition<CR> nnoremap <silent> <buffer> <C-w>mj <C-w>s:OmniSharpGotoDefinition<CR> nnoremap <silent> <buffer> mi :OmniSharpFindImplementations<CR> nnoremap <silent> <buffer> mr :OmniSharpRename<CR> nnoremap <silent> <buffer> mt :OmniSharpTypeLookup<CR> nnoremap <silent> <buffer> mu :OmniSharpFindUsages<CR> nnoremap <silent> <buffer> mx :OmniSharpGetCodeActions<CR>
まとめ
まだまだうまく動いてない機能もあったりしますが、現段階ですでにかなり実用的です。実際私は OmniSharp を導入してから最近は Visual Studio を立ち上げなくなりました。
動かない部分については今後もガンガン修正投げて行こうと思います。
C# を Vim で書きたい人は、是非お試しあれ!