🙆‍♀️

オレオレneovim環境構築&設定

2021/12/13に公開

オレオレneovim環境構築&設定

TSG Advent Calendar 2021の13日目の記事です。

自己紹介

教養過程1年の2lu3と申します。

WindowsとUbuntu、Linux Mintでneovimを使っているneovim初心者です。

概要

  • neovimの環境構築をUbuntuで行う
    • windowsの環境構築は最近やってないから覚えていない
    • さらに、他に良い記事がたくさんある
    • さらに、windowsのほうが導入が簡単
    • なのでUbuntuのみです
  • UbuntuとWindowsで設定の共有をするためのTips

キーワード

neovim, ubuntu20.04, dein, coc, c++, python

環境構築

linuxbrew

まず、linuxbrewをインストールするとよいです。aptではインストールできない最新版を簡単にインストールできます。さらに、linuxbrewならインストールするのにsudo権限を必要としないので、大学のサーバーの中の自分のアカウントでneovimをインストールするときも同様の手順で行なえます。

homebrewのHPに書いてあるとおり、下のようにターミナルで実行します。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

次に、pathを通したりする作業が必要になります。こちらは、Homebrew on Linuxのページに書いてあるように、下のコマンドを実行します。

test -d ~/.linuxbrew && eval "$(~/.linuxbrew/bin/brew shellenv)"
test -d /home/linuxbrew/.linuxbrew && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
test -r ~/.bash_profile && echo "eval \"\$($(brew --prefix)/bin/brew shellenv)\"" >>~/.bash_profile
echo "eval \"\$($(brew --prefix)/bin/brew shellenv)\"" >>~/.profile

もし、上のコマンドを実行した結果、~/.bash_profile~/.profileが両方存在している場合、要注意です。詳しくは触れませんが、両者が存在するときの挙動をよく理解していない場合、どちらか一つに統合し、いらない方を削除すべきです。私の場合、~/.bashrc~/.profileのみ存在しています。以下、私の環境を前提に書いていきます。適宜読み替えてください。

source ~/.profile

または

source ~/.bash_profile

を実行して上のコマンドで変更した内容を反映させます。

ここまできたら、

brew --version

と実行し、バージョン情報が帰ってきたらOKです。

次のステップに進みましょう。

neovim

brewをインストールしているなら、

brew install neovim

だけでOKです。

次に、neovimのプラグインを入れる上で必要になることが多いpythonnodejsをインストールしていきます。

python

pythonの環境構築で重要なのは2つあります。

一つは、pythonのバージョン(3.7.3や3.8.10など)です。pythonはバージョンによって使える文法が違います。バージョンを手軽に変更するために、pyenv, anacondaなど複数の管理システムが存在します。

もう1つは、仮想環境です。これは、同じpythonのバージョンでも、pipでインストールするパッケージの組み合わせがプロジェクトによって違う場合に便利です。こちらも、venv, virtual venv, pipenvなどが存在します。

注意点として、両方の機能を持った管理システムも存在します。anacondaなどがその例です。

私の場合、pyenvでバージョンを管理し、pipenvで仮想環境を管理しています。

それでは、まず、pyenvからインストールします。

brew install pyenv

pathを通したりするのに、下のコマンドを実行しましょう。

echo 'eval "$(pyenv init --path)"' >>~/.profile
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
source ~/.profile
source ~/.bashrc
pyenv install -l

すると、pyenvがインストール可能なバージョンがたくさん出てきたと思います。

この中で、普段使いするpythonのバージョンを選びましょう。私の場合、3.8.12にしています。

では、早速3.8.12をインストールしてみましょう。

pyenv install 3.8.12

結構時間がかかるので気長に待ちましょう。

インストールできたら、このバージョンをデフォルトで使うよ!と宣言するために下のコマンドを実行します。

pyenv global 3.8.12

この状態で、

python --version

をすると、3.8.12であることが確認できると思います。

次に、pipenvのインストールです。公式ドキュメントには、pip install pipenvとすることを推奨されているのですが、私はあえてbrewでインストールしています。

brew install pipenv

pipenvはデフォルトではある1つのフォルダにすべての仮想環境がまとめられているのですが、フォルダ名の中に乱数が入っているのでこのあとneovimにpythonのpathを伝えるのに不便です。これは、別のデバイスでは乱数の数字が変わるため、デバイスが変わるたびにpythonのpathを編集する必要があるためです。そのため、下のコマンドを実行して、仮想環境をそのフォルダの下に作るようにしましょう。

