Go · vim

Go development with Vim

For Go development there are a plethora of editors available that someone can use for their daily editor, Go has a wiki page that lists editors and plugins that support Go development.

It wasn’t too long ago that there were bitter disputes between programmers on which text editor someone should be using to write code with.

Usenet, mailing lists, IRC, anywhere developers interacted, the mention of editor preference would generate fierce debate that would rage for weeks.

Regardless of which editor a developer chooses, it’s my opinion that the better they are with it, the more they can take advantage of its features, the more productive they become.

My favourite, is vim :)

Why Vim?

First and foremost I want a minimal number of windows on my desktop. I have a web browser or 3 open (one for research, one for entertainment/video streaming, one for social media). And I have a terminal open, split into multiple panes using tmux.

Vim works well in this setup, it’s a command line text editor, like nano, and emacs.

Why Vim with Go?

There are two schools of thought in the vim users world. Keep your vim as close to default as possible, or configure it to suit your needs with plugins and a length ~/.vimrc.

The former group tend to be administrators, who are members of teams that are jumping from one machine to another on a regular basis. Having a highly customised vim setup per machine per administrator doesn’t make for good practice.

The latter group are, like me, people who tend to work on one or two machines, and will be the only people that use the vim on those machines. In my case, for example, that’s my home desktop, and my work laptop.

The key thing to remember when learning your IDE, whatever that may be, is that the knowledge is cumulative. That is, you can look at other peoples’ configurations, like mine, and perhaps be bewildered by the amount of knowledge required to understand everything. But that would be a mistake. For example I have been using vim for a little over 18 years now, and as my primary IDE for around 5 of those. The following a reflection on what I’ve found useful over that time, and will continue to change as time goes by.

To start with Vim as an IDE for Go has been helped immensely by the hard work of Fatih Arslan (and others) with vim-go

But I don’t stop there.

YouCompleteMe and Ctags are no longer a necessary part of development (for Go at least) because of the hard work by the team led by Rebecca Stambler building gopls which is thankfully installed when you install vim-go.

Note: Language Server Protocols, initially created by Microsoft, mean that most IDEs have similar feature sets for specific languages, which is an absolute boon.

go-pls provides code completion, jump to definition, and provides definitions for functions.

The next most used plugin that I have installed has to be vim-commentary, I have the command mapped in my ~/.vimrc such that the line I am on can be (un)commented with the correct comment style for the language being worked on, with a single key command \.

For searching: fzf the fuzzy finder. I use it in conjunction with Ag (aka the Silver Searcher), but there’s nothing stopping it being used with Rg (aka RipGrep).

Occasionally I have use for NerdTree but, in all honesty having set wildmenu configured in my ~/.vimrc means that I don’t use it as much as I once did.

Finally, for now at least, I am learning how to use Tim Pope’s vim-fugitive, a Git plugin.

These plugins all work in conjunction with my ~/.vimrc, which I have already alluded to having influence on the way I do things.

I expect that the comments in the file are enough to understand what’s being done, and why (note: comments are lines that start with double quotes).

" Instruct vim to use the behaviour appropriate for the language being edited.
filetype plugin indent on
filetype on
syntax on

" Load plugins
set runtimepath^=~/.vim/bundle/auto-pairs
set runtimepath^=~/.vim/bundle/junegunn/fzf
set runtimepath^=~/.vim/bundle/junegunn/fzf.vim
set runtimepath^=~/.vim/bundle/nerdtree
set runtimepath^=~/.vim/bundle/vim-fugitive
set runtimepath^=~/.vim/bundle/vim-go
set runtimepath+=~/.fzf

" Indent the next line correctly
set smartindent
" Use 4 spaces for a tab
set tabstop=4
" Set indentation to 4 spaces per block
set shiftwidth=4
" Set the \t character to be 4 spaces
set expandtab
" Show line numbers
set number
" I prefer a dark background, and this ensures that the text is appropriately coloured
set background=dark
"Make lowercase searches case-insensitive, mixed/upper-case case-sensitive
set ignorecase
set smartcase
" Highlight items that match the search
set hlsearch
set incsearch
set clipboard=unnamedplus
set textwidth=80
"Show file name in window header
set title
"Enable ruler (bottom right corner)
set ruler
"Prevent lines breaking in the middle of words
set lbr
"Search down into sub folders
"Provides tab-completion for all file related tasks
set path+=**
"Display all matching files when we tab complete
set wildmenu
" Make whitespace visible. The characters set to represent certain whitespace characters are displayed (but cannot be set during editing) 
set listchars=eol:$,tab:>-,trail:~,extends:>,precedes:<
set list
" Always show the status line
set laststatus=2

" toggle GBlame
" this function (when called) toggles Git blame on/off
function! s:ToggleBlame()
    if &l:filetype ==# 'fugitiveblame'
        close
    else
        Gblame
    endif
endfunction

" Key maps
"Avoid q: typo that pops up the annoying command history box
nnoremap q: :q
" Set \ to (un)comment a line
nnoremap <silent> \ :Commentary<cr>
" Set F2 to run spell checking
nnoremap <F2> :setlocal spell! spelllang=en_us<cr>
" Set F3 to bring Nerdtree on/off
nnoremap <silent> <F3> :NERDTreeToggle<cr>
" Set F5 to show Go test coverage on/off
nnoremap <silent> <F5> :GoCoverageToggle<cr>
" Set F6 to show Git blame info on/off
nnoremap <silent> <F6> :call <sid>ToggleBlame()<cr>
"The following three commands insert different code snippets, and place the cursor at certain points within those snippets, in insert mode, ready to add code to
nnoremap <silent> <F7> :-1r ~/.vim/snippets/goErr<cr>wf{a
nnoremap <silent> <F8> :-1r ~/.vim/snippets/goTest<cr>1jwf{a
nnoremap <silent> <F9> :-1r ~/.vim/snippets/index.html<cr>6jwf>a

" Run go build on save
if !exists("autocommands_loaded")
  let autocommands_loaded = 1
  let g:go_metalinter_autosave=1
  autocmd BufWritePost *.go :GoBuild
endif

" Use golangci-lint as the (go) metalinter
let g:go_metalinter_command='golangci-lint'
" When go fmt is called, (on write) use goimports
let g:go_fmt_command = "goimports"
" Gopls
let g:go_def_mode = "gopls"
let g:go_info_mode = "gopls"
let s:counter = 0
let s:timer = -1

"Comments */
autocmd FileType ruby setlocal commentstring=#\ %s

" mouse support for resizing and copying
set mouse=a
" mouse within screen/tmux
set ttymouse=sgr
" vim8 has popup balloons that can be used for completions and hints
set balloonexpr=go#tool#DescribeBalloon()
set balloondelay=250
set ballooneval
set balloonevalterm

Wow, there’s a lot here already and I’ve not even got to the use of vim that touches my heart. The hotkeys (if you will) that perform actions. Having said that, I think that a dedicated hotkeys post is the better option than to mix in with this post, which has morphed into a setup for Go development post.

So, stay tuned for the next exciting episode :)

Published:
comments powered by Disqus