scala+gvim+windows10で補完ができるようになるまで

# 概要
scalaでコーディングする時はEmacsやIntelliJ IDEAを使う場合が多いようですが、Vim派としてはVim以外での開発はあり得ません。Vimでscalaの補完をする方法はあまりないようですが、ensimeという言語サーバをvimから使う方法があります。しかし、このensimeのセットアップ方法に詰まったりしたので、ここにまとめる。

# 環境構築

### sbtとgitとjdk11のインストール
下記コマンドを管理者権限で実行しPackageManagementからChocolateyGet経由でsbt,git jdk11をインストールします。インストールが終わったら一旦powershellを閉じます。

```powershell
Set-ExecutionPolicy -Force RemoteSigned
Install-PackageProvider ChocolateyGet　-Force
Install-Package sbt -ProviderName ChocolateyGet -Force
Install-Package git -ProviderName ChocolateyGet -Force
Install-Package jdk11 -ProviderName ChocolateyGet -Force
```

※PackageManagementについてはこちら
https://qiita.com/k_takashi0309/items/3992b8ee68c256202bcf

### sbtのプラグインインストール準備

```powershell
New-Item ~/.sbt/1.0/plugins -ItemType directory
Write-Output "addSbtPlugin(`"org.ensime`" % `"sbt-ensime`" % `"2.5.1`")"| Add-Content ~/.sbt/1.0/plugins/plugins.sbt
Write-Output "addSbtPlugin(`"com.eed3si9n`" % `"sbt-assembly`" % `"0.14.9`")"| Add-Content ~/.sbt/1.0/plugins/plugins.sbt
```

上記コマンドを実行するとsbtの設定ファイルにsbt-ensimeとsbt-assemblyが追加されます。sbt起動時にインストールされます。

### python付きのgvimのインストール
香り屋からgvimをダウンロード・解凍します。
https://www.kaoriya.net/software/vim/

コマンドでダウンロードする場合は下記実行(Cドライブ直下に解凍します)

```powershell
Invoke-WebRequest -uri https://github.com/koron/vim-kaoriya/releases/download/v8.1.0005-20180520/vim81-kaoriya-win64-8.1.0005-20180520.zip -OutFile $env:temp\gvim.zip
Expand-Archive $env:temp\gvim.zip -DestinationPath C:\
remove-item $env:temp\gvim.zip
```

### python3.5のインストール

gvimはデフォルトではpythonのバージョン3.5を探します。pythonはバージョンやライブラリの環境がインストールするシステムに依存してしまうのでgvim用にembeddable python3.5を入れます。
下記からPython3.5のWindows x86-64 embeddable zip fileをダウンロード・解凍してgvimがあるフォルダに入れときます。
https://www.python.org/downloads/windows/

コマンドでダウンロードする場合は下記実行

```powershell
Invoke-WebRequest -uri https://www.python.org/ftp/python/3.5.4/python-3.5.4-embed-amd64.zip -OutFile $env:temp\embedpython.zip
Expand-Archive $env:temp\embedpython.zip -DestinationPath C:\vim81-kaoriya-win64\python-3.5.4-embed-amd64
remove-item $env:temp\embedpython.zip
```

### pythonにライブラリをインストール
gvimに入れたembeddable pythonに必要なライブラリを入れます。
python35.zipは解凍してフォルダ名をpython35.zipにする必要があります。

```powershell
cd C:\vim81-kaoriya-win64\python-3.5.4-embed-amd64
expand-archive python35.zip
remove-item python35.zip
Rename-Item python35 -newname python35.zip
wget "https://bootstrap.pypa.io/get-pip.py" -O "get-pip.py"
.\python.exe get-pip.py
.\python.exe -m pip install websocket-client sexpdata
```

### gvimでembed-pythonのPATHを通す
下記スクリプトを_vimrcに追加する

```vimscript
if has('vim_starting')
    let $PATH = $VIM . "\\python-3.5.4-embed-amd64;" . $VIM . "\\python-3.5.4-embed-amd64\\Scripts;" . $PATH
    let $PYTHONPATH = $VIM . "\\python-3.5.4-embed-amd64\\Lib\\site-packages;" . $VIM . "\\python-3.5.4-embed-amd64"	
    let g:python3_host_prog = $VIM . "\\python-3.5.4-embed-amd64\\python.exe"
endif
```
下記コマンドをpowershellで実行しても追加できます。

```powershell
$script =@'

if has('vim_starting')
  let $PATH = $VIM . "\\python-3.5.4-embed-amd64;" . $VIM . "\\python-3.5.4-embed-amd64\\Scripts;" . $PATH
  let $PYTHONPATH = $VIM . "\\python-3.5.4-embed-amd64\\Lib\\site-packages;" . $VIM . "\\python-3.5.4-embed-amd64"
  let g:python3_host_prog = $VIM . "\\python-3.5.4-embed-amd64\\python.exe"
endif

'@
$script|Add-Content C:\vim81-kaoriya-win64\_vimrc　-NoNewline
```
### ensime-vimのインストール
下記からvimプラグインのensime-vimをインストールします。
https://github.com/ensime/ensime-vim
vimのプラグインマネージャを利用している場合はプラグインマネージャ経由でインストールするとよいでしょう。
私はプラグインマネージャを使わない派なので下記コマンドでインストールします。

```powershell
New-Item C:\vim81-kaoriya-win64\vimfiles\pack\Mypack\opt -ItemType directory
cd C:\vim81-kaoriya-win64\vimfiles\pack\Mypack\opt
git clone https://github.com/ensime/ensime-vim.git
```

