neovimのプラグインをpythonで作る

## 概要
neovimのプラグインが、pythonでコーディングできるということなので、試してみる

## 環境
- mac
- python3

## インストール
```
brew install neovim
pip3 install neovim
```

## プラグインの作成
### ファイルの作成場所

neovimのruntimepathフォルダー以下の、rplugin/python3/にpythonファイルを作成する

自分の場合
~/.config/nvim/rplugin/python3/test_plugin.py
を作成した

> Neovim allows python3 plugins to be defined by placing python files or packages in rplugin/python3/ (in a runtimepath folder). Python2 rplugins are also supported and placed in rplugin/python/, but are considered deprecated.
> 引用先: https://github.com/neovim/python-client#remote-new-style-plugins

### ファイルの内容
公式のサンプルをコピペ

```python:test_plugin.py
import neovim

@neovim.plugin
class TestPlugin(object):

    def __init__(self, nvim):
        self.nvim = nvim

    @neovim.function("TestFunction", sync=True)
    def testfunction(self, args):
        return 3

    @neovim.command("TestCommand", range='', nargs='*')
    def testcommand(self, args, range):
        self.nvim.current.line = ('Command with args: {}, range: {}'
                                  .format(args, range))

    @neovim.autocmd('BufEnter', pattern='*.py', eval='expand("<afile>")', sync=True)
    def on_bufenter(self, filename):
        self.nvim.out_write("testplugin is in " + filename + "\n")
```

### プラグインの登録
vimのコマンドラインモードで、下記を実行

```
:UpdateRemotePlugins
```
* vimの再起動が必要かも

<img width="1668" alt="スクリーンショット 2018-04-04 14.02.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/18761/2843d4bb-9d55-2d09-10bd-55a851b3dd98.png">

### プラグインが登録されているか確認

~/.local/share/nvim/rplugin.vim を調べて、作成したプラグインが登録されているかを確認

<img width="1668" alt="スクリーンショット 2018-04-04 14.05.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/18761/2c1d31cf-de67-a16f-856a-61b7892acfde.png">

### 実行

とりあえず、TestFunctionとTestCommandを試してみる
![test.gif](https://qiita-image-store.s3.amazonaws.com/0/18761/608933a0-8f01-65f2-daa3-2d55f1ee3e10.gif)

## 自作プラグイン

pythonの強力なライブラリを使ったコマンドが一瞬でできそうなので、とりあえず作成してみる。
コマンドは、testcommand関数を応用して作っていきます。

```python:testcommand
@neovim.command("TestCommand", range='', nargs='*')
    def testcommand(self, args, range):
        self.nvim.current.line = ('Command with args: {}, range: {}'
                                  .format(args, range))
```

今回のコマンドの処理内容は下記の感じ
1. 前提として、ある文書をyankして、clipboardに挿入
2. コマンドを実行し、clipboardに存在する文書を形態素解析して、各形態素とその頻度を計算
3. 現在のカーソルの位置から、頻度を降順に並び替えて、paste

ちょっと、形態素解析のところが適当に書かれてるのですが、大目に見て下さい ><

### 事前準備
- pythonでmecabを使う
    - https://qiita.com/grachro/items/4fbc9bf8174c5abb7bdd
- pyperclipのinstall

```python
import neovim
import pyperclip
import subprocess
import sys
import MeCab
from collections import Counter

@neovim.plugin
class TestPlugin(object):

    def __init__(self, nvim):
        self.nvim = nvim

    @neovim.function("TestFunction", sync=True)
    def testfunction(self, args):
        return 3

    @neovim.command("TestCommand", range='', nargs='*')
    def testcommand(self, args, range):
        self.nvim.current.line = ('Command with args: {}, range: {}'
                                  .format(args, range))

    @neovim.autocmd('BufEnter', pattern='*.py', eval='expand("<afile>")', sync=True)
    def on_bufenter(self, filename):
        self.nvim.out_write("testplugin is in " + filename + "\n")

    @neovim.command("WordCount", range='', nargs='*')
    def wordcountcommand(self, args, range):
        m = MeCab.Tagger("-Ochasen")

        # クリップボードから文書を取得
        sentence = pyperclip.paste()

        # 形態素解析
        out = "\n".join([
            w+"\t"+str(cnt) \
            for w, cnt in \
                Counter([
                    l.split("\t")[0] for l in m.parse(sentence).strip().split("\n")
                ]).most_common()
        ])

        # クリップボードへ挿入
        pyperclip.copy(out)

        # クリップボードからpaste
        self.nvim.command("put")
```
### 自作プラグインの登録
vimのコマンドラインモードで、下記を実行

```
:UpdateRemotePlugins
```
* vimの再起動が必要かも

### 自作プラグインの実行
wikipediaから「オアシス」の概要をコピーしてきて、形態素解析をかけてみました。

![wordcount2.gif](https://qiita-image-store.s3.amazonaws.com/0/18761/326e0b08-2b40-fee8-f3b5-36d36e36c364.gif)

## 感想
強力なツールのvim ✖️強力なpythonのライブラリ = 無限大の幸せ 笑
世の中には、人の時間を大量に搾取する恐ろしい問題がたくさんあるので、適当にプラグインを作っていきながら戦っていきたいですねー

## 参考文献
- python clientのgithub
    - https://github.com/neovim/python-client/
- neovimのプラグインの作成方法を書いている、まとまっている資料
    - https://github.com/jacobsimpson/nvim-example-python-plugin
- めちゃんこ助けられたissue
    - 忘れた、思い出したら貼る