爆速Fuzzy FinderプラグインSnacks.pickerの使い方
snacks.nvimにあるFuzzy Finderプラグインpickerの設定方法や使い方を紹介します。

Snacksとは?
snacks.nvimは便利プラグインが詰め込まれたプラグイン集です。イメージとしてはmini.nvimに近いです。
この記事で紹介する「picker」の他、「ダッシュボード」「スクラッチバッファ」「lazygitとの連携」など20以上の機能があります。
全部知りたい人はREADMEを見るのがオススメです。
pickerとは?
SnacksのpickerはFuzzy Finderプラグインです。
近いプラグインを挙げるとtelescope.nvimなどがあります。毎月Fuzzy Finderプラグインの産声が聞こえるのは気のせいでしょうか。
pickerはビルトインで使える絞り込みが多いです。2025年2月時点では40以上あります。
「複数選択」「横に開く(vsplit)」「quickfixで開く」「レイアウトを変更する」など、さまざまな操作ができるキーマップも簡単に設定できます。
Snacksのpickerは非同期にファイル検索・マッチ処理をしてくれるため、めっちゃ速い&スムーズです。
fzfのSearch syntaxもサポートされてます。
導入方法
folke/snacks.nvim
各々が使っているプラグインマネージャーでインストールします。
インストール
lazy.nvimだと次のように書いてインストールできます。
return { "folke/snacks.nvim", priority = 1000, lazy = false, ---@type snacks.Config opts = {},}
遅延読み込みせずに優先度をあげて早めに読み込むことが推奨されています。
遅延読み込み大好き人間にとっては心配かもしれませんが、snacks本体のsetupはautocmd
の定義ぐらいで、全部の機能を読み込んでしまうわけではありません。
依存プラグイン
依存プラグインはありません。
アイコンを表示させたい人はmini.iconsかnvim-web-deviconsのどちらかを入れておきましょう。
最低限の設定
最低限のプラグインの設定はsetup
を呼び出すだけで完了です。
require('snacks').setup()
lazy.nvimの場合、setup
の中身はopts
に書くためこの記述は不要です。この書き方について知りたい人は別の記事「lazy.nvimの使い方から起動を爆速にする方法までを解説」を読んでください。
pickerの基本的な使い方
さくっと使い方を紹介します。カスタマイズは後で説明します。
snacksはrequire
の他、グローバル変数Snacks
から呼び出すこともできます。
require("snacks.picker").buffers()Snacks.picker.buffers()
この記事では面倒なので次のようにpicker.〇〇()
と書きます。
local picker = require("snacks.picker")picker.buffers()
ピッカーのキーマップの一覧
ピッカーを開くと挿入モードになっています。
まずはEsc
でノーマルモードにしてから?
を入力し、キーマップのヘルプを開いてみましょう。

画面の下に、pickerで使えるデフォルトのキーマップが表示されます。
あるいは:help snacks-picker-config
でデフォルトの設定を見てみましょう(長いけども)。
バッファ一覧
picker.buffers()
バッファの一覧では、見た目がそのまま表示されます。

winbarやsigncolumn、diagnosticsなどがそのまま表示され、まるでスクショみたいです。
ノーマルモードに切り替えてdd
を入力するとバッファを削除できます。
ファイル系
みんな大好きファイルピッカーもあります。

picker.git_files()picker.files()picker.recent()
files()
ではfd
・rg
・find
のコマンドを自動で見つけて使ってくれるようです。
recent
は最近開いたファイルです。
smart
picker.smart()
smart
を実行すると、buffers
・recent
・files
の結果を重複を削除して一覧にしてくれます。
バッファならプレビューがbuffers
のときと同じようになります。
エクスプローラー
ファイルの一覧をツリーでみたいならexplorer
を使います。
picker.explorer()

