メインコンテンツへスキップ

macOSでNeovimを快適に使うための設定入門

macOSでNeovimを快適に使うための設定入門のアイキャッチ画像
目次

TL;DR

はじめに

この記事では、macOSでNeovimを快適に使うための設定を解説します。Vimの基本操作(モード切り替え、カーソル移動、保存・終了など)は知っているが、Neovimのプラグイン設定は初めてという方を想定しています。

以下の4つのトピックを扱います:

  1. macOS IME問題の解決 - 日本語入力で最もハマりやすいポイント
  2. Neovim 0.11のプラグイン互換性 - 最新版を使う際の注意点
  3. Nerd Font不要のミニマル設定 - フォント設定なしで使える環境
  4. LSP/補完の基本設定 - 定義ジャンプや自動補完を実現

前提環境

この記事の設定は以下の環境で動作確認しています:

項目バージョン
macOSSonoma 14.x 以降
Neovim0.11.3 以降(LSP新APIに必要)
Homebrewインストール済み
ターミナルiTerm2(Terminal.appでも可)

まだNeovimをインストールしていない場合は、以下のコマンドでインストールできます:

brew install neovim

1. macOS IME問題の解決

問題の概要

macOSでNeovim(Vim)を使う際、多くの人がつまずくのがIME(日本語入力)の問題です。

具体的には: 日本語入力モードのままノーマルモードに戻ると、jkなどのコマンドが効かなくなる。

これは、InsertモードからNormalモードに戻っても、macOSのIME状態がそのままになるためです。日本語で文章を書いた後、Escでノーマルモードに戻ると、IMEが日本語入力のままなので、jjj...と入力しても「っっっ…」と日本語が入力されてしまいます。

解決策: im-select.nvim + macism

この問題を解決するには、2つのコンポーネントを組み合わせます:

  1. im-select.nvim(Neovimプラグイン)

    • モード切り替え(Insert→Normal等)を検知
    • 外部のCLIツールを呼び出してIMEを切り替え
  2. macism(CLIツール)

    • 実際にmacOSのIMEを切り替えるコマンド
    • im-select.nvimから呼び出される

つまり、im-select.nvimがNeovim内でモード変更を監視し、変更を検知したらmacismコマンドを実行してIMEを英数に切り替える、という仕組みです。

なぜmacismなのか

im-select.nvimはmacOS上でIMEを切り替えるCLIツールを呼び出します。macOS用のツールは複数ありますが、im-select.nvimの公式READMEではmacismを推奨しています。

Please install macism, this is the only one CLI tool can switch CJK and English input methods in macOS correctly. — im-select.nvim README

macismは、日本語などのCJK入力ソースを確実に切り替えられます。他のツール(input-source-switcher等)ではmacOSのバグにより、メニューバーのアイコンは変わっても実際には切り替わらない問題が発生することがあるようです。

インストール手順

macismは公式のHomebrew tapにないため、サードパーティのtapを追加する必要があります:

# tapの追加
brew tap laishulu/homebrew

# macismのインストール
brew install laishulu/homebrew/macism

インストール後、動作確認をしてみましょう:

# 現在の入力ソースを確認
macism

# 出力例: com.apple.inputmethod.Kotoeri.RomajiTyping.Japanese
# または: com.apple.keylayout.ABC

Neovimの設定

im-select.nvimプラグインを使って、モード切り替え時の動作を設定します。

-- プラグインマネージャー(lazy.nvim)での設定例
{
  "keaising/im-select.nvim",
  config = function()
    require("im_select").setup({
      -- 切り替え先の入力ソース(英数キーボード)
      default_im_select = "com.apple.keylayout.ABC",

      -- macismの絶対パス(Intel Macの場合は /usr/local/bin/macism)
      default_command = "/opt/homebrew/bin/macism",

      -- 英数に切り替えるタイミング
      set_default_events = {
        "VimEnter",       -- Neovim起動時
        "FocusGained",    -- ウィンドウにフォーカスが戻った時
        "InsertLeave",    -- Insertモードを抜けた時
        "CmdlineLeave"    -- コマンドラインモードを抜けた時
      },

      -- InsertEnter時に前のIMEに戻す設定(空にして無効化)
      set_previous_events = {},
    })
  end,
}

