Skip to content

Commit 6a25311

Browse files
authored
Merge pull request #4 from obsidian-nvim/snacks-picker
implementing snack picker
2 parents e0c781e + d66b1f0 commit 6a25311

File tree

7 files changed

+177
-4
lines changed

7 files changed

+177
-4
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Added `opts.follow_img_func` option for customizing how to handle image paths.
1313
- Added better handling for undefined template fields, which will now be prompted for.
14+
- Added support for the [`snacks.picker`](https://github.com/folke/snacks.nvim/blob/main/docs/picker.md) picker
1415
- Added support for the [`blink.cmp`](https://github.com/Saghen/blink.cmp) completion plugin.
1516

1617
### Changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ The only **required** plugin dependency is [plenary.nvim](https://github.com/nvi
202202
- **[recommended]** [nvim-telescope/telescope.nvim](https://github.com/nvim-telescope/telescope.nvim): for search and quick-switch functionality.
203203
- [Mini.Pick](https://github.com/echasnovski/mini.pick) from the mini.nvim library: an alternative to telescope for search and quick-switch functionality.
204204
- [ibhagwan/fzf-lua](https://github.com/ibhagwan/fzf-lua): another alternative to telescope for search and quick-switch functionality.
205+
- [Snacks.Picker](https://github.com/folke/snacks.nvim/blob/main/docs/picker.md) from the snacks.nvim library: an alternative to mini and telescope for search and quick-switch functionality.
205206

206207
**Syntax highlighting:**
207208

@@ -415,7 +416,7 @@ This is a complete list of all of the options that can be passed to `require("ob
415416
open_app_foreground = false,
416417

417418
picker = {
418-
-- Set your preferred picker. Can be one of 'telescope.nvim', 'fzf-lua', or 'mini.pick'.
419+
-- Set your preferred picker. Can be one of 'telescope.nvim', 'fzf-lua', 'mini.pick' or 'snacks.pick'.
419420
name = "telescope.nvim",
420421
-- Optional, configure key mappings for the picker. These are the defaults.
421422
-- Not all pickers support all mappings.

doc/obsidian.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ dependencies that enhance the obsidian.nvim experience.
254254
- **[recommended]** nvim-telescope/telescope.nvim <https://github.com/nvim-telescope/telescope.nvim>: for search and quick-switch functionality.
255255
- Mini.Pick <https://github.com/echasnovski/mini.pick> from the mini.nvim library: an alternative to telescope for search and quick-switch functionality.
256256
- ibhagwan/fzf-lua <https://github.com/ibhagwan/fzf-lua>: another alternative to telescope for search and quick-switch functionality.
257+
- Snacks.Pick <https://github.com/folke/snacks.nvim/blob/main/docs/picker.md>: another alternative to telescope for search and quick-switch functionality.
257258

258259
**Syntax highlighting:**
259260

@@ -472,7 +473,7 @@ carefully and customize it to your needs:
472473
open_app_foreground = false,
473474

474475
picker = {
475-
-- Set your preferred picker. Can be one of 'telescope.nvim', 'fzf-lua', or 'mini.pick'.
476+
-- Set your preferred picker. Can be one of 'telescope.nvim', 'fzf-lua', 'mini.pick' or 'snacks.pick'.
476477
name = "telescope.nvim",
477478
-- Optional, configure key mappings for the picker. These are the defaults.
478479
-- Not all pickers support all mappings.

lua/obsidian/commands/debug.lua

+9-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,15 @@ return function(client, data)
7474

7575
log.lazy_info "Dependencies:"
7676

77-
for _, plugin in ipairs { "plenary.nvim", "nvim-cmp", "blink.cmp", "telescope.nvim", "fzf-lua", "mini.pick" } do
77+
for _, plugin in ipairs {
78+
"plenary.nvim",
79+
"nvim-cmp",
80+
"blink.cmp",
81+
"telescope.nvim",
82+
"fzf-lua",
83+
"mini.pick",
84+
"snacks.pick",
85+
} do
7886
local plugin_info = util.get_plugin_info(plugin)
7987
if plugin_info ~= nil then
8088
log.lazy_info(" ✓ %s: %s", plugin, plugin_info.commit or "unknown")

lua/obsidian/config.lua

+1
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ config.Picker = {
344344
telescope = "telescope.nvim",
345345
fzf_lua = "fzf-lua",
346346
mini = "mini.pick",
347+
snacks = "snacks.pick",
347348
}
348349

349350
---@class obsidian.config.PickerOpts

lua/obsidian/pickers/_snacks.lua

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
local snacks_picker = require "snacks.picker"
2+
3+
local Path = require "obsidian.path"
4+
local abc = require "obsidian.abc"
5+
local Picker = require "obsidian.pickers.picker"
6+
7+
local function debug_once(msg, ...)
8+
-- vim.notify(msg .. vim.inspect(...))
9+
end
10+
11+
---@param mapping table
12+
---@return table
13+
local function notes_mappings(mapping)
14+
if type(mapping) == "table" then
15+
local opts = { win = { input = { keys = {} } }, actions = {} }
16+
for k, v in pairs(mapping) do
17+
local name = string.gsub(v.desc, " ", "_")
18+
opts.win.input.keys = {
19+
[k] = { name, mode = { "n", "i" }, desc = v.desc },
20+
}
21+
opts.actions[name] = function(picker, item)
22+
debug_once("mappings :", item)
23+
picker:close()
24+
vim.schedule(function()
25+
v.callback(item.value or item._path)
26+
end)
27+
end
28+
end
29+
return opts
30+
end
31+
return {}
32+
end
33+
34+
---@class obsidian.pickers.SnacksPicker : obsidian.Picker
35+
local SnacksPicker = abc.new_class({
36+
---@diagnostic disable-next-line: unused-local
37+
__tostring = function(self)
38+
return "SnacksPicker()"
39+
end,
40+
}, Picker)
41+
42+
---@param opts obsidian.PickerFindOpts|? Options.
43+
SnacksPicker.find_files = function(self, opts)
44+
opts = opts or {}
45+
46+
---@type obsidian.Path
47+
local dir = opts.dir.filename and Path:new(opts.dir.filename) or self.client.dir
48+
49+
local map = vim.tbl_deep_extend("force", {}, notes_mappings(opts.selection_mappings))
50+
51+
local pick_opts = vim.tbl_extend("force", map or {}, {
52+
source = "files",
53+
title = opts.prompt_title,
54+
cwd = tostring(dir),
55+
confirm = function(picker, item, action)
56+
picker:close()
57+
if item then
58+
if opts.callback then
59+
debug_once("find files callback: ", item)
60+
opts.callback(item._path)
61+
else
62+
debug_once("find files jump: ", item)
63+
snacks_picker.actions.jump(picker, item, action)
64+
end
65+
end
66+
end,
67+
})
68+
snacks_picker.pick(pick_opts)
69+
end
70+
71+
---@param opts obsidian.PickerGrepOpts|? Options.
72+
SnacksPicker.grep = function(self, opts)
73+
opts = opts or {}
74+
75+
debug_once("grep opts : ", opts)
76+
77+
---@type obsidian.Path
78+
local dir = opts.dir.filename and Path:new(opts.dir.filename) or self.client.dir
79+
80+
local map = vim.tbl_deep_extend("force", {}, notes_mappings(opts.selection_mappings))
81+
82+
local pick_opts = vim.tbl_extend("force", map or {}, {
83+
source = "grep",
84+
title = opts.prompt_title,
85+
cwd = tostring(dir),
86+
confirm = function(picker, item, action)
87+
picker:close()
88+
if item then
89+
if opts.callback then
90+
debug_once("grep callback: ", item)
91+
opts.callback(item._path or item.filename)
92+
else
93+
debug_once("grep jump: ", item)
94+
snacks_picker.actions.jump(picker, item, action)
95+
end
96+
end
97+
end,
98+
})
99+
snacks_picker.pick(pick_opts)
100+
end
101+
102+
---@param values string[]|obsidian.PickerEntry[]
103+
---@param opts obsidian.PickerPickOpts|? Options.
104+
---@diagnostic disable-next-line: unused-local
105+
SnacksPicker.pick = function(self, values, opts)
106+
self.calling_bufnr = vim.api.nvim_get_current_buf()
107+
108+
opts = opts or {}
109+
110+
debug_once("pick opts: ", opts)
111+
112+
local buf = opts.buf or vim.api.nvim_get_current_buf()
113+
114+
local entries = {}
115+
for _, value in ipairs(values) do
116+
if type(value) == "string" then
117+
table.insert(entries, {
118+
text = value,
119+
value = value,
120+
})
121+
elseif value.valid ~= false then
122+
local name = self:_make_display(value)
123+
table.insert(entries, {
124+
text = name,
125+
buf = buf,
126+
filename = value.filename,
127+
value = value.value,
128+
pos = { value.lnum, value.col or 0 },
129+
})
130+
end
131+
end
132+
133+
local map = vim.tbl_deep_extend("force", {}, notes_mappings(opts.selection_mappings))
134+
135+
local pick_opts = vim.tbl_extend("force", map or {}, {
136+
tilte = opts.prompt_title,
137+
items = entries,
138+
layout = {
139+
preview = false,
140+
},
141+
format = "text",
142+
confirm = function(picker, item, action)
143+
picker:close()
144+
if item then
145+
if opts.callback then
146+
debug_once("pick callback: ", item)
147+
opts.callback(item.value)
148+
else
149+
debug_once("pick jump: ", item)
150+
snacks_picker.actions.jump(picker, item, action)
151+
end
152+
end
153+
end,
154+
})
155+
156+
snacks_picker.pick(pick_opts)
157+
end
158+
159+
return SnacksPicker

lua/obsidian/pickers/init.lua

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ M.get = function(client, picker_name)
1313
if picker_name then
1414
picker_name = string.lower(picker_name)
1515
else
16-
for _, name in ipairs { PickerName.telescope, PickerName.fzf_lua, PickerName.mini } do
16+
for _, name in ipairs { PickerName.telescope, PickerName.fzf_lua, PickerName.mini, PickerName.snacks } do
1717
local ok, res = pcall(M.get, client, name)
1818
if ok then
1919
return res
@@ -28,6 +28,8 @@ M.get = function(client, picker_name)
2828
return require("obsidian.pickers._mini").new(client)
2929
elseif picker_name == string.lower(PickerName.fzf_lua) then
3030
return require("obsidian.pickers._fzf").new(client)
31+
elseif picker_name == string.lower(PickerName.snacks) then
32+
return require("obsidian.pickers._snacks").new(client)
3133
elseif picker_name then
3234
error("not implemented for " .. picker_name)
3335
end

0 commit comments

Comments
 (0)