ファイルの移動や削除もできるようです。詳しくは?
を入力するか:help snacks-picker-sources-explorer
でデフォルトのキーマップを見てみましょう。
grep
grepもあります。
picker.grep()
実装を見てみると、内部で叩かれるコマンドはripgrepのようです。
LSP系
LSP関係のピッカーも用意されています。よく使いそうなのは次の2つでしょうか。
picker.lsp_references()picker.lsp_definitions()
Vim・Neovim関係
これもたくさんあるのでよく使いそうなやつを。
keymaps
picker.keymaps()
定義されているキーマップの一覧です。

luaの関数で定義した場合、そのファイルがプレビューされて分かりやすいです。
highlights
picker.highlights()
highlights
はハイライトして表示されます。

colorschemes
picker.colorschemes()
colorschemes
はカーソル行のカラースキームがすぐに適用されるため、何度もピッカーを開かなくていいですね。

TODOコメント検索
todo-comments.nvimを使っている場合、TODOコメントを検索可能です。
picker.todo_comments()

ピッカーのピッカー
ビルトインのピッカーが40以上あるため、全部にキーマップを設定するのは大変ですし覚えられません。
使用頻度が少ないものはキーマップをセットせず、ピッカーのピッカーから呼びましょう。
picker.pickers()
ピッカーの一覧が表示され、選んだピッカー実行されます。

