Neovimのconfigファイルをinit.lua化したので覚書

by
カテゴリ:
タグ:

Neovim 0.5からはconfigファイルにinit.luaとしてLuaスクリプトでの記述を推奨しているそうです。

以下の記事でそれを知り、丁度、設定を詰め始めた頃だったこともあり、init.vimからinit.luaへの移行を決断しました。

[第2回] Neovimのすゝめ – 設定ファイルを作成する by won won eaterさん

本記事ではVim/Nvim初心者がどうやって情報を収集したか、途中で得た知見、やり残したことをまとめておきます。

困った時は

Lua言語はちょっとやったことあるものの、Vim言語はコピペのみ、内部設計的なところも知らない私には色々困るところだらけです。

init.lua入門系記事

日本語で書かれた入門記事の類は非常に心強いですね。私が参考にしたものの内、内容が軽いものから順に掲載します。

help

公式のヘルプは心強い存在です。間違った情報に出会う確率も低いはず。

Nvim特有の話はnvim上で検索しなければなりませんが、Vimと共通する部分は日本語の情報も豊富です。

help - Vim日本語ドキュメント by vim-jp

特にLua関係の話はhelpを見るべし。

  • Lua全般: :help lua
  • キーマップ: :help nvim_set_keymap
  • など

また、オプションによっては既定値がVimとNvimとで違うようです。既定値通りの設定を書いても冗長ですし、改めてヘルプを見る価値はあるでしょう。

GitHubで検索

filename:init.luaを含めて検索すると、GitHub上に公開された様々なinit.luaファイルを確認できます。

helpを見てもわからんとか、そもそもhelpの探し方がわからんといった時に、実例ベースの有力な手掛りになるでしょう。

ただし、内容によっては、Luaで書けるところをvim.api.nvim_execを使ってVimスクリプトを実行している場合もあるので、どれを参考にするかはよく吟味しましょう。

たとえば、nvimとOSのクリップボードを連携させる方法として、init.vimならset clipboard+=unnamedplusと記述できます。しかしLua言語に+=はありません。

どうするのか検索してみましょう。

filename:init.lua clipboard unnamedplus

すると、以下のように色々とでてきます。

  1. 文字列を連結して代入
    • vim.o.clipboard = vim.o.clipboard .. 'unnamedplus'
  2. Luaテーブルに追加
    • vim.opt.clipboard:append{'unnamedplus'}
  3. +=ではなく=相当な方法
    • vim.g.clipboard = 'clipboard'
    • vim.api.nvim_set_option('clipboard', 'unnamedplus')

先のinit.lua入門系記事にはvim.oを使った方法が書かれていることもあり、1つ目の方法を採用したくなりますが、要注意です。 :help clipboardを見ればわかるとおり、カンマ区切りの文字列を求められますが、カンマが間に入っていません。現在地が空文字 ("") の場合の例外処理も必要そうです。

そう思うと2つ目の方法が有望そうですが、これまで使ってないvim.optというオブジェクトが出てきて、vim.oとどう違うの?となりますね。 :help vim.optを見ましょう。

こんな感じでGitHub上の例とNvim上のhelpを行ったり来たりする必要があります。

init.lua弄りで気付いたTips

オプション設定

先の入門記事では、グローバルオプションにvim.o, バッファ専用オプションにvim.boなどを使うとありますが、Luaのtableも使えるvim.optvim.opt_localが便利だと思います。 helpにも、Vimスクリプトでいうset-optionに対応するものは、vim.optだとあります。

また、適当にコピペして既定値通りのオプションを無駄に記述しているものもあったので、一つずつhelpを読んで整理しました。

キーマップ

vim.api.nvim_set_keymapをイチイチ呼ぶのはダルい感じがしたので、多数のキーマップを設定したいプラグインではforループを使うことにしました。

以下は連想配列を使う例。配列の配列にしてもいいかなと思ったのですが、ループ中でインデックスをとるのも面倒だったのです。連想配列のキーに複雑な文字列を使いたい場合は['']で囲うと良いみたいです。

