feat: key for indexing

This commit is contained in:
mpaulson 2023-11-09 08:46:05 -07:00
parent e08020477a
commit eafaec8a2e
7 changed files with 104 additions and 344 deletions

View File

@ -1,84 +1,8 @@
### Features ### TODO
* select how to generate the list key * encode being false means no writing to disk
* bring over the ui from harpoon 1.0
#### was * autocmds for leaving buffer and quitteriousing vim
list_key = [cwd [+ git branch]] * write some tests around file moving within the display
* files
* terminals
* tmux
#### is
list_key = [key] + [list_name]
nil = default
false = turn off
listA = {
listLine({ ... })
{ ... }
{ ... }
{ ... }
}
harpoon.setup({
settings = {
jumpToFileLocation: boolean => defaults true
}
default = {
// defaults to json.parse
encode = function(obj) => string
decode = function(string) => object
key = function() ... end
display = function(listLine) => string
select = function(listLine) => void
equals = function(list_line_a, list_line_b) => boolean
# question mark: what does it take to support custom things in here?
# potentially subject to change
add = function() HarpoonListItem
}
frecency = {
... a file list that is generated by harpoon ...
... can be opened via viewer ...
}
events = {
on_change = function(operation, list, value)
}
project = {
//key = vim.loop.cwd
key = git origin?
}
specifics = {
key = vim.loop.cwd + git_branch
}
list_name = {
key = function() ... end
}
})
### Functionality
select by index
prev/next
addToBack
addToFront
checking for deleted files?
- perhaps this could be part of the default select operation and use error
select
- default file select should come with options so you can open split/tab as
well
harpoon.current = "default"
harpoon.current = "listName"
harpoon.set_current(list_name)
### LATER FEATUERS ### LATER FEATUERS
frecency = later feature likely, but great idea frecency = later feature likely, but great idea

View File

@ -6,7 +6,6 @@ local M = {}
---@class HarpoonPartialConfigItem ---@class HarpoonPartialConfigItem
---@field encode? (fun(list_item: HarpoonListItem): string) ---@field encode? (fun(list_item: HarpoonListItem): string)
---@field decode? (fun(obj: string): any) ---@field decode? (fun(obj: string): any)
---@field key? (fun(): string)
---@field display? (fun(list_item: HarpoonListItem): string) ---@field display? (fun(list_item: HarpoonListItem): string)
---@field select? (fun(list_item: HarpoonListItem, options: any?): nil) ---@field select? (fun(list_item: HarpoonListItem, options: any?): nil)
---@field equals? (fun(list_line_a: HarpoonListItem, list_line_b: HarpoonListItem): boolean) ---@field equals? (fun(list_line_a: HarpoonListItem, list_line_b: HarpoonListItem): boolean)
@ -15,6 +14,13 @@ local M = {}
---@class HarpoonSettings ---@class HarpoonSettings
---@field save_on_toggle boolean defaults to true ---@field save_on_toggle boolean defaults to true
---@field jump_to_file_location boolean defaults to true ---@field jump_to_file_location boolean defaults to true
---@field key (fun(): string)
---@class HarpoonPartialSettings
---@field save_on_toggle? boolean
---@field jump_to_file_location? boolean
---@field key? (fun(): string)
---@class HarpoonConfig ---@class HarpoonConfig
---@field default HarpoonPartialConfigItem ---@field default HarpoonPartialConfigItem
@ -22,8 +28,8 @@ local M = {}
---@field [string] HarpoonPartialConfigItem ---@field [string] HarpoonPartialConfigItem
---@class HarpoonPartialConfig ---@class HarpoonPartialConfig
---@field default HarpoonPartialConfigItem? ---@field default? HarpoonPartialConfigItem
---@field settings HarpoonSettings? ---@field settings? HarpoonPartialSettings
---@field [string] HarpoonPartialConfigItem ---@field [string] HarpoonPartialConfigItem
@ -35,9 +41,13 @@ end
---@return HarpoonConfig ---@return HarpoonConfig
function M.get_default_config() function M.get_default_config()
return { return {
settings = { settings = {
save_on_toggle = true, save_on_toggle = true,
jump_to_file_location = true, jump_to_file_location = true,
key = function()
return vim.loop.cwd()
end,
}, },
default = { default = {
@ -53,10 +63,6 @@ function M.get_default_config()
return vim.json.decode(str) return vim.json.decode(str)
end, end,
key = function()
return vim.loop.cwd()
end,
---@param list_item HarpoonListItem ---@param list_item HarpoonListItem
display = function(list_item) display = function(list_item)
return list_item.value return list_item.value
@ -99,7 +105,7 @@ function M.get_default_config()
return list_item_a.value == list_item_b.value return list_item_a.value == list_item_b.value
end, end,
---@param value any ---@param name any
---@return HarpoonListItem ---@return HarpoonListItem
add = function(name) add = function(name)
name = name or vim.api.nvim_buf_get_name(vim.api.nvim_get_current_buf()) name = name or vim.api.nvim_buf_get_name(vim.api.nvim_get_current_buf())

View File

@ -32,10 +32,10 @@ local function has_keys(t)
return false return false
end end
--- @alias HarpoonRawData {[string]: string[]} --- @alias HarpoonRawData {[string]: {[string]: string[]}}
--- @class HarpoonData --- @class HarpoonData
--- @field seen {[string]: boolean} --- @field seen {[string]: {[string]: boolean}}
--- @field _data HarpoonRawData --- @field _data HarpoonRawData
--- @field has_error boolean --- @field has_error boolean
local Data = {} local Data = {}
@ -51,6 +51,7 @@ Data.__index = Data
local function read_data() local function read_data()
local path = Path:new(full_data_path) local path = Path:new(full_data_path)
local exists = path:exists() local exists = path:exists()
if not exists then if not exists then
write_data({}) write_data({})
end end
@ -68,25 +69,45 @@ function Data:new()
has_error = not ok, has_error = not ok,
seen = {} seen = {}
}, self) }, self)
end end
---@param key string
---@param name string ---@param name string
---@return string[] ---@return string[]
function Data:data(name) function Data:_get_data(key, name)
if not self._data[key] then
self._data[key] = {}
end
return self._data[key][name] or {}
end
---@param key string
---@param name string
---@return string[]
function Data:data(key, name)
if self.has_error then if self.has_error then
error("Harpoon: there was an error reading the data file, cannot read data") error("Harpoon: there was an error reading the data file, cannot read data")
end end
self.seen[name] = true
return self._data[name] or {} if not self.seen[key] then
self.seen[key] = {}
end
self.seen[key][name] = true
return self:_get_data(key, name)
end end
---@param name string ---@param name string
---@param values string[] ---@param values string[]
function Data:update(name, values) function Data:update(key, name, values)
if self.has_error then if self.has_error then
error("Harpoon: there was an error reading the data file, cannot update") error("Harpoon: there was an error reading the data file, cannot update")
end end
self._data[name] = values self:_get_data(key, name)
self._data[key][name] = values
end end
function Data:sync() function Data:sync()