設定のポイント: なぜ set_previous_events = {} にしたか

デフォルトでは、set_previous_events = { "InsertEnter" } となっており、Insertモードに入ると直前のIME状態に戻ります。

しかし、この設定を空にして無効化しました。理由は以下の通りです:

トレードオフの比較:

設定メリットデメリット
{ "InsertEnter" }(デフォルト)日本語の連続入力に便利英語コードを書く際に毎回切り替えが必要
{}(無効化)常に英数から始まるので予測しやすい日本語を続けて書く際は手動切り替え

プログラミングでは英語入力が圧倒的に多いため、「常に英数に戻る」動作の方が快適でした。日本語を書く際は、手動で日本語入力に切り替えれば済みます。

もし日本語でドキュメントを書く機会が多い場合は、デフォルトの { "InsertEnter" } の方が便利かもしれません。


2. Neovim 0.11のプラグイン互換性

問題の概要

2025年3月にリリースされたNeovim 0.11では、LSP関連のAPIが大きく変更されました。この影響で、一部のプラグインがそのままでは動作しない場合があります。

Telescope.nvimの互換性問題

最も多くのユーザーが遭遇するのが、Telescope.nvim(ファジーファインダー)の問題です。

症状: Telescopeを開くとエラーが発生する、または表示がおかしい

原因: Telescope.nvimの安定版ブランチ(0.1.x)がNeovim 0.11のAPI変更に追従していない

解決策: 0.1.xタグを使用する(最新版では修正済み)

-- Neovim 0.11対応版
{
  "nvim-telescope/telescope.nvim",
  tag = "0.1.x",  -- 安定版タグ(Neovim 0.11対応済み)
  dependencies = { "nvim-lua/plenary.nvim" },
}

バージョン選択のポイント

2025年末時点では、Telescope v0.2.0もリリースされています。

指定方法特徴推奨度
tag = "0.1.x"安定版、Neovim 0.11対応済み推奨
tag = "0.1.8"特定バージョン固定再現性重視なら
branch = "master"最新開発版新機能を試したい場合

以前は0.1.xブランチがNeovim 0.11非対応でしたが、現在は修正されています。特に理由がなければtag = "0.1.x"を使えば問題ありません。

その他の互換性確認方法

プラグインが動作しない場合は、以下の手順で調査できます:

  1. GitHubのIssuesを確認: [プラグイン名] Neovim 0.11で検索
  2. READMEのRequirementsを確認: 対応するNeovimバージョンが明記されていることが多い
  3. 最新版に更新: :Lazy syncでプラグインを最新化

3. Nerd Font不要のミニマル設定

Nerd Fontとは

多くのNeovim設定記事では「Nerd Fontをインストールしてください」と書かれています。Nerd Fontは、通常のフォントにアイコン(ファイルタイプ、Git状態、フォルダなど)を追加したフォントファミリーです。

しかし、Nerd Fontの導入には以下のステップが必要です:

  1. Nerd Fontのダウンロード
  2. システムへのインストール
  3. ターミナルのフォント設定変更
  4. 設定の反映確認

なぜNerd Fontなしを選んだか

Nerd Fontを使わない選択をした理由は以下の通りです:

メリット:

デメリット:

プログラミング中はファイル名を見ればファイルタイプは分かるため、アイコンがなくても実用上の問題はありませんでした。

アイコンを無効化する設定

主要なプラグインでアイコンを無効化する方法を紹介します。

nvim-tree(ファイルエクスプローラー)

{
  "nvim-tree/nvim-tree.lua",
  config = function()
    require("nvim-tree").setup({
      renderer = {
        icons = {
          show = {
            file = false,        -- ファイルアイコン非表示
            folder = false,      -- フォルダアイコン非表示
            folder_arrow = true, -- 展開/折りたたみの矢印は表示
            git = false,         -- Git状態アイコン非表示
          },
          glyphs = {
            folder = {
              arrow_closed = ">",  -- 折りたたみ時の矢印
              arrow_open = "v",    -- 展開時の矢印
            },
          },
        },
      },
    })
  end,
}

