Alan Donovan | 799a471 | 2024-05-03 18:53:37 -0400 | [diff] [blame] | 1 | # Gopls: Using Vim or Neovim |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 2 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 3 | * [vim-go](#vimgo) |
| 4 | * [LanguageClient-neovim](#lcneovim) |
| 5 | * [Ale](#ale) |
| 6 | * [vim-lsp](#vimlsp) |
| 7 | * [vim-lsc](#vimlsc) |
| 8 | * [coc.nvim](#cocnvim) |
| 9 | * [govim](#govim) |
| 10 | * [Neovim v0.5.0+](#neovim) |
| 11 | * [Installation](#neovim-install) |
| 12 | * [Custom Configuration](#neovim-config) |
| 13 | * [Imports](#neovim-imports) |
| 14 | * [Omnifunc](#neovim-omnifunc) |
| 15 | * [Additional Links](#neovim-links) |
| 16 | |
| 17 | ## <a href="#vimgo" id="vimgo">vim-go</a> |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 18 | |
| 19 | Use [vim-go] ver 1.20+, with the following configuration: |
| 20 | |
Rebecca Stambler | d78b04b | 2020-12-28 13:26:14 -0500 | [diff] [blame] | 21 | ```vim |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 22 | let g:go_def_mode='gopls' |
| 23 | let g:go_info_mode='gopls' |
| 24 | ``` |
| 25 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 26 | ## <a href="#lcneovim" id="lcneovim">LanguageClient-neovim</a> |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 27 | |
| 28 | Use [LanguageClient-neovim], with the following configuration: |
| 29 | |
Rebecca Stambler | d78b04b | 2020-12-28 13:26:14 -0500 | [diff] [blame] | 30 | ```vim |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 31 | " Launch gopls when Go files are in use |
| 32 | let g:LanguageClient_serverCommands = { |
| 33 | \ 'go': ['gopls'] |
| 34 | \ } |
| 35 | " Run gofmt on save |
| 36 | autocmd BufWritePre *.go :call LanguageClient#textDocument_formatting_sync() |
| 37 | ``` |
| 38 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 39 | ## <a href="#ale" id="ale">Ale</a> |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 40 | |
| 41 | Use [ale]: |
| 42 | |
| 43 | ```vim |
| 44 | let g:ale_linters = { |
Rebecca Stambler | d78b04b | 2020-12-28 13:26:14 -0500 | [diff] [blame] | 45 | \ 'go': ['gopls'], |
| 46 | \} |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 47 | ``` |
| 48 | |
| 49 | see [this issue][ale-issue-2179] |
| 50 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 51 | ## <a href="#vimlsp" id="vimlsp">vim-lsp</a> |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 52 | |
| 53 | Use [prabirshrestha/vim-lsp], with the following configuration: |
| 54 | |
| 55 | ```vim |
| 56 | augroup LspGo |
| 57 | au! |
| 58 | autocmd User lsp_setup call lsp#register_server({ |
| 59 | \ 'name': 'go-lang', |
| 60 | \ 'cmd': {server_info->['gopls']}, |
| 61 | \ 'whitelist': ['go'], |
| 62 | \ }) |
| 63 | autocmd FileType go setlocal omnifunc=lsp#complete |
| 64 | "autocmd FileType go nmap <buffer> gd <plug>(lsp-definition) |
| 65 | "autocmd FileType go nmap <buffer> ,n <plug>(lsp-next-error) |
| 66 | "autocmd FileType go nmap <buffer> ,p <plug>(lsp-previous-error) |
| 67 | augroup END |
| 68 | ``` |
| 69 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 70 | ## <a href="#vimlsc" id="vimlsc">vim-lsc</a> |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 71 | |
| 72 | Use [natebosch/vim-lsc], with the following configuration: |
| 73 | |
| 74 | ```vim |
| 75 | let g:lsc_server_commands = { |
| 76 | \ "go": { |
| 77 | \ "command": "gopls serve", |
| 78 | \ "log_level": -1, |
Ainar Garipov | 1ccc110 | 2019-09-07 20:42:26 +0300 | [diff] [blame] | 79 | \ "suppress_stderr": v:true, |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 80 | \ }, |
| 81 | \} |
| 82 | ``` |
| 83 | |
Ainar Garipov | 1ccc110 | 2019-09-07 20:42:26 +0300 | [diff] [blame] | 84 | The `log_level` and `suppress_stderr` parts are needed to prevent breakage from logging. See |
Ainar Garipov | 846f856 | 2019-10-17 10:08:14 +0300 | [diff] [blame] | 85 | issues [#180](https://github.com/natebosch/vim-lsc/issues/180) and |
| 86 | [#213](https://github.com/natebosch/vim-lsc/issues/213). |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 87 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 88 | ## <a href="#cocnvim" id="cocnvim">coc.nvim</a> |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 89 | |
| 90 | Use [coc.nvim], with the following `coc-settings.json` configuration: |
| 91 | |
| 92 | ```json |
| 93 | "languageserver": { |
Hana (Hyang-Ah) Kim | 641e4d7 | 2023-04-18 12:44:01 -0400 | [diff] [blame] | 94 | "go": { |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 95 | "command": "gopls", |
Robert Findley | cf66aec | 2022-02-01 14:20:33 -0500 | [diff] [blame] | 96 | "rootPatterns": ["go.work", "go.mod", ".vim/", ".git/", ".hg/"], |
Shengjing Zhu | 5fa5b17 | 2019-10-14 14:03:50 +0800 | [diff] [blame] | 97 | "filetypes": ["go"], |
| 98 | "initializationOptions": { |
| 99 | "usePlaceholders": true |
| 100 | } |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 101 | } |
| 102 | } |
| 103 | ``` |
| 104 | |
Robert Findley | cf66aec | 2022-02-01 14:20:33 -0500 | [diff] [blame] | 105 | If you use `go.work` files, you may want to set the |
| 106 | `workspace.workspaceFolderCheckCwd` option. This will force coc.nvim to search |
| 107 | parent directories for `go.work` files, even if the current open directory has |
| 108 | a `go.mod` file. See the |
| 109 | [coc.nvim documentation](https://github.com/neoclide/coc.nvim/wiki/Using-workspaceFolders) |
| 110 | for more details. |
| 111 | |
Shengjing Zhu | 5fa5b17 | 2019-10-14 14:03:50 +0800 | [diff] [blame] | 112 | Other [settings](settings.md) can be added in `initializationOptions` too. |
| 113 | |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 114 | The `editor.action.organizeImport` code action will auto-format code and add missing imports. To run this automatically on save, add the following line to your `init.vim`: |
| 115 | |
| 116 | ```vim |
| 117 | autocmd BufWritePre *.go :call CocAction('runCommand', 'editor.action.organizeImport') |
| 118 | ``` |
| 119 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 120 | ## <a href="#govim" id="govim">govim</a> |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 121 | |
| 122 | In vim classic only, use the experimental [`govim`], simply follow the [install steps][govim-install]. |
| 123 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 124 | ## <a href="#neovim" id="neovim">Neovim v0.5.0+</a> |
Ellison Leão | cd5a53e | 2020-04-07 18:57:22 +0000 | [diff] [blame] | 125 | |
GGCristo | de44776 | 2021-07-09 13:24:30 +0000 | [diff] [blame] | 126 | To use the new native LSP client in Neovim, make sure you |
| 127 | [install][nvim-install] Neovim v.0.5.0+, |
Ainar Garipov | 34b80a0 | 2020-09-25 12:50:53 +0300 | [diff] [blame] | 128 | the `nvim-lspconfig` configuration helper plugin, and check the |
| 129 | [`gopls` configuration section][nvim-lspconfig] there. |
| 130 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 131 | ### <a href="#neovim-install" id="neovim-install">Installation</a> |
| 132 | |
| 133 | You can use Neovim's native plugin system. On a Unix system, you can do that by |
| 134 | cloning the `nvim-lspconfig` repository into the correct directory: |
| 135 | |
| 136 | ```sh |
| 137 | dir="${HOME}/.local/share/nvim/site/pack/nvim-lspconfig/opt/nvim-lspconfig/" |
| 138 | mkdir -p "$dir" |
| 139 | cd "$dir" |
| 140 | git clone 'https://github.com/neovim/nvim-lspconfig.git' . |
| 141 | ``` |
| 142 | |
Peter Aronoff | d98bc1a | 2023-09-13 15:43:22 +0000 | [diff] [blame] | 143 | ### <a href="#neovim-config" id="neovim-config">Configuration</a> |
Ainar Garipov | 34b80a0 | 2020-09-25 12:50:53 +0300 | [diff] [blame] | 144 | |
Peter Aronoff | d98bc1a | 2023-09-13 15:43:22 +0000 | [diff] [blame] | 145 | nvim-lspconfig aims to provide reasonable defaults, so your setup can be very |
| 146 | brief. |
Ainar Garipov | 34b80a0 | 2020-09-25 12:50:53 +0300 | [diff] [blame] | 147 | |
Raphael | 668845e | 2023-02-13 14:37:13 +0000 | [diff] [blame] | 148 | ```lua |
Peter Aronoff | d98bc1a | 2023-09-13 15:43:22 +0000 | [diff] [blame] | 149 | local lspconfig = require("lspconfig") |
| 150 | lspconfig.gopls.setup({}) |
| 151 | ``` |
| 152 | |
| 153 | However, you can also configure `gopls` for your preferences. Here's an |
| 154 | example that enables `unusedparams`, `staticcheck`, and `gofumpt`. |
| 155 | |
| 156 | ```lua |
| 157 | local lspconfig = require("lspconfig") |
| 158 | lspconfig.gopls.setup({ |
| 159 | settings = { |
| 160 | gopls = { |
| 161 | analyses = { |
| 162 | unusedparams = true, |
| 163 | }, |
| 164 | staticcheck = true, |
| 165 | gofumpt = true, |
| 166 | }, |
| 167 | }, |
| 168 | }) |
| 169 | ``` |
| 170 | |
| 171 | ### <a href="#neovim-imports" id="neovim-imports">Imports and Formatting</a> |
| 172 | |
| 173 | Use the following configuration to have your imports organized on save using |
| 174 | the logic of `goimports` and your code formatted. |
| 175 | |
| 176 | ```lua |
| 177 | autocmd("BufWritePre", { |
| 178 | pattern = "*.go", |
Raphael | 668845e | 2023-02-13 14:37:13 +0000 | [diff] [blame] | 179 | callback = function() |
Peter Aronoff | d98bc1a | 2023-09-13 15:43:22 +0000 | [diff] [blame] | 180 | local params = vim.lsp.util.make_range_params() |
| 181 | params.context = {only = {"source.organizeImports"}} |
| 182 | -- buf_request_sync defaults to a 1000ms timeout. Depending on your |
| 183 | -- machine and codebase, you may want longer. Add an additional |
| 184 | -- argument after params if you find that you have to write the file |
| 185 | -- twice for changes to be saved. |
| 186 | -- E.g., vim.lsp.buf_request_sync(0, "textDocument/codeAction", params, 3000) |
| 187 | local result = vim.lsp.buf_request_sync(0, "textDocument/codeAction", params) |
| 188 | for cid, res in pairs(result or {}) do |
| 189 | for _, r in pairs(res.result or {}) do |
| 190 | if r.edit then |
| 191 | local enc = (vim.lsp.get_client_by_id(cid) or {}).offset_encoding or "utf-16" |
| 192 | vim.lsp.util.apply_workspace_edit(r.edit, enc) |
| 193 | end |
| 194 | end |
| 195 | end |
| 196 | vim.lsp.buf.format({async = false}) |
Ainar Garipov | 34b80a0 | 2020-09-25 12:50:53 +0300 | [diff] [blame] | 197 | end |
Raphael | 668845e | 2023-02-13 14:37:13 +0000 | [diff] [blame] | 198 | }) |
Ainar Garipov | 34b80a0 | 2020-09-25 12:50:53 +0300 | [diff] [blame] | 199 | ``` |
| 200 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 201 | ### <a href="#neovim-omnifunc" id="neovim-omnifunc">Omnifunc</a> |
Ainar Garipov | 34b80a0 | 2020-09-25 12:50:53 +0300 | [diff] [blame] | 202 | |
Robert Findley | eec389d | 2023-02-13 10:28:41 -0500 | [diff] [blame] | 203 | In Neovim v0.8.1 and later if you don't set the option `omnifunc`, it will auto |
| 204 | set to `v:lua.vim.lsp.omnifunc`. If you are using an earlier version, you can |
| 205 | configure it manually: |
Raphael | 668845e | 2023-02-13 14:37:13 +0000 | [diff] [blame] | 206 | |
| 207 | ```lua |
| 208 | local on_attach = function(client, bufnr) |
| 209 | -- Enable completion triggered by <c-x><c-o> |
| 210 | vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') |
| 211 | end |
| 212 | require('lspconfig').gopls.setup({ |
| 213 | on_attach = on_attach |
| 214 | }) |
Ainar Garipov | 34b80a0 | 2020-09-25 12:50:53 +0300 | [diff] [blame] | 215 | ``` |
| 216 | |
Ainar Garipov | 0f6027f | 2020-12-17 00:48:15 +0300 | [diff] [blame] | 217 | ### <a href="#neovim-links" id="neovim-links">Additional Links</a> |
Ainar Garipov | 34b80a0 | 2020-09-25 12:50:53 +0300 | [diff] [blame] | 218 | |
| 219 | * [Neovim's official LSP documentation][nvim-docs]. |
Ellison Leão | cd5a53e | 2020-04-07 18:57:22 +0000 | [diff] [blame] | 220 | |
Ian Cottrell | 062dbae | 2019-05-09 10:35:27 -0400 | [diff] [blame] | 221 | [vim-go]: https://github.com/fatih/vim-go |
| 222 | [LanguageClient-neovim]: https://github.com/autozimu/LanguageClient-neovim |
| 223 | [ale]: https://github.com/w0rp/ale |
| 224 | [ale-issue-2179]: https://github.com/w0rp/ale/issues/2179 |
| 225 | [prabirshrestha/vim-lsp]: https://github.com/prabirshrestha/vim-lsp/ |
| 226 | [natebosch/vim-lsc]: https://github.com/natebosch/vim-lsc/ |
| 227 | [natebosch/vim-lsc#180]: https://github.com/natebosch/vim-lsc/issues/180 |
| 228 | [coc.nvim]: https://github.com/neoclide/coc.nvim/ |
| 229 | [`govim`]: https://github.com/myitcv/govim |
Ainar Garipov | 1ccc110 | 2019-09-07 20:42:26 +0300 | [diff] [blame] | 230 | [govim-install]: https://github.com/myitcv/govim/blob/master/README.md#govim---go-development-plugin-for-vim8 |
Ainar Garipov | 34b80a0 | 2020-09-25 12:50:53 +0300 | [diff] [blame] | 231 | [nvim-docs]: https://neovim.io/doc/user/lsp.html |
| 232 | [nvim-install]: https://github.com/neovim/neovim/wiki/Installing-Neovim |
Akhil | cadd57e | 2021-11-27 06:22:56 +0000 | [diff] [blame] | 233 | [nvim-lspconfig]: https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#gopls |
Ainar Garipov | 34b80a0 | 2020-09-25 12:50:53 +0300 | [diff] [blame] | 234 | [nvim-lspconfig-imports]: https://github.com/neovim/nvim-lspconfig/issues/115 |