feat(strct-tags): add support for tag options (#126)
* feat(struct_tags): add options support * refactor(struct-tags): give input field better name * feat(struct-tag): add default option * refactor: make it work on neovim version below 0.12 * chore(struct-tags): update the demo * refactor: unite struct_tags util with main logic
This commit is contained in:
parent
0de1892ca9
commit
7a18d9f7bd
19 changed files with 301 additions and 15 deletions
|
|
@ -72,6 +72,9 @@ Requirements:
|
|||
" add json tag
|
||||
:GoTagAdd json
|
||||
|
||||
" add json tag with omitempty option
|
||||
:GoTagAdd json=omitempty
|
||||
|
||||
" remove yaml tag
|
||||
:GoTagRm yaml
|
||||
```
|
||||
|
|
@ -233,6 +236,8 @@ require("gopher").setup {
|
|||
transform = "snakecase",
|
||||
-- default tags to add to struct fields
|
||||
default_tag = "json",
|
||||
-- default tag option added struct fields, set to nil to disable
|
||||
option = nil,
|
||||
},
|
||||
iferr = {
|
||||
-- choose a custom error message
|
||||
|
|
|
|||
|
|
@ -89,6 +89,10 @@ to install them synchronously pass `{sync = true}` as an argument.
|
|||
|
||||
-- default tags to add to struct fields
|
||||
default_tag = "json",
|
||||
|
||||
-- default tag option added struct fields, set to nil to disable
|
||||
---@type string|nil
|
||||
option = nil,
|
||||
},
|
||||
iferr = {
|
||||
-- choose a custom error message
|
||||
|
|
@ -124,6 +128,9 @@ How to add/remove tags to struct fields:
|
|||
2. Run `:GoTagAdd json` to add json tags to struct fields
|
||||
3. Run `:GoTagRm json` to remove json tags to struct fields
|
||||
|
||||
If you want to add/remove tag with options, you can use `json=omitempty` (where json is tag, and omitempty is its option).
|
||||
Example: `:GoTagAdd xml json=omitempty`
|
||||
|
||||
To clear all tags from struct run: `:GoTagClear`
|
||||
|
||||
NOTE: if you dont specify the tag it will use `json` as default
|
||||
|
|
|
|||
|
|
@ -50,4 +50,23 @@ function utils.indent(line, indent)
|
|||
return string.rep(char, indent)
|
||||
end
|
||||
|
||||
---@generic T
|
||||
---@param tbl T[]
|
||||
---@return T[]
|
||||
function utils.list_unique(tbl)
|
||||
if vim.fn.has "nvim-0.12" == 1 then
|
||||
return vim.list.unique(tbl)
|
||||
end
|
||||
|
||||
for i = #tbl, 1, -1 do
|
||||
for j = 1, i - 1 do
|
||||
if tbl[i] == tbl[j] then
|
||||
table.remove(tbl, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
return utils
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ local default_config = {
|
|||
|
||||
-- default tags to add to struct fields
|
||||
default_tag = "json",
|
||||
|
||||
-- default tag option added struct fields, set to nil to disable
|
||||
---@type string|nil
|
||||
option = nil,
|
||||
},
|
||||
iferr = {
|
||||
-- choose a custom error message
|
||||
|
|
@ -105,6 +109,7 @@ function config.setup(user_config)
|
|||
vim.validate("gotag", _config.gotag, "table")
|
||||
vim.validate("gotag.transform", _config.gotag.transform, "string")
|
||||
vim.validate("gotag.default_tag", _config.gotag.default_tag, "string")
|
||||
vim.validate("gotag.option", _config.gotag.option, { "string", "nil" })
|
||||
vim.validate("iferr", _config.iferr, "table")
|
||||
vim.validate("iferr.message", _config.iferr.message, { "string", "nil" })
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@
|
|||
--- 2. Run `:GoTagAdd json` to add json tags to struct fields
|
||||
--- 3. Run `:GoTagRm json` to remove json tags to struct fields
|
||||
---
|
||||
--- If you want to add/remove tag with options, you can use `json=omitempty` (where json is tag, and omitempty is its option).
|
||||
--- Example: `:GoTagAdd xml json=omitempty`
|
||||
---
|
||||
--- To clear all tags from struct run: `:GoTagClear`
|
||||
---
|
||||
--- NOTE: if you dont specify the tag it will use `json` as default
|
||||
|
|
@ -39,7 +42,7 @@ local struct_tags = {}
|
|||
|
||||
---@dochide
|
||||
---@class gopher.StructTagInput
|
||||
---@field tags string[] User provided tags
|
||||
---@field input string[] User provided tags
|
||||
---@field range? gopher.StructTagRange (optional)
|
||||
|
||||
---@dochide
|
||||
|
|
@ -102,18 +105,53 @@ local function handle_tags(fpath, bufnr, range, user_args)
|
|||
)
|
||||
end
|
||||
|
||||
---@param args string[]
|
||||
---@return string
|
||||
---@dochide
|
||||
local function handler_user_tags(args)
|
||||
if #args == 0 then
|
||||
return c.gotag.default_tag
|
||||
---@param option string
|
||||
local function option_to_tag(option)
|
||||
return option:match "^(.-)="
|
||||
end
|
||||
|
||||
---@dochide
|
||||
---@param args string[]
|
||||
local function unwrap_if_needed(args)
|
||||
local out = {}
|
||||
for _, v in pairs(args) do
|
||||
for _, p in pairs(vim.split(v, ",")) do
|
||||
table.insert(out, p)
|
||||
end
|
||||
return table.concat(args, ",")
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
---@dochide
|
||||
---@class gopher.StructTagsArgs
|
||||
---@field tags string
|
||||
---@field options string
|
||||
|
||||
---@dochide
|
||||
---@param args string[]
|
||||
---@return gopher.StructTagsArgs
|
||||
function struct_tags.parse_args(args)
|
||||
args = unwrap_if_needed(args)
|
||||
|
||||
local tags, options = {}, {}
|
||||
for _, v in pairs(args) do
|
||||
if string.find(v, "=") then
|
||||
table.insert(options, v)
|
||||
table.insert(tags, option_to_tag(v))
|
||||
else
|
||||
table.insert(tags, v)
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
tags = table.concat(u.list_unique(tags), ","),
|
||||
options = table.concat(u.list_unique(options), ","),
|
||||
}
|
||||
end
|
||||
|
||||
-- Adds tags to a struct under the cursor
|
||||
-- See |gopher.nvim-struct-tags|
|
||||
-- See `:h gopher.nvim-struct-tags`
|
||||
---@param opts gopher.StructTagInput
|
||||
---@dochide
|
||||
function struct_tags.add(opts)
|
||||
|
|
@ -122,8 +160,13 @@ function struct_tags.add(opts)
|
|||
local fpath = vim.fn.expand "%"
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
|
||||
local user_tags = handler_user_tags(opts.tags)
|
||||
handle_tags(fpath, bufnr, opts.range, { "-add-tags", user_tags })
|
||||
local user_args = struct_tags.parse_args(opts.input)
|
||||
handle_tags(fpath, bufnr, opts.range, {
|
||||
"-add-tags",
|
||||
(user_args.tags ~= "") and user_args.tags or c.gotag.default_tag,
|
||||
(user_args.options ~= "" or c.gotag.option) and "-add-options" or nil,
|
||||
(user_args.options ~= "") and user_args.options or c.gotag.option,
|
||||
})
|
||||
end
|
||||
|
||||
-- Removes tags from a struct under the cursor
|
||||
|
|
@ -136,8 +179,13 @@ function struct_tags.remove(opts)
|
|||
local fpath = vim.fn.expand "%"
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
|
||||
local user_tags = handler_user_tags(opts.tags)
|
||||
handle_tags(fpath, bufnr, opts.range, { "-remove-tags", user_tags })
|
||||
local user_args = struct_tags.parse_args(opts.input)
|
||||
handle_tags(fpath, bufnr, opts.range, {
|
||||
"-remove-tags",
|
||||
(user_args.tags ~= "") and user_args.tags or c.gotag.default_tag,
|
||||
(user_args.options ~= "" or c.gotag.option ~= nil) and "-remove-options" or nil,
|
||||
(user_args.options ~= "") and user_args.options or c.gotag.option,
|
||||
})
|
||||
end
|
||||
|
||||
-- Removes all tags from a struct under the cursor
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ end)
|
|||
-- :GoTag
|
||||
cmd("GoTagAdd", function(opts)
|
||||
require("gopher").tags.add {
|
||||
tags = opts.fargs,
|
||||
input = opts.fargs,
|
||||
range = (opts.count ~= -1) and {
|
||||
start = opts.line1,
|
||||
end_ = opts.line2,
|
||||
|
|
@ -58,7 +58,7 @@ end, "*", true)
|
|||
|
||||
cmd("GoTagRm", function(opts)
|
||||
require("gopher").tags.rm {
|
||||
tags = opts.fargs,
|
||||
input = opts.fargs,
|
||||
range = (opts.count ~= -1) and {
|
||||
start = opts.line1,
|
||||
end_ = opts.line2,
|
||||
|
|
|
|||
8
spec/fixtures/tags/overwrite_default_option_input.go
vendored
Normal file
8
spec/fixtures/tags/overwrite_default_option_input.go
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package main
|
||||
|
||||
type Test struct {
|
||||
ID int
|
||||
Another struct {
|
||||
Second string
|
||||
}
|
||||
}
|
||||
8
spec/fixtures/tags/overwrite_default_option_output.go
vendored
Normal file
8
spec/fixtures/tags/overwrite_default_option_output.go
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package main
|
||||
|
||||
type Test struct {
|
||||
ID int `xml:"id,otheroption"`
|
||||
Another struct {
|
||||
Second string `xml:"second,otheroption"`
|
||||
} `xml:"another,otheroption"`
|
||||
}
|
||||
11
spec/fixtures/tags/remove_with_option_input.go
vendored
Normal file
11
spec/fixtures/tags/remove_with_option_input.go
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
type Test struct {
|
||||
ID int `json:"id,omitempty" xml:"id,someoption"`
|
||||
Name string `json:"name,omitempty" xml:"name,someoption"`
|
||||
Num int64 `json:"num,omitempty" xml:"num,someoption"`
|
||||
Another struct {
|
||||
First int `json:"first,omitempty" xml:"first,someoption"`
|
||||
Second string `json:"second,omitempty" xml:"second,someoption"`
|
||||
} `json:"another,omitempty" xml:"another,someoption"`
|
||||
}
|
||||
11
spec/fixtures/tags/remove_with_option_output.go
vendored
Normal file
11
spec/fixtures/tags/remove_with_option_output.go
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
type Test struct {
|
||||
ID int `xml:"id,someoption"`
|
||||
Name string `xml:"name,someoption"`
|
||||
Num int64 `xml:"num,someoption"`
|
||||
Another struct {
|
||||
First int `xml:"first,someoption"`
|
||||
Second string `xml:"second,someoption"`
|
||||
} `xml:"another,someoption"`
|
||||
}
|
||||
8
spec/fixtures/tags/with_default_option_input.go
vendored
Normal file
8
spec/fixtures/tags/with_default_option_input.go
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package main
|
||||
|
||||
type Test struct {
|
||||
ID int
|
||||
Another struct {
|
||||
Second string
|
||||
}
|
||||
}
|
||||
8
spec/fixtures/tags/with_default_option_output.go
vendored
Normal file
8
spec/fixtures/tags/with_default_option_output.go
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package main
|
||||
|
||||
type Test struct {
|
||||
ID int `xml:"id,theoption"`
|
||||
Another struct {
|
||||
Second string `xml:"second,theoption"`
|
||||
} `xml:"another,theoption"`
|
||||
}
|
||||
11
spec/fixtures/tags/with_option_input.go
vendored
Normal file
11
spec/fixtures/tags/with_option_input.go
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
type Test struct {
|
||||
ID int
|
||||
Name string
|
||||
Num int64
|
||||
Another struct {
|
||||
First int
|
||||
Second string
|
||||
}
|
||||
}
|
||||
11
spec/fixtures/tags/with_option_output.go
vendored
Normal file
11
spec/fixtures/tags/with_option_output.go
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
type Test struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Num int64 `json:"num,omitempty"`
|
||||
Another struct {
|
||||
First int `json:"first,omitempty"`
|
||||
Second string `json:"second,omitempty"`
|
||||
} `json:"another,omitempty"`
|
||||
}
|
||||
|
|
@ -96,4 +96,52 @@ struct_tags["should remove tag with range"] = function()
|
|||
t.cleanup(rs)
|
||||
end
|
||||
|
||||
struct_tags["should add tags with option"] = function()
|
||||
local rs = t.setup_test("tags/with_option", child, { 3, 6 })
|
||||
child.cmd "GoTagAdd json=omitempty"
|
||||
child.cmd "write"
|
||||
|
||||
t.eq(t.readfile(rs.tmp), rs.fixtures.output)
|
||||
t.cleanup(rs)
|
||||
end
|
||||
|
||||
struct_tags["should add tags with default option"] = function()
|
||||
child.lua [[
|
||||
require("gopher").setup {
|
||||
gotag = { option = "xml=theoption" },
|
||||
}
|
||||
]]
|
||||
|
||||
local rs = t.setup_test("tags/with_default_option", child, { 3, 6 })
|
||||
child.cmd "GoTagAdd xml"
|
||||
child.cmd "write"
|
||||
|
||||
t.eq(t.readfile(rs.tmp), rs.fixtures.output)
|
||||
t.cleanup(rs)
|
||||
end
|
||||
|
||||
struct_tags["should add tags and overwrite default option"] = function()
|
||||
child.lua [[
|
||||
require("gopher").setup {
|
||||
gotag = { option = "xml=theoption" },
|
||||
}
|
||||
]]
|
||||
|
||||
local rs = t.setup_test("tags/overwrite_default_option", child, { 3, 6 })
|
||||
child.cmd "GoTagAdd xml=otheroption"
|
||||
child.cmd "write"
|
||||
|
||||
t.eq(t.readfile(rs.tmp), rs.fixtures.output)
|
||||
t.cleanup(rs)
|
||||
end
|
||||
|
||||
struct_tags["should remove tag with specified option"] = function()
|
||||
local rs = t.setup_test("tags/remove_with_option", child, { 3, 6 })
|
||||
child.cmd "GoTagRm json=omitempty"
|
||||
child.cmd "write"
|
||||
|
||||
t.eq(t.readfile(rs.tmp), rs.fixtures.output)
|
||||
t.cleanup(rs)
|
||||
end
|
||||
|
||||
return T
|
||||
|
|
|
|||
68
spec/unit/struct_tag_test.lua
Normal file
68
spec/unit/struct_tag_test.lua
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
local t = require "spec.testutils"
|
||||
local _, T, st = t.setup "struct_tags"
|
||||
|
||||
st["should parse tags"] = function()
|
||||
local out = require("gopher.struct_tags").parse_args { "json", "yaml", "etc" }
|
||||
|
||||
t.eq(out.tags, "json,yaml,etc")
|
||||
t.eq(out.options, "")
|
||||
end
|
||||
|
||||
st["should parse tags separated by commas"] = function()
|
||||
local out = require("gopher.struct_tags").parse_args { "json,yaml,etc" }
|
||||
|
||||
t.eq(out.tags, "json,yaml,etc")
|
||||
t.eq(out.options, "")
|
||||
end
|
||||
|
||||
st["should parse tags separated by command and spaces"] = function()
|
||||
local out = require("gopher.struct_tags").parse_args {
|
||||
"json,yaml",
|
||||
"json=omitempty",
|
||||
"xml=something",
|
||||
}
|
||||
|
||||
t.eq(out.tags, "json,yaml,xml")
|
||||
t.eq(out.options, "json=omitempty,xml=something")
|
||||
end
|
||||
|
||||
st["should parse tag with an option"] = function()
|
||||
local out = require("gopher.struct_tags").parse_args {
|
||||
"json=omitempty",
|
||||
"xml",
|
||||
"xml=theoption",
|
||||
}
|
||||
|
||||
t.eq(out.tags, "json,xml")
|
||||
t.eq(out.options, "json=omitempty,xml=theoption")
|
||||
end
|
||||
|
||||
st["should parse tags with an option"] = function()
|
||||
local out = require("gopher.struct_tags").parse_args { "json=omitempty", "yaml" }
|
||||
|
||||
t.eq(out.tags, "json,yaml")
|
||||
t.eq(out.options, "json=omitempty")
|
||||
end
|
||||
|
||||
st["should parse tags with an option separated with comma"] = function()
|
||||
local out = require("gopher.struct_tags").parse_args { "json=omitempty,yaml" }
|
||||
|
||||
t.eq(out.tags, "json,yaml")
|
||||
t.eq(out.options, "json=omitempty")
|
||||
end
|
||||
|
||||
st["should parse tags with options specified separately"] = function()
|
||||
local out = require("gopher.struct_tags").parse_args { "json", "yaml", "json=omitempty" }
|
||||
|
||||
t.eq(out.tags, "json,yaml")
|
||||
t.eq(out.options, "json=omitempty")
|
||||
end
|
||||
|
||||
st["should parse tags with options specified separately and separated by comma"] = function()
|
||||
local out = require("gopher.struct_tags").parse_args { "json,yaml,json=omitempty" }
|
||||
|
||||
t.eq(out.tags, "json,yaml")
|
||||
t.eq(out.options, "json=omitempty")
|
||||
end
|
||||
|
||||
return T
|
||||
|
|
@ -46,4 +46,14 @@ utils["should add .indent() 2 tabs"] = function()
|
|||
t.eq("\t\t", u.indent(line, indent))
|
||||
end
|
||||
|
||||
utils["should .list_unique on list with duplicates"] = function()
|
||||
local u = require "gopher._utils"
|
||||
t.eq({ "json", "xml" }, u.list_unique { "json", "xml", "json" })
|
||||
end
|
||||
|
||||
utils["should .list_unique on list with no duplicates"] = function()
|
||||
local u = require "gopher._utils"
|
||||
t.eq({ "json", "xml" }, u.list_unique { "json", "xml" })
|
||||
end
|
||||
|
||||
return T
|
||||
|
|
|
|||
BIN
vhs/tags.gif
BIN
vhs/tags.gif
Binary file not shown.
|
Before Width: | Height: | Size: 252 KiB After Width: | Height: | Size: 280 KiB |
|
|
@ -26,6 +26,6 @@ Type ":w" Enter
|
|||
Sleep 1s
|
||||
|
||||
Type@400ms "jVjj"
|
||||
Type ":GoTagAdd xml" Sleep 500ms Enter
|
||||
Type ":GoTagAdd json=omitempty" Sleep 500ms Enter
|
||||
|
||||
Sleep 5s
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue