Last active
April 29, 2022 17:08
-
-
Save pohly/62fb5cb1e2feb06af97fa52e8b790ecd to your computer and use it in GitHub Desktop.
configuring gopls for use with Kubernetes + Emacs over ssh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# In the Kubernetes root, create a k8s-go.work file. | |
(echo "go 1.18"; echo; echo "use ("; find . -name go.mod | grep -v -e '^./vendor' -e '^./_output' | sed -e 's;\(.*\)/go.mod;\t\1;' | sort; echo ")" ) >k8s-go.work | |
# Enable workspace mode by default: | |
ln -s k8s-go.work go.work | |
# Disable workspace mode again: | |
rm go.work | |
# Disable it for some commands which don't work with it: | |
GOWORK=off hack/verify-golangci-lint.sh hack/update-vendor.sh | |
# Make sure that golang.org/x/tools/gopls >= v0.8.0. | |
$ which gopls | |
/usr/local/bin/gopls | |
$ gopls version | |
golang.org/x/tools/gopls v0.8.0 | |
golang.org/x/tools/[email protected] h1:a71KO95TfIvCCMQJrZBSQIGQ9lkc0kWL+dSlEdZd7HI= | |
# In .emacs on a different host: | |
;; https://github.com/golang/tools/blob/master/gopls/doc/emacs.md#configuring-lsp-mode | |
(require 'lsp-mode) | |
(add-hook 'go-mode-hook #'lsp-deferred) | |
(defun lsp-go-install-save-hooks () | |
(add-hook 'before-save-hook #'lsp-format-buffer t t) | |
(add-hook 'before-save-hook #'lsp-organize-imports t t)) | |
(add-hook 'go-mode-hook #'lsp-go-install-save-hooks) | |
;; https://github.com/golang/tools/blob/master/gopls/doc/emacs.md#configuring-gopls-via-lsp-mode | |
(lsp-register-custom-settings | |
'( | |
;; https://github.com/golang/tools/blob/master/gopls/doc/workspace.md#workspace-module-experimental | |
;; Superseeded by https://go.googlesource.com/proposal/+/master/design/45713-workspace.md in Go 1.18 | |
;; ("gopls.experimentalWorkspaceModule" t t) | |
)) | |
;; avoid running gopls through tramp, it seems unstable | |
;; | |
;; https://github.com/emacs-lsp/lsp-mode/issues/2709#issuecomment-860753973 | |
(defun lsp-tramp-connection-over-ssh-port-forwarding () | |
"Like lsp-tcp-connection, but uses SSH portforwarding." | |
(list | |
:connect (lambda (filter sentinel name environment-fn) | |
(let* ((host "localhost") | |
;; PO: passing the command via a function parameter didn't work? | |
(command (cons "gopls" lsp-gopls-server-args)) | |
(_ (message "[tcp/ssh hack connect] running LSP %s " command)) | |
(lsp-port (lsp--find-available-port host (cl-incf lsp--tcp-port))) | |
(command (with-parsed-tramp-file-name buffer-file-name nil | |
(message "[tcp/ssh hack] running LSP %s on %s / %s" command host localname) | |
(let* ((unix-socket (format "/tmp/lsp-ssh-portforward-%s.sock" lsp-port)) | |
(command (list | |
"ssh" | |
;; "-vvv" | |
"-L" (format "%s:%s" lsp-port unix-socket) | |
host | |
"socat" | |
(format "unix-listen:%s" unix-socket) | |
(format "system:'\"cd %s && %s\"'" (file-name-directory localname) command) | |
))) | |
(message "using local command %s" command) | |
command))) | |
(final-command (if (consp command) command (list command))) | |
(_ (unless (executable-find (cl-first final-command)) | |
(user-error (format "Couldn't find executable %s" (cl-first final-command))))) | |
(process-environment | |
(lsp--compute-process-environment environment-fn)) | |
(proc (make-process :name name :connection-type 'pipe :coding 'no-conversion | |
:command final-command :sentinel sentinel :stderr (format "*%s::stderr*" name) :noquery t)) | |
(tcp-proc (progn | |
(sleep-for 1) ; prevent a connection before SSH has run socat. Ugh. | |
(lsp--open-network-stream host lsp-port (concat name "::tcp"))))) | |
;; TODO: Same :noquery issue (see above) | |
(set-process-query-on-exit-flag proc nil) | |
(set-process-query-on-exit-flag tcp-proc nil) | |
(set-process-filter tcp-proc filter) | |
(cons tcp-proc proc))) | |
:test? (lambda () t))) | |
(lsp-register-client | |
(make-lsp-client :new-connection (lsp-tramp-connection-over-ssh-port-forwarding) | |
:major-modes '(go-mode) | |
:remote? t | |
:server-id 'gopls-remote)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment