LoginSignup
3
0

More than 3 years have passed since last update.

pythonでvim pluginを書く時にファイル分割する

Posted at

背景

Pythonでvim pluginを書く

上記リンクの記事を参考にVim(Neovim)のpluginを作っています。
Pythonファイルが大きくなり分割しようとしたところ、少しつまずいたので解決法を共有します。

この記事では、例としてrequestsモジュールを用いてWebページのタイトルを表示するプラグインを作ってみます。

ディレクトリ構成とファイルの中身

sample-vim-plugin
  plugin/
    sample_vim_plugin.vim
  src/
    sample_vim_plugin.py
    requests_caller.py
plugin/sample_vim_plugin.vim
scriptencoding utf-8

if exists('g:loaded_sample_vim_plugin')
    finish
endif
let g:loaded_sample_vim_plugin = 1

let s:save_cpo = &cpo
set cpo&vim

py3file <sfile>:h:h/src/sample_vim_plugin.py

function! sample_vim_plugin#print_title(url)
    py3 sample_vim_plugin_print_title(vim.eval('a:url'))
endfunction

let &cpo = s:save_cpo
unlet s:save_cpo
src/sample_vim_plugin.py
import vim
import requests_caller

def sample_vim_plugin_print_title(url):
    print(requests_caller.get_title(url))
requests_caller.py
import requests
from bs4 import BeautifulSoup

def get_title(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'lxml')
    return soup.title.text

私はdeinでプラグインを管理しているので、tomlファイルに上記のプラグインを追加しneovimを起動すると
ModuleNotFoundError: No module named 'requests_caller'
と言われます。

このモジュール見つからない問題を解決したいと思います。

「Python における 'runtimepath' の処理」

Python では、'runtimepath' のパスのリストを使う代わりに、vim.VIM_SPECIAL_PATH
という特別なディレクトリが使われます。このディレクトリが sys.path 内で使われる
とき、そして vim.path_hooks が sys.path_hooks 内で使われるとき、'runtimepath'
の各パス {rtp} に対して {rtp}/python2 (or python3) と {rtp}/pythonx (両バー
ジョンで読み込まれる) のモジュールがロードされます。

とあります。

よって、二つの方法が考えられます。

解決法1: ディレクトリの名前を変更する

runtimepathの直下にpython2,python3,pythonxのディレクトリがあればロードされるとのことなので、srcディレクトリをpython3にリネームします。
当然読み込む部分を変える必要があるので、下記のように変更します

plugin/sample_vim_plugin.vim
- py3file <sfile>:h:h/src/sample_vim_plugin.py
+ py3file <sfile>:h:h/python3/sample_vim_plugin.py

解決法2: sys.pathに追加する

ディレクトリの名前を変えたくない場合は、直接sys.pathに追加します。

plugin/sample_vim_plugin.vim
+ let s:sample_vim_plugin_root_dir = expand('<sfile>:p:h:h')
  py3file <sfile>:h:h/src/sample_vim_plugin.py
src/sample_vim_plugin.py
  import vim
+ import sys
+ import os
+ plugin_python_dir = os.path.join(vim.eval('s:sample_vim_plugin_root_dir'), 'src')
+ sys.path.append(plugin_python_dir)
  import requests_caller

まとめ

  • python2, python3, pythonxディレクトリにPythonファイルを置く
  • sys.pathにPythonファイルをおいたディレクトリを追加する

という二つの方法でプラグインが動くようになります。

有名どころで言うと、davidhalter/jedi-vimでは解決法1(pythonx)を使っているみたいです。
ソースコードをチラ見しただけですが、Shougo/denite.nvimShougo/deoplete.nvimでは解決法2を使っているように見えます。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0