go.nvim/README.md

280 lines
9.4 KiB
Markdown
Raw Normal View History

2021-04-19 06:09:39 +00:00
# go.nvim
2021-03-10 12:15:06 +00:00
2021-07-10 11:04:24 +00:00
A modern go neovim plugin based on treesitter and nvim-lsp. It is written in Lua and async as much as possible.
2021-03-10 13:21:01 +00:00
PR & Suggestions welcome.
2021-03-12 02:54:08 +00:00
The plugin covers most features required for a gopher.
2021-04-19 06:16:25 +00:00
- Async jobs
2021-03-12 02:54:08 +00:00
- Syntex highlight & Texobject: Native treesitter support is faster and more accurate. All you need is a theme support treesitter, try
[aurora](https://github.com/ray-x/aurora). Also, there are quite a few listed in [awesome-neovim](https://github.com/rockerBOO/awesome-neovim)
- All the GoToXxx (E.g reference, implementation, definition, goto doc, peek code/doc etc) You need lspconfig setup. There are lots of posts on how to
set it up. You can also check my [navigator](https://github.com/ray-x/navigator.lua) gopls setup [lspconfig.lua](https://github.com/ray-x/navigator.lua/blob/master/lua/navigator/lspclient/clients.lua)
- Runtime lint/vet/compile: Supported by lsp (once you setup up your lsp client), GoLint with golangci-lint also supported
2021-03-12 02:54:08 +00:00
- Build/Make/Test: Go.nvim provides supports for these by an async job wrapper.
2021-07-10 11:04:24 +00:00
- Dlv Debug: with Dap UI
2021-03-12 02:54:08 +00:00
- Unit test: Support [gotests](https://github.com/cweill/gotests)
- tag modify: Supports gomodifytags
- Code format: Supports LSP format and GoFmt
- Comments: Add autodocument for your package/function/struct/interface. This feature is unique and can help you suppress golint
errors...
2021-03-10 12:15:06 +00:00
## install
make sure the `$GOPATH/bin` path is added to your `$PATH` environment variable. To check this you can run
```bash
echo $PATH | grep "$GOPATH/bin"
```
if nothing shows up, you can add the following to your shell config file
```bash
export PATH=$PATH:$GOPATH/bin
```
add 'ray-x/go.nvim' to your package manager, the dependency is `treesitter` (and optionally, treesitter-objects)
related binaries will be installed the first time you use it
Add format in your vimrc.
```vim
autocmd BufWritePre *.go :silent! lua require('go.format').gofmt()
```
2021-03-12 02:54:08 +00:00
To startup/setup the plugin
2021-03-10 12:15:06 +00:00
```lua
require('go').setup()
```
2021-04-19 06:09:39 +00:00
## Screenshots
### Add comments
![auto comments](https://github.com/ray-x/files/blob/master/img/go.nvim/comment.gif?raw=true)
### Add/Remove tags
![auto tag](https://github.com/ray-x/files/blob/master/img/go.nvim/tags.gif?raw=true)
2021-04-21 11:24:07 +00:00
## refactor gorename
gorename as an alternative to gopls rename as it supports rename across packages
2021-04-21 11:24:07 +00:00
2021-03-10 12:15:06 +00:00
## code format
nvim-lsp support goimport by default.
2021-03-10 13:21:01 +00:00
2021-03-10 12:15:06 +00:00
```vim
autocmd BufWritePre (InsertLeave?) <buffer> lua vim.lsp.buf.formatting_sync(nil,500)
```
The plugin provides code format, by default is goline + gofumports (stricter version of goimport)
The format tool is a asyn format tool in format.lua
```lua
require("go.format").gofmt()
require("go.format").goimport()
```
2021-04-23 06:31:00 +00:00
## Auto fill struct
Note: auto fill struct also supported by gopls lsp-action
2021-04-23 06:31:00 +00:00
![auto struct](https://github.com/ray-x/files/blob/master/img/go.nvim/fstruct.gif?raw=true)
2021-03-10 12:15:06 +00:00
## Textobject
Supported by treesitter. TS provided better parse result compared to regular expression.
2021-03-12 02:54:08 +00:00
Check [my treesitter config file](https://github.com/ray-x/dotfiles/blob/master/nvim/lua/modules/lang/treesitter.lua) on how to setup
textobjects. Also with treesitter-objects, you can move, swap the selected blocks of codes, which is fast and accurate.
2021-03-10 12:15:06 +00:00
## Build and test
2021-03-12 02:54:08 +00:00
Provided wrapper for gobulild/test etc with async make
Also suggest to use [vim-test](https://github.com/vim-test/vim-test), which can run running tests on different
granularities.
2021-03-10 12:15:06 +00:00
2021-03-12 02:54:08 +00:00
## Unit test with [gotests](https://github.com/cweill/gotests) and testify
2021-03-10 12:15:06 +00:00
Support table based unit test auto generate, parse current function/method name using treesitter
## Modifytags
2021-03-12 02:54:08 +00:00
Modify struct tags by [`gomodifytags`](https://github.com/fatih/gomodifytags) and treesitter
2021-03-10 12:15:06 +00:00
## GoFmt
nvim-lsp support goimport by default. The plugin provided a new formatter, goline + gofumports (stricter version of
goimport)
## Comments and Doc
Auto doc (to suppress golang-lint warning), generate comments by treesitter parsing result
```go
type GoLintComplaining struct{}
```
2021-03-10 13:21:01 +00:00
2021-03-10 13:26:55 +00:00
And run
2021-03-10 12:15:06 +00:00
```lua
2021-03-10 13:26:55 +00:00
lua.require('go.comment').gen() -- or your faviourite key binding and setup placeholder "no more complaint ;P"
2021-03-10 12:15:06 +00:00
```
2021-03-10 13:21:01 +00:00
2021-03-10 12:15:06 +00:00
The code will be:
2021-03-10 13:21:01 +00:00
2021-03-10 12:15:06 +00:00
```go
// GoLintComplaining struct no more complaint ;P
type GoLintComplaining struct{}
```
## LSP
LSP supported by nvim-lsp is good enough for a gopher. If you looking for a better GUI. You can install
[navigator](https://github.com/ray-x/navigator.lua), or lspsaga, and lsp-utils etc.
2021-03-10 12:15:06 +00:00
## Lint
2021-03-12 02:54:08 +00:00
Supported by LSP, also GoLint command (by calling golangcl-lint) if you need background golangci-lint check, you can
configure it with ALE
2021-03-10 12:15:06 +00:00
2021-07-10 11:04:24 +00:00
## Debug with dlv
Setup for Debug provided. Need Dap and Dap UI plugin
![dap](https://user-images.githubusercontent.com/1681295/125160289-743ba080-e1bf-11eb-804f-6a6d227ec33b.jpg)
GDB style key mapping is used
### Keymaps
| Command | Description |
| ----------- | ----------- |
| c | continue |
| n | next |
| s | step |
| o | stepout |
| S | cap S: stop debug |
| u | up |
| D | cap D: down |
| C | cap C: run to cursor |
| b | toggle breakpoint |
| P | cap P: pause |
| p | print, hover value (also in visual mode) |
### Commands
| Command | Description |
| ----------- | ----------- |
| Debug | Start debugger, to debug test, run `Debug test`, to add addition args run `Debug arg1 arg2` |
| BreakToggle | toggle break point |
| BreakCondition | conditional break point |
| ReplRun | dap repl run_last |
| ReplToggle | dap repl toggle |
### Required DAP plugins
The plugin will setup debugger. But you need to install
* dap
* 'mfussenegger/nvim-dap'
* dap ui (optional)
* 'rcarriga/nvim-dap-ui'
* dap virtual text (optional)
* 'theHamsta/nvim-dap-virtual-text'
Also you can check telescope dap extension : nvim-telescope/telescope-dap.nvim
Sample vimrc
```viml
Plug 'mfussenegger/nvim-dap'
Plug 'rcarriga/nvim-dap-ui'
Plug 'theHamsta/nvim-dap-virtual-text'
" Plug 'nvim-telescope/telescope-dap.nvim'
```
## Commands
Check [go.lua](https://github.com/ray-x/go.nvim/blob/master/lua/go.lua) on all the commands provided
2021-03-10 12:15:06 +00:00
## configuration
Configure from lua suggested:
2021-03-10 13:21:01 +00:00
2021-03-10 12:15:06 +00:00
```lua
require('go').setup(cfg = {
2021-07-10 11:04:24 +00:00
goimport='gofumports', -- goimport command
gofmt = 'gofumpt', --gofmt cmd,
max_line_len = 120, -- max line length in goline format
tag_transform = false, -- tag_transfer check gomodifytags for details
2021-03-10 12:15:06 +00:00
test_template = '', -- default to testify if not set; g:go_nvim_tests_template check gotests for details
test_template_dir = '', -- default to nil if not set; g:go_nvim_tests_template_dir check gotests for details
2021-07-10 11:04:24 +00:00
comment_placeholder = '' , -- comment_placeholder your cool placeholder e.g. ﳑ    
2021-03-10 12:15:06 +00:00
verbose = false, -- output loginf in messages
2021-07-10 11:04:24 +00:00
dap_debug = false, -- set to true to enable dap
dap_debug_keymap = true, -- set keymaps for debugger
dap_debug_gui = true, -- set to true to enable dap gui, highly recommand
dap_debug_vt = true, -- set to true to enable dap virtual text
2021-03-10 12:15:06 +00:00
})
```
2021-03-10 13:21:01 +00:00
You will need to add keybind yourself:
e.g
```lua
vim.cmd("autocmd FileType go nmap <Leader><Leader>l GoLint")
vim.cmd("autocmd FileType go nmap <Leader>gc :lua require('go.comment').gen()")
```
2021-07-10 11:04:24 +00:00
2021-03-10 13:26:55 +00:00
## Nvim LSP setup
For golang, the default gopls setup works perfectly fine, or you can install [navigator.lua](https://github.com/ray-x/navigator.lua) which can auto setup all lsp clients.
For diagnostic issue, you can use the default setup. There are also quite a few plugins that you can use to explore issues, e.g. [navigator.lua](https://github.com/ray-x/navigator.lua), [folke/lsp-trouble.nvim](https://github.com/folke/lsp-trouble.nvim). [Nvim-tree](https://github.com/kyazdani42/nvim-tree.lua) and [Bufferline](https://github.com/akinsho/nvim-bufferline.lua) also introduced lsp diagnostic hooks.
2021-03-10 13:21:01 +00:00
Also, you can do this: put **all** diag error/warning of your project in quickfix.
2021-03-10 13:21:01 +00:00
```lua
-- hdlr alternatively, use lua vim.lsp.diagnostic.set_loclist({open_loclist = false})
-- true to open loclist
2021-03-10 13:21:01 +00:00
local diag_hdlr = function(err, method, result, client_id, bufnr, config)
-- vim.lsp.diagnostic.clear(vim.fn.bufnr(), client.id, nil, nil)
vim.lsp.diagnostic.on_publish_diagnostics(err, method, result, client_id, bufnr, config)
if result and result.diagnostics then
local item_list = {}
local s = result.uri
local fname = s
for _, v in ipairs(result.diagnostics) do
i, j = string.find(s, "file://")
if j then
fname = string.sub(s, j + 1)
end
table.insert(item_list, { filename = fname, lnum = v.range.start.line + 1, col = v.range.start.character + 1; text = v.message; })
end
local old_items = vim.fn.getqflist()
for _, old_item in ipairs(old_items) do
local bufnr = vim.uri_to_bufnr(result.uri)
if vim.uri_from_bufnr(old_item.bufnr) ~= result.uri then
table.insert(item_list, old_item)
end
end
vim.fn.setqflist({}, ' ', { title = 'LSP'; items = item_list; })
end
end
vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(
diag_hdlr,
{
-- Enable underline, use default values
underline = true,
-- Enable virtual text, override spacing to 0
virtual_text = {
spacing = 0,
prefix = '', --'',  
},
-- Use a function to dynamically turn signs off
-- and on, using buffer local variables
signs = true,
-- Disable a feature
update_in_insert = false,
}
)
```