lualine(ステータスライン)

{
  "nvim-lualine/lualine.nvim",
  config = function()
    require("lualine").setup({
      options = {
        icons_enabled = false,       -- アイコン全体を無効化
        section_separators = "",     -- セクション区切りなし
        component_separators = "|",  -- 区切り文字をシンプルに
      },
    })
  end,
}

見た目の比較

Nerd Fontあり:

  init.lua    main   lua  utf-8  100%  42:1

Nerd Fontなし:

NORMAL | main | init.lua | lua | utf-8 | 100% | 42:1

アイコンの代わりにテキストで情報が表示されます。慣れれば十分読みやすいです。


4. LSP/補完の基本設定

LSPとは

LSP(Language Server Protocol)は、エディタと言語サーバーの間の通信プロトコルです。これを使うことで、以下の機能が実現できます:

プラグイン構成の全体像

LSP/補完を実現するために、以下のプラグインを組み合わせます:

mason.nvim              # 言語サーバーのインストーラー
  └── mason-lspconfig   # masonとlspconfigの橋渡し
        └── nvim-lspconfig  # 言語サーバーの設定

nvim-cmp                # 補完エンジン
  ├── cmp-nvim-lsp      # LSPからの補完ソース
  ├── cmp-buffer        # バッファ内の単語を補完
  ├── cmp-path          # ファイルパスを補完
  └── LuaSnip           # スニペット展開

なぜこの構成を選んだか

観点選択理由
LSPインストールmason.nvimGUIで管理でき、初心者に分かりやすい
補完エンジンnvim-cmp最も広く使われており、情報が豊富
スニペットLuaSnipnvim-cmpとの連携がスムーズ

mason.nvimによる言語サーバーの自動インストール

mason.nvimを使うと、:MasonコマンドでGUIから言語サーバーを管理できます。また、mason-lspconfigを使えば、必要な言語サーバーを自動でインストールできます。

{
  "neovim/nvim-lspconfig",
  dependencies = {
    "williamboman/mason.nvim",
    "williamboman/mason-lspconfig.nvim",
  },
  config = function()
    -- masonの初期化(:Masonコマンドが使えるようになる)
    require("mason").setup()

    -- 自動インストールする言語サーバーを指定
    require("mason-lspconfig").setup({
      ensure_installed = {
        "lua_ls",   -- Lua
        "ts_ls",    -- TypeScript/JavaScript
        "pyright",  -- Python
      },
    })
  end,
}

初回起動時に、指定した言語サーバーが自動でインストールされます。

Neovim 0.11の新しいLSP設定API

Neovim 0.11では、LSPの設定方法が大きく変わりました。

旧来の方法(nvim-lspconfig依存):

local lspconfig = require("lspconfig")
lspconfig.lua_ls.setup({
  settings = {
    Lua = {
      diagnostics = { globals = { "vim" } },
    },
  },
})

新しい方法(Neovim 0.11.3+ネイティブ):

-- 言語サーバーごとの設定
vim.lsp.config('lua_ls', {
  settings = {
    Lua = {
      diagnostics = { globals = { "vim" } },
    },
  },
})

-- 言語サーバーを有効化
vim.lsp.enable({ "lua_ls", "pyright", "ts_ls" })

Note: nvim-lspconfigは廃止されていません。内部的にvim.lsp.configを呼び出すラッパーとして機能するため、従来のlspconfig.xxx.setup({})形式も引き続き使えます。新規で設定する場合は、プラグイン依存を減らせる新APIがおすすめです。

新しいAPIを使うメリット:

LSPキーマップの設定

LSPの機能をキーに割り当てます。LspAttachイベントを使うと、LSPが有効なバッファでのみキーマップが設定されます。

