Skip to content
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(index-tracking): keep track of the list._index while navigating #574

Open
wants to merge 6 commits into
base: harpoon2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions lua/harpoon/buffer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,6 @@ end

---@param bufnr number
function M.setup_autocmds_and_keymaps(bufnr)
local curr_file = vim.api.nvim_buf_get_name(0)
local cmd = string.format(
"autocmd Filetype harpoon "
.. "let path = '%s' | call clearmatches() | "
-- move the cursor to the line containing the current filename
.. "call search('\\V'.path.'\\$') | "
-- add a hl group to that line
.. "call matchadd('HarpoonCurrentFile', '\\V'.path.'\\$')",
curr_file:gsub("\\", "\\\\")
)
vim.cmd(cmd)

if vim.api.nvim_buf_get_name(bufnr) == "" then
vim.api.nvim_buf_set_name(bufnr, get_harpoon_menu_name())
end
Expand Down
87 changes: 80 additions & 7 deletions lua/harpoon/list.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local Logger = require("harpoon.logger")
local Path = require("plenary.path")
local utils = require("harpoon.utils")
local Extensions = require("harpoon.extensions")

Expand Down Expand Up @@ -77,16 +78,50 @@ end
--- @field items HarpoonItem[]
local HarpoonList = {}

---@param list HarpoonList
---@param options any
local sync_index = function(list, options)
local bufnr = options.bufnr
local filename = options.filename
local index = options.index
if bufnr ~= nil and filename ~= nil then
local config = list.config
local relname = Path:new(filename):make_relative(config.get_root_dir())
if bufnr == vim.fn.bufnr(relname, false) then
local element = config.create_list_item(config, relname)
local index_found =
index_of(list.items, list._length, element, config)
if index_found > -1 then
list._index = index_found
end
elseif index ~= nil then
list._index = index
end
elseif index ~= nil then
list._index = index
end
end

HarpoonList.__index = HarpoonList
function HarpoonList:new(config, name, items)
items = items or {}
return setmetatable({
local list = setmetatable({
items = items,
config = config,
name = name,
_length = guess_length(items),
_index = 1,
_index = 0,
}, self)
vim.api.nvim_create_autocmd({ "BufEnter" }, {
pattern = { "*" },
callback = function(args)
sync_index(list, {
bufnr = args.buf,
filename = args.file,
})
end,
})
return list
end

---@return number
Expand Down Expand Up @@ -151,6 +186,8 @@ function HarpoonList:add(item)
self._length = idx
end

sync_index(self, { index = idx })

Extensions.extensions:emit(
Extensions.event_names.ADD,
{ list = self, item = item, idx = idx }
Expand All @@ -171,6 +208,8 @@ function HarpoonList:prepend(item)
self._length = stop_idx
end

sync_index(self, { index = 1 })

Extensions.extensions:emit(
Extensions.event_names.ADD,
{ list = self, item = item, idx = 1 }
Expand All @@ -191,6 +230,13 @@ function HarpoonList:remove(item)
if i == self._length then
self._length = determine_length(self.items, self._length)
end

local current_buffer = vim.api.nvim_get_current_buf()
sync_index(self, {
bufnr = current_buffer,
filename = vim.api.nvim_buf_get_name(current_buffer),
})

Extensions.extensions:emit(
Extensions.event_names.REMOVE,
{ list = self, item = item, idx = i }
Expand All @@ -212,6 +258,13 @@ function HarpoonList:remove_at(index)
if index == self._length then
self._length = determine_length(self.items, self._length)
end

local current_buffer = vim.api.nvim_get_current_buf()
sync_index(self, {
bufnr = current_buffer,
filename = vim.api.nvim_buf_get_name(current_buffer),
})

Extensions.extensions:emit(
Extensions.event_names.REMOVE,
{ list = self, item = self.items[index], idx = index }
Expand Down Expand Up @@ -242,7 +295,10 @@ end
--- much inefficiencies. dun care
---@param displayed string[]
---@param length number
function HarpoonList:resolve_displayed(displayed, length)
---@param options any
function HarpoonList:resolve_displayed(displayed, length, options)
options = options or {}

local new_list = {}

local list_displayed = self:display()
Expand Down Expand Up @@ -278,6 +334,12 @@ function HarpoonList:resolve_displayed(displayed, length)
end
end

local win_id = options.win_id
if win_id then
local pos = vim.api.nvim_win_get_cursor(win_id)
self._index = pos[1]
end

self.items = new_list
self._length = length
if change > 0 then
Expand All @@ -288,6 +350,8 @@ end
function HarpoonList:select(index, options)
local item = self.items[index]
if item or self.config.select_with_nil then
sync_index(self, { index = index })

Extensions.extensions:emit(
Extensions.event_names.SELECT,
{ list = self, item = item, idx = index }
Expand Down Expand Up @@ -344,8 +408,12 @@ end
--- @return string[]
function HarpoonList:encode()
local out = {}
for _, v in ipairs(self.items) do
table.insert(out, self.config.encode(v))
local items = self.items
for i = 1, self._length do
local item = items[i]
if item then
out[i] = self.config.encode(items[i])
end
end

return out
Expand All @@ -358,8 +426,13 @@ end
function HarpoonList.decode(list_config, name, items)
local list_items = {}

for _, item in ipairs(items) do
table.insert(list_items, list_config.decode(item))
for i = 1, #items do
local item = items[i]
if item == vim.NIL then
list_items[i] = nil -- allow nil-values
else
list_items[i] = list_config.decode(item)
end
end

return HarpoonList:new(list_config, name, list_items)
Expand Down
25 changes: 25 additions & 0 deletions lua/harpoon/test/harpoon_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,31 @@ describe("harpoon", function()
})
end)

it("should ignore removed items", function()
local list = harpoon:list()

utils.create_file("/tmp/harpoon-test1", {}, 1, 0)
list:add()

utils.create_file("/tmp/harpoon-test2", {}, 1, 0)
list:add()

utils.create_file("/tmp/harpoon-test3", {}, 1, 0)
list:add()

list:remove_at(2) -- remove the second item

local count_items = 0
local encoded_items = list:encode()
local i, _ = next(encoded_items, nil)
while i do
count_items = count_items + 1
i, _ = next(encoded_items, i)
end

eq(2, count_items, "expecting two items in the list")
end)

it("out of bounds test: row over", function()
out_of_bounds_test({
row = 5,
Expand Down
10 changes: 8 additions & 2 deletions lua/harpoon/ui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ function HarpoonUI:toggle_quick_menu(list, opts)
local contents = self.active_list:display()
vim.api.nvim_buf_set_lines(self.bufnr, 0, -1, false, contents)

local index = list._index

if index > 0 then
vim.api.nvim_win_set_cursor(win_id, { index, 0 })
end

Extensions.extensions:emit(Extensions.event_names.UI_CREATE, {
win_id = win_id,
bufnr = bufnr,
Expand All @@ -173,7 +179,7 @@ function HarpoonUI:select_menu_item(options)
-- must first save any updates potentially made to the list before
-- navigating
local list, length = self:_get_processed_ui_contents()
self.active_list:resolve_displayed(list, length)
self.active_list:resolve_displayed(list, length, { win_id = self.win_id })

Logger:log(
"ui#select_menu_item selecting item",
Expand All @@ -193,7 +199,7 @@ function HarpoonUI:save()
local list, length = self:_get_processed_ui_contents()

Logger:log("ui#save", list)
self.active_list:resolve_displayed(list, length)
self.active_list:resolve_displayed(list, length, { win_id = self.win_id })
if self.settings.sync_on_ui_close then
require("harpoon"):sync()
end
Expand Down