echo 'export PIPENV_VENV_IN_PROJECT=true' >> ~/.bashrc
source ~/.bashrc

ここで、適切な場所でneovim用の仮想環境を作りましょう。

私の場合、~/python_envs/nvimというディレクトリを作って、その中で

pipenv install pynvim

とすることで、仮想環境を作り、neovimに必要なpythonパッケージであるpynvimをインストールしています。

この場合、neovimに渡すpythonのpathは、~/python_envs/nvim/.venv/bin/pythonとなっています。

node

brewでnodebrewをインストールしてさらにnodeをインストールします。

なぜ、こんなことをと思われた方は、何でHomebrewからじゃなくNodebrewでNode.jsのバージョン管理するのかを読まれるとよいでしょう。

インストールのやり方は、MacにNode.jsをインストールを参考にしてください。Macと書いてありますが、Ubuntuでも同じ手順でできます。

anyenv+nodenvで環境構築するやり方を記事内でおすすめされていますが、少なくともしばらくの間はnodeをバージョン管理することがないので、必要になったら環境構築をやり直すつもりです。

nodeをインストールできたら、

source ~/.bash_profile
npm install -g neovim

を実行してください。

dein

deinは、neovimのプラグインを管理することができます。

curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
# For example, we just use `~/.cache/dein` as installation directory
sh ./installer.sh ~/.cache/dein

を実行しましょう。

また、vim側の設定ファイルにも記載する必要があるのですが、それは後述します。

設定ファイル ~ .vim系 ~

上で、必要なものはインストールできました。これから、設定をいろいろ記載していきましょう。

設定ファイルは、~/.config/nvimというディレクトリを作ってその中に入れましょう。neovimは、~/.vimrcまたは~/.config/nvim/init.vimをデフォルトで読みます。(それ以外もあると思いますが、調べていません)

~/.config/nvim/init.vim

if &compatible
  set nocompatible
endif

" 外部設定ファイルの読み込み
runtime! options.vim
runtime! keymap.vim

" neovim用pythonの設定
" pip install pynvim
if has('win64')
    let g:python3_dir = 'C:\Users\tlaloc\python_envs\nvim\.venv\Scripts\'
    let g:python3_host_prog=g:python3_dir . 'python.exe'
elseif has("unix")
    let g:python3_dir = '~/python_envs/nvim/.venv/bin/'
    let g:python3_host_prog= g:python3_dir . 'python'
endif

" dein関係
"
let g:dein#auto_recache=1

set runtimepath+=~/.cache/dein/repos/github.com/Shougo/dein.vim

let s:watch_files = ['~/.config/nvim/init.vim', '~/.config/nvim/dein.toml', '~/.config/nvim/dein_lazy.toml']

if dein#load_state('~/.cache/dein')
  call dein#begin('~/.cache/dein', s:watch_files)

  call dein#load_toml('~/.config/nvim/dein.toml', {'lazy': 0})
  call dein#load_toml('~/.config/nvim/dein_lazy.toml', {'lazy': 1})

  call dein#end()
  call dein#save_state()
endif

if dein#check_install()
  call dein#install()
endif

syntax enable

順番に説明していきます。

if &compatible
  set nocompatible
endif

はvi互換モードを抑制するみたいな感じです。あまり良くわかっていないし、理解しないといけないほど初心者にとって重要なものでもないと思うのでのでおまじないと考えています。

" 外部設定ファイルを読み込む
runtime! options.vim
runtime! keymap.vim

init.vim以外のファイルを読み込んでいます。これは、optiopns.rc.vimなどがinit.vimなどのデフォルトで読み込まれるファイル名ではないからです。

また、15~17行目で、不足しているプラグインがあったら、自動でインストールしています。

" neovim用pythonの設定
" pip install pynvim
if has('win64')
    let g:python3_dir = 'C:\Users\tlaloc\python_envs\nvim\.venv\Scripts\'
    let g:python3_host_prog=g:python3_dir . 'python.exe'
elseif has("unix")
    let g:python3_dir = '~/python_envs/nvim/.venv/bin/'
    let g:python3_host_prog= g:python3_dir . 'python'
endif

ここで、さきほとインストールしたpythonの場所をneovimに教えています。インストールした場所が違う場合、適宜変更してください。上がwindows用、下がlinux用です。windowsはユーザー名ベタ書きなので注意してください。

" dein関係
set runtimepath+=~/.cache/dein/repos/github.com/Shougo/dein.vim

