rcmdnk's blog

Vimが好きになる本 (技術の泉シリーズ(NextPublishing))

NeovimではPythonを使ったプラグインがありますが、 そのPythonを仮想環境から呼んでやることも出来ます。

Pythonを使ったプラグインを使う際には pynvim(旧neovim)というパッケージが入っていないと 動かない場合がありエラーが出たりします。

ユーザーの全体環境に入れてしまっても良いのですが、 エラーを吐かずに気づかずに使えてない場合とかもあるので、 できれば初期設定としてどの環境でも同じにしたいところです。

そこで.vimrcの中で仮想環境がなければ作って それを使うようにしてみました。

設定

.vimrcの最初の方に、以下のようなブロックを追加します。

.vimrc
1
2
3
4
5
6
7
8
9
10
11
12
if has('nvim') && !filereadable(expand('~/.vim_no_python'))
  let s:python3 = system('which python3')
  if strlen(s:python3) != 0
    let s:python3_dir = $HOME . '/.vim/python3'
    if ! isdirectory(s:python3_dir)
      call system('python3 -m venv ' . s:python3_dir)
      call system('source ' . s:python3_dir . '/bin/activate && pip install neovim flake8 jedi')
    endif
    let g:python3_host_prog = s:python3_dir . '/bin/python'
    let $PATH = s:python3_dir . '/bin:' . $PATH
  endif
endif

以下各所の説明。

各所の説明

実行するかどうかのチェック

if has('nvim') && !filereadable(expand('~/.vim_no_python'))

Vimでもシンタックスチェックでpipで入れた実行ファイルを使いたい場合とかも ありますが、最近は dotfiles 入れる環境ではすべてNeovimを使ってるので余計なことをしないように、ということで Neovimの場合だけ。

さらに、もしこれを入れたくない環境があったらHOMEに.vim_no_pythonというファイルを 置いておけば無視するようになります。

Python3チェック

let s:python3 = system('which python3')
if strlen(s:python3) != 0

これでpython3が環境にある場合だけ以下を行います。

インストール場所

let s:python3_dir = $HOME . '/.vim/python3'

仮想環境は~/.vim/の下にpython3という名前で作ることにしました。

仮想環境構築

if ! isdirectory(s:python3_dir)
  call system('python3 -m venv ' . s:python3_dir)
  call system('source ' . s:python3_dir . '/bin/activate && pip install neovim flake8 jedi')
endif

仮想環境のディレクトリがない場合、-m venvで新たな仮想環境を作ります。 そして、その環境下にpipで必要なパッケージを入れます。

  call system('source ' . s:python3_dir . '/bin/activate')
  call system('pip install neovim flake8 jedi')

みたいに2つに分けてしまうと、2つ目では仮想環境下ではなくユーザーの通常環境への インストールになってしまうのでまとめて(systemは恐らくサブプロセスを呼ぶだけなのでここで行ったものは維持されない。以下にあるPATHの設定とかもsystemの中でexportとかしても意味が無い)。

仮想環境を使う設定

let g:python3_host_prog = s:python3_dir . '/bin/python'
let $PATH = s:python3_dir . '/bin:' . $PATH

1つ目がPythonを使うモジュールが使うPythonの指定。 g:python3_host_progという値に仮想環境の場所の中のPythonを指定してあげればOK。

2つ目が仮想環境下にインストールされた実行ファイル(flake8とか)を使うための設定。 上の仮想環境を使う設定をしてもPythonを直接呼ぶだけで、いわゆる手元でactivateした状態、とは違って シェルのPATHとかは通らないので、インストールしたコマンドを使いたい場合には この様に別途PATHを通す必要があります。

Environment variables Vim Tips Wiki Fandom

せっかく入れるので最優先で見るように一番前に追加。

チェック

Neovimを立ち上げて:checkhealthコマンドを打ってみると、

## Python 3 provider (optional)
  - INFO: Using: g:python3_host_prog = "/home/user/.vim/python3/bin/python"
  - INFO: Executable: /home/user/.vim/python3/bin/python
  - INFO: Python version: 3.8.5
  - INFO: pynvim version: 0.4.1
  - OK: Latest pynvim is installed.

みたいな感じの部分があるかと思います。 ここできちんとg:python3_host_progが指定されていて、 pynvimのパッケージもちゃんと入っていればOK。

他のコマンド類もちゃんと使えるか、

:echo system('which flake8')

とかしてみて、ちゃんと /home/user/.vim/python3/bin/flake8で見つかればOK。

アップデート方法

この方法で作ると手動でアップデートするか、ディレクトリを一旦消すかしないと 仮想環境がアップデートされません。

たまに手でやってもよいのですが、 普段、Homebrewのパッケージやらなにやらを毎日cronでアップデートしていて、 その中でNeovimのプラグインもアップデートしているので その前にディレクトリを削除して再構築するようにしてみます。

update.sh
1
2
3
4
5
6
7
8
9
if type nvim >& /dev/null;then
  vim_proc=$(pgrep -l -f "nvim -c"|cut -d ' ' -f 1)
  if [ -n "$vim_proc" ];then
    echo "previous nvim -c is still running, kill it."
    kill -kill "$vim_proc"
  fi
  rm -rf ~/.vim/python3
  nvim -c "silent call dein#update()" -c "quit"
fi

こんな感じ。

前半部分はたまにスタックしてしまう場合があったので、 残ってたら強制削除して新たに始めるにするためのもの。

その後で仮想環境を削除して、 プラグインのアップデートを呼んでいます。

プラグインはDeinでやってるのでそのupdateを呼んでいます。

このときにNeovimが立ち上がるのでPythonの仮想環境がインストールされます。

これを適当な時間に

30 12 * * * /path/to/update.sh

みたいに設定して呼んであげればOK(上のは毎日お昼の12:30。ずっと動かしてるサーバーとかなら深夜とか使わない時間にしたほうが良いです。)

Deinの自動インストール

同じ様な初期インストールをDeinに関しても行っています。

まとめ

この辺の初期環境構築に関しては、毎回Vim(Neovim)起動時にチェックすることになるので、 別の仕組みで行った方が良いとは思います。

ただ、最初の構築時に数秒かかる程度で、一回作ってしまえばほとんど負荷はかかりません。 それを全部.vimrcの中で出来てしまうならそれで良いかな、という感じ。

アップデートに関しても、適当なタイムスタンプ付けたファイルを作っておいて、 それ見ながらもし期限切れになってたら再構築、 みたいなことを.vimrcの中でやっても良いかな、とも思いましたが、 それはやりすぎかな、というのと、 上の様に別のところで毎日動かしてるcronがあるのでそれに乗ったほうが良いな、という感じです。

ちなみにPython2に関しては作ってないです。 大概のプラグインがPython3があればそちらを使うのでなくても問題がないので。 あと、Python2だとpip install virtualenvする必要があったりひと手間かかるので。 今後消えゆくPython2は無理に入れる必要はないかな、と。

Sponsored Links
Sponsored Links

« GitHub Actions使うWindows環境にリモートデスクトップアクセスする Vimのプラグイン管理dein.vimでの{'merged': 0} »