### deopleteのインストール
Vimは標準で<C-x><C-o>でオムニ補完ができますが、自動で補完を出すプラグインがあるので、それをいれるとコーディングが捗ります。自動補完のプラグインはいろいろありますが、ensimeでの補完は若干時間がかかるので非同期で補完を実行してくれるdeopleteが良いです。

deopleteは下記からプラグインマネージャ等でインストールしてください。
https://github.com/Shougo/deoplete.nvim.git

プラグインマネージャを使わない派は下記コマンドでインストールしてください。

```powershell
New-Item C:\vim81-kaoriya-win64\vimfiles\pack\Mypack\opt -ItemType directory
cd C:\vim81-kaoriya-win64\vimfiles\pack\Mypack\opt
git clone https://github.com/Shougo/deoplete.nvim.git
git clone https://github.com/roxma/vim-hug-neovim-rpc.git
git clone https://github.com/roxma/nvim-yarp.git
```

### deoplete用の設定を_vimrcに追加
下記設定を_vimrcに追加します。

```vimscript
  packadd vim-hug-neovim-rpc "deopleteの依存
  packadd nvim-yarp "deopleteの依存
  let g:deoplete#enable_at_startup = 1
  let g:deoplete#auto_complete_delay = 0
  let g:deoplete#auto_complete_start_length = 1
  let g:deoplete#enable_camel_case = 0
  let g:deoplete#enable_ignore_case = 0
  let g:deoplete#enable_refresh_always = 0
  let g:deoplete#enable_smart_case = 1
  let g:deoplete#file#enable_buffer_path = 1
  let g:deoplete#max_list = 10000
  packadd deoplete.nvim
  call deoplete#custom#option('omni_patterns', {'scala': '[^. *\t]\.\w*'}) "omniが発動するタイミング


```

コマンドで追加する場合は下記

```powershell
$script =@'

  packadd vim-hug-neovim-rpc "deopleteの依存
  packadd nvim-yarp "deopleteの依存
  let g:deoplete#enable_at_startup = 1
  let g:deoplete#auto_complete_delay = 0
  let g:deoplete#auto_complete_start_length = 1
  let g:deoplete#enable_camel_case = 0
  let g:deoplete#enable_ignore_case = 0
  let g:deoplete#enable_refresh_always = 0
  let g:deoplete#enable_smart_case = 1
  let g:deoplete#file#enable_buffer_path = 1
  let g:deoplete#max_list = 10000
  packadd deoplete.nvim
    call deoplete#custom#option('omni_patterns', {'scala': '[^. *\t]\.'}) "omniが発動するタイミング
    call deoplete#custom#option('keyword_patterns', { 'scala': ''}) "omni以外は使わない

'@
$script|Add-Content C:\vim81-kaoriya-win64\_vimrc　-NoNewline
```

### aleをインストール
構文チェックにaleを利用するのでインストールします。

```powershell
New-Item C:\vim81-kaoriya-win64\vimfiles\pack\Mypack\opt -ItemType directory
cd C:\vim81-kaoriya-win64\vimfiles\pack\Mypack\opt
git clone https://github.com/w0rp/ale.git
```

### ale用の設定を_vimrcに追加
下記設定を_vimrcに追加します。

```vimscript
  let g:ale_completion_enabled = 1
  packadd ale 
  let g:ale_linters = {'scala': ['sbtserver']}
  let g:ale_lint_on_save = 1
```

コマンドで追加する場合は下記

```powershell
$script =@'

  let g:ale_completion_enabled = 1
  packadd ale 
  let g:ale_linters = {'scala': ['sbtserver']}
  let g:ale_lint_on_save = 1

'@
$script|Add-Content C:\vim81-kaoriya-win64\_vimrc　-NoNewline
```


### 環境変数HOMEを設定する
ensime-vimで実行されるPythonスクリプト内で環境変数HOMEを参照しているので、設定していないとエラーになる。(これの原因に気付くのに数日かかりました)
powershellでは自動変数としてHOMEが定義されているが、Vimから起動されるPythonではHOMEが定義されないようなので、下記コマンドで環境変数HOMEにPowershellの自動変数HOMEを入れておく。

```powershell
[System.Environment]::SetEnvironmentVariable("HOME", $HOME, "User")
```

# プロジェクト作成

### プロジェクトディレクトリの作成
以降プロジェクトの名前をsampleProjectとします。

```powershell

New-Item sampleProject -ItemType directory
```

### ensimeの初期化
```powershell

cd sampleProject
write-output c|sbt ensimeConfig
write-output c|sbt ensimeConfigProject
```
### gitの初期化
```powershell
git init
Write-Output "target/"| Add-Content .gitignore
```
### build.sbtの作成
```powershell
$projectName = (get-item (get-location).Path).Name
$buildsbt = @"
name := "$projectName"
version := "1.0"
"@
$buildsbt|Add-Content build.sbt　-NoNewline

```


# コーディングの仕方
### 自動コンパイル
scalaのコーディング中はsbtを起動したままにしておき、ファイル保存時に自動コンパイルするコマンドを実行しておきます。

```powershell
sbt
~assembly
```

### 補完
.を入力するとdeopleteによって自動的にomni補完が実行されます。

### 構文チェック
ファイル保存時にaleで構文チェックが行われ、エラーがあれば表示されます。

### 実行
sbt runでも実行できますが、標準入出力を渡したりとかする場合は面倒なのでjavaコマンドで実行します。

```powershell
 java -jar .\target\scala-2.12\sample-assembly-1.0.jar
```

ファイルarg.txtの中身を標準入力に渡す場合は下記のように実行します。

```powershell
Get-Content .\arg.txt | java -jar .\target\scala-2.12\sample-assembly-1.0.jar
```