From 82f96ff91d87433aedc9ae9061dd255a0b3ef0ef Mon Sep 17 00:00:00 2001 From: BYT0723 Date: Wed, 19 Mar 2025 13:04:33 +0800 Subject: [PATCH 1/2] feat: `folke/snacks.nvim` picker support --- lua/leetcode/config/template.lua | 2 +- lua/leetcode/picker/init.lua | 13 ++++- lua/leetcode/picker/language/snacks.lua | 63 ++++++++++++++++++++++++ lua/leetcode/picker/question/snacks.lua | 63 ++++++++++++++++++++++++ lua/leetcode/picker/tabs/snacks.lua | 65 +++++++++++++++++++++++++ 5 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 lua/leetcode/picker/language/snacks.lua create mode 100644 lua/leetcode/picker/question/snacks.lua create mode 100644 lua/leetcode/picker/tabs/snacks.lua diff --git a/lua/leetcode/config/template.lua b/lua/leetcode/config/template.lua index 40c5779..82be384 100644 --- a/lua/leetcode/config/template.lua +++ b/lua/leetcode/config/template.lua @@ -38,7 +38,7 @@ ---@alias lc.storage table<"cache"|"home", string> ----@alias lc.picker { provider?: "fzf-lua" | "telescope" } +---@alias lc.picker { provider?: "fzf-lua" | "telescope" | "snacks-picker" } ---@class lc.UserConfig local M = { diff --git a/lua/leetcode/picker/init.lua b/lua/leetcode/picker/init.lua index 8fabd22..df23fa0 100644 --- a/lua/leetcode/picker/init.lua +++ b/lua/leetcode/picker/init.lua @@ -1,7 +1,7 @@ local log = require("leetcode.logger") local config = require("leetcode.config") ----@return "fzf" | "telescope" +---@return "fzf" | "telescope" | "snacks" local function resolve_provider() ---@type string local provider = config.user.picker.provider @@ -15,9 +15,18 @@ local function resolve_provider() if telescope_ok then return "telescope" end + local snacks_ok = pcall(require, "snacks.picker") + if snacks_ok then + return "snacks" + end error("no supported picker provider found") else - local provider_ok = pcall(require, provider) + local mod = provider + if provider == "snacks-picker" then + provider = "snacks" + mod = "snacks.picker" + end + local provider_ok = pcall(require, mod) assert(provider_ok, ("specified picker provider not found: `%s`"):format(provider)) return provider == "fzf-lua" and "fzf" or provider end diff --git a/lua/leetcode/picker/language/snacks.lua b/lua/leetcode/picker/language/snacks.lua new file mode 100644 index 0000000..c3241ae --- /dev/null +++ b/lua/leetcode/picker/language/snacks.lua @@ -0,0 +1,63 @@ +local log = require("leetcode.logger") +local t = require("leetcode.translator") +local picker = require("snacks.picker") + +local language_picker = require("leetcode.picker.language") + +---@param question lc.ui.Question +return function(question, cb) + local items = language_picker.items(question.q.code_snippets) + local finder_items = {} + local completed = false + + for _, item in ipairs(items) do + local text = language_picker.ordinal(item.value) + table.insert(finder_items, { + text = text, + item = item, + }) + end + + picker.pick({ + source = "select", + items = finder_items, + format = function(item) + local ret = {} + vim.tbl_map(function(col) + if type(col) == "table" then + ret[#ret + 1] = col + else + ret[#ret + 1] = { col } + end + ret[#ret + 1] = { " " } + end, item.item.entry) + return ret + end, + title = t("Available Languages"), + layout = { + preview = false, + layout = { + height = math.floor(math.min(vim.o.lines * 0.8 - 10, #items + 2) + 0.5), + }, + }, + actions = { + confirm = function(p, item) + if completed then + return + end + completed = true + p:close() + vim.schedule(function() + language_picker.select(item.item.value.t, question, cb) + end) + end, + }, + on_close = function() + if completed then + return + end + completed = true + log.warn("No selection") + end, + }) +end diff --git a/lua/leetcode/picker/question/snacks.lua b/lua/leetcode/picker/question/snacks.lua new file mode 100644 index 0000000..7392598 --- /dev/null +++ b/lua/leetcode/picker/question/snacks.lua @@ -0,0 +1,63 @@ +local log = require("leetcode.logger") +local t = require("leetcode.translator") +local question_picker = require("leetcode.picker.question") + +local picker = require("snacks.picker") + +---@param questions lc.cache.Question[] +return function(questions, opts) + local items = question_picker.items(questions, opts) + local finder_items = {} + local completed = false + + for _, item in ipairs(items) do + local text = question_picker.ordinal(item.value) + table.insert(finder_items, { + text = text, + item = item, + }) + end + + picker.pick({ + source = "select", + items = finder_items, + format = function(item) + local ret = {} + vim.tbl_map(function(col) + if type(col) == "table" then + ret[#ret + 1] = col + else + ret[#ret + 1] = { col } + end + ret[#ret + 1] = { " " } + end, item.item.entry) + return ret + end, + title = t("Select a Question"), + layout = { + preview = false, + layout = { + height = math.floor(math.min(vim.o.lines * 0.8 - 10, #items + 2) + 0.5), + }, + }, + actions = { + confirm = function(p, item) + if completed then + return + end + completed = true + p:close() + vim.schedule(function() + question_picker.select(item.value) + end) + end, + }, + on_close = function() + if completed then + return + end + completed = true + log.warn("No selection") + end, + }) +end diff --git a/lua/leetcode/picker/tabs/snacks.lua b/lua/leetcode/picker/tabs/snacks.lua new file mode 100644 index 0000000..770b0b2 --- /dev/null +++ b/lua/leetcode/picker/tabs/snacks.lua @@ -0,0 +1,65 @@ +local log = require("leetcode.logger") +local t = require("leetcode.translator") +local tabs_picker = require("leetcode.picker.tabs") + +local picker = require("snacks.picker") + +return function(tabs) + local items = tabs_picker.items(tabs) + local finder_items = {} + local completed = false + local items_reflect = {} + + for _, item in ipairs(items) do + items_reflect[item.value.question.q.frontend_id] = item.value + local text = tabs_picker.ordinal(item.value.question.q) + table.insert(finder_items, { + entry = item.entry, + item = item.value.question.q.frontend_id, + text = text, + }) + end + + picker.pick({ + source = "select", + items = finder_items, + format = function(item) + local ret = {} + vim.tbl_map(function(col) + if type(col) == "table" then + ret[#ret + 1] = col + else + ret[#ret + 1] = { col } + end + ret[#ret + 1] = { " " } + end, item.entry) + return ret + end, + title = t("Select a Question"), + layout = { + preview = false, + layout = { + height = math.floor(math.min(vim.o.lines * 0.8 - 10, #items + 2) + 0.5), + }, + }, + actions = { + confirm = function(p, item) + if completed then + return + end + completed = true + p:close() + vim.schedule(function() + tabs_picker.select(items_reflect[item.item]) + end) + end, + }, + on_close = function() + if completed then + return + end + completed = true + log.warn("No selection") + end, + }) +end From d3e9c6a6cdde3dce2f1b2853f74589ce07d7616c Mon Sep 17 00:00:00 2001 From: BYT0723 Date: Wed, 19 Mar 2025 17:15:41 +0800 Subject: [PATCH 2/2] fix: snacks-picker question select --- lua/leetcode/picker/question/snacks.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/leetcode/picker/question/snacks.lua b/lua/leetcode/picker/question/snacks.lua index 7392598..b168f67 100644 --- a/lua/leetcode/picker/question/snacks.lua +++ b/lua/leetcode/picker/question/snacks.lua @@ -48,7 +48,7 @@ return function(questions, opts) completed = true p:close() vim.schedule(function() - question_picker.select(item.value) + question_picker.select(item.item.value) end) end, },