-
-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ui): keep track of recently used item #412
Conversation
Thanks for the PR! Neat idea. My initial thought is that |
Before this PR, this mechanism was flawed: legendary didn't remember selection inside groups, which was really annoying... |
Yeah, I took a look and the existing piece of state is also used for repeating last execution, so we'll need to keep that separate. Will give it a code review this morning. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will need to update the documentation as well.
For docs changes this is all we should need: diff --git a/README.md b/README.md
index 5bb6537..5eea0db 100644
--- a/README.md
+++ b/README.md
@@ -385,7 +385,9 @@ require('legendary').setup({
-- }
-- })
sort = {
- -- sort most recently used item to the top
+ -- sort most recently used item to the top,
+ -- this works for both the top-level item list
+ -- as well as items inside of item groups
most_recent_first = true,
-- sort user-defined items before built-in items
user_items_first = true, |
0955adf
to
f5447d1
Compare
* For global itemlist, most recently selected items is kept at `State.most_recent_item` * For itemgroup-relative selection, use `State.most_recent_igroups[id]`
@hinell I checked out locally and prepared a patch. Here's the remaining changes we need to make: diff --git a/lua/legendary/api/executor.lua b/lua/legendary/api/executor.lua
index ee7c175..f164e11 100644
--- a/lua/legendary/api/executor.lua
+++ b/lua/legendary/api/executor.lua
@@ -1,6 +1,7 @@
local Toolbox = require('legendary.toolbox')
local Log = require('legendary.log')
local Config = require('legendary.config')
+local State = require('legendary.data.state')
local util = require('legendary.util')
local function update_item_frecency_score(item)
@@ -83,6 +84,7 @@ end
function M.exec_item(item, context)
vim.schedule(function()
M.restore_context(context, function()
+ State.last_executed_item = item
update_item_frecency_score(item)
if Toolbox.is_function(item) then
item.implementation()
@@ -123,11 +125,11 @@ end
---@param ignore_filters boolean|nil whether to ignore the filters used when selecting the item, default false
function M.repeat_previous(ignore_filters)
local State = require('legendary.data.state')
- if State.most_recent_item then
+ if State.last_executed_item then
if not ignore_filters and State.most_recent_filters then
for _, filter in ipairs(State.most_recent_filters) do
-- if any filter does not match, abort executions
- local err, matches = pcall(filter, State.most_recent_item)
+ local err, matches = pcall(filter, State.last_executed_item)
if not err and not matches then
Log.warn(
'Previously executed item no longer matches previously used filters, use `:LegendaryRepeat!`'
@@ -138,7 +140,7 @@ function M.repeat_previous(ignore_filters)
end
end
local context = M.build_context()
- M.exec_item(State.most_recent_item, context)
+ M.exec_item(State.last_executed_item, context)
end
end
diff --git a/lua/legendary/data/itemlist.lua b/lua/legendary/data/itemlist.lua
index a81bfa7..5d5c51e 100644
--- a/lua/legendary/data/itemlist.lua
+++ b/lua/legendary/data/itemlist.lua
@@ -14,6 +14,8 @@ local Log = require('legendary.log')
---@field private sorted boolean
local ItemList = class('ItemList')
+ItemList.TOPLEVEL_LIST_ID = 'toplevel'
+
---@private
function ItemList:initialize()
self.items = {}
@@ -124,7 +126,13 @@ function ItemList:sort_inplace(opts)
-- if no items have been added, and the most recent item has not changed,
-- we're already sorted
- if self.sorted and (not opts.most_recent_first or (self.items[1] == State.most_recent_item)) then
+ if
+ self.sorted
+ and (
+ not opts.most_recent_first
+ or (self.items[1] == State.itemgroup_history[opts.itemgroup or ItemList.TOPLEVEL_LIST_ID])
+ )
+ then
return
end
@@ -188,10 +196,8 @@ function ItemList:sort_inplace(opts)
end
if opts.most_recent_first then
- if opts.itemgroup then
- return item1 == State.itemgroup_history[opts.itemgroup]
- else
- return item1 == State.most_recent_item
+ if item1 == State.itemgroup_history[opts.itemgroup or ItemList.TOPLEVEL_LIST_ID] then
+ return true
end
end
@@ -224,9 +230,11 @@ function ItemList:sort_inplace(opts)
-- sort by most recent last, and after other sorts are done
-- if most recent is already at top, nothing to do, and attempting to sort will cause
-- an error since it doesn't need to be sorted
- if opts.most_recent_first and State.most_recent_item and State.most_recent_item ~= self.items[1] then
+ if
+ opts.most_recent_first and State.itemgroup_history[opts.itemgroup or ItemList.TOPLEVEL_LIST_ID] ~= self.items[1]
+ then
items = Sorter.mergesort(items, function(item)
- return item == State.most_recent_item
+ return item == State.itemgroup_history[opts.itemgroup or ItemList.TOPLEVEL_LIST_ID]
end)
end
diff --git a/lua/legendary/data/state.lua b/lua/legendary/data/state.lua
index bbbc78a..40249ac 100644
--- a/lua/legendary/data/state.lua
+++ b/lua/legendary/data/state.lua
@@ -2,13 +2,13 @@ local ItemList = require('legendary.data.itemlist')
---@class LegendaryState
---@field items ItemList
----@field most_recent_item LegendaryItem|nil
+---@field last_executed_item LegendaryItem|nil
---@field most_recent_filters LegendaryItemFilter[]|nil
----@field itemgroup_history ItemList[]
+---@field itemgroup_history table<string, LegendaryItem>
local M = {}
M.items = ItemList:create()
-M.most_recent_item = nil
+M.last_executed_item = nil
M.most_recent_filters = nil
M.itemgroup_history = {}
diff --git a/lua/legendary/ui/init.lua b/lua/legendary/ui/init.lua
index d33b0ab..17aa10e 100644
--- a/lua/legendary/ui/init.lua
+++ b/lua/legendary/ui/init.lua
@@ -6,12 +6,13 @@ local Toolbox = require('legendary.toolbox')
local Format = require('legendary.ui.format')
local Executor = require('legendary.api.executor')
local Log = require('legendary.log')
+local ItemList = require('legendary.data.itemlist')
---@class LegendaryUi
---@field select fun(opts:LegendaryFindOpts)
local M = {}
----@class LegendaryFindOpts
+---@class LegendaryFindOpts : ItemListSortInplaceOpts
---@field itemgroup string Find items in this item group only
---@field filters LegendaryItemFilter[]
---@field select_prompt string|fun():string
@@ -82,11 +83,7 @@ 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
+ State.itemgroup_history[opts.itemgroup or ItemList.TOPLEVEL_LIST_ID] = selected
if Toolbox.is_itemgroup(selected) then
local item_group_id = selected:id()
|
If you apply the patch, I'll be happy to test and merge! |
@hinell one small issue from CI, then I can merge:
|
I dunno what legendary.nvim is, but this is clearly critical. Smashed that approve button! |
lol you approved the PR two hours ago though 😆 |
remember-recent-selection.mov
State.most_recent_item
State.itemgroup_history[id]
map is usedHow to Test
Testing for Regressions
I have tested the following:
legendary.nvim
in all modes (normal, insert, visual)legendary.nvim
, then triggering via the keymap in all modes (normal, insert, visual)legendary.nvim
in all modes (normal, insert, visual)legendary.nvim
, then running the command manually from the command lineaugroup
/autocmd
s created throughlegendary.nvim
work correctly