📝

VSCodeVimからVSCode Neovimに移行したのでメモ

2024/01/22に公開

はじめに

こんにちは、VSCodeVimからVSCode Neovimに移行したので、それに関するメモをまとめました。

Neovimの環境はLazyVimを使用しています。その他のプラグインを使用している場合は適宜読み替えてください。

なぜ移行を考えたか

普段からVimエディタは使用せず、VSCodeVimを用いてVS Codeでコーディングをしました。

ただ、.での繰り返しや:を用いたコマンドを使いこなせておらず、Vimをちゃんと勉強したいなと思い、最近になってcrafzdogさんの設定を参考にLazyVimを用いたNeovimの環境を整えて少し触っていました。

結局、GitHub Copilot ChatやRemote SSHなどの有用な拡張機能が手放せないのでVS Codeを利用することにしたのですが、Neovimを触ったことでVSCodeVimのもっさり感が気になったため、VSCode Neovimに移行することを考えました。

移行するメリット

VSCodeVimとVSCode Neovimの違いはyubrotさんの記事にまとまっていますので、こちらを参照してください。

筆者のVSCodeVim環境ではundoが壊れるということはありませんでしたが、カーソルの移動がもっさりしたり、Saveが重くなったりすることがあったので、やはりVSCode Neovimよりは劣っているように感じます。

特に、以下のように:hなどの主要コマンドが実装されていなかったり、コマンドの入力が分かりやすく表示されないのは我慢できませんでした。その点、VSCode Neovimはきちんと動作します。

VSCode Neovimの場合
VSCode Neovimでコマンドを打つと上部に表示され、見やすい

VSCodeVimの場合
VSCodeVimでコマンドを打つと下部に表示され、対応していないコマンドもある

VSCodeVimの設定

VSCodeVimは以下のように設定していました。
少し長いです。

settings.json
/* Vim Settings */
  "vim.hlsearch": true,
  "vim.easymotion": true,
  "vim.leader": "<space>",
  "vim.useSystemClipboard": true,
  "vim.visualstar": true,
  "vim.camelCaseMotion.enable": true,
  "vim.insertModeKeyBindings": [
    {
      "before": [
        "j",
        "k"
      ],
      "after": [
        "<ESC>"
      ]
    }
  ],
  "vim.normalModeKeyBindings": [
    {
      "before": [
        "u"
      ],
      "commands": [
        {
          "command": "undo"
        }
      ]
    },
    {
      "before": [
        "<C-r>"
      ],
      "commands": [
        {
          "command": "redo"
        }
      ]
    },
    {
      "before": [
        "j"
      ],
      "after": [
        "g",
        "j"
      ]
    },
    {
      "before": [
        "k"
      ],
      "after": [
        "g",
        "k"
      ]
    },
    {
      "before": [
        "n"
      ],
      "after": [
        "n",
        "z",
        "z"
      ]
    },
    {
      "before": [
        "N"
      ],
      "after": [
        "N",
        "z",
        "z"
      ]
    },
    {
      "before": [
        "*"
      ],
      "after": [
        "*",
        "z",
        "z"
      ]
    },
    {
      "before": [
        "#"
      ],
      "after": [
        "#",
        "z",
        "z"
      ]
    },
    {
      "before": [
        "+"
      ],
      "after": [
        "<C-a>"
      ]
    },
    {
      "before": [
        "-"
      ],
      "after": [
        "<C-x>"
      ]
    },
    {
      "before": [
        "<Leader>",
        "/"
      ],
      "commands": [
        {
          "command": "editor.action.commentLine"
        }
      ]
    },
    {
      "before": [
        "<Leader>",
        "s"
      ],
      "after": [],
      "commands": [
        {
          "command": "workbench.action.files.save",
        }
      ]
    },
    {
      "before": [
        "<Leader>",
        "w"
      ],
      "after": [],
      "commands": [
        {
          "command": "workbench.action.closeActiveEditor",
        }
      ]
    },
    {
      "before": [
        "<C-h>",
      ],
      "after": [
        "^"
      ]
    },
    {
      "before": [
        "<C-l>",
      ],
      "after": [
        "$"
      ]
    },
    {
      "before": [
        "<Leader>",
        "m"
      ],
      "after": [
        "%"
      ]
    },
    {
      "before": [
        "<Leader>",
        "z"
      ],
      "commands": [
        ":noh"
      ]
    }
  ],
  "vim.visualModeKeyBindings": [
    {
      "before": [
        "<C-h>",
      ],
      "after": [
        "^"
      ]
    },
    {
      "before": [
        "<C-l>",
      ],
      "after": [
        "$"
      ]
    },
    {
      "before": [
        "<Leader>",
        "m"
      ],
      "after": [
        "%"
      ]
    },
  ]

この設定はVimmerのVimmerによるVimmerのためのVSCode環境構築を参考にしています。
上記の設定をVSCode Neovimで同じように設定します。

VSCode Neovimの設定

settings.json

VSCode NeovimはローカルのNeovimと設定ファイルを以下のように設定して読み込みます。

settings.json
  "vscode-neovim.neovimExecutablePaths.darwin": "/opt/homebrew/bin/nvim",
  "vscode-neovim.neovimInitVimPaths.darwin": "/Users/yutanishi/.config/nvim/init.lua",

init.lua

pathに指定したinit.luaは以下のように設定しています。

init.lua
require("config.lazy")

lazy.lua

