vseledkin
4/6/2017 - 3:14 PM

Setting up Vim as your Go IDE

Setting up Vim as your Go IDE

Setting up Vim as your Go IDE

Intro

I've been wanting to do a serious project in Go. One thing holding me back has been a my working environment. As a huge PyCharm user, I was hoping the Go IDE plugin for IntelliJ IDEA would fit my needs. However, it never felt quite right. After a previous experiment a few years ago using Vim, I knew how powerful it could be if I put in the time to make it so. Luckily there are plugins for almost anything you need to do with Go or what you would expect form and IDE. While this is no where near comprehensive, it will get you writing code, building and testing with the power you would expect from Vim.

Getting Started

I'm assuming you're coming with a clean slate. For me this was OSX so I used MacVim. There is nothing in my config files that assumes this is the case.

We're going to need a version of Vim 7.4 with lua support.

brew install macvim --with-cscope --with-lua

While we're at it, let's replace our command line Vim with one that has lua support as well.

brew install vim --with-lua --override-system-vim

Now most of my .vimrc is from this fantastic repo. However, my fork makes a few changes.

  • Updated plugins to their latest and greatest
  • A quick bugfix for Vim 7.4 support in vim-zenroom2
  • Changed file explorer from NERDTree to netrw
  • Added neocomplete for autocompletion
  • Changes from vim-golang to vim-go
  • Updated taglist.vim to understand Go

Following their instructions, you can get this going with two commands.

git clone git://github.com/cridenour/vimrc.git ~/.vim_runtime
sh ~/.vim_runtime/install_awesome_vimrc.sh

Changes Explained

I didn't want to change from the default .vimrc from amix's repo without reason as they have great reasons for each of their plugin choices.

vim-zenroom2 Bugfix

Using the latest release of Vim 7.4 meant an incompatibility with zenroom2, mainly the names of their functions. I followed a pull request that has yet to make it upstream in the project.

NERDTree -> netrw

NERDTree is a fantastic plugin but does not allow you to keep it open in a split window. Using netrw, I can use a split window to always show the file structure and even manage the window that the files open in.

Add neocomplete

There are lots of competing autocomplete, including stock Vim. However, using Ctrl-X Ctrl-O was more of an interruption than anything. Neocomplete was fast (with lua) and highly configurable.

Vim-golang -> Vim-go

Vim-golang is a mirror of the stock files provided with Go. Vim-go provides autocomplete support, ability to go to the documention, gofmt on save and more. Integrates nicely with neocomplete.

Mappings

I use some default mappings for neocomplete as well as some Vim-go mappings. These should go in your ~/.vim_runtime/my_configs.vim

 " Disable AutoComplPop.
 let g:acp_enableAtStartup = 0
 " Use neocomplete.
 let g:neocomplete#enable_at_startup = 1
 " Use smartcase.
 let g:neocomplete#enable_smart_case = 1
 " Set minimum syntax keyword length.
 let g:neocomplete#sources#syntax#min_keyword_length = 3
 
 " Plugin key-mappings.
 inoremap <expr><C-g>     neocomplete#undo_completion()
 inoremap <expr><C-l>     neocomplete#complete_common_string()
 
 " Recommended key-mappings.
 " <CR>: close popup and save indent.
 inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
 function! s:my_cr_function()
     return neocomplete#close_popup() . "\<CR>"
 endfunction
 " <TAB>: completion.
 inoremap <expr><TAB>  pumvisible() ? "\<C-n>" : "\<TAB>"
 " <C-h>, <BS>: close popup and delete backword char.
 inoremap <expr><C-h> neocomplete#smart_close_popup()."\<C-h>"
 inoremap <expr><BS> neocomplete#smart_close_popup()."\<C-h>"
 inoremap <expr><C-y>  neocomplete#close_popup()
 inoremap <expr><C-e>  neocomplete#cancel_popup()
 
 " Go related mappings
 au FileType go nmap <Leader>i <Plug>(go-info)
 au FileType go nmap <Leader>gd <Plug>(go-doc)
 au FileType go nmap <Leader>r <Plug>(go-run)
 au FileType go nmap <Leader>b <Plug>(go-build)
 au FileType go nmap <Leader>t <Plug>(go-test)
 au FileType go nmap gd <Plug>(go-def-tab)

The most used are ,r for running the current file, ,t for testing the current package, ,gd for reading the documentation.

Getting Go Structure with ctags

Using ctags can provide structure information to use with taglist, provided in our vimrc. This is a big part of how I use an IDE and I wanted it to work with Go. Unfortunately, all the versions I could find did not come with Go tags. It took some searching to find exactly what I needed to get this working.

First you need to set up ctags to understand Go. You can do this with a configuration file at ~/.ctags

--langdef=Go
--langmap=Go:.go
--regex-Go=/func([ \t]+\([^)]+\))?[ \t]+([a-zA-Z0-9_]+)/\2/f,func/
--regex-Go=/var[ \t]+([a-zA-Z_][a-zA-Z0-9_]+)/\1/v,var/
--regex-Go=/type[ \t]+([a-zA-Z_][a-zA-Z0-9_]+)/\1/t,type/

I also had to update taglist.vim. If you start from my fork, this is done for you.

" go language
let s:tlist_def_go_settings = 'go;g:enum;s:struct;u:union;t:type;' .
                           \ 'v:variable;f:function'

Setting up the IDE windows

I wanted to use Vim as normal in most cases, but when I need my IDE, I can hit ,, and get the windows I need. A file explorer set to open all files in the main buffer window, a tag list of the current file and your main buffer.

This will also go in your ~/.vim_runtime/my_configs.vim

 " Netrw Style Listing
 let g:netrw_liststyle = 3
 
 nnoremap <Leader><Leader> :Tlist<CR><C-W>h<C-W>s:e .<CR><C-W>l:let g:netrw_chgwin=winnr()<CR><C-W>h

Summary

This setup works for me, but might not for you. Hopefully you can use this as a starting point.