直前のピッカーを呼び出す
直前に閉じたピッカーをもう一度表示するにはresume
を使います。
picker.resume()
Snacks.pickerのカスタマイズ例
ピッカーの紹介はこれぐらいにして、ここからは実際に筆者が使っているカスタマイズの例を解説します。
レイアウトを変えたい
レイアウトの種類を変える場合はlayout.preset
に書きます。
require("snacks").setup({ picker = { layout = { cycle = true, --- Use the default layout or vertical if the window is too narrow preset = function() return vim.o.columns >= 120 and "default" or "vertical" end, }, }})
ピッカー毎に変更したいならpicker.〇〇
の引数に渡してあげましょう。これはレイアウトに限らず、キーマップなど他の設定でも同様です。
次はfiles
のレイアウトをvertical
にする例です。
picker.files({ layout = { preset = "vertical", layout = { width = 0.9 } }})
レイアウトの値を調整したいだけなら次のようにlayouts
(複数形)の方に書きます。
require("snacks").setup({ picker = { layouts = { default = { layout = { width = 0.95 } }, }, }})
上記は、デフォルトのレイアウトの幅を変更しています。
キーマップを変えたい
デフォルトのキーマップを変えるなら、picker.win.input.keys
に書きます。
require("snacks").setup({ picker = { win = { input = { keys = { -- select allを無効化 ["<c-a>"] = false, ["<c-b>"] = false, ["<c-d>"] = { "preview_scroll_down", mode = { "i", "n" } }, ["<c-f>"] = false, ["<c-u>"] = { "preview_scroll_up", mode = { "i", "n" } }, ["<c-s>"] = false, ["<c-x>"] = { "edit_split", mode = { "i", "n" } }, }, }, }, }})
無効化するならfalse
を指定します。
パスの省略表記を変更したい
デフォルトではファイル名が40文字以上だと、パスの一部が省略されます。これを変更したい場合はtruncate
を変えます。
require("snacks").setup({ picker = { formatters = { file = { truncate = 200 } }, }})
visualモードなら選択テキストを検索ワードにしたい
「visualモードでピッカーを起動したら選択テキストを検索ワードにする方法」を紹介します。
まずは選択テキストを取得する関数を定義。
local function get_text() local visual = picker.util.visual() return visual and visual.text or ""end
この関数はpickerを立ち上げる前に呼びます。
files
やgit_files
ならpattern
に渡します。
local text = get_text()picker.files({ pattern = text })picker.git_files({ pattern = text })
grepならon_show
で挿入します。
local text = get_text()picker.grep({ on_show = function() vim.api.nvim_put({ text }, "c", true, true) end,})
git_filesで未追跡ファイルも表示
デフォルトのpicker.git_files()
は、ステージングに上げてないファイルは非表示です。
未追跡でも表示したい場合はuntracked
を指定します。
picker.git_files({ untracked = true })
dotfilesのpicker
dotfilesの一覧を出したいなら次のようにcwd
を変更します。
picker.git_files({ cwd = '~/dotfiles' })
Gitを使っているか気にしないファイル検索
いちいち「カレントディレクトリがGit管理下なのか」を意識するのは面倒です。
そこで、カレントディレクトリがGitを使っていればgit_files
、使っていないならfiles
を呼んでくれるキーマップを定義します。
local function project_files() local text = get_text()
local root = require("snacks.git").get_root() if root == nil then picker.files({ pattern = text }) return end picker.git_files({ untracked = true, pattern = text, })end
先ほど定義したget_text
をここでも使っています。
モノレポ対応
前述のproject_files
をモノレポでも使いやすくします。
次のようなリポジトリを例にします。
./awesome├── .git├── packages│ ├── project-1 # カレントディレクトリ│ └── project-2
「カレントディレクトリ(project-1
)だけを検索対象にしたい」「リポジトリ全体を検索対象にしたい」という2つのケースが出てくると思います。
これに対応するのが次の定義です。
---@param use_git_root boolean git_rootを使うかどうか。モノレポの個別プロジェクトならfalselocal function project_files(use_git_root) local text = get_text()
local root = require("snacks.git").get_root() if root == nil then picker.files({ pattern = text }) return end if use_git_root then picker.git_files({ untracked = true, pattern = text, }) else picker.git_files({ untracked = true, pattern = text, cwd = vim.uv.cwd(), }) endend
project_files(false)
ならカレントディレクトリだけを検索対象にします。
筆者は次のようにlazy.nvimのkeysで定義して使ってます。
{ "<space>ff", function() project_files(false) end, mode = { "n", "x" }, desc = "モノレポでプロジェクト毎"},{ "<space>fF", function() project_files(true) end, mode = { "n", "x" }, desc = "モノレポでプロジェクト全体"},
通常は<space>ff
で検索し、モノレポ構成でリポジトリ全体を見たいときに<space>fF
を使います。
オリジナルのピッカーを作る
ここからはオリジナルのピッカーの作り方を解説します。
同階層のファイルだけを検索
同階層のファイルだけを検索するピッカーを作りました。Angularのような同階層のファイル間を行き来するプロジェクトで重宝しています。
今まではpicker.〇〇
を使っていましたが、今度はpicker()に直接引数を渡します。
先に実装の全体を載せます。次の項目から小分けにして解説します。
picker({ finder = "proc", cmd = "find", args = { vim.fn.expand("%:h"), "-type", "f", "-not", "-name", vim.fn.expand("%:t") }, ---@param item snacks.picker.finder.Item transform = function(item) item.file = item.text end,})
finderをprocにする
finder
をproc
にすると外部コマンドを呼べます。cmd
にコマンド名、引数はargs
にテーブルとして渡します。
picker({ finder = "proc", cmd = "find", args = { vim.fn.expand("%:h"), "-type", "f", "-not", "-name", vim.fn.expand("%:t") }, -- ...})
-not -name ……
を引数に渡すことで、現在カーソルがあるファイルは一覧から省けます。
transformとは
コマンドの実行結果をピッカーで扱えるように変換する処理をtransform
に書きます。
transform = function(item) item.file = item.textend,
find
の出力結果はただのファイル名のみであるため、item.file = item.text
を指定します。
find src/pages/foo/foo-buz -maxdepth 1 -type f -not -name 'foo-buz.html'
src/pages/foo/foo-buz/foo-buz.scsssrc/pages/foo/foo-buz/foo-buz.tssrc/pages/foo/foo-buz/foo-buz.module.ts
ファイル以外のピッカーを作る
ファイル以外を扱うピッカーは、finder
にsnacks.picker.Item[]
型を返す関数を書きます。
ここでは選んだアイテムを通知するだけの簡単なピッカーを例に挙げます。