if dein#load_state('~/.cache/dein')
  call dein#begin('~/.cache/dein')

  call dein#add('~/.cache/dein/repos/github.com/Shougo/dein.vim')
  call dein#load_toml('~/.config/nvim/dein.toml', {'lazy': 0})
  call dein#load_toml('~/.config/nvim/dein_lazy.toml', {'lazy': 1})

  call dein#end()
  call dein#save_state()
endif

if dein#check_install()
  call dein#install()
endif

ここは、deinを使うためのおまじないと考えても良いですが、少しだけ触れておきます。8行目と9行目は、あとで説明するdein.tomldein_lazy.tomlload_tomlしています。ここで、lazyがそれぞれ0と1になっています。lazyは読み込みするときのタイミングを指定しています。詳しくは後述します。

~/.config/nvim/options.vim

" ######################## 見た目 ########################
set termguicolors " True Color対応
set title " ターミナルのタブ名に現在編集中のファイル名を設定
set number " 行番号を表示する
set wrap " 行を折り返す
set showmatch " 括弧入力時の対応する括弧を表示
set list "不可視文字の可視化
set listchars=tab:»-,trail:-,extends:»,precedes:«,nbsp:%,eol:" デフォルト不可視文字は美しくないのでUnicodeできれいに
set matchtime=3 " 対応括弧のハイライト表示を3sにする

" ######################## 検索・置換 ########################

set ignorecase " 大文字小文字の区別なく検索する
set smartcase " 検索文字列に大文字が含まれている場合は区別して検索する
set wrapscan " 検索時に最後まで行ったら最初に戻る
set hlsearch " 検索語をハイライト表示
set incsearch " 検索文字列入力時に順次対象文字列にヒットさせる
set inccommand=split " インタラクティブに変更

" ######################## インデント ########################
set smartindent " オートインデント
set expandtab " softtabstop や shiftwidth で設定されている値分のスペースが挿入されたときに、挿入されたスペース数が tabstop に達してもタブに変換されない
set tabstop=4 " スペースn個分で1つのタブとしてカウントするか
set softtabstop=4 " <tab>を押したとき、n個のスペースを挿入
set shiftwidth=4 " <Enter>や<<, >>などを押したとき、n個のスペースを挿入

" ######################## 補完 ########################
set wildmode=list:longest " コマンドラインの補完
set infercase " 補完時に大文字小文字を区別しない
set wildmenu "コマンドの補完を有効に
au FileType * setlocal formatoptions-=ro " 自動コメント挿入を回避

" ######################## 操作 ########################
set clipboard+=unnamedplus " クリップボードにコピーする
set backspace=indent,eol,start " backspaceで様々な文字を消せるようにした
set hidden
set textwidth=0 "自動改行する文字数

" ######################## ログ ########################
set history=5000 "保持するコマンド履歴の数
set noswapfile " swapファイルを保存しない
set noundofile " undoファイルを保存しない
set nobackup " backupを保存しない
set nowritebackup "writebackupを保存しない
set viminfo= " viminfoファイルに保存しない

" ######################## その他 ########################
filetype plugin indent on " ファイルタイプの検索とプラグインをONにする
set encoding=utf-8 " 文字コード

コメントに書いてあるとおりです。いろんなオプションを分類するのって難しいですよね。

~/.config/nvim/keymap.vim

" leaderを,に変更
let mapleader = "\<Space>"

" 入力モード中に素早くjjと入力した場合はESCとみなす
inoremap <silent> jj <Esc>:<C-u>w<CR>
" 同上を日本語でも打てるように
inoremap <silent> っj <Esc>:<C-u>w<CR>

" ESCを2回押すことでハイライトを消す
nmap <silent> <Esc><Esc> :nohlsearch<CR>

" ##### 日本語用 #####
nnoremap あ a
nnoremap い i
nnoremap う u
nnoremap お o
nnoremap っd dd
nnoremap っy yy

" ##### ウィンドウ操作系 #####
nnoremap <silent> <Leader>v :vs<CR>
nnoremap <silent> <Leader>s :sp<CR>
nnoremap <silent> <Leader>h <C-w>h
nnoremap <silent> <Leader>j <C-w>j
nnoremap <silent> <Leader>k <C-w>k
nnoremap <silent> <Leader>l <C-w>l
nnoremap <silent> <Leader><C-w>h
nnoremap <silent> <Leader><C-w>j
nnoremap <silent> <Leader><C-w>k
nnoremap <silent> <Leader><C-w>l

