1# Emacs 2 3## Installing `gopls` 4 5To use `gopls` with Emacs, you must first 6[install the `gopls` binary](../README.md#installation) and ensure that the directory 7containing the resulting binary (either `$(go env GOBIN)` or `$(go env 8GOPATH)/bin`) is in your `PATH`. 9 10## Choosing an Emacs LSP client 11 12To use `gopls` with Emacs, you will need to choose and install an Emacs LSP 13client package. Two popular client packages are [LSP Mode] and [Eglot]. 14 15LSP Mode takes a batteries-included approach, with many integrations enabled 16“out of the box” and several additional behaviors provided by `lsp-mode` itself. 17 18Eglot takes a minimally-intrusive approach, focusing on smooth integration with 19other established packages. It provides a few of its own `eglot-` commands but 20no additional keybindings by default. 21 22Once you have selected which client you want to use, install it per the packages 23instructions: see [Eglot 1-2-3](https://github.com/joaotavora/eglot#1-2-3) or 24[LSP Mode Installation](https://emacs-lsp.github.io/lsp-mode/page/installation/). 25 26## Common configuration 27 28Both Eglot and LSP Mode can integrate with popular packages in the Emacs 29ecosystem: 30 31* The built-in [`xref`] package provides cross-references. 32* The built-in [Flymake] package provides an on-the-fly diagnostic overlay. 33* [Company] mode displays code completion candidates (with a richer UI than 34 the built-in [`completion-at-point`]). 35 36Eglot provides documentation using the built-in [ElDoc] minor mode, while LSP 37Mode by default provides documentation using its own [`lsp-ui`] mode. 38 39Eglot by default locates the project root using the [`project`] package. In LSP 40Mode, this behavior can be configured using the `lsp-auto-guess-root` setting. 41 42## Configuring LSP Mode 43 44### Loading LSP Mode in `.emacs` 45 46```elisp 47(require 'lsp-mode) 48(add-hook 'go-mode-hook #'lsp-deferred) 49 50;; Set up before-save hooks to format buffer and add/delete imports. 51;; Make sure you don't have other gofmt/goimports hooks enabled. 52(defun lsp-go-install-save-hooks () 53 (add-hook 'before-save-hook #'lsp-format-buffer t t) 54 (add-hook 'before-save-hook #'lsp-organize-imports t t)) 55(add-hook 'go-mode-hook #'lsp-go-install-save-hooks) 56``` 57 58### Configuring `gopls` via LSP Mode 59 60See [settings] for information about available gopls settings. 61 62Stable gopls settings have corresponding configuration variables in `lsp-mode`. 63For example, `(setq lsp-gopls-use-placeholders nil)` will disable placeholders 64in completion snippets. See [`lsp-go`] for a list of available variables. 65 66Experimental settings can be configured via `lsp-register-custom-settings`: 67 68```lisp 69(lsp-register-custom-settings 70 '(("gopls.completeUnimported" t t) 71 ("gopls.staticcheck" t t))) 72``` 73 74Note that after changing settings you must restart gopls using e.g. `M-x 75lsp-restart-workspace`. 76 77## Configuring Eglot 78 79### Configuring `project` for Go modules in `.emacs` 80 81Eglot uses the built-in `project` package to identify the LSP workspace for a 82newly-opened buffer. The `project` package does not natively know about `GOPATH` 83or Go modules. Fortunately, you can give it a custom hook to tell it to look for 84the nearest parent `go.mod` file (that is, the root of the Go module) as the 85project root. 86 87```elisp 88(require 'project) 89 90(defun project-find-go-module (dir) 91 (when-let ((root (locate-dominating-file dir "go.mod"))) 92 (cons 'go-module root))) 93 94(cl-defmethod project-root ((project (head go-module))) 95 (cdr project)) 96 97(add-hook 'project-find-functions #'project-find-go-module) 98``` 99 100### Loading Eglot in `.emacs` 101 102```elisp 103;; Optional: load other packages before eglot to enable eglot integrations. 104(require 'company) 105(require 'yasnippet) 106 107(require 'go-mode) 108(require 'eglot) 109(add-hook 'go-mode-hook 'eglot-ensure) 110 111;; Optional: install eglot-format-buffer as a save hook. 112;; The depth of -10 places this before eglot's willSave notification, 113;; so that that notification reports the actual contents that will be saved. 114(defun eglot-format-buffer-on-save () 115 (add-hook 'before-save-hook #'eglot-format-buffer -10 t)) 116(add-hook 'go-mode-hook #'eglot-format-buffer-on-save) 117``` 118 119### Configuring `gopls` via Eglot 120 121See [settings] for information about available gopls settings. 122 123LSP server settings are controlled by the `eglot-workspace-configuration` 124variable, which can be set either globally in `.emacs` or in a `.dir-locals.el` file in the project root. 125 126`.emacs`: 127```elisp 128(setq-default eglot-workspace-configuration 129 '((:gopls . 130 ((staticcheck . t) 131 (matcher . "CaseSensitive"))))) 132``` 133 134`.dir-locals.el`: 135```elisp 136((nil (eglot-workspace-configuration . ((gopls . ((staticcheck . t) 137 (matcher . "CaseSensitive"))))))) 138``` 139 140### Organizing imports with Eglot 141 142`gopls` provides the import-organizing functionality of `goimports` as an LSP 143code action, which you can invoke as needed by running `M-x eglot-code-actions` 144(or a key of your choice bound to the `eglot-code-actions` function) and 145selecting `Organize Imports` at the prompt. 146 147Eglot does not currently support a standalone function to execute a specific 148code action (see 149[joaotavora/eglot#411](https://github.com/joaotavora/eglot/issues/411)), nor an 150option to organize imports as a `before-save-hook` (see 151[joaotavora/eglot#574](https://github.com/joaotavora/eglot/issues/574)). In the 152meantime, see those issues for discussion and possible workarounds. 153 154## Troubleshooting 155 156Common errors: 157 158* When prompted by Emacs for your project folder, if you are using modules you 159 must select the module's root folder (i.e. the directory with the "go.mod"). 160 If you are using GOPATH, select your $GOPATH as your folder. 161* Emacs must have your environment set properly (PATH, GOPATH, etc). You can 162 run `M-x getenv <RET> PATH <RET>` to see if your PATH is set in Emacs. If 163 not, you can try starting Emacs from your terminal, using [this 164 package][exec-path-from-shell], or moving your shell config from `.bashrc` 165 into `.profile` and logging out and back in. 166* Make sure only one LSP client mode is installed. (For example, if using 167 `lsp-mode`, ensure that you are not _also_ enabling `eglot`.) 168* Look for errors in the `*lsp-log*` buffer or run `M-x eglot-events-buffer`. 169* Ask for help in the `#emacs` channel on the [Gophers slack]. 170 171[LSP Mode]: https://emacs-lsp.github.io/lsp-mode/ 172[Eglot]: https://github.com/joaotavora/eglot/blob/master/README.md 173[`xref`]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html 174[Flymake]: https://www.gnu.org/software/emacs/manual/html_node/flymake/Using-Flymake.html#Using-Flymake 175[Company]: https://company-mode.github.io/ 176[`completion-at-point`]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion-in-Buffers.html 177[ElDoc]: https://elpa.gnu.org/packages/eldoc.html 178[`lsp-ui`]: https://emacs-lsp.github.io/lsp-ui/ 179[`lsp-go`]: https://github.com/emacs-lsp/lsp-mode/blob/master/clients/lsp-go.el 180[`use-package`]: https://github.com/jwiegley/use-package 181[`exec-path-from-shell`]: https://github.com/purcell/exec-path-from-shell 182[settings]: settings.md 183[Gophers slack]: https://invite.slack.golangbridge.org/ 184