View File

@ -6,12 +6,14 @@ local List = require("harpoon2.list")
-- read from a config file -- read from a config file
-- --
-- TODO: rename lists into something better...
local DEFAULT_LIST = "__harpoon_files" local DEFAULT_LIST = "__harpoon_files"
---@class Harpoon ---@class Harpoon
---@field config HarpoonConfig ---@field config HarpoonConfig
---@field data HarpoonData ---@field data HarpoonData
---@field lists HarpoonList[] ---@field lists {[string]: {[string]: HarpoonList}}
local Harpoon = {} local Harpoon = {}
Harpoon.__index = Harpoon Harpoon.__index = Harpoon
@ -39,25 +41,36 @@ end
function Harpoon:list(name) function Harpoon:list(name)
name = name or DEFAULT_LIST name = name or DEFAULT_LIST
local existing_list = self.lists[name] local key = self.config.settings.key()
local lists = self.lists[key]
if existing_list then if not lists then
return self.lists[name] lists = {}
self.lists[key] = lists
end end
local data = self.data:data(name) local existing_list = lists[name]
if existing_list then
return existing_list
end
local data = self.data:data(key, name)
local list_config = Config.get_config(self.config, name) local list_config = Config.get_config(self.config, name)
local list = List.decode(list_config, name, data) local list = List.decode(list_config, name, data)
self.lists[name] = list lists[name] = list
return list return list
end end
function Harpoon:sync() function Harpoon:sync()
for k, _ in pairs(self.data.seen) do local key = self.config.settings.key()
local encoded = self.lists[k]:encode() local seen = self.data.seen[key]
self.data:update(k, encoded) local lists = self.lists[key]
for list_name, _ in pairs(seen) do
local encoded = lists[list_name]:encode()
self.data:update(key, list_name, encoded)
end end
self.data:sync() self.data:sync()
end end
@ -72,7 +85,7 @@ end
function Harpoon:info() function Harpoon:info()
return { return {
paths = Data.info(), paths = Data.info(),
default_key = DEFAULT_LIST, default_list_name = DEFAULT_LIST,
} }
end end

View File