" ##### 行・列関係 #####
nnoremap j gj
nnoremap k gk
vnoremap j gj
vnoremap k gk
inoremap <C-j> <Down>
inoremap <C-k> <Up>
inoremap <C-h> <Left>
inoremap <C-l> <Right>

" 補完
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<S-TAB>"

一番上のmapleaderはneovimにおいて非常に重要なキーです。私は、押しやすいスペースキーを割り当てていますが、自分の好きな使いやすいキーを割り当てれば良いと思います。

その次の、jjはneovimならほとんどの方が設定されています。insertモードからnormalモードに戻ります。私の場合、同時にファイルの内容を保存するようにしています。

また、使うことはあまりないのですが日本語を入力してもいくつかのキーは反応するようにしています。正直、なくても良いです。

また、ウィンドウ操作は画面分割をするときに便利です。私の場合、<Leader>はスペースなので、<Leader>を別のキーにされている方はspaceを適宜読み替えてください。

コマンド 内容
space+v 左右に画面分割
space+s 上下に画面分割
space+h 左の画面に移動
space+j 下の画面に移動
space+k 上の画面に移動
space+l 右の画面に移動
nnoremap j gj
nnoremap k gk
vnoremap j gj
vnoremap k gk

ここでは、本当は1行だが画面の制約上2行として表示されている場合についての動作をカスタマイズしています。もともとのhjklの設定では、このような状況では画面上では2行となっていても1行であるとしてカーソル移動を行います。しかし、それは人間が見た画面上での動きとしてわかりにくいので、折り返しで2行として表示されている場合、実際は1行でも画面上の1行目と2行目をjkで移動できるようにしています。

inoremap <C-j> <Down>
inoremap <C-k> <Up>
inoremap <C-h> <Left>
inoremap <C-l> <Right>

これは設定だけして使い忘れていますが、insertモードでコントロールボタンを押しながらhjklすれば矢印キーが入力されます。

inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<S-TAB>"

この行は、補完をつかったときにtabキーで次の候補に、shift+tabで前の候補に選択を移動させるkeymapです。

設定 ~ dein系 ~

ここからは、deinの設定ファイルについて書いていきます。

細かい文法の説明は他のサイトに譲るとして、注意点をいくつか。

  • source ~系では、追加の設定ファイルを読み込んでいる
    • しかし、キーマップに関する設定がほとんどで、洗練させたキーマップとは言い難いし、淡々と説明するのが苦痛すぎるので解説しません
    • どうしても知りたい場合は、私の設定レポジトリを参考にしてください
  • hook_addとhook_sourceどちらを使うか, deinとdein_lazyの使い分けは、私自身これがベストなのか判断が付きません(betterではあるはず)。他の詳しい方のサイトをご覧になったようが良いと思います。

~/.config/nvim/dein.toml

# [dein.toml]
[[plugins]]
repo = 'Shougo/dein.vim'

#################### ファイル検索 #################### 

# fzf-preview
# ripgrepをインストールするべし
[[plugins]]
repo = 'yuki-yano/fzf-preview.vim'
rev = 'release/rpc'
depends=['junegunn/fzf']
hook_add= '''
source ~/.config/nvim/plugins/fzf-preview.vim
'''

[[plugins]]
repo = 'junegunn/fzf'
build = './install --all'
merged = 0

#################### 見た目 #################### 

# インデントに線を表示する
[[plugins]]
repo = 'Yggdroot/indentLine'

# ---------- Vim Airline ---------- 
[[plugins]]
repo = 'vim-airline/vim-airline'
hook_add = '''
source ~/.config/nvim/plugins/vim-airline.vim
'''

# vim-airlineのテーマ
[[plugins]]
repo = 'vim-airline/vim-airline-themes'


#################### Git #################### 
# Gitコマンドを使用する
[[plugins]]
repo = 'tpope/vim-fugitive'
hook_add = '''
nnoremap <silent> gs :Git status<CR>
nnoremap <silent> gps :Git push<CR>
nnoremap <silent> gpl :Git pull<CR>
nnoremap <silent> gc :Git commit<CR>
'''

# show add/delete sign to left
[[plugins]]
repo = 'airblade/vim-gitgutter'

# #################### Uncategorized ###################

# 対となる括弧を追加/削除する
[[plugins]]
repo = 'jiangmiao/auto-pairs'

# coc
[[plugins]]
repo = 'neoclide/coc.nvim'
merged = 0
rev = 'release'
hook_add = '''
source ~/.config/nvim/plugins/coc.vim
'''

#################### 画像生成 #################### 

