Introducing gogetdoc, a tool for providing Go documentation to editors

I really enjoy Go’s approach to documentation. The conventions are simple (and almost obvious), and the tooling around them is great. If you’re not familiar with Godoc, I’d recommend reading the Go team’s official blog post on the topic.

Why Another Tool?

There are no shortage of tools available for looking up Go documentation, but many of these tools lack a good interface for editor integration.

For example, the go doc tool is very easy to use from the command line:

go doc io            # get doc for package io
go doc io Writer     # get doc for io.Writer interface
go doc fmt.Println   # get doc for Println func in package fmt

Modern IDEs typically provide functionality that allows the user select some source code and get documentation for their selection. There are several editors that provide similar features for Go development, but these tools are forced to use sub-optimal workarounds due to go doc’s interface. Additionally, since each editor comes up with its own tricks, the capabilities and results from different editors differ drastically.

The problem with the command line interface is that it is intended to be used by a human who knows what they are looking for. This makes the editor responsible for figuring out what the user is looking for, which turns out to be harder than you’d think.

Let’s look at a few popular editors for Go devleopment.

Vim-Go

Vim-Go uses a clever approach - it adds the ‘.’ character to the list of characters that can appear in a word, and then gets the word under the cursor. For example, this would return fmt.Println as a single word. This word is then split at the ‘.’, giving you one or two tokens to pass to go doc.

This approach works in a lot of cases. Several months ago I attempted to add documentation support to the go-plus Atom package using this technique. I quickly realized that there are a lot of special cases that this approach cannot handle.

For example, if you attempt to get the documentation for a method call on a variable, you’d end up passing a variable name to the go doc tool, which won’t work.

Vim-Go method call

Similarly, documentation for struct fields will end up using a variable name as a package name:

Vim-Go struct field

If you import a package under a different name, you’ll end up giving go doc a package it doesn’t know about.

Vim-Go package alias

Sublime Text (GoSublime)

I’m not too familiar with how GoSublime works, but I was able to fire it up and give it a try. I found that the documentation support worked quite well, even for several of the cases that failed with Vim-Go.

Unfortunately, method calls still didn’t work.

GoSublime method call

gogetdoc Features

Hopefully by now you’re convinced that there’s room for improvement in this area.

I’ve been working on a tool that uses the go/types packge to identify the item under the cursor and get documentation for it.

gogetdoc has a simple command line interface that accepts a file and (byte) position, similar to many other Go tools:

$ gogetdoc -pos $GOROOT/src/fmt/format.go:#6272
func unicode/utf8.RuneCountInString(s string) (n int)

RuneCountInString is like RuneCount but its input is a string.

It can provide documentation for:

Update!

gogetdoc has seen a few great contributions over the past week, including:

Additionally, both vim-go and Emacs have started adding support for the tool!

Atom Plugin

I put together a rudimentary Atom package in order to demonstrate the features of this tool. You can find it at https://atom.io.packages/godoc. Make sure to install the tool first: go get -u github.com/zmb3/gogetdoc. (Note that gogetdoc requires Go 1.6 to build - this is due to some minor API differences between golang.org/x/tools/go/types and go/types.)

Here are a few screenshots of it in action.

Package documentation from import specs:

Atom package doc

Constants, including their value:

Atom constants

Method calls:

Atom method call

Imports under a different name:

Atom import alias

Struct fields:

Atom struct field

Contributions/Roadmap

These tools aren’t quite ready for prime time, but I don’t think they’re too far off. If you enjoy working on tools to help other developers, I’d love your help. The gogetdoc tool and the Atom package could both use some love.

I’m particularly interested in the following:

For gogetdoc, I would like to implement more structured output. In it’s current form, editors really only have one choice - to display the tool’s output verbatim. If the tool were able to output JSON, for example, it could provide a title, object type (func, var, package, const, etc.), and the documentation separately. This would give editors a little more flexibility as to how to design their UI. Other examples of different output formats include HTML or even Go template language.

Additionally, anything that improves performance would be a welcome addition. I’ve found the performance acceptable so far, but I haven’t tried it on very large projects.

The godoc Atom package could use a UI overhaul. My frontend skills aren’t very good. I’d love to see a nicer tooltip window with scrollbars and a close icon to dismiss it.