Remote Editing Go Code With Emacs

I’ve been in an uncomfortable place for a while: these days I primarily write Go code, but on a machine where I don’t have a Go toolchain (don’t ask). As a result, I basically SSH/tmux into a dev machine and do my work like that. When the conditions are optimal that’s ok-ish, but each network lag or brief disconnection makes itself highly visible, and it’s just not great.

Also, that forces me to use a different Emacs instance than the one I use for the rest of my regular activities, which is yet another annoyance I could easily live without.

Of course Emacs has some support for that, namely TRAMP, which allows not only for editing but also running tools on the remote side “transparently”. That’s great, except that most Go-related Emacs modules I came to rely upon don’t work that well with TRAMP right now. Long story short, they all use variants of call-process instead of the TRAMP-aware process-file (which of course is no drop-in replacement either).

And so I’ve been silently suffering until today, when the magical combination of will and time (yay, holidays !) appeared, and I started hacking my way around the issue.

Tackled so far:

  • go-eldoc (inline documentation for Go functions) here
  • git-gutter+ (git helper, not Go specific) here
  • company-go (Go completion, plus documentation access) here and there
  • go-mode (top-level glue, including godef and gofmt) here and there

Note that for this last one I took a shortcut for gofmt and moved it from a before-write-hook to an after-write-hook: I’m not entirely sure what this dance with patches is about, seems simpler to just modify the file in place, and it’s way easier to handle remotely

So now at least I have the basics working. There’s definitely more, but nothing critical for me at least.

Oh and since I’m using spacemacs, the final integration looks like:

(defun dotspacemacs/layers ()
  (setq-default
...
   dotspacemacs-additional-packages 
   `(
     (company-go :location 
                 (recipe :repo "sigma/gocode"
                         :fetcher github
                         :files ("emacs-company/company-go.el")
                         :version-regexp "v\\.\\(.*\\)"))
     (go-eldoc :location 
               (recipe :fetcher github
                       :repo "sigma/emacs-go-eldoc"))
     (git-gutter+ :location 
                  (recipe :fetcher github
                          :repo "sigma/git-gutter-plus"))
     (go-mode :location 
              (recipe :fetcher github
                      :repo "sigma/go-mode.el"
                      :files ("go-mode.el")))
    )
...))

After I convince myself that this is all working as intended, I shall clean up those patches and propose them for upstream inclusion. In the meantime, it’s probably time to stop shaving that yak and actually work on the code I wanted to write :).