@ -1,228 +0,0 @@
{
"key": [
nothuntoehuntoehuntoehuntoehuntoehun
oentuhnoteuhntoehuouenhtuoenhtuonhtuoenhtuoenht 0,nthouenhtouenthoue
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
1,
3,
5,
7,
9,
11,
13,
15,
17,
19,
21,
23,
2,
5,
8,
11,
14,
17,
20,
23,
26,
29,
32,
35,
3,
7,
11,
15,
19,
23,
27,
31,
35,
39,
43,
47,
4,
9,
14,
19,
24,
29,
34,
39,
44,
49,
54,
59,
5,
11,
17,
23,
29,
35,
41,
47,
53,
59,
65,
71,
6,
13,
20,
27,
34,
41,
48,
55,
62,
69,
76,
83,
7,
15,
23,
31,
39,
47,
55,
63,
71,
79,
87,
95,
8,
17,
26,
35,
44,
53,
62,
71,
80,
89,
98,
107,
9,
19,
29,
39,
49,
59,
69,
79,
89,
99,
109,
119,
10,
21,
32,
43,
54,
65,
76,
87,
98,
109,
120,
131,
11,
23,
35,
47,
59,
71,
83,
95,
107,
119,
131,
143,
12,
25,
38,
51,
64,
77,
90,
103,
116,
129,
142,
155,
13,
27,
41,
55,
69,
83,
97,
111,
125,
139,
153,
167,
14,
29,
44,
59,
74,
89,
104,
119,
134,
149,
164,
179,
15,
31,
47,
63,
79,
95,
111,
127,
143,
159,
175,
191,
16,
33,
50,
67,
84,
101,
118,
135,
152,
169,
186,
203,
]
}

View File

@ -13,14 +13,24 @@ describe("harpoon", function()
Data = require("harpoon2.data") Data = require("harpoon2.data")
Data.set_data_path("/tmp/harpoon2.json") Data.set_data_path("/tmp/harpoon2.json")
harpoon = require("harpoon2") harpoon = require("harpoon2")
utils.clean_files()
harpoon:setup({
settings = {
key = function()
return "testies"
end
}
})
end) end)
it("full harpoon add sync cycle", function() it("full harpoon add sync cycle", function()
local file_name = "/tmp/harpoon-test" local file_name = "/tmp/harpoon-test"
local row = 3 local row = 3
local col = 1 local col = 1
local default_key = harpoon:info().default_key local default_list_name = harpoon:info().default_list_name
local bufnr = utils.create_file(file_name, { utils.create_file(file_name, {
"foo", "foo",
"bar", "bar",
"baz", "baz",
@ -31,12 +41,14 @@ describe("harpoon", function()
harpoon:sync() harpoon:sync()
eq(harpoon:dump(), { eq(harpoon:dump(), {
[default_key] = list:encode() testies = {
[default_list_name] = list:encode()
}
}) })
end) end)
it("prepend/append double add", function() it("prepend/append double add", function()
local default_key = harpoon:info().default_key local default_list_name = harpoon:info().default_list_name
local file_name_1 = "/tmp/harpoon-test" local file_name_1 = "/tmp/harpoon-test"
local row_1 = 3 local row_1 = 3
local col_1 = 1 local col_1 = 1
@ -56,7 +68,9 @@ describe("harpoon", function()
harpoon:sync() harpoon:sync()
eq(harpoon:dump(), { eq(harpoon:dump(), {
[default_key] = list:encode() testies = {
[default_list_name] = list:encode()
}
}) })
eq(list.items, { eq(list.items, {
@ -154,23 +168,22 @@ describe("harpoon", function()
list:resolve_displayed(displayed) list:resolve_displayed(displayed)
eq(list.items, { eq({
{value = file_names[1], context = {row = 4, col = 2}}, {value = file_names[1], context = {row = 4, col = 2}},
{value = file_names[4], context = {row = 4, col = 2}}, {value = file_names[4], context = {row = 4, col = 2}},
{value = "/tmp/harpoon-test-other-file-1", context = {row = 1, col = 0}}, {value = "/tmp/harpoon-test-other-file-1", context = {row = 1, col = 0}},
{value = "/tmp/harpoon-test-other-file-2", context = {row = 1, col = 0}}, {value = "/tmp/harpoon-test-other-file-2", context = {row = 1, col = 0}},
}) }, list.items)
table.remove(displayed, 3) table.remove(displayed, 3)
table.insert(displayed, "/tmp/harpoon-test-4") table.insert(displayed, "/tmp/harpoon-test-4")
list:resolve_displayed(displayed) list:resolve_displayed(displayed)
eq(list.items, { eq({
{value = file_names[1], context = {row = 4, col = 2}}, {value = file_names[1], context = {row = 4, col = 2}},
{value = file_names[4], context = {row = 4, col = 2}}, {value = file_names[4], context = {row = 4, col = 2}},
{value = "/tmp/harpoon-test-other-file-2", context = {row = 1, col = 0}}, {value = "/tmp/harpoon-test-other-file-2", context = {row = 1, col = 0}},
}) }, list.items)
end) end)
end) end)

View File

@ -1,6 +1,16 @@
local M = {} local M = {}
M.created_files = {}
function M.clean_files()
for _, bufnr in ipairs(M.created_files) do
vim.api.nvim_buf_delete(bufnr, {force = true})
end
M.created_files = {}
end
---@param name string ---@param name string
---@param contents string[] ---@param contents string[]
function M.create_file(name, contents, row, col) function M.create_file(name, contents, row, col)
@ -11,6 +21,7 @@ function M.create_file(name, contents, row, col)
vim.api.nvim_win_set_cursor(0, {row, col}) vim.api.nvim_win_set_cursor(0, {row, col})
end end
table.insert(M.created_files, bufnr)
return bufnr return bufnr
end end