From 46725147f77d9492ad0e4a2fcface35750ef8952 Mon Sep 17 00:00:00 2001 From: Oleksandr Smirnov Date: Fri, 29 Aug 2025 18:37:28 +0300 Subject: [PATCH] feat(struct_tags): add range support --- lua/gopher/struct_tags.lua | 52 ++++++++++++++++------- plugin/gopher.lua | 29 ++++++++++--- spec/fixtures/tags/add_range_input.go | 14 ++++++ spec/fixtures/tags/add_range_output.go | 14 ++++++ spec/fixtures/tags/remove_range_input.go | 14 ++++++ spec/fixtures/tags/remove_range_output.go | 14 ++++++ spec/integration/struct_tags_test.lua | 18 ++++++++ 7 files changed, 132 insertions(+), 23 deletions(-) create mode 100644 spec/fixtures/tags/add_range_input.go create mode 100644 spec/fixtures/tags/add_range_output.go create mode 100644 spec/fixtures/tags/remove_range_input.go create mode 100644 spec/fixtures/tags/remove_range_output.go diff --git a/lua/gopher/struct_tags.lua b/lua/gopher/struct_tags.lua index cf990bf..34e4730 100644 --- a/lua/gopher/struct_tags.lua +++ b/lua/gopher/struct_tags.lua @@ -37,11 +37,22 @@ local u = require "gopher._utils" local log = require "gopher._utils.log" local struct_tags = {} +---@dochide +---@class gopher.StructTagInput +---@field tags string[] User provided tags +---@field range? gopher.StructTagRange (optional) + +---@dochide +---@class gopher.StructTagRange +---@field start number +---@field end_ number + ---@param fpath string ---@param bufnr integer +---@param range? gopher.StructTagRange ---@param user_args string[] ---@dochide -local function handle_tags(fpath, bufnr, user_args) +local function handle_tags(fpath, bufnr, range, user_args) local st = ts.get_struct_under_cursor(bufnr) -- stylua: ignore @@ -53,12 +64,19 @@ local function handle_tags(fpath, bufnr, user_args) "-w", } - if st.is_varstruct then + -- since `-strut` and `-line` cannot be combined together set set them only + -- if user doesn't do ranges + if range ~= nil then table.insert(cmd, "-line") - table.insert(cmd, string.format("%d,%d", st.start_line, st.end_line)) + table.insert(cmd, string.format("%d,%d", range.start, range.end_)) else - table.insert(cmd, "-struct") - table.insert(cmd, st.name) + if st.is_varstruct then + table.insert(cmd, "-line") + table.insert(cmd, string.format("%d,%d", st.start_line, st.end_line)) + else + table.insert(cmd, "-struct") + table.insert(cmd, st.name) + end end for _, v in ipairs(user_args) do @@ -102,28 +120,30 @@ end -- Adds tags to a struct under the cursor -- See |gopher.nvim-struct-tags| ----@param ... string Tags to add to the struct fields. If not provided, it will use [config.gotag.default_tag] +---@param opts gopher.StructTagInput ---@dochide -function struct_tags.add(...) - local args = { ... } +function struct_tags.add(opts) + log.debug("adding tags", opts) + local fpath = vim.fn.expand "%" local bufnr = vim.api.nvim_get_current_buf() - local user_tags = handler_user_args(args) - handle_tags(fpath, bufnr, { "-add-tags", user_tags }) + local user_tags = handler_user_args(opts.tags) + handle_tags(fpath, bufnr, opts.range, { "-add-tags", user_tags }) end -- Removes tags from a struct under the cursor -- See `:h gopher.nvim-struct-tags` ---@dochide ----@param ... string Tags to add to the struct fields. If not provided, it will use [config.gotag.default_tag] -function struct_tags.remove(...) - local args = { ... } +---@param opts gopher.StructTagInput +function struct_tags.remove(opts) + log.debug("removing tags", opts) + local fpath = vim.fn.expand "%" local bufnr = vim.api.nvim_get_current_buf() - local user_tags = handler_user_args(args) - handle_tags(fpath, bufnr, { "-remove-tags", user_tags }) + local user_tags = handler_user_args(opts.tags) + handle_tags(fpath, bufnr, opts.range, { "-remove-tags", user_tags }) end -- Removes all tags from a struct under the cursor @@ -132,7 +152,7 @@ end function struct_tags.clear() local fpath = vim.fn.expand "%" local bufnr = vim.api.nvim_get_current_buf() - handle_tags(fpath, bufnr, { "-clear-tags" }) + handle_tags(fpath, bufnr, nil, { "-clear-tags" }) end return struct_tags diff --git a/plugin/gopher.lua b/plugin/gopher.lua index 1ccc74e..4ffda5b 100644 --- a/plugin/gopher.lua +++ b/plugin/gopher.lua @@ -11,10 +11,13 @@ end ---@param name string ---@param fn fun(args: table) ---@param nargs? number|"*"|"?" +---@param range? boolean ---@private -local function cmd(name, fn, nargs) - nargs = nargs or 0 - vim.api.nvim_create_user_command(name, fn, { nargs = nargs }) +local function cmd(name, fn, nargs, range) + vim.api.nvim_create_user_command(name, fn, { + nargs = nargs or 0, + range = range or false, + }) end cmd("GopherLog", function() @@ -44,12 +47,24 @@ end) -- :GoTag cmd("GoTagAdd", function(opts) - require("gopher").tags.add(unpack(opts.fargs)) -end, "*") + require("gopher").tags.add { + tags = opts.fargs, + range = (opts.count ~= -1) and { + start = opts.line1, + end_ = opts.line2, + } or nil, + } +end, "*", true) cmd("GoTagRm", function(opts) - require("gopher").tags.rm(unpack(opts.fargs)) -end, "*") + require("gopher").tags.rm { + tags = opts.fargs, + range = (opts.count ~= -1) and { + start = opts.line1, + end_ = opts.line2, + } or nil, + } +end, "*", true) cmd("GoTagClear", function() require("gopher").tags.clear() diff --git a/spec/fixtures/tags/add_range_input.go b/spec/fixtures/tags/add_range_input.go new file mode 100644 index 0000000..7786518 --- /dev/null +++ b/spec/fixtures/tags/add_range_input.go @@ -0,0 +1,14 @@ +package main + +type Test struct { + ID int + Name string + Num int64 + Cost int + Thingy []string + Testing int + Another struct { + First int + Second string + } +} diff --git a/spec/fixtures/tags/add_range_output.go b/spec/fixtures/tags/add_range_output.go new file mode 100644 index 0000000..2d287ab --- /dev/null +++ b/spec/fixtures/tags/add_range_output.go @@ -0,0 +1,14 @@ +package main + +type Test struct { + ID int + Name string `gopher:"name"` + Num int64 `gopher:"num"` + Cost int `gopher:"cost"` + Thingy []string + Testing int + Another struct { + First int + Second string + } +} diff --git a/spec/fixtures/tags/remove_range_input.go b/spec/fixtures/tags/remove_range_input.go new file mode 100644 index 0000000..efa4c9d --- /dev/null +++ b/spec/fixtures/tags/remove_range_input.go @@ -0,0 +1,14 @@ +package main + +type Test struct { + ID int `asdf:"id"` + Name string `asdf:"name"` + Num int64 `asdf:"num"` + Cost int `asdf:"cost"` + Thingy []string `asdf:"thingy"` + Testing int `asdf:"testing"` + Another struct { + First int `asdf:"first"` + Second string `asdf:"second"` + } `asdf:"another"` +} diff --git a/spec/fixtures/tags/remove_range_output.go b/spec/fixtures/tags/remove_range_output.go new file mode 100644 index 0000000..8c51c55 --- /dev/null +++ b/spec/fixtures/tags/remove_range_output.go @@ -0,0 +1,14 @@ +package main + +type Test struct { + ID int `asdf:"id"` + Name string `asdf:"name"` + Num int64 + Cost int + Thingy []string + Testing int `asdf:"testing"` + Another struct { + First int `asdf:"first"` + Second string `asdf:"second"` + } `asdf:"another"` +} diff --git a/spec/integration/struct_tags_test.lua b/spec/integration/struct_tags_test.lua index 2f99ea1..ae7995b 100644 --- a/spec/integration/struct_tags_test.lua +++ b/spec/integration/struct_tags_test.lua @@ -78,4 +78,22 @@ struct_tags["should add tags on short declr var"] = function() t.cleanup(rs) end +struct_tags["should add tag with range"] = function() + local rs = t.setup_test("tags/add_range", child, { 5, 1 }) + child.cmd ".,+2GoTagAdd gopher" + child.cmd "write" + + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) +end + +struct_tags["should remove tag with range"] = function() + local rs = t.setup_test("tags/remove_range", child, { 6, 1 }) + child.cmd ".,+2GoTagRm asdf" + child.cmd "write" + + t.eq(t.readfile(rs.tmp), rs.fixtures.output) + t.cleanup(rs) +end + return T