← Vim研究所

Neovimのmini.nvimとは 0.12の標準機能と重なるモジュールを見分ける

2026-11-08 公開 ・

mini.nvimは、コメント・補完・括弧の付け外し・ファイラーなどを1つにまとめたNeovimのプラグイン集で、手元に入れた版ではlua/mini/の下に46個のモジュールがありました。Neovim 0.12でコメントのgc、autocomplete、vim.snippet、vim.packが本体に入り、その一部と役目が重なっています。

そこでNeovim 0.12.6で、重なりそうなモジュールを標準機能と同じ操作で動かして比べました。結論を先に書くと、コメントとプラグイン管理は標準で足ります。一方でmini.aiの関数呼び出しと引数のテキストオブジェクト、mini.surround、mini.filesは標準に代わりがありません。

検証環境:NVIM v0.12.6(macOS)、比較用にVim 9.1.1752。mini.nvimは2026-11-07のmainブランチ(コミットf9550dd、CHANGELOG上は0.19.0-dev。最新のstableはv0.18.0)、MiniMaxは同日のコミット9f3ac33です。一時ディレクトリにgit cloneし、nvim -n -uで数行の設定を読ませて起動しました。編集結果はnvim_feedkeys()でキーを送った結果、補完・スニペット・mini.filesはtmuxで操作した画面です。oil.nvimは入れていません。

目次(9項目)

mini.nvimとは何か

モジュールは互いに依存せず、どれもrequire('mini.xxx').setup()を呼ぶまで何もしません。runtimepathに足しただけ、requireしただけ、setup()の後の3つで、キーマップをmaparg()で読み比べました。

before: MiniAi= nil  sa= (none)  gc= Toggle comment  gcc= Toggle comment line  M-j= (none)
after require only: MiniComment= false  gc= Toggle comment
after setup: gc= Comment  gcc= Comment line  sa= Add surrounding  M-j= Move line down  o_a= Around textobject

1行目のgcに付いているToggle commentはNeovim本体のマッピングです。require('mini.comment')だけでは何も変わらず、グローバルのMiniCommentも作られません。setup()を呼んだところで初めてgcがmini.commentのCommentに置き換わり、mini.surroundのsaやmini.moveのAlt-jが生えます。入れたのに効かないときはsetup()の呼び忘れを疑ってください。

入れ方 モジュールごとか丸ごとか

READMEが推奨として最初に挙げているのはvim.packです。丸ごと入れるなら1行で済みます。

-- init.lua(mainブランチ)
vim.pack.add({ 'https://github.com/nvim-mini/mini.nvim' })
-- stableブランチにする場合
vim.pack.add({ { src = 'https://github.com/nvim-mini/mini.nvim', version = 'stable' } })
require('mini.surround').setup()

各モジュールは単独のリポジトリとしても配られています。https://github.com/nvim-mini/mini.surroundをvim.pack.add()に渡して試したところ、入ったのはmini.surroundのディレクトリだけで、require('mini.ai')は失敗しました。ロックファイルnvim-pack-lock.jsonには次の1件が書かれます。

{
  "plugins": {
    "mini.surround": {
      "rev": "5357f00aca51a3b43e7775901b1ad9699f8c2678",
      "src": "https://github.com/nvim-mini/mini.surround"
    }
  }
}

lazy.nvimならREADMEの書き方は{ 'nvim-mini/mini.nvim', version = false }(stableはversion = '*')で、setup()はやはり自分で呼びます。vim.packそのものの使い方はNeovim 0.12の標準プラグイン管理 vim.packにまとめてあります。

Neovim 0.12の標準機能と重なるモジュール

mini.comment と標準のgc

Neovim 0.10から入った標準のgcは、MiniMaxの設定ファイルのコメントによるとmini.commentを元にしています。Luaのバッファで比べると、ほとんど区別が付きません。

操作標準のgcmini.comment
gcc→j→.2行ともコメント化同じ
3gcc3行コメント化同じ
dgcコメントの塊を削除同じ
空行を含む範囲空行にも--が入る同じ(ignore_blank_lineで除外できる)
commentstring=--%s--a = 1-- a = 1

違いは最後の2行です。mini.commentはpad_comment_partsが既定で有効なので、commentstringに空白が無くても記号の後に空白を入れます。ほかにhooksとcustom_commentstringがありますが、こうした調整が要らないなら標準のgcで足ります。

mini.completion と標準のautocomplete