vim.api.nvim_create_autocmd("LspAttach", {
  callback = function(args)
    local bufnr = args.buf
    local opts = { buffer = bufnr, silent = true }

    -- 定義・宣言・実装へのジャンプ
    vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts)
    vim.keymap.set("n", "gD", vim.lsp.buf.declaration, opts)
    vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts)

    -- ドキュメント表示・編集操作
    vim.keymap.set("n", "K", vim.lsp.buf.hover, opts)
    vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename, opts)
    vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, opts)

    -- 診断の移動
    vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts)
    vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts)
    vim.keymap.set("n", "<leader>e", vim.diagnostic.open_float, opts)
  end,
})

なぜLspAttachイベントを使うか

キーマップの設定方法には複数の選択肢があります:

方法説明問題点
グローバルキーマップ全バッファで有効LSPがないファイルでもキーが有効
lspconfig.on_attachlspconfig経由で設定lspconfigに依存
LspAttachイベントLSPアタッチ時に設定なし

LspAttachはNeovimのビルトインイベントなので、プラグインに依存せず、確実に動作します。

nvim-cmpによる補完設定

補完エンジンnvim-cmpの基本設定です。

{
  "hrsh7th/nvim-cmp",
  dependencies = {
    "hrsh7th/cmp-nvim-lsp",   -- LSP補完ソース
    "hrsh7th/cmp-buffer",     -- バッファ補完
    "hrsh7th/cmp-path",       -- パス補完
    "L3MON4D3/LuaSnip",       -- スニペットエンジン
    "saadparwaiz1/cmp_luasnip", -- スニペット補完
  },
  config = function()
    local cmp = require("cmp")
    local luasnip = require("luasnip")

    cmp.setup({
      -- スニペット展開の設定
      snippet = {
        expand = function(args)
          luasnip.lsp_expand(args.body)
        end,
      },

      -- キーマップ
      mapping = cmp.mapping.preset.insert({
        ["<C-Space>"] = cmp.mapping.complete(),   -- 手動で補完を開く
        ["<C-e>"] = cmp.mapping.abort(),          -- 補完をキャンセル
        ["<CR>"] = cmp.mapping.confirm({ select = true }), -- 確定
        ["<Tab>"] = cmp.mapping(function(fallback)
          if cmp.visible() then
            cmp.select_next_item()  -- 次の候補
          else
            fallback()
          end
        end, { "i", "s" }),
        ["<S-Tab>"] = cmp.mapping(function(fallback)
          if cmp.visible() then
            cmp.select_prev_item()  -- 前の候補
          else
            fallback()
          end
        end, { "i", "s" }),
      }),

      -- 補完ソースの優先順位
      sources = cmp.config.sources({
        { name = "nvim_lsp" },  -- LSP(最優先)
        { name = "luasnip" },   -- スニペット
      }, {
        { name = "buffer" },    -- バッファ内の単語
        { name = "path" },      -- ファイルパス
      }),
    })
  end,
}

補完ソースの優先順位は、最初のグループ(LSP、スニペット)が優先され、該当がなければ次のグループ(バッファ、パス)から候補が表示されます。


設定ファイルの構成について

この記事で紹介した設定は、すべて~/.config/nvim/init.lua一つにまとめています。

なぜ単一ファイルにしたか:

構成メリットデメリット
単一ファイル全体が見渡せる、検索しやすい長くなると見づらい
複数ファイル責務が明確、大規模向きファイル間の依存関係が複雑

400行程度の設定であれば、単一ファイルで十分管理できます。設定が増えてきたら分割を検討すれば良いでしょう。


まとめ

この記事では、macOSでNeovimを快適に使うための4つの設定を解説しました。

  1. IME問題: im-select.nvim + macismで解決。set_previous_events = {}で常に英数に戻す設定がプログラミング向き
  2. Neovim 0.11互換性: Telescopeは0.1.xタグを使用(修正済み)
  3. Nerd Font不要: 各プラグインでアイコンを無効化すればシンプルな環境が作れる
  4. LSP/補完: mason.nvim + nvim-cmpの組み合わせで、GUIでの管理と豊富な補完が実現

これらの設定は、あくまで一つの選択肢です。使っていく中で、自分の好みや用途に合わせてカスタマイズしていってください。

参考資料

公式ドキュメント

プラグイン

関連記事

ZSL
ZSL

AIエンジニア

生成AIを活用した開発ワークフローの研究・実践をしています。