📝

VSCode+Vim(.vimrc)からVSCode+NeoVim(lua)に移行してみた+プラグイン色々紹介

2023/09/14に公開

はじめに

zenn初投稿になります。
ある時ふとVimのを使いこなせるようになったら効率上がりそうだなと思い、一旦VScodeにVimの拡張機能を入れました。
しかしVim の拡張機能とは違い、NeoVimの拡張機能の方が実際に内部でNeoVimを動かすと書かれている記事を見かけ、なんか良さそうだと思って移行してみることにしました(?)。
自分と同じような考えに至った方の参考になれば幸いです。

ターゲット

  • VSCodeでVimを使っていて.vimrcの蓄えがあり、NeoVimに移行するついでにluaにしたい人
  • 初めてNeoVimのカスタマイズをしたくてコピペでもある程度使えるものを探してる人
  • 良さげなプラグインを探してる人

ターゲットじゃないかもしれない人

  • 記述されている設定やキーマップの意味を知りたい人

今回やったこと

  1. NeoVimのインストール
  2. VSCodeのNeoVim拡張機能のインストール
  3. .vimrc(init.vim)をinit.luaに書き換え
  4. プラグインマネージャ(wbthomason/packer.nvim)の導入
  5. プラグインの導入

動作環境

M1 MacBook Air
MacOS Ventura 13.5.2
NeoVim 0.9.1

NeoVimのインストール

MacなのでHomebrewでインストールしました。他のOSを使用されている方はそれぞれ対応している方法でインストールしてください。

brew install neovim

VSCodeのNeoVim拡張機能のインストール

拡張機能のマーケットプレイスで「neovim」と調べて最上に出てくるであろう「VSCode Neovim」をインストールしました。
その後 VSCode に対して NeoVimPATH の設定をしました。
まずwhich nvimで NeoVim のパスを調べ、NeoVim 拡張機能の設定に移り、"Executable Path"に先ほど調べたパスをコピペしました。
Darwin(MacOS)、Windows、Linuxとそれぞれ欄があると思うので自分のOSの欄にコピペしてください。
次に"NeoVim Init Vim Paths"にVimのInitファイルのパスを指定します。ここについては後述するので後でいいです。

.vimrc(init.vim)をinit.luaに書き換え

最終的には以下のようなディレクトリ構造にしました。
init.vim.disabledは以降元のinit.vimファイルで、読み込まれるのを防ぐ目的且つ、分かりやすくするために拡張子を.disabledとしました。特に意味はないです。自分がわかりやすければいいと思います。
coc-settings.jsonplugin/はプラグイン導入の過程で勝手に出来上がるもので、こちらで作成するのはinit.lualua/xxx.luaのみになります。

$ tree
nvim
├── coc-settings.json
├── init.lua
├── init.vim.disabled
├── lua
│   ├── keymaps.lua
│   ├── option.lua
│   ├── plugins.lua
└── plugin
    └── packer_compiled.lua

まず~/.config/nvimディレクトリがあるかを確認します。自分の場合はなかったので作りました。

cd ~/.config
mkdir nvim && cd nvim
touch init.lua && mkdir lua

また違うディレクトリに.vimrcがある場合は移動させるか標準出力で書き写しましょう。
移行する際にタブ分割で見ながらのほうが効率がおそらく良く、同ディレクトリ直下にあることで開きやすくなるためです。
自分の場合は当初luaに移行するのをめんどくさがっていたのでinit.vimで標準出力をしました。

mv .vimrc ~/.config/nvim/
// or
cat .vimrc >> ~/.config/nvim/init.vim

次に、以下のサイトを参考にしながらinit.vimの内容をluaに書き換えていきます。

https://minerva.mamansoft.net/Notes/📜init.vimからinit.luaへ移行する

そこで、今までは.vimrc(init.vim)に全ての設定をぶちこんでいましたが、管理しやすくするためにファイルを分けることにします。それが先のxxx.luaです。

まず大元となるinit.luaを作成します。

~/.config/nvim/
touch init.lua

そして分けたファイルを読み込んでもらうために、以下のように記述します。

init.lua
require ("plugins") -- プラグイン管理
require ("option")  -- シンタックスハイライトやインデントなどの各種設定
require ("keymaps") -- キーマップ(キーバインド)の設定

init.vimの該当部分とxxx.luaとの比較で示しますが、それぞれ以下のように書き換えました。