LSP無しでfoobar foobaz footballと書いたバッファにfooと打つと、vim.o.autocomplete = trueだけでもrequire('mini.completion').setup()だけでも、同じ3つの候補が出ました。LSPが無いときのmini.completionは100ミリ秒待ってCtrl-nを実行するだけです。

差が出るのはLSPを使うときです。mini.completionはLSPの候補を先に取り、無ければCtrl-nへ落ちる2段構えで、候補の説明と関数の引数も浮動ウィンドウに出します。標準側はvim.lsp.completion.enable()にautotrigger = trueを渡します。設定はVim/Neovimの標準自動補完(autocomplete)で扱っています。

mini.snippets と vim.snippet

vim.snippetにあるのはvim.snippet.expand()とジャンプの仕組みだけです。vim.snippet.expand('function ${1:name}($2)\n\t$0\nend')を呼ぶと3行の関数が展開されますが、fnと打ってから展開する手段は本体にありません。素の状態でfnのあとCtrl-jを押すと、ただ改行が入りました。

mini.snippetsは同じ本文をprefix = 'fn'で登録しておくと、fn→Ctrl-jで展開します。nameの位置でfooと打つと仮の文字が置き換わり、Ctrl-lで括弧の中、次のCtrl-lで本文の行へ移りました。戻るのはCtrl-h、やめるのはCtrl-cです。JSONのスニペット集を読む仕組みもmini側にしかありません。詳しい境目はNeovimでスニペットを使う vim.snippetとLuaSnipの境目を見てください。

mini.deps と vim.pack

ここは比べるまでもありません。mini.depsのヘルプの冒頭に、vim.packがmini.depsを設計の参考にして入ったこと、開発は凍結したこと、0.12以降ではvim.packを使うよう勧めることが書いてあります。mini.depsにあったMiniDeps.nowとMiniDeps.laterの代わりは、mini.miscのMiniMisc.safelyです。

local misc = require('mini.misc')
misc.safely('now', function() table.insert(order, 'now') end)
misc.safely('later', function() table.insert(order, 'later') end)
table.insert(order, 'end-of-init')
misc.safely('now', function() error('boom') end)
-- 出力: now -> end-of-init -> later
-- error('boom') は (mini.misc) Error during safe execution: ... の警告になり、起動は続く

'later'の関数は設定ファイルを読み終えてから実行され、error('boom')は警告になって残りの設定は止まりませんでした。

mini.ai と標準のテキストオブジェクトの差

カーソルを行頭に置いたlocal x = foo(bar, "baz qux") + baz(1)で、同じキーを標準とmini.aiの両方で打ちました。

キーカーソル標準mini.ai
di"行頭foo(bar, "")同じ
di)行頭foo()同じ
din)barの上変化なしbaz(1)の1を削除
dif行頭変化なしfoo()
daf行頭変化なしfoo(...)ごと削除
diabarの上変化なしfoo(, "baz qux")
diq行頭変化なしfoo(bar, "")

意外だったのは2行目です。括弧の外からでも、標準のdi)は同じ行の先の括弧を見つけて中身を消しました(Vim 9.1.1752でも同じ)。これはmini.aiだけの利点ではありません。mini.aiにしかないのは、関数呼び出しのf、引数1つぶんのa、引用符の種類を問わないq、そして「次の」括弧を指すin/anです。

そのinとanには注意が要ります。Neovim 0.12はビジュアルモードと演算子待ちのan/inに、構文木やLSPで選択範囲を広げ縮めする機能を割り当てました。標準のままdin)を打つとvim.lsp: method "textDocument/selectionRange" is not supportedと出て何も起きなかったのはこのためです。mini.aiはsetup()でこれを上書きします。

before x an Select parent (outer) node
before x in Select child (inner) node
after x an Around next textobject
after x in Inside next textobject

:h MiniAi-default-an-inは上書きを意図したものとしたうえで、setup()の前に標準のマッピングを別のキーへ写す方法と、around_next = 'aN'のように名前を変える方法を載せています。同じように「前の」を指すal/ilも、Neovimに行と全体のテキストオブジェクトが入る al と ilで扱った0.13の新機能と名前が重なります。

mini.surround・mini.move・mini.filesで標準に無いこと

この3つは0.12.6の本体に相当する機能がありません。mini.surroundはsaで付け、sdで外し、srで付け替えます。hello worldの先頭でsaiw)なら(hello) world、saiw(なら( hello ) worldです。setup()のあとmaparg('s', 'n')は<Nop>を返し、素のsは使えなくなります(代わりはcl)。f(a)でsr)]はf[a]、x = foo(bar)のfooの上でsdfは関数名ごと外してx = barになりました。

