+1
.github/workflows/tests.yml
+1
.github/workflows/tests.yml
+41
-6
README.md
+41
-6
README.md
···
8
9
> All development of new and maybe undocumented, and unstable features is happening on [develop](https://github.com/olexsmir/gopher.nvim/tree/develop) branch.
10
11
## Install (using [lazy.nvim](https://github.com/folke/lazy.nvim))
12
13
Requirements:
···
16
- Treesitter parser for `go`(`:TSInstall go` if you use [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter))
17
- [Go](https://github.com/golang/go) installed
18
19
```lua
20
-
-- NOTE: this plugin is already lazy-loaded, it adds only about 1ms of load
21
-
-- time to your config
22
{
23
"olexsmir/gopher.nvim",
24
ft = "go",
25
-- branch = "develop"
26
-
-- (optional) will update plugin's deps on every update
27
build = function()
28
vim.cmd.GoInstallDeps()
29
end,
···
64
```vim
65
" add json tag
66
:GoTagAdd json
67
68
" remove yaml tag
69
:GoTagRm yaml
···
201
-- timeout for running internal commands
202
timeout = 2000,
203
204
commands = {
205
go = "go",
206
gomodifytags = "gomodifytags",
···
209
iferr = "iferr",
210
},
211
gotests = {
212
-
-- gotests doesn't have template named "default" so this plugin uses "default" to set the default template
213
template = "default",
214
-- path to a directory containing custom test code templates
215
template_dir = nil,
216
-
-- switch table tests from using slice to map (with test name for the key)
217
named = false,
218
},
219
gotag = {
220
transform = "snakecase",
221
-- default tags to add to struct fields
222
default_tag = "json",
223
},
224
iferr = {
225
-
-- choose a custom error message
226
message = nil,
227
},
228
}
229
```
230
231
## Contributing
232
···
8
9
> All development of new and maybe undocumented, and unstable features is happening on [develop](https://github.com/olexsmir/gopher.nvim/tree/develop) branch.
10
11
+
## Table of content
12
+
* [How to install](#install-using-lazynvim)
13
+
* [Features](#features)
14
+
* [Configuration](#configuration)
15
+
* [Troubleshooting](#troubleshooting)
16
+
* [Contributing](#contributing)
17
+
18
## Install (using [lazy.nvim](https://github.com/folke/lazy.nvim))
19
20
Requirements:
···
23
- Treesitter parser for `go`(`:TSInstall go` if you use [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter))
24
- [Go](https://github.com/golang/go) installed
25
26
+
> [!IMPORTANT]
27
+
> If you prefer using other forges, this repository is also mirrored at:
28
+
> - [tangled.org](https://tangled.org): [`https://tangled.org/olexsmir.xyz/gopher.nvim`](https://tangled.org/olexsmir.xyz/gopher.nvim)
29
+
> - [codeberg.org](https://codeberg.org): [`https://codeberg.org/olexsmir/gopher.nvim`](https://codeberg.org/olexsmir/gopher.nvim)
30
+
31
```lua
32
+
-- NOTE: this plugin is already lazy-loaded and adds only about 1ms
33
+
-- of load time to your config
34
{
35
"olexsmir/gopher.nvim",
36
ft = "go",
37
-- branch = "develop"
38
+
-- (optional) updates the plugin's dependencies on each update
39
build = function()
40
vim.cmd.GoInstallDeps()
41
end,
···
76
```vim
77
" add json tag
78
:GoTagAdd json
79
+
80
+
" add json tag with omitempty option
81
+
:GoTagAdd json=omitempty
82
83
" remove yaml tag
84
:GoTagRm yaml
···
216
-- timeout for running internal commands
217
timeout = 2000,
218
219
+
-- timeout for running installer commands(e.g :GoDepsInstall, :GoDepsInstallSync)
220
+
installer_timeout = 999999,
221
+
222
+
-- user specified paths to binaries
223
commands = {
224
go = "go",
225
gomodifytags = "gomodifytags",
···
228
iferr = "iferr",
229
},
230
gotests = {
231
+
-- a default template that gotess will use.
232
+
-- gotets doesn't have template named `default`, we use it to represent absence of the provided template.
233
template = "default",
234
+
235
-- path to a directory containing custom test code templates
236
template_dir = nil,
237
+
238
+
-- use named tests(map with test name as key) in table tests(slice of structs by default)
239
named = false,
240
},
241
gotag = {
242
transform = "snakecase",
243
+
244
-- default tags to add to struct fields
245
default_tag = "json",
246
+
247
+
-- default tag option added struct fields, set to nil to disable
248
+
-- e.g: `option = "json=omitempty,xml=omitempty`
249
+
option = nil,
250
},
251
iferr = {
252
+
-- choose a custom error message, nil to use default
253
+
-- e.g: `message = 'fmt.Errorf("failed to %w", err)'`
254
message = nil,
255
},
256
}
257
```
258
+
259
+
## Troubleshooting
260
+
The most common issue with the plugin is missing dependencies.
261
+
Run `:checkhealth gopher` to verify that the plugin is installed correctly.
262
+
If any binaries are missing, install them using `:GoInstallDeps`.
263
+
264
+
If the issue persists, feel free to [open a new issue](https://github.com/olexsmir/gopher.nvim/issues/new).
265
266
## Contributing
267
+2
Taskfile.yml
+2
Taskfile.yml
+52
-31
doc/gopher.nvim.txt
+52
-31
doc/gopher.nvim.txt
···
36
------------------------------------------------------------------------------
37
*gopher.nvim-dependencies*
38
`gopher.install_deps`
39
-
Gopher.nvim implements most of its features using third-party tools.
40
-
To install these tools, you can run `:GoInstallDeps` command
41
-
or call `require("gopher").install_deps()` if you want to use lua api.
42
-
By default dependencies will be installed asynchronously,
43
-
to install them synchronously pass `{sync = true}` as an argument.
44
45
46
==============================================================================
···
57
---@type number
58
timeout = 2000,
59
60
-
--- timeout for running installer commands(e.g :GoDepsInstall, :GoDepsInstallSync)
61
installer_timeout = 999999,
62
63
-- user specified paths to binaries
···
71
},
72
---@class gopher.ConfigGotests
73
gotests = {
74
-
-- gotests doesn't have template named "default" so this plugin uses "default" to set the default template
75
template = "default",
76
-- path to a directory containing custom test code templates
77
---@type string|nil
78
template_dir = nil,
79
-
-- switch table tests from using slice to map (with test name for the key)
80
named = false,
81
},
82
---@class gopher.ConfigGoTag
···
86
87
-- default tags to add to struct fields
88
default_tag = "json",
89
},
90
iferr = {
91
-
-- choose a custom error message
92
---@type string|nil
93
message = nil,
94
},
···
96
<
97
Class ~
98
{gopher.Config}
99
100
101
==============================================================================
···
110
------------------------------------------------------------------------------
111
*gopher.nvim-struct-tags*
112
113
-
`struct_tags` is utilizing the `gomodifytags` tool to add or remove tags to struct fields.
114
115
Usage ~
116
117
-
How to add/remove tags to struct fields:
118
1. Place cursor on the struct
119
2. Run `:GoTagAdd json` to add json tags to struct fields
120
3. Run `:GoTagRm json` to remove json tags to struct fields
121
122
-
To clear all tags from struct run: `:GoTagClear`
123
124
NOTE: if you dont specify the tag it will use `json` as default
125
···
147
Integration of `impl` tool to generate method stubs for interfaces.
148
149
Usage ~
150
1. Automatically implement an interface for a struct:
151
-
- Place your cursor on the struct where you want to implement the interface.
152
-
- Run `:GoImpl io.Reader`
153
-
- This will automatically determine the receiver and implement the `io.Reader` interface.
154
155
2. Specify a custom receiver:
156
-
- Place your cursor on the struct
157
-
- Run `:GoImpl w io.Writer`, where:
158
-
- `w` is the receiver.
159
-
- `io.Writer` is the interface to implement.
160
161
3. Explicitly specify the receiver, struct, and interface:
162
-
- No need to place the cursor on the struct if all arguments are provided.
163
-
- Run `:GoImpl r RequestReader io.Reader`, where:
164
-
- `r` is the receiver.
165
-
- `RequestReader` is the struct.
166
-
- `io.Reader` is the interface to implement.
167
168
Example:
169
>go
···
184
Usage ~
185
186
- Generate unit test for specific function/method:
187
-
1. Place your cursor on the desired function/method.
188
-
2. Run `:GoTestAdd`
189
190
- Generate unit tests for *all* functions/methods in current file:
191
-
- run `:GoTestsAll`
192
193
- Generate unit tests *only* for *exported(public)* functions/methods:
194
-
- run `:GoTestsExp`
195
196
-
You can also specify the template to use for generating the tests. See |gopher.nvim-config|
197
-
More details about templates can be found at: https://github.com/cweill/gotests
198
199
If you prefer named tests, you can enable them in |gopher.nvim-config|.
200
···
217
This module provides a way to generate comments for Go code.
218
219
Usage ~
220
-
Set cursor on line with function/method/struct/etc and run `:GoCmt` to generate a comment.
221
222
223
vim:tw=78:ts=8:noet:ft=help:norl:
···
36
------------------------------------------------------------------------------
37
*gopher.nvim-dependencies*
38
`gopher.install_deps`
39
+
40
+
Gopher.nvim implements most of its features using third-party tools. To
41
+
install plugin's dependencies, you can run:
42
+
`:GoInstallDeps` or `:GoInstallDepsSync`
43
+
or use `require("gopher").install_deps()` if you prefer lua api.
44
45
46
==============================================================================
···
57
---@type number
58
timeout = 2000,
59
60
+
-- timeout for running installer commands(e.g :GoDepsInstall, :GoDepsInstallSync)
61
+
---@type number
62
installer_timeout = 999999,
63
64
-- user specified paths to binaries
···
72
},
73
---@class gopher.ConfigGotests
74
gotests = {
75
+
-- a default template that gotess will use.
76
+
-- gotets doesn't have template named `default`, we use it to represent absence of the provided template.
77
template = "default",
78
+
79
-- path to a directory containing custom test code templates
80
---@type string|nil
81
template_dir = nil,
82
+
83
+
-- use named tests(map with test name as key) in table tests(slice of structs by default)
84
named = false,
85
},
86
---@class gopher.ConfigGoTag
···
90
91
-- default tags to add to struct fields
92
default_tag = "json",
93
+
94
+
-- default tag option added struct fields, set to nil to disable
95
+
-- e.g: `option = "json=omitempty,xml=omitempty`
96
+
---@type string|nil
97
+
option = nil,
98
},
99
iferr = {
100
+
-- choose a custom error message, nil to use default
101
+
-- e.g: `message = 'fmt.Errorf("failed to %w", err)'`
102
---@type string|nil
103
message = nil,
104
},
···
106
<
107
Class ~
108
{gopher.Config}
109
+
Fields ~
110
+
{setup} `(fun(user_config?: gopher.Config))`
111
112
113
==============================================================================
···
122
------------------------------------------------------------------------------
123
*gopher.nvim-struct-tags*
124
125
+
`struct_tags` is utilizing the `gomodifytags` tool to add or remove tags to
126
+
struct fields.
127
128
Usage ~
129
130
+
How to add/remove/clear tags to struct fields:
131
1. Place cursor on the struct
132
2. Run `:GoTagAdd json` to add json tags to struct fields
133
3. Run `:GoTagRm json` to remove json tags to struct fields
134
+
4. Run `:GoTagClear` to clear all tags from struct fields
135
136
+
If you want to add/remove tag with options, you can use `json=omitempty`
137
+
(where json is tag, and omitempty is its option).
138
+
Example: `:GoTagAdd xml json=omitempty`
139
+
140
141
NOTE: if you dont specify the tag it will use `json` as default
142
···
164
Integration of `impl` tool to generate method stubs for interfaces.
165
166
Usage ~
167
+
168
1. Automatically implement an interface for a struct:
169
+
- Place your cursor on the struct where you want to implement the interface.
170
+
- Run `:GoImpl io.Reader`
171
+
- This will automatically determine the receiver and implement the `io.Reader` interface.
172
173
2. Specify a custom receiver:
174
+
- Place your cursor on the struct
175
+
- Run `:GoImpl w io.Writer`, where:
176
+
- `w` is the receiver.
177
+
- `io.Writer` is the interface to implement.
178
179
3. Explicitly specify the receiver, struct, and interface:
180
+
- No need to place the cursor on the struct if all arguments are provided.
181
+
- Run `:GoImpl r RequestReader io.Reader`, where:
182
+
- `r` is the receiver.
183
+
- `RequestReader` is the struct.
184
+
- `io.Reader` is the interface to implement.
185
186
Example:
187
>go
···
202
Usage ~
203
204
- Generate unit test for specific function/method:
205
+
1. Place your cursor on the desired function/method.
206
+
2. Run `:GoTestAdd`
207
208
- Generate unit tests for *all* functions/methods in current file:
209
+
- run `:GoTestsAll`
210
211
- Generate unit tests *only* for *exported(public)* functions/methods:
212
+
- run `:GoTestsExp`
213
214
+
You can also specify the template to use for generating the tests.
215
+
See |gopher.nvim-config|.
216
+
More details about templates: https://github.com/cweill/gotests
217
218
If you prefer named tests, you can enable them in |gopher.nvim-config|.
219
···
236
This module provides a way to generate comments for Go code.
237
238
Usage ~
239
+
240
+
Set cursor on line with function/method/struct/etc and
241
+
run `:GoCmt` to generate a comment.
242
243
244
vim:tw=78:ts=8:noet:ft=help:norl:
-51
lua/gopher/_utils/gocmd.lua
-51
lua/gopher/_utils/gocmd.lua
···
1
-
local r = require "gopher._utils.runner"
2
-
local c = require("gopher.config").commands
3
-
local u = require "gopher._utils"
4
-
local gocmd = {}
5
-
6
-
---@param args string[]
7
-
---@return string[]
8
-
local function if_get(args)
9
-
for i, arg in ipairs(args) do
10
-
local m = string.match(arg, "^https://(.*)$") or string.match(arg, "^http://(.*)$") or arg
11
-
table.remove(args, i)
12
-
table.insert(args, i, m)
13
-
end
14
-
return args
15
-
end
16
-
17
-
---@param args unknown[]
18
-
---@return string[]
19
-
local function if_generate(args)
20
-
if #args == 1 and args[1] == "%" then
21
-
args[1] = vim.fn.expand "%"
22
-
end
23
-
return args
24
-
end
25
-
26
-
---@param subcmd string
27
-
---@param args string[]
28
-
---@return string
29
-
function gocmd.run(subcmd, args)
30
-
if #args == 0 and subcmd ~= "generate" then
31
-
error "please provide any arguments"
32
-
end
33
-
34
-
if subcmd == "get" then
35
-
args = if_get(args)
36
-
end
37
-
38
-
if subcmd == "generate" then
39
-
args = if_generate(args)
40
-
end
41
-
42
-
local rs = r.sync { c.go, subcmd, unpack(args) }
43
-
if rs.code ~= 0 then
44
-
error("go " .. subcmd .. " failed: " .. rs.stderr)
45
-
end
46
-
47
-
u.notify(c.go .. " " .. subcmd .. " ran successful")
48
-
return rs.stdout
49
-
end
50
-
51
-
return gocmd
···
+32
-1
lua/gopher/_utils/init.lua
+32
-1
lua/gopher/_utils/init.lua
···
3
local utils = {}
4
5
---@param msg string
6
-
---@param lvl? number by default `vim.log.levels.INFO`
7
function utils.notify(msg, lvl)
8
lvl = lvl or vim.log.levels.INFO
9
vim.notify(msg, lvl, {
···
36
function utils.trimend(s)
37
local r, _ = string.gsub(s, "%s+$", "")
38
return r
39
end
40
41
return utils
···
3
local utils = {}
4
5
---@param msg string
6
+
---@param lvl? integer by default `vim.log.levels.INFO`
7
function utils.notify(msg, lvl)
8
lvl = lvl or vim.log.levels.INFO
9
vim.notify(msg, lvl, {
···
36
function utils.trimend(s)
37
local r, _ = string.gsub(s, "%s+$", "")
38
return r
39
+
end
40
+
41
+
-- Since indentation can be spaces or tabs, that's my hack around it
42
+
---@param line string
43
+
---@param indent integer
44
+
---@return string
45
+
function utils.indent(line, indent)
46
+
local char = string.sub(line, 1, 1)
47
+
if char ~= " " and char ~= "\t" then
48
+
char = " "
49
+
end
50
+
return string.rep(char, indent)
51
+
end
52
+
53
+
---@generic T
54
+
---@param tbl T[]
55
+
---@return T[]
56
+
function utils.list_unique(tbl)
57
+
if vim.fn.has "nvim-0.12" == 1 then
58
+
return vim.list.unique(tbl)
59
+
end
60
+
61
+
for i = #tbl, 1, -1 do
62
+
for j = 1, i - 1 do
63
+
if tbl[i] == tbl[j] then
64
+
table.remove(tbl, i)
65
+
break
66
+
end
67
+
end
68
+
end
69
+
return tbl
70
end
71
72
return utils
+2
-2
lua/gopher/_utils/log.lua
+2
-2
lua/gopher/_utils/log.lua
···
3
-- for the code i have stolen(or have inspected by idk)
4
local c = require "gopher.config"
5
6
-
---@class Gopher.Logger
7
---@field get_outfile fun():string
8
---@field trace fun(...)
9
---@field fmt_trace fun(...)
···
44
float_precision = 0.01,
45
}
46
47
-
---@type Gopher.Logger
48
---@diagnostic disable-next-line: missing-fields
49
local log = {}
50
···
3
-- for the code i have stolen(or have inspected by idk)
4
local c = require "gopher.config"
5
6
+
---@class gopher.Logger
7
---@field get_outfile fun():string
8
---@field trace fun(...)
9
---@field fmt_trace fun(...)
···
44
float_precision = 0.01,
45
}
46
47
+
---@type gopher.Logger
48
---@diagnostic disable-next-line: missing-fields
49
local log = {}
50
+40
-16
lua/gopher/_utils/ts.lua
+40
-16
lua/gopher/_utils/ts.lua
···
11
right: (expression_list (composite_literal
12
type: (struct_type))))]
13
]],
14
func = [[
15
[(function_declaration name: (identifier) @_name)
16
-
(method_declaration name: (field_identifier) @_name)]
17
]],
18
package = [[
19
(package_identifier) @_name
···
23
name: (type_identifier) @_name
24
type: (interface_type))
25
]],
26
}
27
28
---@param parent_type string[]
29
---@param node TSNode
30
---@return TSNode?
31
-
local function get_parrent_node(parent_type, node)
32
---@type TSNode?
33
local current = node
34
while current do
···
64
end
65
66
---@class gopher.TsResult
67
-
---@field name string
68
-
---@field start integer
69
-
---@field end_ integer
70
-
---@field is_varstruct boolean
71
72
---@param bufnr integer
73
---@param parent_type string[]
···
78
error "No treesitter parser found for go"
79
end
80
81
-
local node = vim.treesitter.get_node {
82
-
bufnr = bufnr,
83
-
}
84
if not node then
85
-
error "No nodes found under cursor"
86
end
87
88
-
local parent_node = get_parrent_node(parent_type, node)
89
if not parent_node then
90
-
error "No parent node found under cursor"
91
end
92
93
local q = vim.treesitter.query.parse("go", query)
94
local res = get_captures(q, parent_node, bufnr)
95
assert(res.name ~= nil, "No capture name found")
96
97
-
local start_row, _, end_row, _ = parent_node:range()
98
res["start"] = start_row + 1
99
res["end_"] = end_row + 1
100
···
104
---@param bufnr integer
105
function ts.get_struct_under_cursor(bufnr)
106
--- should be both type_spec and type_declaration
107
-
--- because in cases like `type ( T struct{}, U strict{} )`
108
-
--- i will be choosing always last struct in the list
109
---
110
--- var_declaration is for cases like `var x struct{}`
111
--- short_var_declaration is for cases like `x := struct{}{}`
112
return do_stuff(bufnr, {
113
"type_spec",
114
"type_declaration",
···
118
end
119
120
---@param bufnr integer
121
function ts.get_func_under_cursor(bufnr)
122
--- since this handles both and funcs and methods we should check for both parent nodes
123
-
return do_stuff(bufnr, { "function_declaration", "method_declaration" }, queries.func)
124
end
125
126
---@param bufnr integer
···
131
---@param bufnr integer
132
function ts.get_interface_under_cursor(bufnr)
133
return do_stuff(bufnr, { "type_declaration" }, queries.interface)
134
end
135
136
return ts
···
11
right: (expression_list (composite_literal
12
type: (struct_type))))]
13
]],
14
+
struct_field = [[
15
+
(field_declaration name: (field_identifier) @_name)
16
+
]],
17
func = [[
18
[(function_declaration name: (identifier) @_name)
19
+
(method_declaration name: (field_identifier) @_name)
20
+
(method_elem name: (field_identifier) @_name)]
21
]],
22
package = [[
23
(package_identifier) @_name
···
27
name: (type_identifier) @_name
28
type: (interface_type))
29
]],
30
+
var = [[
31
+
[(var_declaration (var_spec name: (identifier) @_name))
32
+
(short_var_declaration
33
+
left: (expression_list (identifier) @_name @_var))]
34
+
]],
35
}
36
37
---@param parent_type string[]
38
---@param node TSNode
39
---@return TSNode?
40
+
local function get_parent_node(parent_type, node)
41
---@type TSNode?
42
local current = node
43
while current do
···
73
end
74
75
---@class gopher.TsResult
76
+
---@field name string Name of the struct, function, etc
77
+
---@field start integer Line number where the declaration starts
78
+
---@field end_ integer Line number where the declaration ends
79
+
---@field indent integer Number of spaces/tabs in the current cursor line
80
+
---@field is_varstruct boolean Is struct declared as `var S struct{}` or `s := struct{}{}`
81
82
---@param bufnr integer
83
---@param parent_type string[]
···
88
error "No treesitter parser found for go"
89
end
90
91
+
local node = vim.treesitter.get_node { bufnr = bufnr }
92
if not node then
93
+
error "No nodes found under the cursor"
94
end
95
96
+
local parent_node = get_parent_node(parent_type, node)
97
if not parent_node then
98
+
error "No parent node found under the cursor"
99
end
100
101
local q = vim.treesitter.query.parse("go", query)
102
local res = get_captures(q, parent_node, bufnr)
103
assert(res.name ~= nil, "No capture name found")
104
105
+
local start_row, start_col, end_row, _ = parent_node:range()
106
+
res["indent"] = start_col
107
res["start"] = start_row + 1
108
res["end_"] = end_row + 1
109
···
113
---@param bufnr integer
114
function ts.get_struct_under_cursor(bufnr)
115
--- should be both type_spec and type_declaration
116
+
--- because in cases like `type ( T struct{}, U struct{} )`
117
---
118
--- var_declaration is for cases like `var x struct{}`
119
--- short_var_declaration is for cases like `x := struct{}{}`
120
+
---
121
+
--- it always chooses last struct type in the list
122
return do_stuff(bufnr, {
123
"type_spec",
124
"type_declaration",
···
128
end
129
130
---@param bufnr integer
131
+
function ts.get_struct_field_under_cursor(bufnr)
132
+
return do_stuff(bufnr, { "field_declaration" }, queries.struct_field)
133
+
end
134
+
135
+
---@param bufnr integer
136
function ts.get_func_under_cursor(bufnr)
137
--- since this handles both and funcs and methods we should check for both parent nodes
138
+
return do_stuff(bufnr, {
139
+
"method_elem",
140
+
"function_declaration",
141
+
"method_declaration",
142
+
}, queries.func)
143
end
144
145
---@param bufnr integer
···
150
---@param bufnr integer
151
function ts.get_interface_under_cursor(bufnr)
152
return do_stuff(bufnr, { "type_declaration" }, queries.interface)
153
+
end
154
+
155
+
---@param bufnr integer
156
+
function ts.get_variable_under_cursor(bufnr)
157
+
return do_stuff(bufnr, { "var_declaration", "short_var_declaration" }, queries.var)
158
end
159
160
return ts
+31
-17
lua/gopher/comment.lua
+31
-17
lua/gopher/comment.lua
···
3
---@text
4
--- This module provides a way to generate comments for Go code.
5
---
6
-
---@usage Set cursor on line with function/method/struct/etc and run `:GoCmt` to generate a comment.
7
8
local ts = require "gopher._utils.ts"
9
local log = require "gopher._utils.log"
10
local comment = {}
11
12
-
---@param name string
13
-
---@return string
14
-
---@dochide
15
-
local function template(name)
16
-
return "// " .. name .. " "
17
-
end
18
-
19
---@param bufnr integer
20
---@return string
21
---@dochide
22
-
local function generate(bufnr)
23
local s_ok, s_res = pcall(ts.get_struct_under_cursor, bufnr)
24
if s_ok then
25
-
return template(s_res.name)
26
end
27
28
local f_ok, f_res = pcall(ts.get_func_under_cursor, bufnr)
29
if f_ok then
30
-
return template(f_res.name)
31
end
32
33
local i_ok, i_res = pcall(ts.get_interface_under_cursor, bufnr)
34
if i_ok then
35
-
return template(i_res.name)
36
end
37
38
local p_ok, p_res = pcall(ts.get_package_under_cursor, bufnr)
···
45
46
function comment.comment()
47
local bufnr = vim.api.nvim_get_current_buf()
48
-
local cmt = generate(bufnr)
49
-
log.debug("generated comment: " .. cmt)
50
51
-
local pos = vim.fn.getcurpos()[2]
52
-
vim.fn.append(pos - 1, cmt)
53
-
vim.fn.setpos(".", { 0, pos, #cmt })
54
vim.cmd "startinsert!"
55
end
56
···
3
---@text
4
--- This module provides a way to generate comments for Go code.
5
---
6
+
---@usage
7
+
--- Set cursor on line with function/method/struct/etc and
8
+
--- run `:GoCmt` to generate a comment.
9
10
local ts = require "gopher._utils.ts"
11
local log = require "gopher._utils.log"
12
+
local u = require "gopher._utils"
13
local comment = {}
14
15
+
--- NOTE: The order of functions executed inside this function is IMPORTANT.
16
+
--- This function is extremely fragile; run tests after making any changes.
17
+
---
18
---@param bufnr integer
19
+
---@param line string
20
---@return string
21
---@dochide
22
+
local function generate(bufnr, line)
23
+
local sf_ok, sf_res = pcall(ts.get_struct_field_under_cursor, bufnr)
24
+
if sf_ok then
25
+
return u.indent(line, sf_res.indent) .. "// " .. sf_res.name .. " "
26
+
end
27
+
28
local s_ok, s_res = pcall(ts.get_struct_under_cursor, bufnr)
29
if s_ok then
30
+
return u.indent(line, s_res.indent) .. "// " .. s_res.name .. " "
31
+
end
32
+
33
+
local v_ok, v_res = pcall(ts.get_variable_under_cursor, bufnr)
34
+
if v_ok then
35
+
return u.indent(line, v_res.indent) .. "// " .. v_res.name .. " "
36
end
37
38
local f_ok, f_res = pcall(ts.get_func_under_cursor, bufnr)
39
if f_ok then
40
+
return u.indent(line, f_res.indent) .. "// " .. f_res.name .. " "
41
end
42
43
local i_ok, i_res = pcall(ts.get_interface_under_cursor, bufnr)
44
if i_ok then
45
+
return u.indent(line, i_res.indent) .. "// " .. i_res.name .. " "
46
end
47
48
local p_ok, p_res = pcall(ts.get_package_under_cursor, bufnr)
···
55
56
function comment.comment()
57
local bufnr = vim.api.nvim_get_current_buf()
58
+
local lnum = vim.fn.getcurpos()[2]
59
+
local line = vim.fn.getline(lnum)
60
+
local cmt = generate(bufnr, line)
61
+
log.debug("generated comment:", {
62
+
comment = cmt,
63
+
line = line,
64
+
})
65
66
+
vim.fn.append(lnum - 1, cmt)
67
+
vim.fn.setpos(".", { bufnr, lnum, #cmt })
68
vim.cmd "startinsert!"
69
end
70
+22
-8
lua/gopher/config.lua
+22
-8
lua/gopher/config.lua
···
1
local config = {}
2
3
---@tag gopher.nvim-config.ConfigGoTagTransform
···
16
---@tag gopher.nvim-config
17
---@eval return MiniDoc.afterlines_to_code(MiniDoc.current.eval_section)
18
---@class gopher.Config
19
local default_config = {
20
-- log level, you might consider using DEBUG or TRACE for debugging the plugin
21
---@type number
···
25
---@type number
26
timeout = 2000,
27
28
-
--- timeout for running installer commands(e.g :GoDepsInstall, :GoDepsInstallSync)
29
installer_timeout = 999999,
30
31
-- user specified paths to binaries
···
39
},
40
---@class gopher.ConfigGotests
41
gotests = {
42
-
-- gotests doesn't have template named "default" so this plugin uses "default" to set the default template
43
template = "default",
44
-- path to a directory containing custom test code templates
45
---@type string|nil
46
template_dir = nil,
47
-
-- switch table tests from using slice to map (with test name for the key)
48
named = false,
49
},
50
---@class gopher.ConfigGoTag
···
54
55
-- default tags to add to struct fields
56
default_tag = "json",
57
},
58
iferr = {
59
-
-- choose a custom error message
60
---@type string|nil
61
message = nil,
62
},
···
92
vim.validate("commands.iferr", _config.commands.iferr, "string")
93
vim.validate("gotests", _config.gotests, "table")
94
vim.validate("gotests.template", _config.gotests.template, "string")
95
-
vim.validate("gotests.template_dir", _config.gotests.template_dir, "string", true)
96
vim.validate("gotests.named", _config.gotests.named, "boolean")
97
vim.validate("gotag", _config.gotag, "table")
98
vim.validate("gotag.transform", _config.gotag.transform, "string")
99
vim.validate("gotag.default_tag", _config.gotag.default_tag, "string")
100
vim.validate("iferr", _config.iferr, "table")
101
-
vim.validate("iferr.message", _config.iferr.message, "string", true)
102
end
103
104
setmetatable(config, {
···
108
})
109
110
---@dochide
111
-
---@return gopher.Config
112
-
return config --[[ @as gopher.Config ]]
···
1
+
---@type gopher.Config
2
+
---@dochide
3
+
---@diagnostic disable-next-line: missing-fields .setup() gets injected later
4
local config = {}
5
6
---@tag gopher.nvim-config.ConfigGoTagTransform
···
19
---@tag gopher.nvim-config
20
---@eval return MiniDoc.afterlines_to_code(MiniDoc.current.eval_section)
21
---@class gopher.Config
22
+
---@field setup fun(user_config?: gopher.Config)
23
local default_config = {
24
-- log level, you might consider using DEBUG or TRACE for debugging the plugin
25
---@type number
···
29
---@type number
30
timeout = 2000,
31
32
+
-- timeout for running installer commands(e.g :GoDepsInstall, :GoDepsInstallSync)
33
+
---@type number
34
installer_timeout = 999999,
35
36
-- user specified paths to binaries
···
44
},
45
---@class gopher.ConfigGotests
46
gotests = {
47
+
-- a default template that gotess will use.
48
+
-- gotets doesn't have template named `default`, we use it to represent absence of the provided template.
49
template = "default",
50
+
51
-- path to a directory containing custom test code templates
52
---@type string|nil
53
template_dir = nil,
54
+
55
+
-- use named tests(map with test name as key) in table tests(slice of structs by default)
56
named = false,
57
},
58
---@class gopher.ConfigGoTag
···
62
63
-- default tags to add to struct fields
64
default_tag = "json",
65
+
66
+
-- default tag option added struct fields, set to nil to disable
67
+
-- e.g: `option = "json=omitempty,xml=omitempty`
68
+
---@type string|nil
69
+
option = nil,
70
},
71
iferr = {
72
+
-- choose a custom error message, nil to use default
73
+
-- e.g: `message = 'fmt.Errorf("failed to %w", err)'`
74
---@type string|nil
75
message = nil,
76
},
···
106
vim.validate("commands.iferr", _config.commands.iferr, "string")
107
vim.validate("gotests", _config.gotests, "table")
108
vim.validate("gotests.template", _config.gotests.template, "string")
109
+
vim.validate("gotests.template_dir", _config.gotests.template_dir, { "string", "nil" })
110
vim.validate("gotests.named", _config.gotests.named, "boolean")
111
vim.validate("gotag", _config.gotag, "table")
112
vim.validate("gotag.transform", _config.gotag.transform, "string")
113
vim.validate("gotag.default_tag", _config.gotag.default_tag, "string")
114
+
vim.validate("gotag.option", _config.gotag.option, { "string", "nil" })
115
vim.validate("iferr", _config.iferr, "table")
116
+
vim.validate("iferr.message", _config.iferr.message, { "string", "nil" })
117
end
118
119
setmetatable(config, {
···
123
})
124
125
---@dochide
126
+
return config
+56
lua/gopher/go.lua
+56
lua/gopher/go.lua
···
···
1
+
local c = require "gopher.config"
2
+
local u = require "gopher._utils"
3
+
local r = require "gopher._utils.runner"
4
+
local go = {}
5
+
6
+
local function run(subcmd, args)
7
+
local rs = r.sync { c.commands.go, subcmd, unpack(args) }
8
+
if rs.code ~= 0 then
9
+
error("go " .. subcmd .. " failed: " .. rs.stderr)
10
+
end
11
+
12
+
u.notify(c.commands.go .. " " .. subcmd .. " ran successful")
13
+
return rs.stdout
14
+
end
15
+
16
+
---@param args string[]
17
+
function go.get(args)
18
+
for i, arg in ipairs(args) do
19
+
local m = string.match(arg, "^https://(.*)$") or string.match(arg, "^http://(.*)$") or arg
20
+
table.remove(args, i)
21
+
table.insert(args, i, m)
22
+
end
23
+
24
+
run("get", args)
25
+
end
26
+
27
+
---@param args string[]
28
+
function go.mod(args)
29
+
run("mod", args)
30
+
end
31
+
32
+
---@param args string[]
33
+
function go.work(args)
34
+
-- TODO: use `gopls.tidy`
35
+
36
+
run("work", args)
37
+
end
38
+
39
+
---Executes `go generate`
40
+
---If only argument is `%` it's going to be equivalent to `go generate <path to current file>`
41
+
---@param args string[]
42
+
function go.generate(args)
43
+
-- TODO: use `gopls.generate`
44
+
45
+
if #args == 0 then
46
+
error "please provide arguments"
47
+
end
48
+
49
+
if #args == 1 and args[1] == "%" then
50
+
args[1] = vim.fn.expand "%"
51
+
end
52
+
53
+
run("generate", args)
54
+
end
55
+
56
+
return go
+7
-6
lua/gopher/gotests.lua
+7
-6
lua/gopher/gotests.lua
···
3
---@text gotests is utilizing the `gotests` tool to generate unit tests boilerplate.
4
---@usage
5
--- - Generate unit test for specific function/method:
6
-
--- 1. Place your cursor on the desired function/method.
7
-
--- 2. Run `:GoTestAdd`
8
---
9
--- - Generate unit tests for *all* functions/methods in current file:
10
-
--- - run `:GoTestsAll`
11
---
12
--- - Generate unit tests *only* for *exported(public)* functions/methods:
13
-
--- - run `:GoTestsExp`
14
---
15
-
--- You can also specify the template to use for generating the tests. See |gopher.nvim-config|
16
-
--- More details about templates can be found at: https://github.com/cweill/gotests
17
---
18
--- If you prefer named tests, you can enable them in |gopher.nvim-config|.
19
···
3
---@text gotests is utilizing the `gotests` tool to generate unit tests boilerplate.
4
---@usage
5
--- - Generate unit test for specific function/method:
6
+
--- 1. Place your cursor on the desired function/method.
7
+
--- 2. Run `:GoTestAdd`
8
---
9
--- - Generate unit tests for *all* functions/methods in current file:
10
+
--- - run `:GoTestsAll`
11
---
12
--- - Generate unit tests *only* for *exported(public)* functions/methods:
13
+
--- - run `:GoTestsExp`
14
---
15
+
--- You can also specify the template to use for generating the tests.
16
+
--- See |gopher.nvim-config|.
17
+
--- More details about templates: https://github.com/cweill/gotests
18
---
19
--- If you prefer named tests, you can enable them in |gopher.nvim-config|.
20
+33
-37
lua/gopher/health.lua
+33
-37
lua/gopher/health.lua
···
1
local health = {}
2
-
local cmd = require("gopher.config").commands
3
4
local deps = {
5
bin = {
6
{
7
-
bin = cmd.go,
8
msg = "required for `:GoGet`, `:GoMod`, `:GoGenerate`, `:GoWork`, `:GoInstallDeps`, `:GoInstallDepsSync`",
9
-
optional = false,
10
},
11
-
{ bin = cmd.gomodifytags, msg = "required for `:GoTagAdd`, `:GoTagRm`", optional = true },
12
-
{ bin = cmd.impl, msg = "required for `:GoImpl`", optional = true },
13
-
{ bin = cmd.iferr, msg = "required for `:GoIfErr`", optional = true },
14
-
{
15
-
bin = cmd.gotests,
16
-
msg = "required for `:GoTestAdd`, `:GoTestsAll`, `:GoTestsExp`",
17
-
optional = true,
18
-
},
19
},
20
treesitter = {
21
{ parser = "go", msg = "required for most of the parts of `gopher.nvim`" },
22
},
23
}
24
25
-
---@param bin string
26
-
---@return boolean
27
-
local function is_binary_found(bin)
28
-
return vim.fn.executable(bin) == 1
29
end
30
31
-
---@param ft string
32
-
---@return boolean
33
-
local function is_treesitter_parser_available(ft)
34
-
local ok, parser = pcall(vim.treesitter.get_parser, 0, ft)
35
-
return ok and parser ~= nil
36
end
37
38
function health.check()
39
-
vim.health.start "required binaries"
40
-
vim.health.info "all those binaries can be installed by `:GoInstallDeps`"
41
for _, bin in ipairs(deps.bin) do
42
-
if is_binary_found(bin.bin) then
43
-
vim.health.ok(bin.bin .. " installed")
44
-
else
45
-
if bin.optional then
46
-
vim.health.warn(bin.bin .. " not found, " .. bin.msg)
47
-
else
48
-
vim.health.error(bin.bin .. " not found, " .. bin.msg)
49
-
end
50
-
end
51
end
52
53
-
vim.health.start "required treesitter parsers"
54
for _, parser in ipairs(deps.treesitter) do
55
-
if is_treesitter_parser_available(parser.parser) then
56
-
vim.health.ok(parser.parser .. " parser installed")
57
-
else
58
-
vim.health.error(parser.parser .. " parser not found, " .. parser.msg)
59
-
end
60
end
61
end
62
···
1
+
local c = require("gopher.config").commands
2
local health = {}
3
4
local deps = {
5
+
vim_version = "nvim-0.10",
6
bin = {
7
{
8
+
bin = c.go,
9
msg = "required for `:GoGet`, `:GoMod`, `:GoGenerate`, `:GoWork`, `:GoInstallDeps`, `:GoInstallDepsSync`",
10
},
11
+
{ bin = c.gomodifytags, msg = "required for `:GoTagAdd`, `:GoTagRm`" },
12
+
{ bin = c.impl, msg = "required for `:GoImpl`" },
13
+
{ bin = c.iferr, msg = "required for `:GoIfErr`" },
14
+
{ bin = c.gotests, msg = "required for `:GoTestAdd`, `:GoTestsAll`, `:GoTestsExp`" },
15
},
16
treesitter = {
17
{ parser = "go", msg = "required for most of the parts of `gopher.nvim`" },
18
},
19
}
20
21
+
---@param bin {bin:string, msg:string, optional:boolean}
22
+
local function check_binary(bin)
23
+
if vim.fn.executable(bin.bin) == 1 then
24
+
vim.health.ok(bin.bin .. " is found oh PATH: `" .. vim.fn.exepath(bin.bin) .. "`")
25
+
else
26
+
vim.health.error(bin.bin .. " not found on PATH, " .. bin.msg)
27
+
end
28
end
29
30
+
---@param ts {parser:string, msg:string}
31
+
local function check_treesitter(ts)
32
+
local ok, parser = pcall(vim.treesitter.get_parser, 0, ts.parser)
33
+
if ok and parser ~= nil then
34
+
vim.health.ok("`" .. ts.parser .. "` parser is installed")
35
+
else
36
+
vim.health.error("`" .. ts.parser .. "` parser not found")
37
+
end
38
end
39
40
function health.check()
41
+
vim.health.start "Neovim version"
42
+
if vim.fn.has(deps.vim_version) == 1 then
43
+
vim.health.ok "Neovim version is compatible"
44
+
else
45
+
vim.health.error(deps.vim_version .. " or newer is required")
46
+
end
47
+
48
+
vim.health.start "Required binaries (those can be installed with `:GoInstallDeps`)"
49
for _, bin in ipairs(deps.bin) do
50
+
check_binary(bin)
51
end
52
53
+
vim.health.start "Treesitter"
54
for _, parser in ipairs(deps.treesitter) do
55
+
check_treesitter(parser)
56
end
57
end
58
+1
-1
lua/gopher/iferr.lua
+1
-1
lua/gopher/iferr.lua
+14
-13
lua/gopher/impl.lua
+14
-13
lua/gopher/impl.lua
···
3
---@text
4
--- Integration of `impl` tool to generate method stubs for interfaces.
5
---
6
-
---@usage 1. Automatically implement an interface for a struct:
7
-
--- - Place your cursor on the struct where you want to implement the interface.
8
-
--- - Run `:GoImpl io.Reader`
9
-
--- - This will automatically determine the receiver and implement the `io.Reader` interface.
10
---
11
--- 2. Specify a custom receiver:
12
-
--- - Place your cursor on the struct
13
-
--- - Run `:GoImpl w io.Writer`, where:
14
-
--- - `w` is the receiver.
15
-
--- - `io.Writer` is the interface to implement.
16
---
17
--- 3. Explicitly specify the receiver, struct, and interface:
18
-
--- - No need to place the cursor on the struct if all arguments are provided.
19
-
--- - Run `:GoImpl r RequestReader io.Reader`, where:
20
-
--- - `r` is the receiver.
21
-
--- - `RequestReader` is the struct.
22
-
--- - `io.Reader` is the interface to implement.
23
---
24
--- Example:
25
--- >go
···
3
---@text
4
--- Integration of `impl` tool to generate method stubs for interfaces.
5
---
6
+
---@usage
7
+
--- 1. Automatically implement an interface for a struct:
8
+
--- - Place your cursor on the struct where you want to implement the interface.
9
+
--- - Run `:GoImpl io.Reader`
10
+
--- - This will automatically determine the receiver and implement the `io.Reader` interface.
11
---
12
--- 2. Specify a custom receiver:
13
+
--- - Place your cursor on the struct
14
+
--- - Run `:GoImpl w io.Writer`, where:
15
+
--- - `w` is the receiver.
16
+
--- - `io.Writer` is the interface to implement.
17
---
18
--- 3. Explicitly specify the receiver, struct, and interface:
19
+
--- - No need to place the cursor on the struct if all arguments are provided.
20
+
--- - Run `:GoImpl r RequestReader io.Reader`, where:
21
+
--- - `r` is the receiver.
22
+
--- - `RequestReader` is the struct.
23
+
--- - `io.Reader` is the interface to implement.
24
---
25
--- Example:
26
--- >go
+10
-21
lua/gopher/init.lua
+10
-21
lua/gopher/init.lua
···
13
local log = require "gopher._utils.log"
14
local tags = require "gopher.struct_tags"
15
local tests = require "gopher.gotests"
16
-
local gocmd = require("gopher._utils.gocmd").run
17
local gopher = {}
18
19
---@toc_entry Setup
···
35
36
---@toc_entry Install dependencies
37
---@tag gopher.nvim-dependencies
38
-
---@text Gopher.nvim implements most of its features using third-party tools.
39
-
--- To install these tools, you can run `:GoInstallDeps` command
40
-
--- or call `require("gopher").install_deps()` if you want to use lua api.
41
-
--- By default dependencies will be installed asynchronously,
42
-
--- to install them synchronously pass `{sync = true}` as an argument.
43
gopher.install_deps = require("gopher.installer").install_deps
44
45
gopher.impl = require("gopher.impl").impl
···
58
all = tests.all_tests,
59
}
60
61
-
gopher.get = function(...)
62
-
gocmd("get", ...)
63
-
end
64
-
65
-
gopher.mod = function(...)
66
-
gocmd("mod", ...)
67
-
end
68
-
69
-
gopher.generate = function(...)
70
-
gocmd("generate", ...)
71
-
end
72
-
73
-
gopher.work = function(...)
74
-
gocmd("work", ...)
75
-
end
76
77
return gopher
···
13
local log = require "gopher._utils.log"
14
local tags = require "gopher.struct_tags"
15
local tests = require "gopher.gotests"
16
+
local go = require "gopher.go"
17
local gopher = {}
18
19
---@toc_entry Setup
···
35
36
---@toc_entry Install dependencies
37
---@tag gopher.nvim-dependencies
38
+
---@text
39
+
--- Gopher.nvim implements most of its features using third-party tools. To
40
+
--- install plugin's dependencies, you can run:
41
+
--- `:GoInstallDeps` or `:GoInstallDepsSync`
42
+
--- or use `require("gopher").install_deps()` if you prefer lua api.
43
gopher.install_deps = require("gopher.installer").install_deps
44
45
gopher.impl = require("gopher.impl").impl
···
58
all = tests.all_tests,
59
}
60
61
+
gopher.get = go.get
62
+
gopher.mod = go.mod
63
+
gopher.work = go.work
64
+
gopher.generate = go.generate
65
66
return gopher
+3
-3
plugin/gopher.lua
+3
-3
plugin/gopher.lua
···
48
-- :GoTag
49
cmd("GoTagAdd", function(opts)
50
require("gopher").tags.add {
51
-
tags = opts.fargs,
52
range = (opts.count ~= -1) and {
53
start = opts.line1,
54
end_ = opts.line2,
···
58
59
cmd("GoTagRm", function(opts)
60
require("gopher").tags.rm {
61
-
tags = opts.fargs,
62
range = (opts.count ~= -1) and {
63
start = opts.line1,
64
end_ = opts.line2,
···
98
end, "*")
99
100
cmd("GoGenerate", function(opts)
101
-
require("gopher").generate(opts.fargs or "")
102
end, "?")
···
48
-- :GoTag
49
cmd("GoTagAdd", function(opts)
50
require("gopher").tags.add {
51
+
input = opts.fargs,
52
range = (opts.count ~= -1) and {
53
start = opts.line1,
54
end_ = opts.line2,
···
58
59
cmd("GoTagRm", function(opts)
60
require("gopher").tags.rm {
61
+
input = opts.fargs,
62
range = (opts.count ~= -1) and {
63
start = opts.line1,
64
end_ = opts.line2,
···
98
end, "*")
99
100
cmd("GoGenerate", function(opts)
101
+
require("gopher").generate(opts.fargs or { "" })
102
end, "?")
-1
scripts/minimal_init.lua
-1
scripts/minimal_init.lua
+6
spec/fixtures/comment/interface_many_method_input.go
+6
spec/fixtures/comment/interface_many_method_input.go
+7
spec/fixtures/comment/interface_many_method_output.go
+7
spec/fixtures/comment/interface_many_method_output.go
+5
spec/fixtures/comment/interface_method_input.go
+5
spec/fixtures/comment/interface_method_input.go
+6
spec/fixtures/comment/interface_method_output.go
+6
spec/fixtures/comment/interface_method_output.go
+18
spec/fixtures/comment/many_structs_fields_input.go
+18
spec/fixtures/comment/many_structs_fields_input.go
+19
spec/fixtures/comment/many_structs_fields_output.go
+19
spec/fixtures/comment/many_structs_fields_output.go
+7
spec/fixtures/comment/struct_fields_input.go
+7
spec/fixtures/comment/struct_fields_input.go
+8
spec/fixtures/comment/struct_fields_output.go
+8
spec/fixtures/comment/struct_fields_output.go
+5
spec/fixtures/comment/svar_input.go
+5
spec/fixtures/comment/svar_input.go
+6
spec/fixtures/comment/svar_output.go
+6
spec/fixtures/comment/svar_output.go
+5
spec/fixtures/comment/var_input.go
+5
spec/fixtures/comment/var_input.go
+6
spec/fixtures/comment/var_output.go
+6
spec/fixtures/comment/var_output.go
+8
spec/fixtures/comment/var_struct_fields_input.go
+8
spec/fixtures/comment/var_struct_fields_input.go
+9
spec/fixtures/comment/var_struct_fields_output.go
+9
spec/fixtures/comment/var_struct_fields_output.go
+28
spec/integration/comment_test.lua
+28
spec/integration/comment_test.lua
···
18
do_the_test("struct", { 4, 1 })
19
end
20
21
comment["should add comment to function"] = function()
22
do_the_test("func", { 3, 1 })
23
end
···
28
29
comment["should add comment to interface"] = function()
30
do_the_test("interface", { 3, 6 })
31
end
32
33
comment["otherwise should add // above cursor"] = function()
···
18
do_the_test("struct", { 4, 1 })
19
end
20
21
+
comment["should add a comment on struct field"] = function()
22
+
do_the_test("struct_fields", { 5, 8 })
23
+
end
24
+
25
+
comment["should add a comment on var struct field"] = function()
26
+
do_the_test("var_struct_fields", { 6, 4 })
27
+
end
28
+
29
+
comment["should add a comment on one field of many structs"] = function()
30
+
do_the_test("many_structs_fields", { 10, 4 })
31
+
end
32
+
33
comment["should add comment to function"] = function()
34
do_the_test("func", { 3, 1 })
35
end
···
40
41
comment["should add comment to interface"] = function()
42
do_the_test("interface", { 3, 6 })
43
+
end
44
+
45
+
comment["should add comment on interface method"] = function()
46
+
do_the_test("interface_method", { 4, 2 })
47
+
end
48
+
49
+
comment["should add a comment on interface with many method"] = function()
50
+
do_the_test("interface_many_method", { 5, 2 })
51
+
end
52
+
53
+
comment["should add a comment on a var"] = function()
54
+
do_the_test("var", { 4, 2 })
55
+
end
56
+
57
+
comment["should add a comment on a short declared var"] = function()
58
+
do_the_test("svar", { 4, 8 })
59
end
60
61
comment["otherwise should add // above cursor"] = function()
+2
-1
spec/integration/iferr_test.lua
+2
-1
spec/integration/iferr_test.lua
+3
spec/unit/config_test.lua
+3
spec/unit/config_test.lua
···
7
end
8
9
config["can be called with empty table"] = function()
10
+
---@diagnostic disable-next-line: missing-fields
11
require("gopher").setup {}
12
end
13
14
config["should change option"] = function()
15
local log_level = 1234567890
16
+
17
+
---@diagnostic disable-next-line: missing-fields
18
require("gopher").setup {
19
log_level = log_level,
20
}
+68
spec/unit/struct_tag_test.lua
+68
spec/unit/struct_tag_test.lua
···
···
1
+
local t = require "spec.testutils"
2
+
local _, T, st = t.setup "struct_tags"
3
+
4
+
st["should parse tags"] = function()
5
+
local out = require("gopher.struct_tags").parse_args { "json", "yaml", "etc" }
6
+
7
+
t.eq(out.tags, "json,yaml,etc")
8
+
t.eq(out.options, "")
9
+
end
10
+
11
+
st["should parse tags separated by commas"] = function()
12
+
local out = require("gopher.struct_tags").parse_args { "json,yaml,etc" }
13
+
14
+
t.eq(out.tags, "json,yaml,etc")
15
+
t.eq(out.options, "")
16
+
end
17
+
18
+
st["should parse tags separated by command and spaces"] = function()
19
+
local out = require("gopher.struct_tags").parse_args {
20
+
"json,yaml",
21
+
"json=omitempty",
22
+
"xml=something",
23
+
}
24
+
25
+
t.eq(out.tags, "json,yaml,xml")
26
+
t.eq(out.options, "json=omitempty,xml=something")
27
+
end
28
+
29
+
st["should parse tag with an option"] = function()
30
+
local out = require("gopher.struct_tags").parse_args {
31
+
"json=omitempty",
32
+
"xml",
33
+
"xml=theoption",
34
+
}
35
+
36
+
t.eq(out.tags, "json,xml")
37
+
t.eq(out.options, "json=omitempty,xml=theoption")
38
+
end
39
+
40
+
st["should parse tags with an option"] = function()
41
+
local out = require("gopher.struct_tags").parse_args { "json=omitempty", "yaml" }
42
+
43
+
t.eq(out.tags, "json,yaml")
44
+
t.eq(out.options, "json=omitempty")
45
+
end
46
+
47
+
st["should parse tags with an option separated with comma"] = function()
48
+
local out = require("gopher.struct_tags").parse_args { "json=omitempty,yaml" }
49
+
50
+
t.eq(out.tags, "json,yaml")
51
+
t.eq(out.options, "json=omitempty")
52
+
end
53
+
54
+
st["should parse tags with options specified separately"] = function()
55
+
local out = require("gopher.struct_tags").parse_args { "json", "yaml", "json=omitempty" }
56
+
57
+
t.eq(out.tags, "json,yaml")
58
+
t.eq(out.options, "json=omitempty")
59
+
end
60
+
61
+
st["should parse tags with options specified separately and separated by comma"] = function()
62
+
local out = require("gopher.struct_tags").parse_args { "json,yaml,json=omitempty" }
63
+
64
+
t.eq(out.tags, "json,yaml")
65
+
t.eq(out.options, "json=omitempty")
66
+
end
67
+
68
+
return T
+34
spec/unit/utils_test.lua
+34
spec/unit/utils_test.lua
···
22
t.eq(u.trimend " hi ", " hi")
23
end
24
25
+
utils["should add .indent() spaces"] = function()
26
+
local u = require "gopher._utils"
27
+
local line = " func Test() error {"
28
+
local indent = 4
29
+
30
+
t.eq(" ", u.indent(line, indent))
31
+
end
32
+
33
+
utils["should add .indent() a tab"] = function()
34
+
local u = require "gopher._utils"
35
+
local line = "\tfunc Test() error {"
36
+
local indent = 1
37
+
38
+
t.eq("\t", u.indent(line, indent))
39
+
end
40
+
41
+
utils["should add .indent() 2 tabs"] = function()
42
+
local u = require "gopher._utils"
43
+
local line = "\t\tfunc Test() error {"
44
+
local indent = 2
45
+
46
+
t.eq("\t\t", u.indent(line, indent))
47
+
end
48
+
49
+
utils["should .list_unique on list with duplicates"] = function()
50
+
local u = require "gopher._utils"
51
+
t.eq({ "json", "xml" }, u.list_unique { "json", "xml", "json" })
52
+
end
53
+
54
+
utils["should .list_unique on list with no duplicates"] = function()
55
+
local u = require "gopher._utils"
56
+
t.eq({ "json", "xml" }, u.list_unique { "json", "xml" })
57
+
end
58
+
59
return T
vhs/iferr.gif
vhs/iferr.gif
This is a binary file and will not be displayed.