Skip to content

Commit

Permalink
feat: hashing on a per config.settings.key() basis
Browse files Browse the repository at this point in the history
  • Loading branch information
theprimeagen committed Apr 3, 2024
1 parent 4ad05be commit 3e32576
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 115 deletions.
15 changes: 15 additions & 0 deletions lua/harpoon/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ function M.get_default_config()
settings = {
save_on_toggle = false,
sync_on_ui_close = false,

key = function()
return vim.loop.cwd()
end,
Expand Down Expand Up @@ -205,6 +206,11 @@ function M.get_default_config()

item.context.row = pos[1]
item.context.col = pos[2]

Extensions.extensions:emit(
Extensions.event_names.POSITION_UPDATED,
item
)
end
end,

Expand All @@ -231,4 +237,13 @@ function M.merge_config(partial_config, latest_config)
return config
end

---@param settings HarpoonPartialSettings
function M.create_config(settings)
local config = M.get_default_config()
for k, v in ipairs(settings) do
config.settings[k] = v
end
return config
end

return M
83 changes: 40 additions & 43 deletions lua/harpoon/data.lua
Original file line number Diff line number Diff line change
@@ -1,43 +1,44 @@
local Path = require("plenary.path")

local data_path = vim.fn.stdpath("data")
local full_data_path = string.format("%s/harpoon.json", data_path)

---@param config HarpoonConfig
local filename = function(config)
return config.settings.key()
end

local function hash(path)
return vim.fn.sha256(path)
end

---@param config HarpoonConfig
local function fullpath(config)
local h = hash(filename(config))
return string.format("%s/%s.json", data_path, h)
end

---@param data any
local function write_data(data)
Path:new(full_data_path):write(vim.json.encode(data), "w")
---@param config HarpoonConfig
local function write_data(data, config)
Path:new(fullpath(config)):write(vim.json.encode(data), "w")
end

local M = {}

function M.__dangerously_clear_data()
write_data({})
---@param config HarpoonConfig
function M.__dangerously_clear_data(config)
write_data({}, config)
end

function M.info()
return {
data_path = data_path,
full_data_path = full_data_path,
}
end

function M.set_data_path(path)
full_data_path = path
end

local function has_keys(t)
-- luacheck: ignore 512
for _ in pairs(t) do
return true
end

return false
end

--- @alias HarpoonRawData {[string]: {[string]: string[]}}

--- @class HarpoonData
--- @field seen {[string]: {[string]: boolean}}
--- @field _data HarpoonRawData
--- @field has_error boolean
local Data = {}
Expand All @@ -48,34 +49,37 @@ local Data = {}

Data.__index = Data

---@param config HarpoonConfig
---@param provided_path string?
---@return HarpoonRawData
local function read_data()
local path = Path:new(full_data_path)
local function read_data(config, provided_path)
provided_path = provided_path or fullpath(config)
local path = Path:new(provided_path)
local exists = path:exists()

if not exists then
write_data({})
write_data({}, config)
end

local out_data = path:read()

if not out_data or out_data == "" then
write_data({})
out_data = path:read()
write_data({}, config)
out_data = "{}"
end

local data = vim.json.decode(out_data)
return data
end

---@param config HarpoonConfig
---@return HarpoonData
function Data:new()
local ok, data = pcall(read_data)
function Data:new(config)
local ok, data = pcall(read_data, config)

return setmetatable({
_data = data,
has_error = not ok,
seen = {},
}, self)
end

Expand All @@ -100,12 +104,6 @@ function Data:data(key, name)
)
end

if not self.seen[key] then
self.seen[key] = {}
end

self.seen[key][name] = true

return self:_get_data(key, name)
end

Expand All @@ -126,10 +124,6 @@ function Data:sync()
return
end

if not has_keys(self.seen) then
return
end

local ok, data = pcall(read_data)
if not ok then
error("Harpoon: unable to sync data, error reading data file")
Expand All @@ -139,13 +133,16 @@ function Data:sync()
data[k] = v
end

ok = pcall(write_data, data)

if ok then
self.seen = {}
end
pcall(write_data, data)
end

M.Data = Data
M.test = {
set_fullpath = function(fp)
fullpath = fp
end,

read_data = read_data,
}

return M
8 changes: 8 additions & 0 deletions lua/harpoon/extensions/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ local HarpoonExtensions = {}
---@field LIST_CREATED? fun(...): nil
---@field LIST_READ? fun(...): nil
---@field NAVIGATE? fun(...): nil
---@field POSITION_UPDATED? fun(...): nil

HarpoonExtensions.__index = HarpoonExtensions

Expand Down Expand Up @@ -71,6 +72,13 @@ return {
ADD = "ADD",
SELECT = "SELECT",
REMOVE = "REMOVE",
POSITION_UPDATED = "POSITION_UPDATED",

--- This exists because the ui can change the list in dramatic ways
--- so instead of emitting a REMOVE, then an ADD, then a REORDER, we
--- instead just emit LIST_CHANGE
LIST_CHANGE = "LIST_CHANGE",

REORDER = "REORDER",
UI_CREATE = "UI_CREATE",
SETUP_CALLED = "SETUP_CALLED",
Expand Down
34 changes: 23 additions & 11 deletions lua/harpoon/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,37 @@ local Harpoon = {}

Harpoon.__index = Harpoon

---@param harpoon Harpoon
local function sync_on_change(harpoon)
local function sync(_)
return function()
harpoon:sync()
end
end

Extensions.extensions:add_listener({
ADD = sync("ADD"),
REMOVE = sync("REMOVE"),
REORDER = sync("REORDER"),
LIST_CHANGE = sync("LIST_CHANGE"),
POSITION_UPDATED = sync("POSITION_UPDATED"),
})
end

---@return Harpoon
function Harpoon:new()
local config = Config.get_default_config()

local harpoon = setmetatable({
config = config,
data = Data.Data:new(),
data = Data.Data:new(config),
logger = Log,
ui = Ui:new(config.settings),
_extensions = Extensions.extensions,
lists = {},
hooks_setup = false,
}, self)
sync_on_change(harpoon)

return harpoon
end
Expand All @@ -51,10 +69,6 @@ function Harpoon:list(name)
local existing_list = lists[name]

if existing_list then
if not self.data.seen[key] then
self.data.seen[key] = {}
end
self.data.seen[key][name] = true
self._extensions:emit(Extensions.event_names.LIST_READ, existing_list)
return existing_list
end
Expand All @@ -72,16 +86,14 @@ end
---@param cb fun(list: HarpoonList, config: HarpoonPartialConfigItem, name: string)
function Harpoon:_for_each_list(cb)
local key = self.config.settings.key()
local seen = self.data.seen[key]
local lists = self.lists[key]

if not seen then
if not lists then
return
end

for list_name, _ in pairs(seen) do
local list_config = Config.get_config(self.config, list_name)
cb(lists[list_name], list_config, list_name)
for name, list in pairs(lists) do
local list_config = Config.get_config(self.config, name)
cb(list, list_config, name)
end
end

Expand Down
Loading

0 comments on commit 3e32576

Please sign in to comment.