ℹ️
Neovim は Lua で設定する 旧来の Vimscript(.vimrc)でも動きますが、Neovim は Lua による設定を公式に推奨しています。 Lua はシンプルな構文で、プログラミング経験がなくてもすぐ書けます。

設定ファイルの場所

Neovim の設定ファイルは ~/.config/nvim/ ディレクトリに置きます。メインとなるエントリーポイントは init.lua です。

設定ファイルのパス
$ ls ~/.config/nvim/
init.lua lua/

$ nvim ~/.config/nvim/init.lua ← 設定ファイルを開く
💡
設定を素早く開くキーマップを作ろう <leader>ve などに :e ~/.config/nvim/init.lua<CR> を割り当てておくと、 どこからでも即座に設定ファイルを開けます。

ディレクトリ構成

小さい設定なら init.lua 一ファイルで完結しますが、 プラグインが増えてきたら lua/ ディレクトリに分割するのがベストプラクティスです。

ディレクトリ構成例 ~/.config/nvim/
~/.config/nvim/
├── init.lua              ← エントリーポイント(全体の読み込み)
└── lua/
    ├── options.lua       ← vim.opt によるオプション設定
    ├── keymaps.lua       ← キーマップ設定
    ├── autocmds.lua      ← オートコマンド
    └── plugins/          ← プラグイン別設定
        ├── init.lua      ← Lazy.nvim のセットアップ
        ├── lsp.lua       ← LSP 関連
        ├── treesitter.lua
        └── telescope.lua

init.lua では各モジュールを require で読み込むだけにすると、見通しが良くなります。

Lua ~/.config/nvim/init.lua(最小構成)
-- エントリーポイント: 各モジュールを読み込む
require("options")
require("keymaps")
require("autocmds")
require("plugins")

vim.opt でオプション設定

init.lua を NVIM で編集している様子(シンタックスハイライト付き)

vim.opt は Neovim のオプションを Lua から設定するインターフェースです。 旧来の :set コマンドに対応します。

Lua lua/options.lua
local opt = vim.opt

-- 行番号
opt.number         = true   -- 行番号を表示
opt.relativenumber = true   -- 相対行番号(移動時に便利)

-- インデント・タブ
opt.tabstop        = 2      -- タブ幅(見た目)
opt.shiftwidth     = 2      -- インデント幅
opt.expandtab      = true   -- タブをスペースに展開
opt.autoindent     = true   -- 自動インデント
opt.smartindent    = true   -- スマートインデント

-- 検索
opt.ignorecase     = true   -- 検索で大文字小文字を無視
opt.smartcase      = true   -- 大文字を含む場合は区別
opt.hlsearch       = true   -- 検索結果をハイライト
opt.incsearch      = true   -- インクリメンタル検索

-- 見た目
opt.termguicolors  = true   -- 24bit カラーを有効化
opt.signcolumn     = "yes" -- 記号列を常に表示(ガタつき防止)
opt.cursorline     = true   -- カーソル行をハイライト
opt.scrolloff      = 8      -- スクロール時に上下8行を常に表示
opt.wrap           = false  -- 折り返し表示しない

-- その他
opt.clipboard      = "unnamedplus"  -- システムクリップボードと同期
opt.undofile       = true           -- Undo 履歴をファイルに永続化
opt.splitright     = true           -- 縦分割は右に開く
opt.splitbelow     = true           -- 横分割は下に開く
opt.updatetime     = 250            -- 更新間隔を短くする(LSP 用)
💡
vim.opt vs vim.o vim.opt はリスト型オプションで :append():remove() が使えるため推奨です。 vim.o は文字列として直接操作するシンプルな方法で、どちらを使っても構いません。

vim.keymap.set でキーマップ設定

vim.keymap.set(mode, lhs, rhs, opts) でキーマップを定義します。 mode には "n"(Normal)、"i"(Insert)、"v"(Visual)などを指定します。

Lua lua/keymaps.lua
local map = vim.keymap.set

-- Leader キーを Space に設定(必ず keymap より前に宣言)
vim.g.mapleader      = " "
vim.g.maplocalleader = " "

-- ファイル操作
map("n", "<leader>w", "<cmd>w<CR>",  { desc = "保存" })
map("n", "<leader>q", "<cmd>q<CR>",  { desc = "終了" })
map("n", "<leader>Q", "<cmd>qa!<CR>",{ desc = "強制終了" })

-- ウィンドウ移動(Ctrl + hjkl)
map("n", "<C-h>", "<C-w>h", { desc = "左ウィンドウへ" })
map("n", "<C-j>", "<C-w>j", { desc = "下ウィンドウへ" })
map("n", "<C-k>", "<C-w>k", { desc = "上ウィンドウへ" })
map("n", "<C-l>", "<C-w>l", { desc = "右ウィンドウへ" })

-- 検索ハイライト解除
map("n", "<Esc>", "<cmd>noh<CR><Esc>", { desc = "ハイライト解除" })

-- インデントをビジュアルモードで維持
map("v", "<", "<gv", { desc = "インデント削除(選択維持)" })
map("v", ">", ">gv", { desc = "インデント追加(選択維持)" })

-- 行を上下に移動(Alt + j/k)
map("n", "<A-j>", "<cmd>m .+1<CR>==",        { desc = "行を下へ移動" })
map("n", "<A-k>", "<cmd>m .-2<CR>==",        { desc = "行を上へ移動" })
map("v", "<A-j>", ":m '>+1<CR>gv=gv",      { desc = "選択行を下へ移動" })
map("v", "<A-k>", ":m '<-2<CR>gv=gv",      { desc = "選択行を上へ移動" })