for k, v in pairs({
  ['<C-H>'] = '<Plug>(wintabs_next)',
  ['<C-L>'] = '<Plug>(wintabs_previous)',
  ['<C-L>'] = '<Plug>(wintabs_previous)',
  ['<C-T>c'] = '<Plug>(wintabs_close)',
  ['<C-T>u'] = '<Plug>(wintabs_undo)',
  ['<C-T>o'] = '<Plug>(wintabs_only)',
  ['<C-W>c'] = '<Plug>(wintabs_close_window)',
  ['<C-W>o'] = '<Plug>(wintabs_only_window)',
  ['<C-T>c'] = '<Plug>(wintabs_close)',
  ['<C-T>u'] = '<Plug>(wintabs_undo)',
  ['<C-T>o'] = '<Plug>(wintabs_only)',
  ['<C-W>c'] = '<Plug>(wintabs_close_window)',
  ['<C-W>o'] = '<Plug>(wintabs_only_window)'
}) do
  vim.api.nvim_set_keymap('', k, v, {})
end

VSCode Neo Vimに優しくする

VSCodeにエクステンションを入れると、NeovimのキーマップやプラグインをVSCodeからも使えて最高です。

超融合!時空を越えた絆 Neo Vim(VSCode)を試してみた by yukatさん

Jupyter Notebookの操作にVSCodeを使いたいので採用しています。

ConfigファイルはNeovim本体と別に用意してもいいのですが、監理が大変なので、共通化しています。しかし、私のinit.vimはステータスライン関係のプラグインなど、VSCodeには不要なものも問答無用で読み込んでいました。

VSCodeのNeo Vimエクステンションを使っているかは、nvim.g.vscodeで確認できるので、適宜if nvim.g.vscode then return endを使ってearly returnするようにしました。

-- プラグイン読み込み
require('jetpack').startup(function(use)
  use 'tpope/vim-commentary'
  use 'easymotion/vim-easymotion'
  use 'haya14busa/vim-edgemotion'
  
  if vim.g.vscode then return nil end

  use 'feline-nvim/feline.nvim'
  use 'zefei/vim-wintabs'
  use {'neoclide/coc.nvim', branch = 'release'}
  use 'lambdalisue/fern.vim'
  use {'nvim-treesitter/nvim-treesitter', ['do'] = ':TSUpdate'}
  use 'airblade/vim-gitgutter'
  use 'simeji/winresizer'
end)

(不採用) 標準プラグインの無効化

nvim --startuptime statup.logなどとして、起動ログをとると、Neovimがいくつか標準プラグインを読んでいて、無効化すると起動が速くなるそうです。

Neovimの設定を見直して起動を30倍速にした by kawarimidollさん

ただ、現状で50msecで起動しているのが、5msec程度しか縮まないようだったので、init.luaそのもののシンプルさを重視することにしました。

TODO

nvim_execを減らす

プラグインマネージャに高速さがウリなvim-jetpackを使っています。これを自動でインストールするスクリプトがZennの記事にありますがVimスクリプトです。 nvim_execするとオーバーヘッドがありそうですし、省きたいところ。

とりあえずはnvim_execが必要かどうかを判定するところまでLua言語化しておきました。 vim-jetpackがインストール済みならnvim_execすることもないので、及第点と思ってます。 autocmdなど、Luaでどう書けばいいか分かっていない部分があるので、ここから先は宿題です。

if vim.fn.empty(vim.fn.glob(vim.fn.stdpath('data') .. '/site/autoload/jetpack.vim')) == 1 then
vim.api.nvim_exec(
  [[
    let jetpack = stdpath('data') . '/site/autoload/jetpack.vim'
    autocmd VimEnter * JetpackSync | source $MYVIMRC
    silent execute '!curl -fLo '.jetpack.' --create-dirs  https://raw.githubusercontent.com/tani/vim-jetpack/master/autoload/jetpack.vim'
    silent execute '!curl -fLo "$HOME/.config/nvim/lua/jetpack.lua" --create-dirs https://raw.githubusercontent.com/tani/vim-jetpack/master/lua/jetpack.lua'
  ]],
  false
)
end

気になるプラグインを試す

以下のサイトにはeasymotionのLua実装であるhop.nvimなど、速そうなプラグインや便利そうなプラグインが色々。

Neovimの設定を見直して起動を30倍速にした by kawarimidollさん

lazygit.nvimもよさげだが、これはもっと一般的な用途に使えるtoggleterm.nvimが公式にalternativeとして指定されている。

VSCodeのターミナルでgrepした時に、マッチしたファイルの該当行にクリックで飛べるのが便利なので、似たようなことをしたい。

ENJOY!!