インフラよりvim環境

[Vim2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/vim2) 13th day

# 前置き
筆者が普段AWSにおいてdevopsするときに利用する環境とvimの使い方(plugin)を紹介する記事。
導入をメインとしているので詳細な設定項目やカスタマイズは個々のplugin公式サイトを参照してほしい。AWSの設定は言及しないがある程度の知識を前提としている。


## 開発環境とは？

文脈がないと限定しにくいがプログラマにとっての開発環境はIDEなら、インフラエンジニアにとっての開発環境とはなにか？

**infrastructure as code** を行いやすい環境というのは最近なら想像に難くない。ただ具体的な定義はまだないと思われる。そのためのツール群が扱うファイル群の作成や編集を容易に行えて、オペレーションまで行えるものと個人的には考えている。

上記は経験による結果論で、普段は[Amazon Linux 2](https://aws.amazon.com/amazon-linux-2/?nc1=h_ls)のEC2を立ててそこにツール群などをインストールしている。

EC2を使う理由は主に以下となる

- サーバ用途で提供されているディストリビューションなので通常使用するサーバと基本的近いもの
- AWS環境のオペレーションを行うためのツール群が提供されメンテナンスされている
- sshログインを行えるterminalがあれば手元のOSを選ばない(anywhere)
- 環境のバックアップ、破棄、再構築が容易(AMIやAnsible)
- セキュリティを高めることも容易(通信の遮断や証跡の方法が多い)

(いずれも手元のマシーンでも当然できるが、始端を固定化することが変更への対応のコストになると考えている)



# vim環境の準備

以下は既に`Amazon Linux 2`のEC2を立てたあとsshによるログインを行った状態とする。

```bash
$ uname -r
4.14.152-127.182.amzn2.x86_64
```
デフォルトでは8.1が既にinstallされている

```bash

$ vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Jul 17 2019 17:46:26)
Included patches: 1-1602
Modified by Amazon Linux https://forums.aws.amazon.com/
Compiled by Amazon Linux https://forums.aws.amazon.com/
```





## vimをinstallする

rpmのrebuildをするのは面倒なので、デフォルトを利用せずにソースからインストールする。

<details><summary>rpmからrebuildする場合(大体の手順)</summary><div>

提供されているvimのバージョンを確認

```bash
$ sudo yum --showduplicates list vim-common
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Installed Packages
vim-common.x86_64                         2:8.1.1602-1.amzn2                             installed
Available Packages
vim-common.x86_64                         2:7.4.160-2.amzn2                              amzn2-core
vim-common.x86_64                         2:7.4.160-4.amzn2.0.16                         amzn2-core
vim-common.x86_64                         2:8.0.1257-1.amzn2                             amzn2extra-vim
vim-common.x86_64                         2:8.0.1257-2.amzn2                             amzn2extra-vim
vim-common.x86_64                         2:8.1.1602-1.amzn2                             amzn2-core
```

8.1のsrc.rpmをダウンロードする

```bash
$ yumdownloader --source vim-common-2:8.1.1602-1.amzn2.x86_64
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Enabling amzn2extra-vim-source repository
Enabling amzn2extra-docker-source repository
Enabling amzn2-core-source repository
vim-8.1.1602-1.amzn2.src.rpm                                                    |  11 MB  00:00:00
```

展開

```bash
$ rpm -ivh vim-8.1.1602-1.amzn2.src.rpm
```

依存関係パッケージのチェックとインストール

```bash
$ sudo yum-builddep rpmbuild/SPECS/vim.spec
```

rpmbuildをインストールする

```bash
$ sudo yum install rpm-build
```

vim.specを編集してrebuildする

```bash
$ rpmbuild --rebuild rpmbuild/SPECS/vim.spec
```

</div></details>

インストールに必要なパッケージ

- git
- ncurses-devel
- gcc
- python3-devel(deopleteで利用)
- ruby-devel(vim-terraform-completionで利用)

```bash
$ sudo yum install -y git python3-devel ruby-devel ncurses-devel gcc
```

デフォルトのvimを残したままユーザ環境(ec2-user)にインストールする場合は予めディレクトリを作成しておく

```bash
$ mkdir -p $HOME/.local/bin
```
ソースを取得

```bash
$ git clone https://github.com/vim/vim.git
$ cd vim
```
python3を有効にしてmake

```bash
$ ./configure \
--enable-rubyinterp \
--enable-python3interp \
--prefix=$HOME/.local/vim
$ make
```
install

```bash
$ make install
```

pathを設定

```bash
$ echo 'export PATH=$HOME/.local/vim/bin:$PATH' >> ~/.bashrc
$ source ~/.bashrc
```

versionをチェック

```bash
$ vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Dec 12 2019 08:50:33)
Included patches: 1-2424
Compiled by ec2-user@ip-172-31-18-199.us-east-2.compute.internal
```

`+python3`、`+ruby`となっている


## vimのpluginについて

[vimawesome](https://vimawesome.com/)では各pluginのインストール方法は`Vundle`、`NeBundle`、`VimPlug`、`Pathogen`の４種のpluginマネージャのいずれかを利用してインストールすることになる。こだわりや差異を理解している場合でなければ大きくは変わらない。ここではVundleでの利用を紹介する。

### Vundleをinstallする

```bash
$ git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim
```

`~/.vimrc`

```vim
set nocompatible              " be iMproved, required
filetype off                  " required
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()

Plugin 'VundleVim/Vundle.vim'
"--ここから

"--ここまでの間にpluginの記述を行う
call vundle#end()            " required
filetype plugin indent on    " required
```

## vimのcolorscheme

みんな大好き[solarized](https://github.com/altercation/vim-colors-solarized)

### vim-colors-solarizedをinstallする

```bash
$ mkdir -p ~/.vim/colors/
$ curl -LSs -o ~/.vim/colors/solarized.vim https://raw.githubusercontent.com/altercation/vim-colors-solarized/master/colors/solarized.vim
```

`~/.vimrc`に設定する

```vim
let g:solarized_termcolors=16
let g:solarized_termtrans=1
let g:solarized_degrade=0
let g:solarized_bold=1
let g:solarized_underline=1
let g:solarized_italic=1
let g:solarized_contrast='normal'
let g:solarized_visibility='normal'

syntax enable
set background=dark
colorscheme solarized
```


## vimのstatus情報

[powerline](https://github.com/powerline/powerline)系表示があると情報がわかりやすく効率アップにつながるので利用しよう。ここでは[vim-airline](https://github.com/vim-airline/vim-airline)を利用する。

### vim-airlineをinstallする

`~/.vimrc`のVundleのPluginを記述すべきブロックの間に下記を追記

```vim
" airline
Plugin 'vim-airline/vim-airline'
Plugin 'vim-airline/vim-airline-themes'

let g:airline#extensions#tabline#enabled = 1
let g:airline_theme='violet'
let g:airline_powerline_fonts = 1
```

vimrcを読み込む

```vim
:source %
```
pluginのinstallを行う

```vim
:PluginInstall
```

`Done!`が表示されれば正常にインストールが完了

[いろんなテーマ](https://github.com/vim-airline/vim-airline/wiki/Screenshots)があるので気に入ったものに変更できる。

コマンドラインから

```vim
:AirlineTheme solarized
```

もしくは`~/.vimrc`に記述する

```vim
let g:airline_solarized_bg='dark'
```


### powerlineのフォントをinstallする
powerlineのフォントがないと一部表示が崩れるのでfontのinstallが必要となる。font自体はクライアントにインストールする。

#### macの場合

terminalからfontをインストール

```bash
$ git clone https://github.com/powerline/fonts.git
$ cd fonts
$ ./install.sh

Copying fonts...
Powerline fonts installed to /Users/YOURNAME/Library/Fonts
```


iTerm2を利用しているなら

Preferences -> Profiles -> Text(tab)

Fontのプルダウンメニューから`DejaVu Sans Mono for Powerline`を選択する

#### windowsの場合

https://github.com/powerline/fonts からzipでダウンロードして展開し、PowerShellから`install.ps1`を実行してfontをインストール

Puttyを利用しているなら

window -> Appearance -> Font settings 

から`DejaVu Sans Mono for Powerline`を選択する

## formatについて

[prettier](https://github.com/prettier/vim-prettier)を利用する。

### vim-prettierをinstallする

node環境をまず用意する。


nvmをinstallする

```bash
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash
```
nvmを使えるように設定する

```
$ source ~/.bashrc
```

nodeをinstall

```bash
$ nvm install node
Downloading and installing node v13.3.0...
Downloading https://nodejs.org/dist/v13.3.0/node-v13.3.0-linux-x64.tar.xz...
################################################################################################################## 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v13.3.0 (npm v6.13.1)
Creating default alias: default -> node (-> v13.3.0)
```

yarnをinstallする

```bash
$ npm i -g yarn
```

Vundleからprettierをinstallする

```vim
" prettier
Plugin 'prettier/vim-prettier'
```
```vim
:source %
```
```vim
:PluginInstall
```

言語のformatはmodule化しているのでvim-prettierのディレクトリ内で必要な言語をyarnでinstallする(例 typescript)

```bash
$ cd ~/.vim/bundle/vim-prettier/
$ yarn add typescript 
```
`yarn add css` ` yarn add json`など、他にも利用言語がある場合は追加する

formatの細かい設定は[公式](https://github.com/prettier/vim-prettier)を参照

## 行数表示

[vim-numbertoggle](https://github.com/jeffkreeftmeijer/vim-numbertoggle)を利用する。

カレント行以外の行番号は相対表示してくれるの上下の移動が便利になる。

### vim-numbertoggleをinstallする

Vundleでinstallする

```vim
" vim-numbertoggle
Plugin 'jeffkreeftmeijer/vim-numbertoggle'
set number relativenumber
```

```vim
:source %
```
```vim
:PluginInstall
```

解除する場合は


`:se nu! rnu!`

## 補完の強化

[deoplete](https://github.com/Shougo/deoplete.nvim)を利用する。

### deopleteをinstallする

pynvimが必要のため先にpip3からinstallしておく

```bash
$ pip3 install --user pynvim
```

Vundleからinstallする

```vim
" deoplete
Plugin 'Shougo/deoplete.nvim'
Plugin 'roxma/nvim-yarp'
Plugin 'roxma/vim-hug-neovim-rpc'
let g:deoplete#enable_at_startup = 1
```
```vim
:source %
```
```vim
:PluginInstall
```



 
## terraformのためのplugin

[vim-terraform](https://github.com/hashivim/vim-terraform)と[vim-terraform-completion](https://github.com/juliosueiras/vim-terraform-completion)があると便利。

### vim-terraform、vim-terraform-completionをinstallする

Vundleからinstall

```vim
" vim-terraform
Plugin 'hashivim/vim-terraform'
let g:terraform_align=1
let g:terraform_fmt_on_save=1

" vim-terraform-completion 
Plugin 'juliosueiras/vim-terraform-completion'
```

```vim
:source %
```
```vim
:PluginInstall
```

詳細設定はそれぞれ参照

- [vim-terraform](https://github.com/hashivim/vim-terraform)
- [vim-terraform-completion](https://github.com/juliosueiras/vim-terraform-completion)

## typescriptのためのplugin

[tsuquyomi]()を利用する。

### tsuquyomiをinstallする

nodeのtypescriptが必要なのでinstallする

```bash
$ npm i -g typescript
```

Vundleからinstallする

```vim
" tsuquyomi
Plugin 'Quramy/tsuquyomi'
```
```vim
:source %
```
```vim
:PluginInstall
```


## golangのためのplugin

[vim-go](https://github.com/fatih/vim-go)を利用する。


### vim-goをinstallする

まずはgolangの環境を整える

amzn2-coreが提供するversionは1.9なので最新の1.13を利用する

```bash
$ sudo rpm --import https://mirror.go-repo.io/centos/RPM-GPG-KEY-GO-REPO
$ curl -s https://mirror.go-repo.io/centos/go-repo.repo | sudo tee /etc/yum.repos.d/go-repo.repo
$ sudo sed -e 's/\$releasever/7/' -i /etc/yum.repos.d/go-repo.repo 
$ sudo yum install -y gcc
$ sudo yum install -y golang --disablerepo=amzn2-core,amzn2extra-golang* --enablerepo=go-repo
```

```bash
$ go version
go version go1.13.5 linux/amd64
```

pathを設定

```bash
export GOPATH=$(go env GOPATH)    # "$HOME/go"
export PATH="$PATH:${GOPATH//://bin:}/bin"
```

`~/.bashrc`に記述するなら 

```bash
$ source ~/.bashrc
```


Vundleからinstallする

```vim
" vim-go
Plugin 'fatih/vim-go'
let g:go_list_type = "quickfix"
let g:go_fmt_command = "goimports"
let g:go_highlight_functions = 1
let g:go_highlight_methods = 1
let g:go_highlight_structs = 1
let g:go_highlight_operators = 1
let g:go_highlight_fields = 1
let g:go_highlight_variable_declarations = 1
let g:go_highlight_variable_assignments = 0
let g:go_highlight_string_spellcheck = 1
let g:go_highlight_types = 1
let g:go_highlight_function_parameters = 1
let g:go_highlight_extra_types = 1
```
```vim
:source %
```
```vim
:PluginInstall
```

GoInstallBinariesを実行する(vim-goが利用するツールをgo get)

```vim
:GoInstallBinaries
```

### tagbarをinstallする

ctagsにgolangがないの[gotags](https://github.com/jstemmer/gotags)を先にinstall

```bash
$ go get -u github.com/jstemmer/gotags
```

Vundleからinstallする

```vim
" tagbar
Plugin 'majutsushi/tagbar'
nmap <F8> :TagbarToggle<CR>
let g:tagbar_type_go = {
        \ 'ctagstype' : 'go',
        \ 'kinds'     : [
                \ 'p:package',
                \ 'i:imports:1',
                \ 'c:constants',
                \ 'v:variables',
                \ 't:types',
                \ 'n:interfaces',
                \ 'w:fields',
                \ 'e:embedded',
                \ 'm:methods',
                \ 'r:constructor',
                \ 'f:functions'
        \ ],
        \ 'sro' : '.',
        \ 'kind2scope' : {
                \ 't' : 'ctype',
                \ 'n' : 'ntype'
        \ },
        \ 'scope2kind' : {
                \ 'ctype' : 't',
                \ 'ntype' : 'n'
        \ },
        \ 'ctagsbin'  : 'gotags',
        \ 'ctagsargs' : '-sort -silent'
\ }
```
```vim
:source %
```
```vim
:PluginInstall
```

`F8`もしくは`:Tagbar`で表示非表示を切り替える

## ansibleのためのplugin
[ansible-vim](https://github.com/pearofducks/ansible-vim)を利用する。


Vundleからinstallする

```vim
" ansible-vim
Plugin 'pearofducks/ansible-vim'
let g:ansible_extra_keywords_highlight = 1
au BufRead,BufNewFile */playbooks/*.yml set filetype=yaml.ansible
```

```vim
:source %
```
```vim
:PluginInstall
```

自動検知されない場合は`:se ft=yaml.ansible`で指定する


# まとめの前
pluginをたくさん紹介したがまだまだ便利なものはたくさんある。`NERDTree`、`fugitive`などなど。ただしpluginをたくさん使用しようしているとそれだけ重くなっていく。不要なもの使わないものは読み込まないように注意する必要がある。

読み込まれているファイルの確認

```vim
:script
```

読み込む時間の確認

```bash
$ vim openfile --startuptime vimuptimelog
```

```
times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.006  000.006: --- VIM STARTING ---
000.140  000.134: Allocated generic buffers
000.218  000.078: locale set
000.222  000.004: window checked
000.624  000.402: inits 1
000.708  000.084: parsing arguments
000.711  000.003: expanding arguments
000.735  000.024: shell init
001.054  000.319: Termcap init
001.074  000.020: inits 2
001.199  000.125: init highlight
001.492  000.036  000.036: sourcing /home/ec2-user/.local/vim/share/vim/vim81/ftoff.vim
002.490  000.787  000.787: sourcing /home/ec2-user/.local/vim/share/vim/vim81/syntax/syncolor.vim
002.605  001.001  000.214: sourcing /home/ec2-user/.local/vim/share/vim/vim81/syntax/synload.vim
008.657  006.010  006.010: sourcing /home/ec2-user/.local/vim/share/vim/vim81/filetype.vim
008.696  007.147  000.136: sourcing /home/ec2-user/.local/vim/share/vim/vim81/syntax/syntax.vim
008.999  000.167  000.167: sourcing /home/ec2-user/.local/vim/share/vim/vim81/syntax/syncolor.vim
009.855  000.172  000.172: sourcing /home/ec2-user/.local/vim/share/vim/vim81/syntax/syncolor.vim
010.124  000.160  000.160: sourcing /home/ec2-user/.local/vim/share/vim/vim81/syntax/syncolor.vim
012.138  003.102  002.770: sourcing /home/ec2-user/.vim/colors/solarized.vim
012.756  000.212  000.212: sourcing /home/ec2-user/.vim/bundle/Vundle.vim/autoload/vundle.vim
012.997  000.152  000.152: sourcing /home/ec2-user/.vim/bundle/Vundle.vim/autoload/vundle/config.vim
015.858  000.015  000.015: sourcing /home/ec2-user/.local/vim/share/vim/vim81/filetype.vim
016.065  000.039  000.039: sourcing /home/ec2-user/.local/vim/share/vim/vim81/ftplugin.vim
016.260  000.034  000.034: sourcing /home/ec2-user/.local/vim/share/vim/vim81/indent.vim
016.340  015.011  004.107: sourcing $HOME/.vimrc
016.344  000.134: sourcing vimrc file(s)
・・・
・・・
406.016  028.532: first screen update
406.019  000.003: --- VIM STARTED ---
```

約400msかかっている


```
078.747  000.002: --- VIM STARTED ---
```

pluginを入れないデフォルトの状態だと78msしか必要としない

# まとめ

インフラのdevopsで便利に利用できるvimのpluginはたくさんある。ただし軽さやシンプルさがあまり犠牲にならないように利用することをおすすめしたい。vimの真髄は操作系だと個人的に思っているので操作がサクサクできる状態を保つ方がcool。