2025年2月 Neovimセットアップ
Table of Contents
Introduction
Neovimに入門したいと思い早n年だったが、vim-jpの皆さんのおかげでようやくミニマムの設定が完了したのでブログにまとめておきます。
VimとNeovimの使い分けと最小構成 の通りVimは最小構成にしているので、Neovimはヘビーカスタマイズしていく方針です。
Neovimの設定はこちら。
https://github.com/takeokunn/nixos-configuration/tree/main/home-manager/programs/neovim
Setup
Neovim本体
Nix経由でインストールしています。
https://github.com/takeokunn/nixos-configuration/blob/main/home-manager/programs/neovim/default.nix
withNodeJs
や withRuby
などはイマドキ使わない設定まらしいので false
にしました。
{ pkgs, sources }:
{
programs.neovim = {
enable = true;
withNodeJs = false;
withRuby = false;
withPython3 = false;
plugins = import ./plugins { inherit pkgs sources; };
extraLuaConfig = builtins.readFile ./init.lua;
};
}
Plugin Manager
VimのPlugin Managerは乱立しているようで、デファクトスタンダードはないらしいです。 私はNixユーザーなのでNixで管理することにしました。
また、各Pluginごとの設定もNix内に記述する方針にしました。
# 実際の例
{ pkgs }:
with pkgs.vimPlugins;
[
{
type = "lua";
plugin = dracula-nvim;
config = ''
vim.cmd[[colorscheme dracula]]
'';
}
]
Terminal Emulator
「Terminal Emulatorにこだわらない」というこだわりを持っていたが、Mac標準のTerminal.appだとうまく描画してくれない問題があった。
一応以下が候補だったが、NixOS環境でも安定的に動いてくれる、かつ友人のnatsukiumが使っているKittyを採用しました。
現状Kittyで特に困っていないしTerminal Emulatorに情熱がないのでこのまま続投するつもりです。
Config
Neovimの設定はVim scriptではなくLuaを使うのがイマドキであり、多くのNeovim PluginはLuaで書かれているらしい。 それにならって自分もLuaで設定していくことにしました。
init.lua
基本的な設定は以下。 行番号はそもそも表示不要というのが最近の結論なので消しました。
vim.opt.number = false
vim.opt.relativenumber = false
vim.opt.encoding = "utf-8"
vim.opt.fileencodings = "utf-8,euc-jp,cp932"
vim.opt.clipboard:append("unnamed")
vim.opt.backspace = "indent,eol,start"
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.laststatus = 3
vim.opt.statusline = "%y"
vim.opt.showmatch = true
vim.opt.wrapscan = true
vim.opt.hlsearch = true
vim.opt.showcmd = true
vim.opt.title = true
vim.opt.foldenable = false
vim.opt.swapfile = false
vim.opt.expandtab = true
vim.opt.splitbelow = true
vim.opt.splitright = true
vim.opt.incsearch = true
vim.opt.ignorecase = true
vim.opt.smartcase = true
vim.opt.termguicolors = true
簡単なkeymapは以下。
mapleader
をスペースに割り当てている人が多数派みたいですが、個人的には ,
が昔から好きです。
vim.g.mapleader = ","
vim.keymap.set("n", "/", "/\\v", { remap = false })
vim.keymap.set("n", "U", "<C-r>", { remap = false })
vim.keymap.set("n", "<Leader><Leader>", "V", { remap = false })
vim.keymap.set("n", "<Esc><Esc>", "<Cmd>nohlsearch<CR><Esc>", { remap = false })
vim.keymap.set("i", "<C-j>", "<CR>")
windowやbufferの切り替えは簡単な設定をしています。
-- window keymap
vim.keymap.set("n", "sj", "<C-w>j", { noremap = true, silent = true })
vim.keymap.set("n", "sk", "<C-w>k", { noremap = true, silent = true })
vim.keymap.set("n", "sl", "<C-w>l", { noremap = true, silent = true })
vim.keymap.set("n", "sh", "<C-w>h", { noremap = true, silent = true })
vim.keymap.set("n", "sJ", "<C-w>J", { noremap = true, silent = true })
vim.keymap.set("n", "sK", "<C-w>K", { noremap = true, silent = true })
vim.keymap.set("n", "sL", "<C-w>L", { noremap = true, silent = true })
vim.keymap.set("n", "sH", "<C-w>H", { noremap = true, silent = true })
vim.keymap.set("n", "sw", "<C-w>w", { noremap = true, silent = true })
-- buffer keymap
vim.keymap.set("n", "sp", ":<C-u>bp<CR>", { noremap = true, silent = true })
vim.keymap.set("n", "sn", ":<C-u>bn<CR>", { noremap = true, silent = true })
package
項目分けは雑なのでもう少しpluginが増えたら考え直します。
basic
- hop-nvim
- easymotionみたいなplugin
- Emacsで言う所のavy
- vim-bracketed-paste
- クリップボード用
- vim-fern
- ありすえwareのファイラ
- Emacsで言う所のneotree
- vim-nerdfont
- nerdfontを扱えるようにするやつ
- vim-fern-renderer-nerdfont
- ファイラにアイコンを表示するやつ
- undotree
- undo historyを可視化するやつ
- Emacsで言う所のundo-fu
- vim-textobj-entire
- buffer全体をテキストオブジェクトにするやつ
- vimdoc-ja
- 日本語help
- auto-pairs
- Emacsで言う所のelectric-pair-modeみたいなやつ
- rainbow
- 括弧の対応をハイライトしてくれるやつ
- Emacsで言う所のrainbow-delimiters
- vim-sandwich
- 括弧の操作を簡単にできるやつ
- Emacsで言う所のpuni-mode
- denops-vim
- Deno製plugin用
ざっくりこのあたりを入れています。
Git
- gitsigns-nvim
- 変更を可視化してくれるやつ
- Emacsで言う所のgit-gutter
- gin
- ありすえwareのGit clinet
- Emacsで言う所のmagit
そこまで使っていないです。 Git操作はTerminalでも良いのかなという気持ちになってます。
language
基本的にTree-sitterがhighlightしてくれるので特別入れる必要がなかったです。
lsp
- nvim-cmp
- nvim-lspconfig
- Emacsで言う所のlsp-mode
- lspsaga-nvim
- Emacsで言う所のlsp-ui
ざっくりとした設定は以下。最低限満足するUIになってくれました。
nvim-cmp
:
local cmp = require("cmp")
cmp.setup({
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body)
end,
},
sources = {
{ name = "nvim_lsp" },
{ name = "path" },
},
mapping = cmp.mapping.preset.insert({
["<C-p>"] = cmp.mapping.select_prev_item(),
["<C-n>"] = cmp.mapping.select_next_item(),
['<C-l>'] = cmp.mapping.complete(),
['<C-e>'] = cmp.mapping.abort(),
["<CR>"] = cmp.mapping.confirm { select = true },
}),
experimental = {
ghost_text = true,
},
})
nvim-lspconfig
:
local lspconfig = require('lspconfig')
vim.keymap.set('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', { silent = true, buffer = buffer })
if vim.fn.executable('nil') == 1 then
lspconfig.nil_ls.setup {
settings = {
['nil'] = {
formatting = {
command = { 'nixfmt' }
}
}
}
}
end
if vim.fn.executable('typescript-language-server') == 1 then
lspconfig.ts_ls.setup { }
end
if vim.fn.executable('intelephense') == 1 then
lspconfig.intelephense.setup { }
end
lspsaga-nvim
:
require('lspsaga').setup({
code_action = {
extend_gitsigns = true,
},
finder = {
max_height = 0.7,
left_width = 0.3,
right_width = 0.6,
keys = {
shuttle = "<Space>w",
toggle_or_open = "<CR>"
}
},
lightbulb = {
enable = false,
}
})
vim.keymap.set('n', 'K', '<cmd>Lspsaga hover_doc<CR>')
vim.keymap.set({ 'n', 'i' }, '<S-M-r>', "<cmd>Lspsaga rename<CR>", opts)
vim.keymap.set('n', '<M-d>', "<cmd>Lspsaga finder def+ref<CR>", opts)
vim.keymap.set('n', '<M-r>', "<cmd>Lspsaga peek_definition<CR>", opts)
vim.keymap.set('n', '<M-j>', "<cmd>Lspsaga diagnostic_jump_next<CR>", opts)
vim.keymap.set('n', '<M-k>', "<cmd>Lspsaga diagnostic_jump_prev<CR>", opts)
skk
- skkeleton
- Emacsで言う所のddskk
- skkeleton-azik-kanatable
簡易的な設定とskkservへの接続、AZIKの有効化をしました。
skkeleton#register_kanatable
で独自のかなテーブルを定義できるらしいです。
skkeleton
:
vim.fn['skkeleton#config']({
eggLikeNewline = true,
keepState = true,
sources = { "skk_server" }
})
vim.keymap.set({ 'i', 'c' }, '<C-j>', '<Plug>(skkeleton-toggle)', { silent = true })
skkeleton-azik-kanatable
:
vim.fn['skkeleton#azik#add_table']('us')
vim.fn['skkeleton#config']({
kanaTable = 'azik'
})
vim.call("skkeleton#register_kanatable", "azik", {
ss = { "せい" },
})
telescope
telescopeは簡単に導入できるということで導入しました。
Emacsで言う所の、というのは説明が難しいですね。 tomoyaさんの Emacsの次世代ミニバッファ補完UI あたりが参考になりそうです。
<leader>
はデフォルトでマッピングされてないのでこれで問題ないようです。
require('telescope').setup {
extensions = {
fzf = {
fuzzy = true,
override_generic_sorter = true,
override_file_sorter = true,
case_mode = "smart_case",
}
}
}
local builtin = require('telescope.builtin')
vim.keymap.set('n', '<leader>f', builtin.git_files, { desc = 'Telescope find git files' })
vim.keymap.set('n', '<leader>o', builtin.current_buffer_fuzzy_find, { desc = 'Telescope buffer fuzzy find' })
vim.keymap.set('n', '<leader>g', builtin.live_grep, { desc = 'Telescope live grep' })
vim.keymap.set('n', '<leader>b', builtin.buffers, { desc = 'Telescope buffers' })
vim.keymap.set('n', '<leader>h', builtin.help_tags, { desc = 'Telescope help tags' })
themes
- dracula-nvim
- Emacsで言う所のdoom-theme
- lualine-nvim
- Emacsで言う所のdoom-modeline
すべてのカラーテーマをdraculaに寄せているので導入しました。 また、modelineはlualine-nvimがイマドキらしいです。
終わりに
vim-jpの皆さん(特にkuuさん、Kento Ogataさん、Shougoさん、こまもかくん、おもちあいす)のおかげで無事日常生活できるくらいの設定になりました。 もう少しVimに慣れたらDark Poweredなpackageを試していくつもりです。