先に実装の全体を載せます。次の項目から小分けにして解説します。
picker({ finder = function() local my_list = { { quote = "選ばれるのは私よ!", thanks = "ありがとうなのだわ!" }, { quote = "うるさいんですけどぉ〜", thanks = "別にありがとうとか思ってないんだからね!" }, { quote = "ちっす", thanks = "どうも" }, } ---@type snacks.picker.Item[] local items = {} for i, person in ipairs(my_list) do ---@type snacks.picker.Item local item = { idx = i, score = 0, text = person.quote, thanks = person.thanks, } table.insert(items, item) end return items end, ---@type snacks.picker.Action.spec confirm = function(the_picker, item) the_picker:close() vim.notify(item.thanks) end, format = "text", preview = "none", layout = { preset = "vscode" },})
finderでリストを返す
finderの中身を見てみましょう。
local my_list = { { quote = "選ばれるのは私よ!", thanks = "ありがとうなのだわ!" }, { quote = "うるさいんですけどぉ〜", thanks = "別にありがとうとか思ってないんだからね!", }, { quote = "ちっす", thanks = "どうも" },}---@type snacks.picker.Item[]local items = {}for i, person in ipairs(my_list) do ---@type snacks.picker.Item local item = { idx = i, score = 0, text = person.quote, thanks = person.thanks, } table.insert(items, item)endreturn items
ピッカーに渡すItemはidx
・score
・text
が必須です。thanks
のように独自のキーも追加できます。
confirm
confirmには、アイテムを選択したときに実行する処理を書きます。
---@type snacks.picker.Action.specconfirm = function(the_picker, item) the_picker:close() vim.notify(item.thanks)end,
残りのキー
残りのキーは見た目に関するものです。
{ -- ... format = "text", preview = "none", layout = { preset = "vscode" },}
text-case.nvimをSnacksに対応させる
text-case.nvimはテキストをPascalCase
やsnake_case
に変更してくれるプラグインです。
これをpickerで選んで実行できるようにしました。

長いので折りたたみの中に書きました。
設定例(クリックで開きます)
require("textcase").setup({})local plugin = require("textcase.plugin.plugin")local picker = require("snacks.picker")local constants = require("textcase.shared.constants")local api = require("textcase").apilocal api_list = { api.to_upper_case, api.to_lower_case, api.to_snake_case, api.to_dash_case, api.to_title_dash_case, api.to_constant_case, api.to_dot_case, api.to_comma_case, api.to_phrase_case, api.to_camel_case, api.to_pascal_case, api.to_title_case, api.to_path_case,}
---@param mode string---@return snacks.picker.Item[]local function create_items(mode) ---@type snacks.picker.Item[] local items = {}
---@type { prefix: string, type: string }[] local conversion_dict = {} if mode ~= "n" then table.insert(conversion_dict, { prefix = "Convert to ", type = constants.change_type.VISUAL }) else table.insert(conversion_dict, { prefix = "Convert to ", type = constants.change_type.CURRENT_WORD }) table.insert(conversion_dict, { prefix = "Lsp rename ", type = constants.change_type.LSP_RENAME }) end
local i = 1 for _, conversion in pairs(conversion_dict) do for _, method in pairs(api_list) do ---@type snacks.picker.Item local item = { idx = i, score = 0, text = conversion.prefix .. method.desc, method_name = method.method_name, type = conversion.type, } table.insert(items, item) i = i + 1 end end return itemsend
---@type snacks.picker.Action.speclocal function invoke_replacement(the_picker, item) the_picker:close() if item.type == constants.change_type.CURRENT_WORD then plugin.current_word(item.method_name) elseif item.type == constants.change_type.LSP_RENAME then plugin.lsp_rename(item.method_name) elseif item.type == constants.change_type.VISUAL then plugin.visual(item.method_name) endend
vim.keymap.set({ "n", "v" }, "gt", function() local mode = vim.api.nvim_get_mode().mode picker({ finder = function() return create_items(mode) end, confirm = invoke_replacement, format = "text", preview = "none", layout = { preset = "vscode" }, })end, { desc = "Picker: textcase" })end,
以上、snacks.nvimのpickerの紹介でした。めちゃくちゃ便利!