Joplin用のddu.vim sourceとkindプラグインを作りました

まとめ

ノートアプリであるJoplinのノートやフォルダをVim/NeoVimから操作できるようにするためのddu.vimのsource/kindプラグインを作りました。 github.com github.com

経緯と今後

普段、僕は技術的なメモや記録をJoplinというノートアプリに書いて保存しています。

一方でコーディングにはNeovimを使っているため、コーディング中にメモを取りたいときにはJoplinのウィンドウにわざわざ移動しなければならず面倒なことやNeoVimの様々なショートカットが利用できないことが不満点でした。 調べたところVimからJoplinを使うためのプラグインもあることにはありましたがIssuesが放置されていることやPython3拡張に依存しているなどから選択しませんでした。

github.com

そこで、自作することを決め、去年話題になっていたDenopsとTypeScript製のJoplinのAPIクライアントを使って自分でも素朴にJoplinのノートを編集するためのプラグイン開発に挑戦しました。しかし、UI表示などの実装が自分の知識と技術レベルでは難しく途中で断念していました。

しばらく開発を放置していましたがddu.vimを知り、ddu.vimフレームワークとして使うことでVim/NeovimからJoplinのノートを閲覧、編集したいという目的を UIや候補絞りこみの実装を避けて達成できそうと考えました。 ddu.vimはui, source, filter,kindという機能に分離されており、それぞれを独立してユーザが選択して利用および開発できます。ddu.vimの詳しい機能は、 新世代の UI 作成プラグイン ddu.vim をご参照ください。

その結果、開発したプラグインが冒頭でも紹介したddu-source-joplinとddu-kind-joplinです。 当初は、ddu-source-joplinにkindプラグインも含めてしまっていたのですが、sourceとkindで結合しているのは良くないと思い途中からリポジトリを分離しました。

ddu-source-joplinでは、以下の2種類のsourceを提供しています。

  • joplin: ノート/TODOの一覧用
  • joplin_tree: 通常のファイラと同様にツリー形式のサポート用

ddu-kind-joplinはJoplin専用のkindです。アイテムアクションは現在のところnewNote/newTodo/newFolder/delete/renameをサポートしており開発中ではありますが基本的な操作は行えると思います。 また、開いたノートは通常のファイル編集時と同様に:wで保存するための実装もkindに含めています。

ノートの移動やTODOの完了、未完了状態を更新するためのアクションは現時点では未実装ですが、今後追加していく予定です。 未実装のアクションに関しては、Joplinのアプリ本体で操作してください。

サンプルとして、筆者が現在使っている設定を紹介します。 ,jによるノート/TODOの一覧表示や,kでのカーソル下の単語での検索はフォルダは一覧されていなくてもいいので一覧表示用のsourceを使っています。 ツリー表示は、フォルダの新規作成や実装予定のノート移動で使うため,tマッピングしました。

joplin_tree sourceのsourceOptionsでカラムにfilenameを指定していますが、将来的に専用のcolumnプラグインを開発予定です。 開発が必要な理由は、JoplinではノートやTODOごとに固有のidによって管理されているため一般的にファイル名として使われない/のような文字もタイトルに利用でき、ノートタイトルに/が入った場合にfilenameをカラムとして使っていると/の後しか表示されなくなってしまうことやTODOの状態が表示できないためです。

call ddu#custom#patch_global(#{
    \   sourceParams: #{
    \     joplin: #{
    \       token: $JOPLIN_TOKEN,
    \       fullPath: v:true
    \     },
    \     joplin_tree: #{
    \       token: $JOPLIN_TOKEN,
    \     },
    \   },
    \   kindOptions: #{
    \     joplin: #{
    \       defaultAction: 'open',
    \     },
    \   },
    \   sourceOptions: {
    \     'joplin_tree': #{
    \       columns: ['filename'],
    \     },
    \   },
    \ })

" 全てのノート/TODOのタイトル、本文をカーソル下の単語で検索した結果を一覧表示
nmap <silent> ,k <Cmd>call ddu#start(#{
    \       ui: 'ff',
    \       name: 'joplin',
    \       sources: [
    \           { 'name': 'joplin', 'params': { 'input': expand('<cword>') } }
    \       ]
    \   }
    \   )<CR>
" 全てのノート/TODOを一覧表示
nmap <silent> ,j <Cmd>call ddu#start(#{
    \   ui: 'ff',
    \   name: 'joplin',
    \   sources: [
    \       #{ name: 'joplin' },
    \   ],
    \   })<CR>
" フォルダ/ノート/TODOをツリー表示
nmap <silent> ,t <Cmd>call ddu#start(#{
    \   ui: 'filer',
    \   name: 'joplin_tree',
    \   sources: [
    \       #{ name: 'joplin_tree' },
    \   ],
    \   })<CR>

最後に、実際にノート/TODO一覧を表示した時のスクリーンショットを貼って終わります。

joplin sourceでの一覧表示
joplin_treeでのツリー表示