From a0fb01d63d91cb2c17c01e5b481cd05391527343 Mon Sep 17 00:00:00 2001 From: Calvin Bochulak Date: Thu, 29 Feb 2024 19:20:44 -0700 Subject: [PATCH] feat: add actions for loaded scopes window --- lua/grapple.lua | 44 ++++++++++++++++++++++--------- lua/grapple/container_actions.lua | 14 ++++++++++ lua/grapple/container_content.lua | 6 ++--- lua/grapple/scope_manager.lua | 16 ++++++++++- lua/grapple/settings.lua | 16 +++++++++-- lua/grapple/tag_container.lua | 12 ++++----- 6 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 lua/grapple/container_actions.lua diff --git a/lua/grapple.lua b/lua/grapple.lua index 2d4bbd44..e44f4635 100644 --- a/lua/grapple.lua +++ b/lua/grapple.lua @@ -316,23 +316,34 @@ end ---Clear all tags for a given scope ---By default, uses the current scope ----@param opts? { scope?: string } +---@param opts? { scope?: string, id?: string } function Grapple.reset(opts) local App = require("grapple.app") opts = opts or {} local app = App.get() - local scope, err = app.scope_manager:get_resolved(opts.scope or app.settings.scope) - if not scope then - ---@diagnostic disable-next-line: param-type-mismatch - return vim.notify(err, vim.log.levels.ERROR) + + ---@type string + local id + if opts.id then + id = opts.id + else + local scope, err = app.scope_manager:get_resolved(opts.scope or app.settings.scope) + if not scope then + ---@diagnostic disable-next-line: param-type-mismatch + return vim.notify(err, vim.log.levels.ERROR) + end + + id = scope.id end - ---@diagnostic disable-next-line: redefined-local - local err = app.tag_manager:reset(scope.id) + if not id then + return vim.notify(string.format("must provide a valid scope or id: %s", vim.inspect(opts))) + end + + local err = app.tag_manager:reset(id) if err then - ---@diagnostic disable-next-line: param-type-mismatch vim.notify(err, vim.log.levels.ERROR) end end @@ -351,13 +362,13 @@ function Grapple.use_scope(scope) local App = require("grapple.app") local app = App.get() - local scope, err = app.scope_manager:get(scope) - if not scope then + local resolved, err = app.scope_manager:get(scope) + if not resolved then ---@diagnostic disable-next-line: param-type-mismatch return vim.notify(err, vim.log.levels.ERROR) end - app.settings:update({ scope = scope.name }) + app.settings:update({ scope = resolved.name }) end ---@param scope? string @@ -387,7 +398,7 @@ end ---Open a floating window populated with all tags for a given scope ---By default, uses the current scope ----@param opts? { scope?: string } +---@param opts? { scope?: string, id?: string } function Grapple.open_tags(opts) local App = require("grapple.app") local TagContent = require("grapple.tag_content") @@ -395,7 +406,14 @@ function Grapple.open_tags(opts) opts = opts or {} local app = App.get() - local scope, err = app.scope_manager:get_resolved(opts.scope or app.settings.scope) + + local scope, err + if opts.id then + scope, err = app.scope_manager:lookup(opts.id) + else + scope, err = app.scope_manager:get_resolved(opts.scope or app.settings.scope) + end + if not scope then ---@diagnostic disable-next-line: param-type-mismatch return vim.notify(err, vim.log.levels.ERROR) diff --git a/lua/grapple/container_actions.lua b/lua/grapple/container_actions.lua new file mode 100644 index 00000000..4f7221e8 --- /dev/null +++ b/lua/grapple/container_actions.lua @@ -0,0 +1,14 @@ +local ScopeActions = {} + +---@class grapple.action.container_options +--- +---User-provided information +---@field id? string + +---@param opts grapple.action.container_options +---@return string? error +function ScopeActions.select(opts) + require("grapple").open_tags({ id = opts.id }) +end + +return ScopeActions diff --git a/lua/grapple/container_content.lua b/lua/grapple/container_content.lua index 75761996..f400727d 100644 --- a/lua/grapple/container_content.lua +++ b/lua/grapple/container_content.lua @@ -62,7 +62,7 @@ function ContainerContent:entities() ---@param cont_a grapple.tag_container ---@param cont_b grapple.tag_container local function by_name(cont_a, cont_b) - return string.lower(cont_a.name) < string.lower(cont_b.name) + return string.lower(cont_a.id) < string.lower(cont_b.id) end local containers = vim.tbl_values(self.tag_manager.containers) @@ -79,14 +79,14 @@ function ContainerContent:create_entry(container, index) local id = string.format("/%03d", index) -- In compliance with "grapple" syntax - local line = string.format("%s %s", id, container.name) + local line = string.format("%s %s", id, container.id) local min_col = assert(string.find(line, "%s")) -- width of id ---@type grapple.window.entry local entry = { ---@class grapple.scope_content.data data = { - name = container.name, + id = container.id, }, line = line, diff --git a/lua/grapple/scope_manager.lua b/lua/grapple/scope_manager.lua index 1b4f9e74..ad20969e 100644 --- a/lua/grapple/scope_manager.lua +++ b/lua/grapple/scope_manager.lua @@ -4,6 +4,7 @@ local Scope = require("grapple.scope") ---@field tag_manager grapple.tag_manager ---@field cache grapple.cache ---@field scopes table +---@field resolved_lookup table local ScopeManager = {} ScopeManager.__index = ScopeManager @@ -15,6 +16,7 @@ function ScopeManager:new(tag_manager, cache) tag_manager = tag_manager, cache = cache, scopes = {}, + resolved_lookup = {}, }, self) end @@ -26,12 +28,23 @@ end ---@return grapple.scope | nil, string? error function ScopeManager:get(name) if not self:exists(name) then - return nil, string.format("Could not find scope %s", name) + return nil, string.format("could not find scope: %s", name) end return self.scopes[name], nil end +---@param id string +---@return grapple.resolved_scope | nil, string? error +function ScopeManager:lookup(id) + local resolved = self.resolved_lookup[id] + if not resolved then + return nil, string.format("could not find resolved scope for id: %s", id) + end + + return self.resolved_lookup[id], nil +end + ---@param name string scope name ---@return grapple.resolved_scope | nil, string? error function ScopeManager:get_resolved(name) @@ -52,6 +65,7 @@ function ScopeManager:get_resolved(name) end self.cache:store(name, resolved) + self.resolved_lookup[resolved.id] = resolved return resolved end diff --git a/lua/grapple/settings.lua b/lua/grapple/settings.lua index cb963c6d..66ac4697 100644 --- a/lua/grapple/settings.lua +++ b/lua/grapple/settings.lua @@ -205,7 +205,7 @@ local DEFAULT_SETTINGS = { local entry = window:current_entry() local name = entry.data.name - local err = window:perform(ScopeActions.select, { name = entry.data.name }) + local err = window:perform(ScopeActions.select, { name = name }) if err then return vim.notify(err, vim.log.levels.ERROR) end @@ -223,7 +223,19 @@ local DEFAULT_SETTINGS = { ---Not user documented ---@type grapple.hook_fn - loaded_hook = function(window) end, + loaded_hook = function(window) + local ContainerActions = require("grapple.container_actions") + + window:map("n", "", function() + local entry = window:current_entry() + local id = entry.data.id + + local err = window:perform(ContainerActions.select, { id = id }) + if err then + return vim.notify(err, vim.log.levels.ERROR) + end + end, { desc = "" }) + end, ---Additional window options for Grapple windows ---@type grapple.vim.win_opts diff --git a/lua/grapple/tag_container.lua b/lua/grapple/tag_container.lua index 5f7130d6..30a8e828 100644 --- a/lua/grapple/tag_container.lua +++ b/lua/grapple/tag_container.lua @@ -17,18 +17,18 @@ local Tag = require("grapple.tag") ---@field index integer ---@class grapple.tag_container ----@field name string +---@field id string ---@field tags grapple.tag[] ---@field paths_index table ---@field names_index table local TagContainer = {} TagContainer.__index = TagContainer ----@param name string +---@param id string ---@return grapple.tag_container -function TagContainer:new(name) +function TagContainer:new(id) return setmetatable({ - name = name, + id = id, tags = {}, paths_index = {}, names_index = {}, @@ -219,7 +219,7 @@ function TagContainer:into_table() ---@class grapple.tag.container.format return { - name = self.name, + id = self.id, tags = vim.tbl_map(into_table, self.tags), } end @@ -228,7 +228,7 @@ end ---@param tbl grapple.tag.container.format ---@return grapple.tag_container | nil, string? error function TagContainer.from_table(tbl) - local container = TagContainer:new(tbl.name) + local container = TagContainer:new(tbl.id) for _, tag_tbl in ipairs(tbl.tags) do local tag, err = Tag.from_table(tag_tbl)