diff --git a/README.md b/README.md index b42a9867..d57259ad 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,17 @@ require"octo".setup({ merge_pr = { lhs = "", desc = "merge pull request" }, }, snacks = { -- snacks specific config + -- Snacks picker configuration (see https://github.com/folke/snacks.nvim/blob/main/docs/picker.md) + layout = { -- layout configuration for all pickers + preset = "sidebar", -- preset layout: "dropdown", "ivy", "sidebar", "telescope" + -- Additional layout options: + -- reverse = true, + -- width = 0.8, + -- height = 0.8, + }, + -- Any other Snacks picker option can be configured here: + -- win = { height = 20 }, -- window configuration + -- jump = { autojump = true }, -- jump configuration actions = { -- custom actions for specific snacks pickers (array of tables) issues = { -- actions for the issues picker -- { name = "my_issue_action", fn = function(picker, item) print("Issue action:", vim.inspect(item)) end, lhs = "a", desc = "My custom issue action" }, diff --git a/doc/octo.txt b/doc/octo.txt index c3d3e9c3..6608abca 100644 --- a/doc/octo.txt +++ b/doc/octo.txt @@ -240,6 +240,33 @@ CONFIGURATION *octo-config* See the README () for an example configuration in Lua. + *octo-picker-config* +When using the Snacks picker (`picker = "snacks"`), you can customize picker +behavior via the `picker_config.snacks` table. This supports all options from +the Snacks picker configuration: + +>lua + require"octo".setup({ + picker = "snacks", + picker_config = { + snacks = { + layout = { + preset = "sidebar", -- "dropdown", "ivy", "sidebar", "telescope" + reverse = true, -- reverse layout + width = 0.8, -- window width as fraction + height = 0.8, -- window height as fraction + }, + win = { height = 20 }, -- window configuration + jump = { autojump = true }, -- jump configuration + -- ... any other Snacks picker option + }, + }, + }) +< + +For complete Snacks picker options, see: + + PR REVIEW *octo-pr-review* diff --git a/lua/octo/pickers/snacks/provider.lua b/lua/octo/pickers/snacks/provider.lua index cf5515fb..07b432cb 100644 --- a/lua/octo/pickers/snacks/provider.lua +++ b/lua/octo/pickers/snacks/provider.lua @@ -9,6 +9,16 @@ local Snacks = require "snacks" local M = {} +-- Helper function to merge user snacks config with picker options +local function merge_snacks_config(picker_opts, user_config) + if not user_config then + return picker_opts + end + + -- Deep merge: user config as base, picker options override + return vim.tbl_deep_extend("force", user_config, picker_opts) +end + local function get_filter(opts, kind) local filter = "" local allowed_values = {} @@ -126,7 +136,7 @@ function M.issues(opts) final_keys[cfg.picker_config.mappings.copy_url.lhs] = { "copy_url", mode = default_mode } end - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ title = opts.preview_title or "Issues", items = issues, format = function(item, _) @@ -156,7 +166,9 @@ function M.issues(opts) }, }, actions = final_actions, -- Use the constructed actions map - } + }, cfg.picker_config.snacks) + + Snacks.picker.pick(snacks_opts) end end, } @@ -287,7 +299,7 @@ function M.pull_requests(opts) final_keys[cfg.picker_config.mappings.copy_sha.lhs] = { "copy_sha", mode = default_mode } end - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ title = opts.preview_title or "Pull Requests", items = pull_requests, format = function(item, _) @@ -306,7 +318,9 @@ function M.pull_requests(opts) }, }, actions = final_actions, -- Use the constructed actions map - } + }, cfg.picker_config.snacks) + + Snacks.picker.pick(snacks_opts) end end, } @@ -463,7 +477,8 @@ function M.notifications(opts) final_keys[cfg.mappings.notification.read.lhs] = { "mark_notification_read", mode = default_mode } end - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ + title = opts.preview_title or "Notifications", items = safe_notifications, format = function(item, _) @@ -484,7 +499,9 @@ function M.notifications(opts) }, }, actions = final_actions, -- Use the constructed actions map - } + }, cfg.picker_config.snacks) + + Snacks.picker.pick(snacks_opts) end end, } @@ -559,7 +576,8 @@ function M.issue_templates(templates, cb) -- Default key for confirm is usually handled by Snacks itself, but allow override -- No explicit default key mapping added here unless specified in config - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ + title = "Issue Templates", items = formatted_templates, format = function(item) @@ -584,7 +602,9 @@ function M.issue_templates(templates, cb) }, }, actions = final_actions, -- Use the constructed actions map - } + }, cfg.picker_config.snacks) + + Snacks.picker.pick(snacks_opts) end function M.commits(opts) @@ -668,7 +688,8 @@ function M.commits(opts) final_keys[cfg.picker_config.mappings.copy_url.lhs] = { "copy_url", mode = default_mode } end - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ + title = opts.title or "PR Commits", items = results, format = function(item, _) @@ -711,7 +732,9 @@ function M.commits(opts) }, }, actions = final_actions, - } + }, cfg.picker_config.snacks) + + Snacks.picker.pick(snacks_opts) end, }, }, @@ -849,7 +872,8 @@ function M.review_commits(callback) final_keys[cfg.picker_config.mappings.copy_url.lhs] = { "copy_url", mode = default_mode } end - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ + title = "Review Commits", items = results, format = function(item, _) @@ -912,7 +936,7 @@ function M.review_commits(callback) }, }, actions = final_actions, - } + }, cfg.picker_config.snacks) end, }, }, @@ -1048,7 +1072,8 @@ function M.search(opts) final_keys[cfg.picker_config.mappings.copy_sha.lhs] = { "copy_sha", mode = default_mode } end - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ + title = opts.preview_title or "GitHub Search Results", items = search_results, format = function(item, _) @@ -1085,7 +1110,9 @@ function M.search(opts) }, }, actions = final_actions, -- Use the constructed actions map - } + }, cfg.picker_config.snacks) + + Snacks.picker.pick(snacks_opts) else utils.info "No search results found" end @@ -1162,7 +1189,8 @@ function M.changed_files(opts) final_keys[cfg.picker_config.mappings.open_in_browser.lhs] = { "open_in_browser", mode = default_mode } end - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ + title = opts.title or "Changed Files", items = results, format = function(item, _) @@ -1241,7 +1269,7 @@ function M.changed_files(opts) }, }, actions = final_actions, - } + }, cfg.picker_config.snacks) end, }, }, @@ -1333,7 +1361,8 @@ function M.assignees(cb) final_keys[cfg.picker_config.mappings.open_in_browser.lhs] = { "open_in_browser", mode = default_mode } end - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ + title = "Assignees", items = assignees, format = function(item, _) @@ -1370,7 +1399,9 @@ function M.assignees(cb) }, }, actions = final_actions, - } + }, cfg.picker_config.snacks) + + Snacks.picker.pick(snacks_opts) end end, } @@ -1491,7 +1522,8 @@ function M.users(cb) end -- Sub-picker for teams - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ + title = "Select Team from " .. item.login, items = teams, format = function(team_item, _) @@ -1507,7 +1539,7 @@ function M.users(cb) end end, }, - } + }, cfg.picker_config.snacks) end end end @@ -1522,7 +1554,8 @@ function M.users(cb) final_keys[cfg.picker_config.mappings.open_in_browser.lhs] = { "open_in_browser", mode = default_mode } end - Snacks.picker.pick { + local snacks_opts = merge_snacks_config({ + title = "Users", items = all_items, format = function(item, _) @@ -1562,7 +1595,7 @@ function M.users(cb) }, }, actions = final_actions, - } + }, cfg.picker_config.snacks) end end, }