-- バッファ操作
map("n", "<S-h>", "<cmd>bprev<CR>", { desc = "前のバッファ" })
map("n", "<S-l>", "<cmd>bnext<CR>", { desc = "次のバッファ" })
ℹ️
desc オプションをつけよう { desc = "説明文" } をつけると、which-key.nvim などのプラグインで キーマップの一覧が読みやすく表示されます。後から見返す際にも便利です。

vim.api.nvim_create_autocmd

オートコマンドは「特定のイベントが発生したときに自動で実行する処理」です。 ファイルを開いたとき、保存したとき、モードを切り替えたときなど、様々なタイミングで処理を差し込めます。

Lua lua/autocmds.lua
local autocmd = vim.api.nvim_create_autocmd
local augroup = vim.api.nvim_create_augroup

-- グループを作成(重複を防ぐ)
local general = augroup("General", { clear = true })

-- ① ヤンク時にハイライトを一瞬表示
autocmd("TextYankPost", {
  group    = general,
  callback = function()
    vim.highlight.on_yank({ higroup = "IncSearch", timeout = 200 })
  end,
})

-- ② Markdown ファイルで折り返しを有効にする
autocmd("FileType", {
  group   = general,
  pattern = "markdown",
  callback = function()
    vim.opt_local.wrap      = true
    vim.opt_local.linebreak = true
    vim.opt_local.spell     = true
  end,
})

-- ③ 最後に開いていた位置にカーソルを戻す
autocmd("BufReadPost", {
  group    = general,
  callback = function()
    local mark = vim.api.nvim_buf_get_mark(0, '"')
    if mark[1] > 0 and mark[1] <= vim.api.nvim_buf_line_count(0) then
      vim.api.nvim_win_set_cursor(0, mark)
    end
  end,
})

-- ④ ターミナルを開くときに自動で Insert モードへ
autocmd("TermOpen", {
  group    = general,
  callback = function()
    vim.opt_local.number         = false
    vim.opt_local.relativenumber = false
    vim.cmd("startinsert")
  end,
})

モジュール分割と require

Lua の require("モジュール名") は、lua/ ディレクトリ以下の Lua ファイルを読み込みます。 ファイルが深い階層にある場合はドット区切りで指定します。

Lua require のパス対応表
-- lua/options.lua を読み込む
require("options")

-- lua/plugins/telescope.lua を読み込む
require("plugins.telescope")

-- lua/config/lsp/init.lua を読み込む(フォルダ内の init.lua は省略可)
require("config.lsp")
💡
pcall で安全に読み込む プラグインが未インストールのときにエラーを出さないよう、 local ok, plugin = pcall(require, "telescope") のように pcall で保護するのが定番パターンです。

実用的な init.lua サンプル

プラグインなしで使える、30行程度の完全な init.lua です。 Neovimをインストールしたばかりの状態でこれを貼り付けるだけで快適に使い始められます。

Lua ~/.config/nvim/init.lua(完全版・プラグインなし)
-- ============================================================
--  Neovim 設定 init.lua — プラグインなし最小構成
-- ============================================================

-- Leader を Space に設定
vim.g.mapleader = " "

-- ---- オプション ----
local opt = vim.opt
opt.number         = true
opt.relativenumber = true
opt.tabstop        = 2
opt.shiftwidth     = 2
opt.expandtab      = true
opt.ignorecase     = true
opt.smartcase      = true
opt.hlsearch       = true
opt.termguicolors  = true
opt.signcolumn     = "yes"
opt.cursorline     = true
opt.scrolloff      = 8
opt.clipboard      = "unnamedplus"
opt.undofile       = true
opt.splitright     = true
opt.splitbelow     = true

-- ---- キーマップ ----
local map = vim.keymap.set
map("n", "<leader>w", "<cmd>w<CR>",          { desc = "保存" })
map("n", "<leader>q", "<cmd>q<CR>",          { desc = "終了" })
map("n", "<Esc>",      "<cmd>noh<CR><Esc>",   { desc = "ハイライト解除" })
map("n", "<C-h>",      "<C-w>h")
map("n", "<C-j>",      "<C-w>j")
map("n", "<C-k>",      "<C-w>k")
map("n", "<C-l>",      "<C-w>l")
map("v", "<",          "<gv")
map("v", ">",          ">gv")

-- ---- オートコマンド ----
local au = vim.api.nvim_create_autocmd
local ag = vim.api.nvim_create_augroup("MyInit", { clear = true })

-- ヤンクのフラッシュ
au("TextYankPost", {
  group = ag,
  callback = function() vim.highlight.on_yank({ timeout = 200 }) end,
})

-- カラースキーム(内蔵)
vim.cmd.colorscheme("habamax")  -- Neovim 同梱の dark テーマ
💡
設定を反映するには 保存後に :source % で現在のファイルを再読み込みできます。 または :so ~/.config/nvim/init.lua と打っても同じです。 Neovim を再起動すると確実に全設定が反映されます。

よく使う vim.opt オプション一覧

オプション説明推奨値
number行番号を表示true
relativenumber相対行番号true
tabstopタブの表示幅2 or 4
shiftwidth自動インデント幅2 or 4
expandtabタブをスペースに変換true
hlsearch検索結果をハイライトtrue
ignorecase大文字小文字を区別しないtrue
smartcase大文字を含む場合は区別true
termguicolors24bitカラーを有効化true
clipboardクリップボードとの同期"unnamedplus"
undofileUndo 履歴を永続化true
scrolloffスクロール時の余白行数8
cursorlineカーソル行をハイライトtrue
wrap長い行の折り返しfalse
splitrightvsplit で右に開くtrue
splitbelowsplit で下に開くtrue