diff --git a/README.md b/README.md index 5803ca1..8923eb6 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ require("artio").setup({ [""] = "accept", [""] = "cancel", [""] = "mark", + [""] = "togglelive", [""] = "togglepreview", [""] = "setqflist", [""] = "setqflistmark", diff --git a/lua/artio/config.lua b/lua/artio/config.lua index 7f028f1..91c5342 100644 --- a/lua/artio/config.lua +++ b/lua/artio/config.lua @@ -49,6 +49,7 @@ M.default = { [""] = "accept", [""] = "cancel", [""] = "mark", + [""] = "togglelive", [""] = "togglepreview", [""] = "setqflist", [""] = "setqflistmark", diff --git a/lua/artio/picker.lua b/lua/artio/picker.lua index 7530b4d..a63f89d 100644 --- a/lua/artio/picker.lua +++ b/lua/artio/picker.lua @@ -17,6 +17,7 @@ local View = require("artio.view") ---@field get_icon? fun(item: artio.Picker.item): string, string ---@field hl_item? fun(item: artio.Picker.item): artio.Picker.hl[] ---@field on_quit? fun() +---@field live? boolean ---@field prompt? string ---@field defaulttext? string ---@field prompttext? string @@ -28,9 +29,11 @@ local View = require("artio.view") ---@class artio.Picker : artio.Picker.config ---@field co thread|nil ---@field input string +---@field liveinput? string ---@field idx integer 1-indexed ---@field matches artio.Picker.match[] ---@field marked table +---@field live boolean local Picker = {} Picker.__index = Picker Picker.active_picker = nil @@ -45,6 +48,7 @@ function Picker:new(props) closed = false, prompt = "", input = nil, + liveinput = nil, idx = 0, items = {}, matches = {}, @@ -55,7 +59,15 @@ function Picker:new(props) t.prompttext = t.opts.prompt_title and ("%s %s"):format(t.prompt, t.opts.promptprefix) or t.opts.promptprefix end - t.input = t.defaulttext or "" + t.live = vim.F.if_nil(t.live, t.get_items ~= nil) + + if t.live then + t.input = "" + t.liveinput = t.defaulttext or "" + else + t.input = t.defaulttext or "" + t.liveinput = "" + end Picker.getitems(t, "") @@ -204,7 +216,10 @@ local function item_is_structured(item) end function Picker:getitems(input) - self.items = self.get_items and self.get_items(input) or self.items + if self.live then + self.items = self.get_items and self.get_items(input) or self.items + end + if #self.items > 0 and not item_is_structured(self.items[1]) then self.items = vim .iter(ipairs(self.items)) @@ -226,14 +241,33 @@ end ---@param input? string function Picker:getmatches(input) - input = input or self.input + if not input then + input = self.live and self.liveinput or self.input + end self:getitems(input) + + -- if live, ignore sorting + if self.live then + self.matches = self:getallmatches() + return + end + self.matches = vim.tbl_values(self.fn(self.items, input)) table.sort(self.matches, function(a, b) return a[3] > b[3] end) end +---@return artio.Picker.match[] +function Picker:getallmatches() + return vim + .iter(ipairs(self.items)) + :map(function(_, v) + return { v.id, {}, 0 } + end) + :totable() +end + ---@param idx integer ---@param yes? boolean function Picker:mark(idx, yes) @@ -264,4 +298,17 @@ function Picker:getcurrent(idx) return self.items[idx] end +function Picker:togglelive() + -- check if live can be toggled + if not self.get_items then + return + end + + -- reset fuzzy search when enabling live search + if not self.live then + self.input = "" + end + self.live = not self.live +end + return Picker diff --git a/lua/artio/view.lua b/lua/artio/view.lua index e136a77..8ecfcc0 100644 --- a/lua/artio/view.lua +++ b/lua/artio/view.lua @@ -394,7 +394,13 @@ end function View:trigger_show() logdebug("trigger_show") - self:show({ { 0, self.picker.input } }, -1, "", self.picker.prompttext, cmdline.indent, cmdline.level, prompt_hl_id) + local input + if self.picker.live then + input = self.picker.liveinput + else + input = self.picker.input + end + self:show({ { 0, input } }, -1, "", self.picker.prompttext, cmdline.indent, cmdline.level, prompt_hl_id) end ---@param force? boolean @@ -409,7 +415,11 @@ function View:update(force) local text = vim.api.nvim_get_current_line() text = text:sub(promptlen + 1) - self.picker.input = text + if self.picker.live then + self.picker.liveinput = text + else + self.picker.input = text + end vim.schedule(coroutine.wrap(function() logdebug("getmatches") diff --git a/plugin/artio.lua b/plugin/artio.lua index eb5d723..031dd0e 100644 --- a/plugin/artio.lua +++ b/plugin/artio.lua @@ -159,3 +159,11 @@ vim.keymap.set( self.view:togglepreview() end) ) +vim.keymap.set( + "i", + "(artio-action-togglelive)", + wrap(function(self) + self:togglelive() + self.view:trigger_show() -- update input + end) +)