ただしmini.surroundの検索は既定でsearch_method = 'cover'、つまりカーソルを囲んでいるものしか探しません。x = "hi"の行頭でsd"を打つとNo surrounding '"' found within 20 linesと出て失敗し、引用符の中からなら外れました。先を探すmini.aiとは既定が違います。vim-surroundのys/cs/dsとの対応はVimのsurroundで括弧や引用符を付け替える(ys / cs / ds)にあります。

mini.moveはAlt-j/Alt-kで行や選択範囲を上下に動かします。a b c dの4行でVj→Alt-jならc a b dの順になりました。標準では:mを自分でマップします(Vimで行を上下に移動する :mコマンドとddpの違い)。キーはnvim_feedkeys()で送ったので、端末のAltキーが届くかは確かめていません。

mini.filesはディレクトリを列で並べるファイラーです。:lua MiniFiles.open()で開き、lで子のディレクトリが右の列に開き、hで戻ります。ファイルの操作は列のバッファを書き換えて=を押すと確定します。srcの列でoからnew.luaと書いて=を押すと、次の確認が出ました。

CONFIRM FILE SYSTEM ACTIONS

.../proj/src
  CREATE │ new.lua (file)

[Y]es, (N)o, (C)ancel:

ここで気を付けたいのが改名です。util.luaの行をccで丸ごと書き直して=を押すと、確認画面はDELETE │ util.lua (permanently)とCREATE │ helpers.lua (file)の2行になりました。行の先頭には見えない識別子が隠れていて、ccはそれごと消すからです。名前の部分だけをciwなどで書き換えたときはRENAMEと出ました。既定のpermanent_delete = trueでは削除がゴミ箱を通りません。

oil.nvimは:wで確定しますが、mini.filesで:wを打つとE382: Cannot write, 'buftype' option is setになりました(buftypeはnofile)。確定のキーは=だけです。oil.nvim側の操作はNeovimのoil.nvimの使い方にあります。標準のnetrwは%やRで1つずつ操作する方式です。

公式の雛形MiniMaxは何を有効にしているか

MiniMaxはmini.nvimの作者による設定の生成スクリプトで、NVIM_APPNAME=nvim-minimax nvim -l ./MiniMax/setup.luaを流すとNeovimの版に合った雛形を写します。0.12用の雛形はプラグインをvim.pack.add()で入れ、mini.depsは使わず、読み込みの順番をMiniMisc.safelyで書いています。

plugin/30_mini.luaでrequireしているモジュールを数えると37個でした。使っていないのはanimate base16 colors cursorword deps doc fuzzy hues testの9個です。標準と重なるmini.commentも有効のままで、「標準のコメント機能はmini.commentが元だが、調整の余地が多いので有効にしておく」という趣旨のコメントが付いています。mini.snippetsはfriendly-snippetsを読む形でした。

標準で足りるもの、miniを入れる価値があるもの

モジュール比べた標準機能判定決め手
mini.depsvim.pack標準で足りる開発凍結。作者もvim.packを勧める
mini.commentgc標準で足りる差は空白の補い・空行の扱い・hooksだけ
mini.completionautocompleteLSP次第LSP無しなら同じ。説明と引数の表示はmini
mini.snippetsvim.snippetminiに差あり接頭辞から展開・スニペット集の読み込み
mini.aii( i"miniに差ありf a qと次の括弧。an/inは上書き
mini.surroundなしminiにしかない付け・外し・付け替え
mini.move:mminiにしかない選択範囲ごと動かせる
mini.filesnetrwminiにしかない列表示と=での一括確定

0.12で本体に入った機能全体の一覧はNeovim 0.12の新機能 外せるプラグインと外せないものにあります。

使ってみて

mini.filesで改名を試したとき、最初は手に馴染んだccで行を打ち直しました。確認画面にRENAMEではなくDELETEが出ていて、しかも(permanently)と付いていたので慌ててcで取り消しました。一時ディレクトリの空ファイルでしたが、本物のプロジェクトでyを反射的に押していたらゴミ箱にも残りません。

まとめ

Neovim 0.12で使うなら、mini.depsとmini.commentは入れなくて困りません。最初に入れる3つを選ぶなら、標準に代わりのないmini.ai、mini.surround、mini.filesです。mini.aiは0.12のan/inを上書きすること、mini.filesの改名は名前の部分だけを書き換えることの2つを覚えておけば足ります。補完とスニペットは、LSPとスニペット集を使うかどうかで決めてください。

関連記事

← Vim研究所 トップへ戻る