mirror of
https://github.com/ThePrimeagen/harpoon.git
synced 2025-07-14 10:00:29 +00:00
feat: list adding now works but duplicates are a problem
This commit is contained in:
parent
543f3a16e1
commit
c1f49fef43
@ -1,41 +0,0 @@
|
|||||||
local Data = require("harpoon.data")
|
|
||||||
local Config = require("harpoon.config")
|
|
||||||
|
|
||||||
-- setup
|
|
||||||
-- read from a config file
|
|
||||||
--
|
|
||||||
|
|
||||||
local DEFAULT_LIST = "__harpoon_files"
|
|
||||||
|
|
||||||
---@class Harpoon
|
|
||||||
---@field config HarpoonConfig
|
|
||||||
---@field data Data
|
|
||||||
local Harpoon = {}
|
|
||||||
|
|
||||||
Harpoon.__index = Harpoon
|
|
||||||
|
|
||||||
---@return Harpoon
|
|
||||||
function Harpoon:new()
|
|
||||||
local config = Config.get_default_config()
|
|
||||||
|
|
||||||
return setmetatable({
|
|
||||||
config = config,
|
|
||||||
data = Data:new()
|
|
||||||
}, self)
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param partial_config HarpoonPartialConfig
|
|
||||||
---@return Harpoon
|
|
||||||
function Harpoon:setup(partial_config)
|
|
||||||
self.config = Config.merge_config(partial_config, self.config)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param list string?
|
|
||||||
---@return HarpoonList
|
|
||||||
function Harpoon:list(name)
|
|
||||||
name = name or DEFAULT_LIST
|
|
||||||
end
|
|
||||||
|
|
||||||
return Harpoon:new()
|
|
||||||
|
|
@ -3,8 +3,24 @@ local Path = require("plenary.path")
|
|||||||
local data_path = vim.fn.stdpath("data")
|
local data_path = vim.fn.stdpath("data")
|
||||||
local full_data_path = string.format("%s/harpoon2.json", data_path)
|
local full_data_path = string.format("%s/harpoon2.json", data_path)
|
||||||
|
|
||||||
|
---@param data any
|
||||||
|
local function write_data(data)
|
||||||
|
Path:new(full_data_path):write(vim.json.encode(data), "w")
|
||||||
|
end
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
function M.__dangerously_clear_data()
|
||||||
|
write_data({})
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.info()
|
||||||
|
return {
|
||||||
|
data_path = data_path,
|
||||||
|
full_data_path = full_data_path,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
function M.set_data_path(path)
|
function M.set_data_path(path)
|
||||||
full_data_path = path
|
full_data_path = path
|
||||||
end
|
end
|
||||||
@ -16,33 +32,34 @@ local function has_keys(t)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @alias RawData {[string]: string[]}
|
--- @alias HarpoonRawData {[string]: string[]}
|
||||||
|
|
||||||
--- @class Data
|
--- @class HarpoonData
|
||||||
--- @field seen {[string]: boolean}
|
--- @field seen {[string]: boolean}
|
||||||
--- @field _data RawData
|
--- @field _data HarpoonRawData
|
||||||
--- @field has_error boolean
|
--- @field has_error boolean
|
||||||
|
local Data = {}
|
||||||
|
|
||||||
|
|
||||||
-- 1. load the data
|
-- 1. load the data
|
||||||
-- 2. keep track of the lists requested
|
-- 2. keep track of the lists requested
|
||||||
-- 3. sync save
|
-- 3. sync save
|
||||||
|
|
||||||
local Data = {}
|
|
||||||
|
|
||||||
Data.__index = Data
|
Data.__index = Data
|
||||||
|
|
||||||
---@param data any
|
---@return HarpoonRawData
|
||||||
local function write_data(data)
|
|
||||||
Path:new(full_data_path):write_data(vim.json.encode(data))
|
|
||||||
end
|
|
||||||
|
|
||||||
---@return RawData
|
|
||||||
local function read_data()
|
local function read_data()
|
||||||
return vim.json.decode(Path:new(full_data_path):read())
|
local path = Path:new(full_data_path)
|
||||||
|
local exists = path:exists()
|
||||||
|
if not exists then
|
||||||
|
write_data({})
|
||||||
end
|
end
|
||||||
|
|
||||||
---@return Harpoon
|
local data = vim.json.decode(path:read())
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return HarpoonData
|
||||||
function Data:new()
|
function Data:new()
|
||||||
local ok, data = pcall(read_data)
|
local ok, data = pcall(read_data)
|
||||||
|
|
||||||
@ -59,6 +76,7 @@ function Data:data(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 {}
|
return self._data[name] or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -68,7 +86,6 @@ function Data:update(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.seen[name] = true
|
|
||||||
self._data[name] = values
|
self._data[name] = values
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -90,11 +107,14 @@ function Data:sync()
|
|||||||
data[k] = v
|
data[k] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
pcall(write_data, data)
|
ok = pcall(write_data, data)
|
||||||
|
|
||||||
|
if ok then
|
||||||
|
self.seen = {}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
M.Data = Data
|
M.Data = Data
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|
86
lua/harpoon2/init.lua
Normal file
86
lua/harpoon2/init.lua
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
local Data = require("harpoon2.data")
|
||||||
|
local Config = require("harpoon2.config")
|
||||||
|
local List = require("harpoon2.list")
|
||||||
|
|
||||||
|
-- setup
|
||||||
|
-- read from a config file
|
||||||
|
--
|
||||||
|
|
||||||
|
local DEFAULT_LIST = "__harpoon_files"
|
||||||
|
|
||||||
|
---@class Harpoon
|
||||||
|
---@field config HarpoonConfig
|
||||||
|
---@field data HarpoonData
|
||||||
|
---@field lists HarpoonList[]
|
||||||
|
local Harpoon = {}
|
||||||
|
|
||||||
|
Harpoon.__index = Harpoon
|
||||||
|
|
||||||
|
---@return Harpoon
|
||||||
|
function Harpoon:new()
|
||||||
|
local config = Config.get_default_config()
|
||||||
|
|
||||||
|
return setmetatable({
|
||||||
|
config = config,
|
||||||
|
data = Data.Data:new(),
|
||||||
|
lists = {},
|
||||||
|
}, self)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param partial_config HarpoonPartialConfig
|
||||||
|
---@return Harpoon
|
||||||
|
function Harpoon:setup(partial_config)
|
||||||
|
self.config = Config.merge_config(partial_config, self.config)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param name string?
|
||||||
|
---@return HarpoonList
|
||||||
|
function Harpoon:list(name)
|
||||||
|
name = name or DEFAULT_LIST
|
||||||
|
|
||||||
|
local existing_list = self.lists[name]
|
||||||
|
|
||||||
|
if existing_list then
|
||||||
|
return self.lists[name]
|
||||||
|
end
|
||||||
|
|
||||||
|
local data = self.data:data(name)
|
||||||
|
local list_config = Config.get_config(self.config, name)
|
||||||
|
|
||||||
|
local list = List.decode(list_config, name, data)
|
||||||
|
self.lists[name] = list
|
||||||
|
|
||||||
|
return list
|
||||||
|
end
|
||||||
|
|
||||||
|
function Harpoon:sync()
|
||||||
|
for k, _ in pairs(self.data.seen) do
|
||||||
|
local encoded = self.lists[k]:encode()
|
||||||
|
self.data:update(k, encoded)
|
||||||
|
end
|
||||||
|
self.data:sync()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Harpoon:setup_hooks()
|
||||||
|
-- setup the autocommands
|
||||||
|
-- vim exits sync data
|
||||||
|
-- buf exit setup the cursor location
|
||||||
|
error("I haven't implemented this yet")
|
||||||
|
end
|
||||||
|
|
||||||
|
function Harpoon:info()
|
||||||
|
return {
|
||||||
|
paths = Data.info(),
|
||||||
|
default_key = DEFAULT_LIST,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- PLEASE DONT USE THIS OR YOU WILL BE FIRED
|
||||||
|
function Harpoon:dump()
|
||||||
|
return self.data._data
|
||||||
|
end
|
||||||
|
|
||||||
|
return Harpoon:new()
|
||||||
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
|||||||
local get_config = require "harpoon.config".get_config
|
|
||||||
|
|
||||||
-- TODO: Define the config object
|
-- TODO: Define the config object
|
||||||
|
|
||||||
--- @class HarpoonItem
|
--- @class HarpoonItem
|
||||||
@ -8,7 +6,7 @@ local get_config = require "harpoon.config".get_config
|
|||||||
|
|
||||||
--- create a table object to be new'd
|
--- create a table object to be new'd
|
||||||
--- @class HarpoonList
|
--- @class HarpoonList
|
||||||
--- @field config any
|
--- @field config HarpoonPartialConfigItem
|
||||||
--- @field name string
|
--- @field name string
|
||||||
--- @field items HarpoonItem[]
|
--- @field items HarpoonItem[]
|
||||||
local HarpoonList = {}
|
local HarpoonList = {}
|
||||||
@ -22,25 +20,35 @@ function HarpoonList:new(config, name, items)
|
|||||||
}, self)
|
}, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return HarpoonList
|
||||||
function HarpoonList:push(item)
|
function HarpoonList:push(item)
|
||||||
|
item = item or self.config.add()
|
||||||
table.insert(self.items, item)
|
table.insert(self.items, item)
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return HarpoonList
|
||||||
function HarpoonList:addToFront(item)
|
function HarpoonList:addToFront(item)
|
||||||
|
item = item or self.config.add()
|
||||||
table.insert(self.items, 1, item)
|
table.insert(self.items, 1, item)
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return HarpoonList
|
||||||
function HarpoonList:remove(item)
|
function HarpoonList:remove(item)
|
||||||
for i, v in ipairs(self.items) do
|
for i, v in ipairs(self.items) do
|
||||||
if get_config(self.config, self.name)(v, item) then
|
if self.config.equals(v, item) then
|
||||||
table.remove(self.items, i)
|
table.remove(self.items, i)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return HarpoonList
|
||||||
function HarpoonList:removeAt(index)
|
function HarpoonList:removeAt(index)
|
||||||
table.remove(self.items, index)
|
table.remove(self.items, index)
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function HarpoonList:get(index)
|
function HarpoonList:get(index)
|
||||||
@ -51,12 +59,11 @@ end
|
|||||||
---@param displayed string[]
|
---@param displayed string[]
|
||||||
function HarpoonList:resolve_displayed(displayed)
|
function HarpoonList:resolve_displayed(displayed)
|
||||||
local not_found = {}
|
local not_found = {}
|
||||||
local config = get_config(self.config, self.name)
|
|
||||||
|
|
||||||
for _, v in ipairs(displayed) do
|
for _, v in ipairs(displayed) do
|
||||||
local found = false
|
local found = false
|
||||||
for _, in_table in ipairs(self.items) do
|
for _, in_table in ipairs(self.items) do
|
||||||
if config.display(in_table) == v then
|
if self.config.display(in_table) == v then
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@ -75,9 +82,8 @@ end
|
|||||||
--- @return string[]
|
--- @return string[]
|
||||||
function HarpoonList:display()
|
function HarpoonList:display()
|
||||||
local out = {}
|
local out = {}
|
||||||
local config = get_config(self.config, self.name)
|
|
||||||
for _, v in ipairs(self.items) do
|
for _, v in ipairs(self.items) do
|
||||||
table.insert(out, config.display(v))
|
table.insert(out, self.config.display(v))
|
||||||
end
|
end
|
||||||
|
|
||||||
return out
|
return out
|
||||||
@ -86,27 +92,25 @@ end
|
|||||||
--- @return string[]
|
--- @return string[]
|
||||||
function HarpoonList:encode()
|
function HarpoonList:encode()
|
||||||
local out = {}
|
local out = {}
|
||||||
local config = get_config(self.config, self.name)
|
|
||||||
for _, v in ipairs(self.items) do
|
for _, v in ipairs(self.items) do
|
||||||
table.insert(out, config.encode(v))
|
table.insert(out, self.config.encode(v))
|
||||||
end
|
end
|
||||||
|
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @return HarpoonList
|
--- @return HarpoonList
|
||||||
--- @param config HarpoonConfig
|
--- @param list_config HarpoonPartialConfigItem
|
||||||
--- @param name string
|
--- @param name string
|
||||||
--- @param items string[]
|
--- @param items string[]
|
||||||
function HarpoonList.decode(config, name, items)
|
function HarpoonList.decode(list_config, name, items)
|
||||||
local list_items = {}
|
local list_items = {}
|
||||||
local c = get_config(config, name)
|
|
||||||
|
|
||||||
for _, item in ipairs(items) do
|
for _, item in ipairs(items) do
|
||||||
table.insert(list_items, c.decode(item))
|
table.insert(list_items, list_config.decode(item))
|
||||||
end
|
end
|
||||||
|
|
||||||
return HarpoonList:new(config, name, list_items)
|
return HarpoonList:new(list_config, name, list_items)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
local List = require("harpoon.list")
|
local List = require("harpoon2.list")
|
||||||
local Config = require("harpoon.config")
|
local Config = require("harpoon2.config")
|
||||||
local eq = assert.are.same
|
local eq = assert.are.same
|
||||||
|
|
||||||
describe("config", function()
|
describe("config", function()
|
||||||
@ -10,7 +10,6 @@ describe("config", function()
|
|||||||
local bufnr = vim.fn.bufnr("/tmp/harpoon-test", true)
|
local bufnr = vim.fn.bufnr("/tmp/harpoon-test", true)
|
||||||
|
|
||||||
vim.api.nvim_set_current_buf(bufnr)
|
vim.api.nvim_set_current_buf(bufnr)
|
||||||
|
|
||||||
vim.api.nvim_buf_set_text(0, 0, 0, 0, 0, {
|
vim.api.nvim_buf_set_text(0, 0, 0, 0, 0, {
|
||||||
"foo",
|
"foo",
|
||||||
"bar",
|
"bar",
|
41
lua/harpoon2/test/harpoon_spec.lua
Normal file
41
lua/harpoon2/test/harpoon_spec.lua
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
local Data = require("harpoon2.data")
|
||||||
|
local harpoon = require("harpoon2")
|
||||||
|
|
||||||
|
local eq = assert.are.same
|
||||||
|
|
||||||
|
describe("harpoon", function()
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
Data.set_data_path("/tmp/harpoon2.json")
|
||||||
|
Data.__dangerously_clear_data()
|
||||||
|
require("plenary.reload").reload_module("harpoon2")
|
||||||
|
Data = require("harpoon2.data")
|
||||||
|
Data.set_data_path("/tmp/harpoon2.json")
|
||||||
|
harpoon = require("harpoon2")
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("full harpoon add sync cycle", function()
|
||||||
|
local file_name = "/tmp/harpoon-test"
|
||||||
|
local row = 3
|
||||||
|
local col = 1
|
||||||
|
local bufnr = vim.fn.bufnr(file_name, true)
|
||||||
|
local default_key = harpoon:info().default_key
|
||||||
|
vim.api.nvim_set_current_buf(bufnr)
|
||||||
|
vim.api.nvim_buf_set_text(0, 0, 0, 0, 0, {
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
"qux"
|
||||||
|
})
|
||||||
|
vim.api.nvim_win_set_cursor(0, {row, col})
|
||||||
|
|
||||||
|
local list = harpoon:list():push()
|
||||||
|
harpoon:sync()
|
||||||
|
|
||||||
|
eq(harpoon:dump(), {
|
||||||
|
[default_key] = list:encode()
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
local List = require("harpoon.list")
|
local List = require("harpoon2.list")
|
||||||
local Config = require("harpoon.config")
|
local Config = require("harpoon2.config")
|
||||||
local eq = assert.are.same
|
local eq = assert.are.same
|
||||||
|
|
||||||
describe("list", function()
|
describe("list", function()
|
Loading…
x
Reference in New Issue
Block a user