# ソースコードをいい感じの画像にしてくれる
[[plugins]]
repo = 'skanehira/denops-germanium.vim'
depends = ['denops.vim']
hook_add = '''
nnoremap <Leader>pic :Germanium<CR>
vnoremap <Leader>pic :Germanium<CR>
'''

[[plugins]]
repo = 'vim-denops/denops.vim'

インストールしているプラグインを順番に説明していきます。

  • dein

プラグインマネージャーです。deindein自身を管理しています。

  • fzf-preview

こんな感じで、ファイルをfuzzy検索して開けるようになる。このプラグインを使う場合、

brew install ripgrep

するとよい。

  • indentLine

インデントに縦の線を書いてくれます。

  • vim-airline

ステータスバーをかっこよくしてくれる。

  • vim-fugitive

vimのコマンドでgitの操作が出来る。

  • vim-gitgutter

差分(前回のcommitから追加したか削除したか)を左側に表示してくれる

  • auto-pairs

カッコを自動補完

  • coc

様々な言語の補完とかを設定してくれる。

例えば、pythonなら、:CocInstall coc-pyrightとするとpython用のLanguage Serverをインストールしてくれる。

  • denops-germanium

ソースコードをかっこいい画像にしてくれる。

~/.config/nvim/dein_lazy.toml

# [dein_lazy.toml]


# hook_add : deinによってプラグインが認識されたとき
# hook_source : プラグインを読み込む直前に
# hook_post_source : プラグインを読み込んだ直後


# on_i : インサートモードに入ったら読み込む
# on_ft : 特定のファイルタイプで読み込む
# on_func : 関数が事項されるときにロード
# on_event :  イベントが実行されるときにロード
# on_cmd : 

#################### エクスプローラー #################### 

# ファイルツリーを表示
[[plugins]]
repo = 'scrooloose/nerdtree'
depends = ['ryanoasis/vim-devicons']
on_event='NERDTreeToggle'
hook_add='''
nnoremap <silent> <Leader>e :NERDTreeToggle<CR>
'''

# file icon for filetree
[[plugins]]
repo = 'ryanoasis/vim-devicons'
on_source='nerdtree'


#################### 画面サイズ変更 #################### 

# ウィンドウの分割サイズを変更
[[plugins]]
repo = 'simeji/winresizer'
on_event='WinResizerStartResize'
hook_add='''
nnoremap <Leader>r :WinResizerStartResize<CR>
'''
#################### Quick Run #################### 

# vimを閉じずに編集中のファイルを素早く実行する
[[plugins]]
repo = 'thinca/vim-quickrun'
hook_add = '''
source ~/.config/nvim/plugins/vim-quickrun.vim
'''

# quick runに必要なライブラリ(非同期処理)
[[plugins]]
repo = 'Shougo/vimproc.vim'

#################### 言語ごとの設定 #################### 

# ---------- c++ ---------- 
[[plugins]]
repo = 'vim-scripts/DoxygenToolkit.vim'
on_ft = ['c', 'cpp']
hook_add = '''
nmap <leader>dox :Dox<CR>
'''

# ---------- Python ---------- 
[[plugins]]
repo = 'heavenshell/vim-pydocstring'
build='make install'
on_ft = ['python']
hook_add= '''
source ~/.config/nvim/plugins/vim-pydocstring.vim
'''

# ---------- TOML ---------- 
[[plugins]]
repo = 'cespare/vim-toml'
on_ft = ['toml']


# ---------- WEB ---------- 

# カッコを自動で補完
[[plugins]]
repo = 'alvan/vim-closetag'
on_ft = ['js', 'html']
hook_add = '''
source ~/.config/nvim/plugins/vim-closetag.vim
'''
  • nerdtree

左側にエクスプローラーもどきを開くことが出来る。fzf入れてからは余り使わない。

  • winresizer

左右・上下分割したときに、左と右のスペースを変更することが出来る。たまに、横幅が短いソースコードと長いソースコードを左右で分割して開くときに使う。

  • vim-quickrun

わざわざターミナル戻ってそのソースコードを実行するのが面倒くさいときに使う。pythonでやることが多い。

  • DoxygenToolkit

doxygenという形式のコメントを自動挿入できる。

  • vim-pydocstring

上のpythonバージョン

  • vim-toml

tomlファイルのsyntax highlight

  • vim-closetag

閉じる方のタグを自動で入れてくれる。

終わりに

以上が、私の現在のneovim設定です。こうしたほうが良い等あればコメント等で教えていただけると嬉しいです。

Discussion