Skip to content

Commit

Permalink
feat(State): keep track of recently used item
Browse files Browse the repository at this point in the history
* For global itemlist, most recently selected items is kept at `State.most_recent_item`
* For itemgroup-relative selection, use `State.most_recent_igroups[id]`
  • Loading branch information
Hinell committed Oct 19, 2023
1 parent 76f96aa commit a7d140f
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 20 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ require('legendary').setup({
-- }
-- })
sort = {
-- sort most recently used item to the top
-- put most recently selected item first, this works
-- both within global and item group lists
most_recent_first = true,
-- sort user-defined items before built-in items
user_items_first = true,
Expand Down
19 changes: 15 additions & 4 deletions lua/legendary/data/itemlist.lua
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,21 @@ function ItemList:filter(filters, context)
end, 'Took %s ms to filter items in context.')
end

---@class ItemListSortInplaceOpts
---@field itemgroup string

---Sort the list *IN PLACE* according to config.
---THIS MODIFIES THE LIST IN PLACE.
function ItemList:sort_inplace()
--- @param opts ItemListSortInplaceOpts
function ItemList:sort_inplace(opts)
-- inline require to avoid circular dependency
local State = require('legendary.data.state')
local opts = Config.sort
vim.validate({
itemgroup = { opts.itemgroup, 'string', true },
})

-- Merge Config into local opts
opts = vim.tbl_extend('keep', opts, Config.sort)

-- if no items have been added, and the most recent item has not changed,
-- we're already sorted
Expand Down Expand Up @@ -179,8 +188,10 @@ function ItemList:sort_inplace()
end

if opts.most_recent_first then
if item1 == State.most_recent_item then
return true
if opts.itemgroup then
return item1 == State.itemgroup_history[opts.itemgroup]
else
return item1 == State.most_recent_item
end
end

Expand Down
2 changes: 2 additions & 0 deletions lua/legendary/data/state.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ local ItemList = require('legendary.data.itemlist')
---@field items ItemList
---@field most_recent_item LegendaryItem|nil
---@field most_recent_filters LegendaryItemFilter[]|nil
---@field itemgroup_history ItemList[]
local M = {}

M.items = ItemList:create()
M.most_recent_item = nil
M.most_recent_filters = nil
M.itemgroup_history = {}

return M
42 changes: 27 additions & 15 deletions lua/legendary/ui/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,26 @@ local M = {}
---@overload fun(opts:LegendaryFindOpts,context:LegendaryEditorContext)
local function select_inner(opts, context, itemlist)
opts = opts or {}

vim.validate({
itemgroup = { opts.itemgroup, 'string', true },
select_prompt = { opts.select_prompt, 'function', true },
})

if itemlist then
Log.trace('Relaunching select UI for an item group')
else
Log.trace('Launching select UI')
end

-- if no itemlist passed
if itemlist == nil then
-- if an item group is specified, use that
else
Log.trace('Relaunching select UI for an item group')
-- if no itemlist passed, try to use itemgroup
-- if an item group id is specified, use that
local itemgroup = State.items:get_item_group(opts.itemgroup)
if itemgroup then
itemlist = itemgroup.items
else
Log.error('Expected itemlist, got %s.\n %s', type(itemlist), vim.inspect(itemlist))
end
end

-- finally, use full item list if no other lists are specified
itemlist = itemlist or State.items
opts = opts or {}

local prompt = opts.select_prompt or Config.select_prompt
if type(prompt) == 'function' then
prompt = prompt()
Expand All @@ -51,7 +52,7 @@ local function select_inner(opts, context, itemlist)
-- implementation of `sort_inplace` checks if
-- sorting is actually needed and does nothing
-- if it does not need to be sorted.
itemlist:sort_inplace()
itemlist:sort_inplace(opts)

local filters = opts.filters or {}
if type(filters) ~= 'table' then
Expand Down Expand Up @@ -81,12 +82,23 @@ local function select_inner(opts, context, itemlist)
return
end

if opts.itemgroup then
State.itemgroup_history[opts.itemgroup] = selected
else
State.most_recent_item = selected
end

if Toolbox.is_itemgroup(selected) then
return select_inner(opts, context, selected.items)
local item_group_id = selected:id()

local opts_next = vim.tbl_extend('force', opts, {
itemgroup = item_group_id,
})

return select_inner(opts_next, context)
end

Log.trace('Preparing to execute selected item')
State.most_recent_item = selected
Executor.exec_item(selected, context)
end)
end
Expand All @@ -96,7 +108,7 @@ end
function M.select(opts)
vim.cmd('doautocmd User LegendaryUiPre')
local context = Executor.build_context()
select_inner(opts, context)
select_inner(opts, context, State.items)
end

return M

0 comments on commit a7d140f

Please sign in to comment.