option

init.vim
set title
set number
syntax on
set ruler
set smartcase
set cursorline
set shiftwidth=2
set tabstop=2
set hls
set clipboard=unnamed
set showmatch
set encoding=utf-8
set fileencodings=iso-2022-jp,euc-jp,sjis,utf-8
set fileformats=unix,dos,mac
option.lua
local set = vim.opt

set.swapfile = false
set.helplang = "ja"
set.syntax = "on"
set.encoding = "utf-8"
set.title = true
set.number = true
set.ruler = true
set.smartcase = true
set.cursorline = true
set.shiftwidth = 2
set.tabstop = 2
set.hls = true
set.clipboard = "unnamed"
set.showmatch = true
set.fileencodings = "utf-8"
set.updatetime = 300
set.laststatus = 2
set.expandtab = true
set.autoindent = true
set.smartindent = true

keymaps

init.vim
let mapleader = "\<Space>"
inoremap <silent> jj <Esc>
inoremap <silent> っj <Esc>
inoremap <C-j> <Down>
inoremap <C-k> <Up>
inoremap <C-h> <Left>
inoremap <C-l> <Right>
nnoremap あ a
nnoremap い i
nnoremap う u
nnoremap え e
nnoremap お o
nnoremap っd dd
nnoremap っy yy	
noremap ;; $
inoremap { {}<LEFT> 
inoremap [ []<LEFT>
inoremap ( ()<LEFT>
inoremap " ""<LEFT>
inoremap ' ''<LEFT>
noremap <S-h> 0
noremap <S-l> $
nnoremap <Leader>s :w<CR>
map <C-n> :NeoTreeShowToggle<CR>
nnoremap Y y$
keymaps.lua
vim.g.mapleader = "<Space>"
vim.keymap.set('i', 'jj', "<Esc>", { silent = true, noremap = true})
vim.keymap.set('i', 'っj', "<Esc>", { silent = true, noremap = true})
vim.keymap.set('i', '<C-j>', "<Down>", {noremap = true})
vim.keymap.set('i', '<C-k>', "<Up>", {noremap = true})
vim.keymap.set('i', '<C-h>', "<Left>", {noremap = true})
vim.keymap.set('i', '<C-l>', "<Right>", {noremap = true})
vim.keymap.set('n', 'あ', "a", {noremap = true})
vim.keymap.set('n', 'い', "i", {noremap = true})
vim.keymap.set('n', 'う', "u", {noremap = true})
vim.keymap.set('n', 'え', "e", {noremap = true})
vim.keymap.set('n', 'っy', "yy", {noremap = true})
vim.keymap.set('n', 'っd', "dd", {noremap = true})
vim.keymap.set('', ';;', "$", {noremap = true})
vim.keymap.set('i', '{', '{}<Left>', {noremap = true})
vim.keymap.set('i', '[', '[]<Left>', {noremap = true})
vim.keymap.set('i', '(', '()<Left>', {noremap = true})
vim.keymap.set('i', '\"', '\"\"<Left>', {noremap = true})
vim.keymap.set("i", "\'", "\'\'<Left>", {noremap = true})
vim.keymap.set('', '<S-h>', '0', {noremap = true})
vim.keymap.set('', '<S-l>', '$', {noremap = true})
vim.keymap.set('n', '<leader>s', ':w<CR>', {noremap = true})
vim.keymap.set('n', 'Y', 'y$')
vim.keymap.set("n", "<C-n>", ":NeoTreeShowToggle<Return>", {noremap = true, silent = true})
vim.keymap.set("n", "<C-j>", ":bnext<CR>", { silent = true, noremap = true })
vim.keymap.set("n", "<C-k>", ":bprev<CR>", { silent = true, noremap = true })

新たに追加した部分もありますが、このように書き換えられます。plugins.luaはパッケージマネージャーの導入に伴い新たに作成したものですので移行するものはありません。
また、.vimrcにはじめから関数が書かれている場合があるかと思います(自分の記憶では気づいた頃には勝手に書かれてました)。
それも移行しようかと考えたのですが、しなくても問題なく動いてそうだったのでしておりません。
ここまで設定したらこちらの"NeoVim Init Vim Paths"にinit.luaのPATHを通しましょう。

VSCodeでのキーバインドの追加

VSCode上では一部動作しないキーバインドがあります。特にインサートモード中に使用するコマンド(<Esc>jjなど)は動作しません。そのためVSCode上でキーバインドの設定をする必要があります。
また、VSCodeのエクスプローラをNeoVimのファイラープラグインのように使いたい場合も一部こちらで設定する必要があります。

まず<Shift>+⌘+Pもしくは<Shift>+<Ctrl>+Pと押してコマンドパレットを開きます。
そこで「ショートカット」と検索して[基本設定: キーボードショートカットを開く(JSON)]を選択すると、キーバインドを設定するjsonファイルが開きます。ここで自身の好きなようにキーバインドの設定ができます。
自分は以下のように設定しています。

keybindings.json
// 既定値を上書きするには、このファイル内にキーバインドを挿入します
[
  // インサートモード中に"jj"でノーマルモードに抜ける
  {
    "command": "vscode-neovim.compositeEscape1",
    "key": "j",
    "when": "neovim.mode == insert && editorTextFocus",
    "args": "j"
  },
  // インサートモード中にCtrl+hjklでノーマルモードと同じようにカーソル移動
  {
    "key": "ctrl+l",
    "command": "cursorRight",
    "when": "neovim.mode == insert && editorTextFocus"
  },
  {
    "key": "ctrl+h",
    "command": "cursorLeft",
    "when": "neovim.mode == insert && editorTextFocus"
  },
  {
    "key": "ctrl+j",
    "command": "cursorDown",
    "when": "neovim.mode == insert && editorTextFocus"
  },
  {
    "key": "ctrl+k",
    "command": "cursorUp",
    "when": "neovim.mode == insert && editorTextFocus"
  },
  // エクスプローラ(左欄のファイル見れるやつ)から編集中ファイルにフォーカスを合わせる
  {
    "key": "ctrl+w l",
    "command": "workbench.action.focusFirstEditorGroup",
    "when": "listFocus && !inputFocus"
  },
  // ノーマルモード時行頭へ("0"と同じ)
  {
    "key": "shift+h",
    "command": "cursorHome",
    "when": "neovim.mode == normal && editorTextFocus"
  },
  // ノーマルモード時行末へ("$と同じ")
  {
    "key": "shift+l",
    "command": "cursorEnd",
    "when": "neovim.mode == normal && editorTextFocus"
  },
  // エクスプローラでファイル名変更
  {
    "key": "m r",
    "command": "renameFile",
    "when": "explorerViewletVisible && filesExplorerFocus && !inputFocus"
  },
  // フォーカスをエクスプローラ←→ファイル間で行き来
  {
    "key": "ctrl+n",
    "command": "workbench.explorer.fileView.focus",
    "when": "!filesExplorerFocus"
  },
  {
    "key": "ctrl+n",
    "command": "workbench.action.toggleSidebarVisibility",
    "when": "filesExplorerFocus"
  },
  // エクスプローラでファイルコピー
  {
    "key": "m c",
    "command": "filesExplorer.copy",
    "when": "explorerViewletVisible && filesExplorerFocus && !inputFocus"
  },
  // エクスプローラでファイルペースト
  {
    "key": "m p",
    "command": "filesExplorer.paste",
    "when": "explorerViewletVisible && filesExplorerFocus && !inputFocus"
  },
  // エクスプローラでファイル新規作成
  {
    "key": "m a",
    "command": "explorer.newFile",
    "when": "explorerViewletVisible && filesExplorerFocus && !inputFocus"
  },
  // エクスプローラでファイル削除
  {
    "key": "m d",
    "command": "deleteFile",
    "when": "explorerViewletVisible && filesExplorerFocus && !inputFocus"
  },
  // エクスプローラでフォルダ新規作成
  {
    "key": "m f",
    "command": "explorer.newFolder",
    "when": "explorerViewletVisible && filesExplorerFocus && !inputFocus"
  }
]

パッケージマネージャの導入

(Neo)Vimの有名なパッケージマネージャにはdein.vimpacker.nvimなどがありますが、今回はpacker.nvimを採用しました。

リンク先のREADMEに記載がありますが、一応インストールコマンドを示しておくと、

git clone --depth 1 https://github.com/wbthomason/packer.nvim\
 ~/.local/share/nvim/site/pack/packer/start/packer.nvim

となります。
https://zenn.dev/kenkenlysh/articles/a4fd67d23b7f53
こちらの記事を参考にplugins.luaの雛形の記述を行いました。

plugins.lua
vim.cmd.packadd "packer.nvim"

require("packer").startup(function()
  -- Write plugins you wanna add below.
  -- use "hoge/hoge-plugin"
  use 'wbthomason/packer.nvim'
end)

こちらに導入したいパッケージのリポジトリ名を構文とともに載せてNeoVim内で:PackerInstallとコマンドを打てば自動でインストールしてくれます。すごく楽で便利です。
尚、こいつはこのファイル内に記述がない導入済のプラグインは削除するかを問う旨のポップアップを出してきます、自爆を防ぐためにもuse 'wbthomason/packer.nvim'と記述しましょう。自分はこのポップアップによくわからずYと押してしまい再インスコする羽目になりました......。

おすすめプラグイン

kylechui/nvim-surround

https://github.com/kylechui/nvim-surround

kylechui/nvim-surround"" '' [] {} ()やHTMLタグ(<p>)などの単語を囲む記号の編集をするコマンドを追加することができるプラグインです。
以下は上記のリンクから参照できるコマンド例を引用したものです。*がカーソル位置になります。

    Old text                    Command         New text
-----------------------------------------------------------------------------
    surr*ound_words             ysiw)           (surround_words)
    *make strings               ys$"            "make strings"
    [delete ar*ound me!]        ds]             delete around me!
    remove <b>HTML t*ags</b>    dst             remove HTML tags
    'change quot*es'            cs'"            "change quotes"
    <b>or tag* types</b>        csth1<CR>       <h1>or tag types</h1>
    delete(functi*on calls)     dsf             function calls

導入するためには以下の記述を追加します。

plugins.lua
use({
    "kylechui/nvim-surround",
    tag = "*", features
    config = function()
        require("nvim-surround").setup({
        })
    end
})

おわりに

はい、以上になります。
「え?これだけ?」と思うかもしれませんが、VSCode上で使うだけであればこれだけで十分です。
このほかにもNeoVimにはカラースキームやファイラー、シンタックスハイライトを扱うプラグインが多数存在しますが、それらはVSCode上では意味を成さない上に、わざわざ導入せずともVSCodeにそのような機能はある程度あるためです。
一応そのようなプラグインもある程度導入してはいますが、自己満足でしかなくほとんど役には立っていません。
念の為、plugins.luaの内容と、プラグイン探しの際に参考にしたサイトを次節に記しておきますので、興味がある方がいましたらどうぞ。
細かな解説ができませんで恐縮ですが、これからNeoVimに移行する・NeoVimに触れてみるという人の参考になれば幸いです。
かくいう自分もまだVimに目覚めてから日は浅く、使いこなせているかというと微妙なところです。Vimの成長曲線は急だと良く聞きますので、精進して参ります。

おまけ

plugins.lua
vim.cmd.packadd "packer.nvim"

require("packer").startup(function()
	-- Write plugins you wanna add below.
	-- use "hoge/hoge-plugin"
	use 'wbthomason/packer.nvim'
  use "Shougo/ddc-around"
  use 'Shougo/ddc.vim'
	use 'vim-denops/denops.vim'
  use "folke/tokyonight.nvim"
  use "kdheepak/tabline.nvim"
  use "tpope/vim-commentary"
  use "dinhhuy258/git.nvim"
  use { 
    "neoclide/coc.nvim",
    branch = "release"
  }
  use({
  "nvim-treesitter/nvim-treesitter",
  run = ":TSUpdate",
  })
  use {
  "nvim-lualine/lualine.nvim",
  requires = { "nvim-tree/nvim-web-devicons", opt = true }
}
  use {'kyazdani42/nvim-web-devicons'}
  -- use("nvim-tree/nvim-web-devicons")
  use {
  "nvim-neo-tree/neo-tree.nvim",
    branch = "v2.x",
    requires = {
      "nvim-lua/plenary.nvim",
      "nvim-tree/nvim-web-devicons", -- not strictly required, but recommended
      "MunifTanjim/nui.nvim",
    }
  }
	use({
    "kylechui/nvim-surround",
    tag = "*", -- Use for stability; omit to use `main` branch for the latest features
    config = function()
        require("nvim-surround").setup({
            -- Configuration here, or leave empty to use defaults
        })
    end
})
end)

https://namileriblog.com/mac/neovim_plugins_ui/#i-46
https://zenn.dev/fukakusa_kadoma/articles/4d48fb4e67c945

Discussion