lazy.luaでの条件分岐は以下のように設定しています。

lazy.luaの抜粋
-- Set up lazy.nvim
if not vim.g.vscode then
  require("lazy").setup({
    spec = {
      -- LazyVim core plugins
      {
        "LazyVim/LazyVim",
        import = "lazyvim.plugins",
        opts = {
          colorscheme = "everforest",
          news = { lazyvim = true, neovim = true },
        },
      },

      -- Import extra modules
      { import = "lazyvim.plugins.extras.linting.eslint" },
      { import = "lazyvim.plugins.extras.formatting.prettier" },
      { import = "lazyvim.plugins.extras.lang.typescript" },
      { import = "lazyvim.plugins.extras.lang.json" },
      { import = "lazyvim.plugins.extras.lang.rust" },
      { import = "lazyvim.plugins.extras.coding.copilot" },
      { import = "lazyvim.plugins.extras.util.mini-hipatterns" },
      { import = "plugins" },
    },

    defaults = {
      -- Don't lazy-load custom plugins by default
      lazy = false,
      -- Use the latest git commit
      version = false,
    },

    checker = {
      -- Automatically check for plugin updates
      enabled = true,
    },

    performance = {
      cache = {
        -- Enable caching for all plugins
        enabled = true,
      },
      rtp = {
        -- Disable some rtp plugins
        disabled_plugins = {
          "gzip",
          "netrwPlugin",
          "rplugin",
          "tarPlugin",
          "tohtml",
          "tutor",
          "zipPlugin",
        },
      },
    },

    debug = false,
  })
else
  require("config.keymaps")
  require("config.options")
  require("lazy").setup({
    -- Surround plugin
    {
      "kylechui/nvim-surround",
      version = "*", -- Use for stability; omit to use `main` branch for the latest features
      event = "VeryLazy",
      config = function()
        require("nvim-surround").setup({
          -- Configuration here, or leave empty to use defaults
        })
      end
    }
  })
end

vim.g.vscodeでVSCode Neovimを使用する場合の判定をしています。lazy.nvimpacker.nvimではデフォルトで提供されているので楽です。

keymapsoptionsを有効にしています。
プラグインはnvim-surroundだけ入れています。

参考:

keymaps.lua

keymaps.luaは以下のように設定しています。

keymaps.lua
local keymap = vim.keymap
local opts = { noremap = true, silent = true }

-- Insert mode mapping
keymap.set("i", "jk", "<ESC>", opts)

-- Normal mode mappings
keymap.set("n", "<C-h>", "^", opts)
keymap.set("n", "<C-l>", "$", opts)

-- To avoid easymotion
keymap.set("n", "s", '"_s', opts)

-- Visual mode mappings
keymap.set("v", "<C-h>", "^", opts)
keymap.set("v", "<C-l>", "$", opts)

options.lua

options.luaは以下のように設定しています。
ただ、元々多くの設定をしているのでどれが反映されているか分かっていません。
意図的に追加した設定を抜粋しています。

options.luaの抜粋
vim.g.mapleader = " "
vim.opt.clipboard = "unnamedplus"

設定で詰まったところ

Neovim移行で詰まったところは以下の3点です。

insert mode mappingが反映されない

keymaps.luaの設定を先述しましたが、VSCode Neovimではinsert modeに対するカスタムマッピング設定は適用できません。公式ドキュメントの通りにsettings.jsonを設定して解決しました。

settings.jsonの抜粋
  "vscode-neovim.compositeKeys": {
    "jk": {
      "command": "vscode-neovim.escape",
    }
  },

SpaceをLeaderに割り当てられない

options.luavim.g.mapleader = " "を設定しているのでSpaceがLeaderに割り当てられています。しかし、VSCode NeovimではLeaderを用いた操作が想定されていないようでこの設定は反映されませんでした。

仕方ないので、Spaceを用いたVS Codeの操作はkeybindings.jsonで設定して解決しました。

keybindings.jsonの抜粋
  {
    "key": "space s",
    "command": "workbench.action.files.save",
    "when": "neovim.mode == normal && editorTextFocus"
  },
  {
    "key": "space /",
    "command": "editor.action.commentLine",
    "when": "neovim.mode == normal && editorTextFocus"
  },
  {
    "key": "space w",
    "command": "workbench.action.closeActiveEditor",
    "when": "neovim.mode == normal && editorTextFocus"
  }

yankがclipboardにコピーされない

元々のLazyVimではカスタムの設定を追加しなくてもyankがclipboardにコピーされていました。
多分LazyVimのデフォルトの設定でそうなっていたので、VSCode Neovimでもコピーされるようにoptions.luaで明示的に設定しました。

options.luaの抜粋
vim.opt.clipboard = "unnamedplus"

解決できなかったこと

VSCode NeovimはLeaderの設定が反映されなかったので、下記のようにVS Codeの機能ではないLeaderを用いたカスタムキーバインドが適用できませんでした。もしわかる方がいらっしゃれば、コメントしていただけると嬉しいです。

ただ、普段からあまり使わない設定ばかりだったので、ダメージは0です。

settings.jsonの抜粋
    {
      "before": [
        "<Leader>",
        "m"
      ],
      "after": [
        "%"
      ]
    }

さいごに

VSCode Neovimに移行して快適にコーディングができています。満足です。
Neovimの操作感が欲しいけど、プラグインの管理が面倒くさいという方におすすめです。

GitHubで編集を提案

Discussion