Skip to content

Commit

Permalink
feat: add scope priority
Browse files Browse the repository at this point in the history
  • Loading branch information
cbochs committed Mar 27, 2024
1 parent a274117 commit 5e85367
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 25 deletions.
75 changes: 57 additions & 18 deletions lua/grapple/settings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,13 @@ local DEFAULT_SETTINGS = {

---@class grapple.scope_definition
---@field name string
---@field force? boolean
---@field desc? string
---@field force? boolean
---@field fallback? string name of scope to fall back on
---@field cache? grapple.cache.options | boolean
---@field priority? integer
---@field hidden? boolean
---@field delete? boolean
---@field resolver grapple.scope_resolver

---Default scopes provided by Grapple
Expand Down Expand Up @@ -483,32 +486,68 @@ end
---@return grapple.scope_definition[]
---@diagnostic disable-next-line: assign-type-mismatch
function Settings:scopes()
-- HACK: Define the order so that fallbacks are defined first
local default_order = {
"global",
"cwd",
"git",
"git_branch",
"lsp",
}

---@type grapple.scope_definition[]
local scopes = {}

for _, name in ipairs(default_order) do
local definition = self.inner.default_scopes[name]
-- Lookup table of whether a scope is used as a fallback
---@type table<string, boolean>
local fallback_lookup = {}

-- Add default scopes
for name, definition in pairs(self.inner.default_scopes) do
if definition == false then
table.insert(scopes, { name = name, delete = true })
elseif type(definition) == "table" then
table.insert(scopes, self.inner.default_scopes[name])
else
error(string.format("invalid default scope: %s", vim.inspect(definition)))
definition = { delete = true }
end

definition = vim.tbl_extend("keep", definition, {
name = name,
desc = "",
})

assert(type(definition.name) == "string")

table.insert(scopes, definition)
end

for _, definition in ipairs(self.inner.scopes) do
-- Add user-defined scopes
for name, definition in pairs(self.inner.scopes) do
definition = vim.tbl_extend("keep", definition, {
name = name,
desc = "",
})

assert(type(definition.name) == "string")

if definition.fallback then
fallback_lookup[definition.fallback] = true
end

table.insert(scopes, definition)
end

-- Prioritize scope loading
for _, scope in ipairs(scopes) do
if scope.priority then
-- Skip. Already given an explicit priority
elseif not scope.fallback then
scope.priority = 1000
elseif fallback_lookup[scope.name] then
scope.priority = 100
else
scope.priority = 1
end
end

local function by_priority(scope_a, scope_b)
if scope_a.priority == scope_b.priority then
return string.lower(scope_a.name) < string.lower(scope_b.name)
else
return scope_a.priority > scope_b.priority
end
end

table.sort(scopes, by_priority)

return scopes
end

Expand Down
2 changes: 1 addition & 1 deletion tests/grapple/app_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe("App", function()
app:update()
local names = vim.tbl_keys(app.scope_manager.scopes)
table.sort(names, Util.as_lower)
assert.same({ "cwd", "git", "git_branch", "global", "lsp" }, names)
assert.same({ "cwd", "git", "git_branch", "global", "lsp", "static" }, names)
end)
end)
end)
14 changes: 8 additions & 6 deletions tests/grapple/settings_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,35 +38,37 @@ describe("Settings", function()
end)

describe(".scopes", function()
it("has the correct scopes default", function()
it("has the correct scope defaults in priority order", function()
local settings = Settings:new()
-- stylua: ignore
local names = vim.tbl_map(function(def) return def.name end, settings:scopes())
assert.same({ "global", "cwd", "git", "git_branch", "lsp" }, names)
assert.same({ "cwd", "global", "static", "git", "git_branch", "lsp" }, names)
end)

it("merges default and user-defined scopes", function()
local settings = Settings:new()
settings:update({ scopes = { { name = "test" } } })
settings:update({ scopes = { test = {} } })
-- stylua: ignore
local names = vim.tbl_map(function(def) return def.name end, settings:scopes())
assert.same({ "global", "cwd", "git", "git_branch", "lsp", "test" }, names)
assert.same({ "cwd", "global", "static", "test", "git", "git_branch", "lsp" }, names)
end)

it("overrides default scope definitions", function()
local settings = Settings:new()
settings:update({ default_scopes = { global = { name = "bob" } } })
-- stylua: ignore
local names = vim.tbl_map(function(def) return def.name end, settings:scopes())
assert.same({ "bob", "cwd", "git", "git_branch", "lsp" }, names)
assert.same({ "bob", "cwd", "static", "git", "git_branch", "lsp" }, names)
end)

it("marks default scopes to be deleted", function()
local settings = Settings:new()
settings:update({ default_scopes = { cwd = false } })
-- stylua: ignore
local deleted = vim.tbl_filter(function(def) return def.delete end, settings:scopes())
assert.same({ { name = "cwd", delete = true } }, deleted)
assert.same(1, #deleted)
assert.same("cwd", deleted[1].name)
assert.same(true, deleted[1].delete)
end)
end)
end)

0 comments on commit 5e85367

Please sign in to comment.