[mirror] Make your go dev experience better github.com/olexsmir/gopher.nvim
neovim golang
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #121 from olexsmir/develop

sync develop with main

authored by

Oleksandr Smirnov and committed by
GitHub
7e8c6f41 de585144

+472 -188
+8 -7
.github/workflows/tests.yml
··· 15 15 version: 16 16 - stable 17 17 - nightly 18 + - v0.10.0 19 + - v0.10.4 20 + - v0.11.0 21 + - v0.11.1 22 + - v0.11.2 23 + - v0.11.3 18 24 runs-on: ${{ matrix.os }} 19 25 steps: 20 26 - name: Install Task ··· 47 53 key: ${{ runner.os }}-tests-${{ hashFiles('${{ github.workspace }}/.tests') }} 48 54 49 55 - name: Install Go bins 50 - run: | 51 - # TODO: install with :GoInstallDeps 52 - go install github.com/fatih/gomodifytags@latest 53 - go install github.com/josharian/impl@latest 54 - go install github.com/cweill/gotests/...@latest 55 - go install github.com/koron/iferr@latest 56 + run: task install-deps 56 57 57 58 - name: Run Tests 58 59 run: | 59 60 nvim --version 60 - task tests 61 + task test
+10 -12
CONTRIBUTING.md
··· 1 1 # Contributing to `gopher.nvim` 2 - 3 2 Thank you for taking the time to submit some code to gopher.nvim. It means a lot! 4 3 5 4 ### Task running 6 - 7 5 In this codebase for running tasks is used [Taskfile](https://taskfile.dev). 8 6 You can install it with: 9 7 ```bash 10 8 go install github.com/go-task/task/v3/cmd/task@latest 11 9 ``` 12 10 13 - ### Styling and formatting 14 - 11 + ### Formatting and linting 15 12 Code is formatted by [stylua](https://github.com/JohnnyMorganz/StyLua) and linted using [selene](https://github.com/Kampfkarren/selene). 16 13 You can install these with: 17 14 ··· 22 19 23 20 For formatting use this following commands, or setup your editor to integrate with selene/stylua: 24 21 ```bash 25 - task stylua 26 - task lint # lintering and format chewing 22 + task format 23 + task lint 27 24 ``` 28 25 29 26 ### Documentation 27 + Here we're using [mini.doc](https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-doc.md) 28 + for generating vimhelp files based on [LuaCats](https://luals.github.io/wiki/annotations/) annotations in comments. 30 29 31 - Here we are using [mini.doc](https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-doc.md) 32 - for generating help files based on EmmyLua-like annotations in comments 30 + For demo gifs in [readme](./README.md) we're using [vhs](https://github.com/charmbracelet/vhs). 31 + All files related to demos live in [/vhs](./vhs) dir. 33 32 34 33 You can generate docs with: 35 34 ```bash 36 - task docgen 35 + task docgen # generates vimhelp 36 + task vhs:generate # generates demo gifs 37 37 ``` 38 38 39 39 ### Commit messages 40 - 41 40 We use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/), please follow it. 42 41 43 42 ### Testing 44 - 45 43 For testing this plugins uses [mini.test](https://github.com/echasnovski/mini.nvim/blob/main/readmes/mini-test.md). 46 44 All tests live in [/spec](./spec) dir. 47 45 48 46 You can run tests with: 49 47 ```bash 50 - task tests 48 + task test 51 49 ```
+58 -54
README.md
··· 4 4 5 5 Minimalistic plugin for Go development in Neovim written in Lua. 6 6 7 - It's **NOT** an LSP tool, the main goal of this plugin is to add go tooling support in Neovim. 7 + It's **NOT** an LSP tool, the goal of this plugin is to add go tooling support in Neovim. 8 8 9 - > If you want to use new and maybe undocumented, and unstable features you might use [develop](https://github.com/olexsmir/gopher.nvim/tree/develop) branch. 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 10 11 11 ## Install (using [lazy.nvim](https://github.com/folke/lazy.nvim)) 12 12 13 13 Requirements: 14 14 15 15 - **Neovim 0.10** or later 16 - - Treesitter `go` parser(`:TSInstall go` if you use [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter)) 17 - - [Go](https://github.com/golang/go) installed (tested on 1.23) 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 18 19 19 ```lua 20 + -- NOTE: this plugin is already lazy-loaded, it adds only about 1ms of load 21 + -- time to your config 20 22 { 21 23 "olexsmir/gopher.nvim", 22 24 ft = "go", ··· 25 27 build = function() 26 28 vim.cmd.GoInstallDeps() 27 29 end, 30 + ---@module "gopher" 28 31 ---@type gopher.Config 29 32 opts = {}, 30 33 } 31 34 ``` 32 35 33 - ## Configuration 34 - 35 - > [!IMPORTANT] 36 - > 37 - > If you need more info look `:h gopher.nvim` 38 - 39 - **Take a look at default options (might be a bit outdated, look `:h gopher.nvim-config`)** 40 - 41 - ```lua 42 - require("gopher").setup { 43 - -- log level, you might consider using DEBUG or TRACE for debugging the plugin 44 - log_level = vim.log.levels.INFO, 45 - 46 - -- timeout for running internal commands 47 - timeout = 2000, 48 - 49 - commands = { 50 - go = "go", 51 - gomodifytags = "gomodifytags", 52 - gotests = "gotests", 53 - impl = "impl", 54 - iferr = "iferr", 55 - }, 56 - gotests = { 57 - -- gotests doesn't have template named "default" so this plugin uses "default" to set the default template 58 - template = "default", 59 - -- path to a directory containing custom test code templates 60 - template_dir = nil, 61 - -- switch table tests from using slice to map (with test name for the key) 62 - named = false, 63 - }, 64 - gotag = { 65 - transform = "snakecase", 66 - -- default tags to add to struct fields 67 - default_tag = "json", 68 - }, 69 - iferr = { 70 - -- choose a custom error message 71 - message = nil, 72 - }, 73 - } 74 - ``` 75 - 76 36 ## Features 77 - 78 - <!-- markdownlint-disable --> 79 37 80 38 <details> 81 39 <summary> ··· 99 57 <b>Add and remove tags for structs via <a href="https://github.com/fatih/gomodifytags">gomodifytags</a></b> 100 58 </summary> 101 59 60 + ![Add tags demo](./vhs/tags.gif) 61 + 102 62 By default `json` tag will be added/removed, if not set: 103 63 104 64 ```vim ··· 176 136 <b>Interface implementation via <a href="https://github.com/josharian/impl">impl<a></b> 177 137 </summary> 178 138 139 + ![Auto interface implementation demo](./vhs/impl.gif) 140 + 179 141 Syntax of the command: 180 142 ```vim 181 143 :GoImpl [receiver] [interface] ··· 198 160 <summary> 199 161 <b>Generate boilerplate for doc comments</b> 200 162 </summary> 163 + 164 + ![Generate comments](./vhs/comment.gif) 201 165 202 166 First set a cursor on **public** package/function/interface/struct and execute: 203 167 ··· 212 176 <b>Generate <code>if err != nil {</code> via <a href="https://github.com/koron/iferr">iferr</a></b> 213 177 </summary> 214 178 179 + ![Generate if err != nil {](./vhs/iferr.gif) 180 + 215 181 Set the cursor on the line with `err` and execute 216 182 217 183 ```vim ··· 219 185 ``` 220 186 </details> 221 187 222 - ## Contributing 188 + ## Configuration 223 189 224 - PRs are always welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) 190 + > [!IMPORTANT] 191 + > 192 + > If you need more info look `:h gopher.nvim` 225 193 226 - ## Thanks 194 + **Take a look at default options (might be a bit outdated, look `:h gopher.nvim-config`)** 227 195 228 - - [go.nvim](https://github.com/ray-x/go.nvim) 229 - - [iferr](https://github.com/koron/iferr) 196 + ```lua 197 + require("gopher").setup { 198 + -- log level, you might consider using DEBUG or TRACE for debugging the plugin 199 + log_level = vim.log.levels.INFO, 200 + 201 + -- timeout for running internal commands 202 + timeout = 2000, 203 + 204 + commands = { 205 + go = "go", 206 + gomodifytags = "gomodifytags", 207 + gotests = "gotests", 208 + impl = "impl", 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 + 233 + PRs are always welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md)
+20 -14
Taskfile.yml
··· 1 1 version: "3" 2 + 3 + includes: 4 + vhs: 5 + taskfile: ./vhs/Taskfile.yml 6 + dir: ./vhs 7 + 2 8 tasks: 3 9 lint: 4 - desc: runs all linters 5 10 cmds: 6 - - task: selene 11 + - selene . 7 12 - stylua --check . 8 13 9 - selene: 10 - desc: runs lua linter(selene) 11 - cmds: 12 - - selene . 13 - 14 - stylua: 15 - desc: runs lua formatter 16 - cmds: 17 - - stylua . 14 + format: 15 + cmd: stylua . 18 16 19 - tests: 20 - desc: run all tests 17 + test: 21 18 cmds: 22 19 - | 23 20 nvim --clean --headless \ 24 21 -u ./scripts/minimal_init.lua \ 25 - -c "lua MiniTest.run()" 22 + -c "lua MiniTest.run()" \ 23 + -c ":qa!" 26 24 27 25 docgen: 28 26 desc: generate vimhelp ··· 32 30 -u "./scripts/minimal_init.lua" \ 33 31 -c "luafile ./scripts/docgen.lua" \ 34 32 -c ":qa!" 33 + 34 + install-deps: 35 + desc: installs go bin (used in CI) 36 + cmds: 37 + - | 38 + nvim --clean --headless \ 39 + -u "./scripts/minimal_init.lua" \ 40 + +GoInstallDepsSync +qa
+4 -4
lua/gopher/_utils/ts.lua
··· 65 65 66 66 ---@class gopher.TsResult 67 67 ---@field name string 68 - ---@field start_line integer 69 - ---@field end_line integer 68 + ---@field start integer 69 + ---@field end_ integer 70 70 ---@field is_varstruct boolean 71 71 72 72 ---@param bufnr integer ··· 95 95 assert(res.name ~= nil, "No capture name found") 96 96 97 97 local start_row, _, end_row, _ = parent_node:range() 98 - res["start_line"] = start_row + 1 99 - res["end_line"] = end_row + 1 98 + res["start"] = start_row + 1 99 + res["end_"] = end_row + 1 100 100 101 101 return res 102 102 end
+1 -1
lua/gopher/config.lua
··· 109 109 110 110 ---@dochide 111 111 ---@return gopher.Config 112 - return config 112 + return config --[[ @as gopher.Config ]]
+29 -15
lua/gopher/struct_tags.lua
··· 37 37 local log = require "gopher._utils.log" 38 38 local struct_tags = {} 39 39 40 + ---@dochide 41 + ---@class gopher.StructTagInput 42 + ---@field tags string[] User provided tags 43 + ---@field range? gopher.StructTagRange (optional) 44 + 45 + ---@dochide 46 + ---@class gopher.StructTagRange 47 + ---@field start number 48 + ---@field end_ number 49 + 40 50 ---@param fpath string 41 51 ---@param bufnr integer 52 + ---@param range? gopher.StructTagRange 42 53 ---@param user_args string[] 43 54 ---@dochide 44 - local function handle_tags(fpath, bufnr, user_args) 55 + local function handle_tags(fpath, bufnr, range, user_args) 45 56 local st = ts.get_struct_under_cursor(bufnr) 46 57 47 58 -- stylua: ignore ··· 53 64 "-w", 54 65 } 55 66 56 - if st.is_varstruct then 67 + -- `-struct` and `-line` cannot be combined, setting them separately 68 + if range or st.is_varstruct then 57 69 table.insert(cmd, "-line") 58 - table.insert(cmd, string.format("%d,%d", st.start_line, st.end_line)) 70 + table.insert(cmd, string.format("%d,%d", (range or st).start, (range or st).end_)) 59 71 else 60 72 table.insert(cmd, "-struct") 61 73 table.insert(cmd, st.name) ··· 93 105 ---@param args string[] 94 106 ---@return string 95 107 ---@dochide 96 - local function handler_user_args(args) 108 + local function handler_user_tags(args) 97 109 if #args == 0 then 98 110 return c.gotag.default_tag 99 111 end ··· 102 114 103 115 -- Adds tags to a struct under the cursor 104 116 -- See |gopher.nvim-struct-tags| 105 - ---@param ... string Tags to add to the struct fields. If not provided, it will use [config.gotag.default_tag] 117 + ---@param opts gopher.StructTagInput 106 118 ---@dochide 107 - function struct_tags.add(...) 108 - local args = { ... } 119 + function struct_tags.add(opts) 120 + log.debug("adding tags", opts) 121 + 109 122 local fpath = vim.fn.expand "%" 110 123 local bufnr = vim.api.nvim_get_current_buf() 111 124 112 - local user_tags = handler_user_args(args) 113 - handle_tags(fpath, bufnr, { "-add-tags", user_tags }) 125 + local user_tags = handler_user_tags(opts.tags) 126 + handle_tags(fpath, bufnr, opts.range, { "-add-tags", user_tags }) 114 127 end 115 128 116 129 -- Removes tags from a struct under the cursor 117 130 -- See `:h gopher.nvim-struct-tags` 118 131 ---@dochide 119 - ---@param ... string Tags to add to the struct fields. If not provided, it will use [config.gotag.default_tag] 120 - function struct_tags.remove(...) 121 - local args = { ... } 132 + ---@param opts gopher.StructTagInput 133 + function struct_tags.remove(opts) 134 + log.debug("removing tags", opts) 135 + 122 136 local fpath = vim.fn.expand "%" 123 137 local bufnr = vim.api.nvim_get_current_buf() 124 138 125 - local user_tags = handler_user_args(args) 126 - handle_tags(fpath, bufnr, { "-remove-tags", user_tags }) 139 + local user_tags = handler_user_tags(opts.tags) 140 + handle_tags(fpath, bufnr, opts.range, { "-remove-tags", user_tags }) 127 141 end 128 142 129 143 -- Removes all tags from a struct under the cursor ··· 132 146 function struct_tags.clear() 133 147 local fpath = vim.fn.expand "%" 134 148 local bufnr = vim.api.nvim_get_current_buf() 135 - handle_tags(fpath, bufnr, { "-clear-tags" }) 149 + handle_tags(fpath, bufnr, nil, { "-clear-tags" }) 136 150 end 137 151 138 152 return struct_tags
-40
nvim.toml
··· 3 3 4 4 [MiniTest] 5 5 any = true 6 - 7 - [describe] 8 - any = true 9 - [[describe.args]] 10 - type = "string" 11 - [[describe.args]] 12 - type = "function" 13 - 14 - [it] 15 - any = true 16 - [[it.args]] 17 - type = "string" 18 - [[it.args]] 19 - type = "function" 20 - 21 - [before_each] 22 - any = true 23 - [[before_each.args]] 24 - type = "function" 25 - [[after_each.args]] 26 - type = "function" 27 - 28 - [assert] 29 - any = true 30 - 31 - [assert.is_not] 32 - any = true 33 - 34 - [[assert.equals.args]] 35 - type = "any" 36 - [[assert.equals.args]] 37 - type = "any" 38 - [[assert.equals.args]] 39 - type = "any" 40 - required = false 41 - 42 - [[assert.same.args]] 43 - type = "any" 44 - [[assert.same.args]] 45 - type = "any"
+22 -7
plugin/gopher.lua
··· 11 11 ---@param name string 12 12 ---@param fn fun(args: table) 13 13 ---@param nargs? number|"*"|"?" 14 + ---@param range? boolean 14 15 ---@private 15 - local function cmd(name, fn, nargs) 16 - nargs = nargs or 0 17 - vim.api.nvim_create_user_command(name, fn, { nargs = nargs }) 16 + local function cmd(name, fn, nargs, range) 17 + vim.api.nvim_create_user_command(name, fn, { 18 + nargs = nargs or 0, 19 + range = range or false, 20 + }) 18 21 end 19 22 20 23 cmd("GopherLog", function() ··· 44 47 45 48 -- :GoTag 46 49 cmd("GoTagAdd", function(opts) 47 - require("gopher").tags.add(unpack(opts.fargs)) 48 - end, "*") 50 + require("gopher").tags.add { 51 + tags = opts.fargs, 52 + range = (opts.count ~= -1) and { 53 + start = opts.line1, 54 + end_ = opts.line2, 55 + } or nil, 56 + } 57 + end, "*", true) 49 58 50 59 cmd("GoTagRm", function(opts) 51 - require("gopher").tags.rm(unpack(opts.fargs)) 52 - end, "*") 60 + require("gopher").tags.rm { 61 + tags = opts.fargs, 62 + range = (opts.count ~= -1) and { 63 + start = opts.line1, 64 + end_ = opts.line2, 65 + } or nil, 66 + } 67 + end, "*", true) 53 68 54 69 cmd("GoTagClear", function() 55 70 require("gopher").tags.clear()
+10
scripts/minimal_init.lua
··· 23 23 install_plug "nvim-lua/plenary.nvim" 24 24 install_plug "nvim-treesitter/nvim-treesitter" 25 25 install_plug "echasnovski/mini.doc" -- used for docs generation 26 + install_plug "folke/tokyonight.nvim" -- theme for generating demos 26 27 install_plug "echasnovski/mini.test" 27 28 28 29 vim.env.XDG_CONFIG_HOME = root ".tests/config" ··· 32 33 33 34 vim.opt.runtimepath:append(root()) 34 35 vim.opt.packpath:append(root ".tests/site") 36 + vim.o.swapfile = false 37 + vim.o.writebackup = false 35 38 vim.notify = vim.print 36 39 37 40 -- install go treesitter parse ··· 51 54 end, 52 55 }, 53 56 } 57 + end 58 + 59 + -- set colorscheme only when running ui 60 + if #vim.api.nvim_list_uis() == 1 then 61 + vim.cmd.colorscheme "tokyonight-night" 62 + vim.o.cursorline = true 63 + vim.o.number = true 54 64 end 55 65 56 66 -- needed for tests, i dont know the reason why, but on start
+14
spec/fixtures/tags/add_range_input.go
··· 1 + package main 2 + 3 + type Test struct { 4 + ID int 5 + Name string 6 + Num int64 7 + Cost int 8 + Thingy []string 9 + Testing int 10 + Another struct { 11 + First int 12 + Second string 13 + } 14 + }
+14
spec/fixtures/tags/add_range_output.go
··· 1 + package main 2 + 3 + type Test struct { 4 + ID int 5 + Name string `gopher:"name"` 6 + Num int64 `gopher:"num"` 7 + Cost int `gopher:"cost"` 8 + Thingy []string 9 + Testing int 10 + Another struct { 11 + First int 12 + Second string 13 + } 14 + }
+14
spec/fixtures/tags/remove_range_input.go
··· 1 + package main 2 + 3 + type Test struct { 4 + ID int `asdf:"id"` 5 + Name string `asdf:"name"` 6 + Num int64 `asdf:"num"` 7 + Cost int `asdf:"cost"` 8 + Thingy []string `asdf:"thingy"` 9 + Testing int `asdf:"testing"` 10 + Another struct { 11 + First int `asdf:"first"` 12 + Second string `asdf:"second"` 13 + } `asdf:"another"` 14 + }
+14
spec/fixtures/tags/remove_range_output.go
··· 1 + package main 2 + 3 + type Test struct { 4 + ID int `asdf:"id"` 5 + Name string `asdf:"name"` 6 + Num int64 7 + Cost int 8 + Thingy []string 9 + Testing int `asdf:"testing"` 10 + Another struct { 11 + First int `asdf:"first"` 12 + Second string `asdf:"second"` 13 + } `asdf:"another"` 14 + }
+7 -7
spec/integration/comment_test.lua
··· 1 1 local t = require "spec.testutils" 2 - local child, T = t.setup "comment" 2 + local child, T, comment = t.setup "comment" 3 3 4 4 local function do_the_test(fixture, pos) 5 5 local rs = t.setup_test("comment/" .. fixture, child, pos) ··· 10 10 t.cleanup(rs) 11 11 end 12 12 13 - T["comment"]["should add comment to package"] = function() 13 + comment["should add comment to package"] = function() 14 14 do_the_test("package", { 1, 1 }) 15 15 end 16 16 17 - T["comment"]["should add comment to struct"] = function() 17 + comment["should add comment to struct"] = function() 18 18 do_the_test("struct", { 4, 1 }) 19 19 end 20 20 21 - T["comment"]["should add comment to function"] = function() 21 + comment["should add comment to function"] = function() 22 22 do_the_test("func", { 3, 1 }) 23 23 end 24 24 25 - T["comment"]["should add comment to method"] = function() 25 + comment["should add comment to method"] = function() 26 26 do_the_test("method", { 5, 1 }) 27 27 end 28 28 29 - T["comment"]["should add comment to interface"] = function() 29 + comment["should add comment to interface"] = function() 30 30 do_the_test("interface", { 3, 6 }) 31 31 end 32 32 33 - T["comment"]["otherwise should add // above cursor"] = function() 33 + comment["otherwise should add // above cursor"] = function() 34 34 do_the_test("empty", { 1, 1 }) 35 35 end 36 36
+3 -3
spec/integration/gotests_test.lua
··· 1 1 local t = require "spec.testutils" 2 - local child, T = t.setup "gotests" 2 + local child, T, gotests = t.setup "gotests" 3 3 4 4 --- NOTE: :GoTestAdd is the only place that has actual logic 5 5 --- All other parts are handled `gotests` itself. ··· 10 10 return t.readfile(fpath:gsub(".go", "_test.go")) 11 11 end 12 12 13 - T["gotests"]["should add test for function under cursor"] = function() 13 + gotests["should add test for function under cursor"] = function() 14 14 local rs = t.setup_test("tests/function", child, { 3, 5 }) 15 15 child.cmd "GoTestAdd" 16 16 ··· 18 18 t.cleanup(rs) 19 19 end 20 20 21 - T["gotests"]["should add test for method under cursor"] = function() 21 + gotests["should add test for method under cursor"] = function() 22 22 local rs = t.setup_test("tests/method", child, { 5, 19 }) 23 23 child.cmd "GoTestAdd" 24 24
+3 -3
spec/integration/iferr_test.lua
··· 1 1 local t = require "spec.testutils" 2 - local child, T = t.setup "iferr" 2 + local child, T, iferr = t.setup "iferr" 3 3 4 - T["iferr"]["should add if != nil {"] = function() 4 + iferr["should add if != nil {"] = function() 5 5 local rs = t.setup_test("iferr/iferr", child, { 8, 2 }) 6 6 child.cmd "GoIfErr" 7 7 child.cmd "write" ··· 10 10 t.cleanup(rs) 11 11 end 12 12 13 - T["iferr"]["should add if err with custom message"] = function() 13 + iferr["should add if err with custom message"] = function() 14 14 child.lua [[ 15 15 require("gopher").setup { 16 16 iferr = { message = 'fmt.Errorf("failed to %w", err)' }
+4 -4
spec/integration/impl_test.lua
··· 1 1 local t = require "spec.testutils" 2 - local child, T = t.setup "impl" 2 + local child, T, impl = t.setup "impl" 3 3 4 - T["impl"]["should do impl with 'w io.Writer'"] = function() 4 + impl["should do impl with 'w io.Writer'"] = function() 5 5 local rs = t.setup_test("impl/writer", child, { 3, 0 }) 6 6 child.cmd "GoImpl w io.Writer" 7 7 child.cmd "write" ··· 12 12 t.cleanup(rs) 13 13 end 14 14 15 - T["impl"]["should work with full input, 'r Read io.Reader'"] = function() 15 + impl["should work with full input, 'r Read io.Reader'"] = function() 16 16 local rs = t.setup_test("impl/reader", child) 17 17 child.cmd "GoImpl r Read io.Reader" 18 18 child.cmd "write" ··· 22 22 t.cleanup(rs) 23 23 end 24 24 25 - T["impl"]["should work with minimal input 'io.Closer'"] = function() 25 + impl["should work with minimal input 'io.Closer'"] = function() 26 26 local rs = t.setup_test("impl/closer", child, { 3, 6 }) 27 27 child.cmd "GoImpl io.Closer" 28 28 child.cmd "write"
+26 -8
spec/integration/struct_tags_test.lua
··· 1 1 local t = require "spec.testutils" 2 - local child, T = t.setup "struct_tags" 2 + local child, T, struct_tags = t.setup "struct_tags" 3 3 4 - T["struct_tags"]["should add tag"] = function() 4 + struct_tags["should add tag"] = function() 5 5 local rs = t.setup_test("tags/add", child, { 3, 6 }) 6 6 child.cmd "GoTagAdd json" 7 7 child.cmd "write" ··· 10 10 t.cleanup(rs) 11 11 end 12 12 13 - T["struct_tags"]["should remove tag"] = function() 13 + struct_tags["should remove tag"] = function() 14 14 local rs = t.setup_test("tags/remove", child, { 4, 6 }) 15 15 child.cmd "GoTagRm json" 16 16 child.cmd "write" ··· 19 19 t.cleanup(rs) 20 20 end 21 21 22 - T["struct_tags"]["should be able to handle many structs"] = function() 22 + struct_tags["should be able to handle many structs"] = function() 23 23 local rs = t.setup_test("tags/many", child, { 10, 3 }) 24 24 child.cmd "GoTagAdd testing" 25 25 child.cmd "write" ··· 28 28 t.cleanup(rs) 29 29 end 30 30 31 - T["struct_tags"]["should clear struct"] = function() 31 + struct_tags["should clear struct"] = function() 32 32 local rs = t.setup_test("tags/clear", child, { 3, 1 }) 33 33 child.cmd "GoTagClear" 34 34 child.cmd "write" ··· 37 37 t.cleanup(rs) 38 38 end 39 39 40 - T["struct_tags"]["should add more than one tag"] = function() 40 + struct_tags["should add more than one tag"] = function() 41 41 local tmp = t.tmpfile() 42 42 local fixtures = t.get_fixtures "tags/add_many" 43 43 t.writefile(tmp, fixtures.input) ··· 60 60 t.cleanup { tmp = tmp } 61 61 end 62 62 63 - T["struct_tags"]["should add tags on var"] = function() 63 + struct_tags["should add tags on var"] = function() 64 64 local rs = t.setup_test("tags/var", child, { 5, 6 }) 65 65 child.cmd "GoTagAdd yaml" 66 66 child.cmd "write" ··· 69 69 t.cleanup(rs) 70 70 end 71 71 72 - T["struct_tags"]["should add tags on short declr var"] = function() 72 + struct_tags["should add tags on short declr var"] = function() 73 73 local rs = t.setup_test("tags/svar", child, { 4, 3 }) 74 74 child.cmd "GoTagAdd xml" 75 + child.cmd "write" 76 + 77 + t.eq(t.readfile(rs.tmp), rs.fixtures.output) 78 + t.cleanup(rs) 79 + end 80 + 81 + struct_tags["should add tag with range"] = function() 82 + local rs = t.setup_test("tags/add_range", child, { 5, 1 }) 83 + child.cmd ".,+2GoTagAdd gopher" 84 + child.cmd "write" 85 + 86 + t.eq(t.readfile(rs.tmp), rs.fixtures.output) 87 + t.cleanup(rs) 88 + end 89 + 90 + struct_tags["should remove tag with range"] = function() 91 + local rs = t.setup_test("tags/remove_range", child, { 6, 1 }) 92 + child.cmd ".,+2GoTagRm asdf" 75 93 child.cmd "write" 76 94 77 95 t.eq(t.readfile(rs.tmp), rs.fixtures.output)
+11 -5
spec/testutils.lua
··· 6 6 testutils.mininit_path = vim.fs.joinpath(base_dir, "scripts", "minimal_init.lua") 7 7 testutils.fixtures_dir = vim.fs.joinpath(base_dir, "spec/fixtures") 8 8 9 - ---@param name string 10 - ---@return MiniTest.child, table 11 - function testutils.setup(name) 9 + ---@param mod string Module name for which to create a nested test set. 10 + ---@return MiniTest.child child nvim client. 11 + ---@return table T root test set created by `MiniTest.new_set()`. 12 + ---@return table mod_name nested set of tests in `T[mod]`. 13 + function testutils.setup(mod) 12 14 local child = MiniTest.new_child_neovim() 13 15 local T = MiniTest.new_set { 14 16 hooks = { ··· 19 21 }, 20 22 } 21 23 22 - T[name] = MiniTest.new_set {} 23 - return child, T 24 + T[mod] = MiniTest.new_set {} 25 + return child, T, T[mod] 24 26 end 25 27 26 28 ---@generic T ··· 76 78 ---@param pos? number[] 77 79 ---@return gopher.TestUtilsSetup 78 80 function testutils.setup_test(fixture, child, pos) 81 + vim.validate("pos", pos, "table", true) 82 + 79 83 local tmp = testutils.tmpfile() 80 84 local fixtures = testutils.get_fixtures(fixture) 81 85 ··· 84 88 85 89 local bufnr = child.fn.bufnr(tmp) 86 90 if pos then 91 + assert(#pos == 2, "invalid cursor position") 92 + 87 93 child.fn.setpos(".", { bufnr, unpack(pos) }) 88 94 end 89 95
+22
spec/unit/config_test.lua
··· 1 + local t = require "spec.testutils" 2 + local _, T, config = t.setup "config" 3 + 4 + config["can be called without any arguments passed"] = function() 5 + ---@diagnostic disable-next-line: missing-parameter 6 + require("gopher").setup() 7 + end 8 + 9 + config["can be called with empty table"] = function() 10 + require("gopher").setup {} 11 + end 12 + 13 + config["should change option"] = function() 14 + local log_level = 1234567890 15 + require("gopher").setup { 16 + log_level = log_level, 17 + } 18 + 19 + t.eq(log_level, require("gopher.config").log_level) 20 + end 21 + 22 + return T
+4 -4
spec/unit/utils_test.lua
··· 1 1 local t = require "spec.testutils" 2 - local _, T = t.setup "utils" 2 + local _, T, utils = t.setup "utils" 3 3 4 - T["utils"]["should .remove_empty_lines()"] = function() 4 + utils["should .remove_empty_lines()"] = function() 5 5 local u = require "gopher._utils" 6 6 local inp = { "hi", "", "a", "", "", "asdf" } 7 7 8 8 t.eq(u.remove_empty_lines(inp), { "hi", "a", "asdf" }) 9 9 end 10 10 11 - T["utils"]["should .readfile_joined()"] = function() 11 + utils["should .readfile_joined()"] = function() 12 12 local data = "line1\nline2\nline3" 13 13 local tmp = t.tmpfile() 14 14 local u = require "gopher._utils" ··· 17 17 t.eq(u.readfile_joined(tmp), data) 18 18 end 19 19 20 - T["utils"]["should .trimend()"] = function() 20 + utils["should .trimend()"] = function() 21 21 local u = require "gopher._utils" 22 22 t.eq(u.trimend " hi ", " hi") 23 23 end
+20
vhs/Taskfile.yml
··· 1 + version: "3" 2 + tasks: 3 + generate: 4 + deps: 5 + - comment 6 + - iferr 7 + - tags 8 + - impl 9 + 10 + comment: 11 + cmd: vhs comment.tape 12 + 13 + iferr: 14 + cmd: vhs iferr.tape 15 + 16 + tags: 17 + cmd: vhs tags.tape 18 + 19 + impl: 20 + cmd: vhs impl.tape
vhs/comment.gif

This is a binary file and will not be displayed.

+7
vhs/comment.go
··· 1 + package demos 2 + 3 + func doSomethingImportant() {} 4 + 5 + type User struct{} 6 + 7 + type DataProvider interface{}
+34
vhs/comment.tape
··· 1 + Output comment.gif 2 + Require nvim 3 + 4 + Set FontFamily "JetBrains Mono" 5 + Set Height 800 6 + Set Width 1500 7 + Set Padding 20 8 + Set Shell "bash" 9 + Set Theme "tokyonight" 10 + Set TypingSpeed 250ms 11 + 12 + Hide 13 + Type@0ms "alias nvim='./nvim.sh'" Enter 14 + Type@0ms "clear" Enter 15 + Show 16 + 17 + Type "nvim comment.go" Sleep 150ms Enter 18 + 19 + # package 20 + Type ":GoCmt" Enter Sleep 500ms Escape Sleep 700ms 21 + 22 + # func 23 + Type "3j" 24 + Type ":GoCmt" Enter Sleep 500ms Escape Sleep 700ms 25 + 26 + # struct 27 + Type "3j" 28 + Type ":GoCmt" Enter Sleep 500ms Escape Sleep 700ms 29 + 30 + # interface 31 + Type "3j" 32 + Type ":GoCmt" Enter Sleep 500ms Escape Sleep 700ms 33 + 34 + Sleep 5s
+3
vhs/go.mod
··· 1 + module demos 2 + 3 + go 1.25.0
vhs/iferr.gif

This is a binary file and will not be displayed.

+11
vhs/iferr.go
··· 1 + package demos 2 + 3 + func ifErr() { 4 + out, err := doSomething() 5 + 6 + _ = out 7 + } 8 + 9 + func doSomething() (string, error) { 10 + return "", nil 11 + }
+23
vhs/iferr.tape
··· 1 + Output iferr.gif 2 + Require nvim 3 + Require iferr 4 + 5 + Set FontFamily "JetBrains Mono" 6 + Set Height 800 7 + Set Width 1500 8 + Set Padding 20 9 + Set Shell "bash" 10 + Set Theme "tokyonight" 11 + Set TypingSpeed 250ms 12 + 13 + Hide 14 + Type@0ms "alias nvim='./nvim.sh'" Enter 15 + Type@0ms "clear" Enter 16 + Show 17 + 18 + Type "nvim iferr.go" Sleep 150ms Enter 19 + 20 + Type "3j" 21 + Type ":GoIfErr" Sleep 500ms Enter 22 + 23 + Sleep 5s
vhs/impl.gif

This is a binary file and will not be displayed.

+3
vhs/impl.go
··· 1 + package demos 2 + 3 + type CloserExample struct{}
+23
vhs/impl.tape
··· 1 + Output impl.gif 2 + Require nvim 3 + Require iferr 4 + 5 + Set FontFamily "JetBrains Mono" 6 + Set Height 800 7 + Set Width 1500 8 + Set Padding 20 9 + Set Shell "bash" 10 + Set Theme "tokyonight" 11 + Set TypingSpeed 250ms 12 + 13 + Hide 14 + Type@0ms "alias nvim='./nvim.sh'" Enter 15 + Type@0ms "clear" Enter 16 + Show 17 + 18 + Type "nvim impl.go" Sleep 150ms Enter 19 + 20 + Type "2j" 21 + Type ":GoImpl io.Reader" Sleep 500ms Enter 22 + 23 + Sleep 5s
+2
vhs/nvim.sh
··· 1 + #!/usr/bin/env bash 2 + nvim --clean -u "../scripts/minimal_init.lua" $@
vhs/tags.gif

This is a binary file and will not be displayed.

+12
vhs/tags.go
··· 1 + package demos 2 + 3 + type AddTagsToMe struct { 4 + Name string 5 + ID int 6 + Address string 7 + Aliases []string 8 + Nested struct { 9 + Foo string 10 + Bar float32 11 + } 12 + }
+36
vhs/tags.tape
··· 1 + Output tags.gif 2 + Require nvim 3 + Require gomodifytags 4 + 5 + Set FontFamily "JetBrains Mono" 6 + Set Height 800 7 + Set Width 1500 8 + Set Padding 20 9 + Set Shell "bash" 10 + Set Theme "tokyonight" 11 + Set TypingSpeed 250ms 12 + 13 + Hide 14 + Type@0ms "alias nvim='./nvim.sh'" Enter 15 + Type@0ms "clear" Enter 16 + Show 17 + 18 + Type "nvim tags.go" Sleep 150ms Enter 19 + 20 + Type "3j" 21 + Type ":GoTagAdd json yaml" Sleep 500ms Enter 22 + Type@120ms ":w" Enter 23 + Sleep 1s 24 + 25 + Type ":GoTagRm json" Sleep 500ms Enter 26 + Type@120ms ":w" Enter 27 + Sleep 1s 28 + 29 + Type ":GoTagClear" Sleep 500ms Enter 30 + Type@120ms ":w" Enter 31 + Sleep 1s 32 + 33 + Type "jV2j" 34 + Type ":GoTagAdd xml" Sleep 500ms Enter 35 + 36 + Sleep 5s