Closed4

[WIP] VimでGoを書く環境を作る

sh05sh05

目指すこと

  • importしているライブラリの補完が出る
    • go mod tidyでインストールされたやつら(正しい表現が分からなかった)も含めて
  • 型を宣言しているところに飛べる
  • そのほかこまごましたこともやる

やらないこと

  • プラグイン開発

開始時の情報

Vim

入っていたVim

$ vim --version
VIM - Vi IMproved 9.0 (2022 Jun 28, compiled Dec 20 2023 18:58:31)
macOS version - arm64
Included patches: 1-2136
Compiled by root@apple.com
Normal version without GUI.  Features included (+) or not (-):
+acl               +file_in_path      +mouse_urxvt       -tag_any_white
-arabic            +find_in_path      +mouse_xterm       -tcl
+autocmd           +float             +multi_byte        +termguicolors
+autochdir         +folding           +multi_lang        +terminal
-autoservername    -footer            -mzscheme          +terminfo
-balloon_eval      +fork()            +netbeans_intg     +termresponse
-balloon_eval_term -gettext           +num64             +textobjects
-browse            -hangul_input      +packages          +textprop
++builtin_terms    +iconv             +path_extra        +timers
+byte_offset       +insert_expand     -perl              +title
+channel           +ipv6              +persistent_undo   -toolbar
+cindent           +job               +popupwin          +user_commands
-clientserver      +jumplist          +postscript        -vartabs
+clipboard         -keymap            +printer           +vertsplit
+cmdline_compl     +lambda            -profile           +vim9script
+cmdline_hist      -langmap           -python            +viminfo
+cmdline_info      +libcall           -python3           +virtualedit
+comments          +linebreak         +quickfix          +visual
+conceal           +lispindent        +reltime           +visualextra
+cryptv            +listcmds          -rightleft         +vreplace
+cscope            +localmap          -ruby              +wildignore
+cursorbind        -lua               +scrollbind        +wildmenu
+cursorshape       +menu              +signs             +windows
+dialog_con        +mksession         +smartindent       +writebackup
+diff              +modify_fname      -sodium            -X11
+digraphs          +mouse             -sound             -xattr
-dnd               -mouseshape        +spell             -xfontset
-ebcdic            +mouse_dec         +startuptime       -xim
-emacs_tags        -mouse_gpm         +statusline        -xpm
+eval              -mouse_jsbterm     -sun_workshop      -xsmp
+ex_extra          +mouse_netterm     +syntax            -xterm_clipboard
+extra_search      +mouse_sgr         +tag_binary        -xterm_save
-farsi             -mouse_sysmouse    -tag_old_static
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H   -DMACOS_X_UNIX  -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: gcc   -L/usr/local/lib -o vim        -lm -lncurses  -liconv -framework Cocoa

Go

asdfでGoを入れる、途中の出力は割愛
https://asdf-vm.com/

$ asdf plugin add golang
$ asdf install golang 1.22.0
$ asdf global golang 1.22.0
$ go version
go version go1.22.0 darwin/arm64
sh05sh05

適当なGoのコードを準備

とりあえずGinにする、READMEにあるexample.goをもらう
https://github.com/gin-gonic/gin

$ mkdir hello-gin
$ cd hello-gin/
$ vim example.go  # READMEのexample.goをコピペ
$ go run example.go # とりあえず実行
example.go:6:3: no required module provides package github.com/gin-gonic/gin: go.mod file not found in current directory or any parent directory; see 'go help modules'
$ go mod init hello-gin
go: creating new go.mod: module hello-gin
go: to add module requirements and sums:
        go mod tidy
$ go mod tidy
-- 割愛 --
$ go run example.go # 動く
-- 割愛 --
sh05sh05

今回育てていくvimrcを作成&指定してVimを起動

$ touch .vimrc-for-golang
$ vim example.go -u .vimrc-for-golang # 白文字であることを確認

自分なりの最低限を用意

基本設定

(既存のvimrcから持ってきたから変なのもありそう)

.vimrc-for-golang
" ファイル読み込み時の文字コードの設定
set encoding=utf-8
" 保存時の文字コード
set fileencoding=utf-8
" 改行コードの自動判別. 左側が優先される
set fileformats=unix,dos,mac
" □や○文字が崩れる問題を解決
set ambiwidth=double
" タブ入力を複数の空白入力に置き換える
set expandtab
" 改行時に前の行のインデントを継続する
set autoindent
" 改行時に前の行の構文をチェックし次の行のインデントを増減する
set smartindent
" smartindentで増減する幅
set shiftwidth=2
" 行番号を表示
set number
" インクリメンタルサーチ. 1文字入力毎に検索を行う
set incsearch
" 検索パターンに大文字小文字を区別しない
set ignorecase
" 検索パターンに大文字を含んでいたら大文字小文字を区別する
set smartcase
" 検索結果をハイライト
set hlsearch
" バックスペースキーの有効化 https://vim-jp.org/vimdoc-ja/options.html#'backspace'
set backspace=indent,eol,start
" カーソルラインをハイライト
set cursorline
" 括弧の対応関係を一瞬表示する
set showmatch
" Vimの「%」を拡張する
source $VIMRUNTIME/macros/matchit.vim
" コマンドモードの補完
set wildmenu
" netrwのvで開く方向を右にする
let g:netrw_altv = 1
" netrwのoで開く方向を右にする
let g:netrw_alto = 1
" netrwのEnterでPと同じにする
let g:netrw_browse_split = 4
" ファイルタイプ検出してインデントを有効化 https://vim-jp.org/vimdoc-ja/filetype.html
filetype plugin indent on
" 色 https://vim-jp.org/vimdoc-ja/syntax.html
syntax on
set background=dark
" コードの折り畳み関連 最初は展開されている状態にする
set foldmethod=indent
set foldcolumn=4
autocmd BufRead * normal zR
highlight Folded guibg=grey guifg=blue
highlight FoldColumn guibg=darkgrey guifg=white

これを指定して起動

$ touch .vimrc-for-golang
$ vim example.go -u .vimrc-for-golang # 見た目が変わっていることを確認

プラグインマネージャー

dein.vimに下記のようにあったので

Note: Active developement on dein.vim has stopped. The only future changes will be bug fixes.

これを機にdpp.vimにしようかと思ったが試行錯誤を前提としていそうで、一応本分はGo開発環境なのでdein.vimにする
(何気にVimのバージョンもあってない)

.vimrc-for-golangに追記
" プラグインがキャッシュされるディレクトリ 本当は'~/.cache/'が良いと思う
let $CACHE = expand('.cache')
if !($CACHE->isdirectory())
  call mkdir($CACHE, 'p')
endif
if &runtimepath !~# '/dein.vim'
  let s:dir = 'dein.vim'->fnamemodify(':p')
  if !(s:dir->isdirectory())
    let s:dir = $CACHE .. '/dein/repos/github.com/Shougo/dein.vim'
    if !(s:dir->isdirectory())
      execute '!git clone https://github.com/Shougo/dein.vim' s:dir
    endif
  endif
  execute 'set runtimepath^='
        \ .. s:dir->fnamemodify(':p')->substitute('[/\\]$', '', '')
endif

let s:dein_dir = $CACHE . expand('/dein')
if dein#load_state(s:dein_dir)
  call dein#begin(s:dein_dir)

  " プラグインを記述するtomlファイル
  let g:rc_dir    = expand('.vim/rc')
  let s:toml      = g:rc_dir . '/dein.toml'
  call dein#load_toml(s:toml,      {'lazy': 0})
  let s:lazy_toml = g:rc_dir . '/dein_lazy.toml'
  call dein#load_toml(s:lazy_toml, {'lazy': 1})

  call dein#end()
  call dein#save_state()
endif

" インストールチェック
if dein#check_install()
  call dein#install()
endif

let s:removed_plugins = dein#check_clean()
if len(s:removed_plugins) > 0
  call map(s:removed_plugins, "delete(v:val, 'rf')")
  call dein#recache_runtimepath()
endif
sh05sh05

一旦こうなった(仮コピペ)
コメントアウトのやつとか括弧の対応合わせてくれるやつとかはまだ入れていない
あとdefxのためにPython3を有効にしなきゃいけない

.vimrc-for-golang
set nocompatible

" プラグインがキャッシュされるディレクトリ 本当は'~/.cache/'が良いと思うがこの記事での作業だけカレントディレクトリにする
let $CACHE = expand('.cache')
if !($CACHE->isdirectory())
  call mkdir($CACHE, 'p')
endif
if &runtimepath !~# '/dein.vim'
  let s:dir = 'dein.vim'->fnamemodify(':p')
  if !(s:dir->isdirectory())
    let s:dir = $CACHE .. '/dein/repos/github.com/Shougo/dein.vim'
    if !(s:dir->isdirectory())
      execute '!git clone https://github.com/Shougo/dein.vim' s:dir
    endif
  endif
  execute 'set runtimepath^='
        \ .. s:dir->fnamemodify(':p')->substitute('[/\\]$', '', '')
endif

let s:dein_dir = $CACHE . expand('/dein')
if dein#load_state(s:dein_dir)
  call dein#begin(s:dein_dir)

  " プラグインを記述するtomlファイル
  let g:rc_dir    = expand('.vim/rc')
  let s:toml      = g:rc_dir . '/dein.toml'
  call dein#load_toml(s:toml,      {'lazy': 0})
  let s:lazy_toml = g:rc_dir . '/dein_lazy.toml'
  call dein#load_toml(s:lazy_toml, {'lazy': 1})

  call dein#end()
  call dein#save_state()
endif

" インストールチェック
if dein#check_install()
  call dein#install()
endif

let s:removed_plugins = dein#check_clean()
if len(s:removed_plugins) > 0
  call map(s:removed_plugins, "delete(v:val, 'rf')")
  call dein#recache_runtimepath()
endif

" ファイル読み込み時の文字コードの設定
set encoding=utf-8
" 保存時の文字コード
set fileencoding=utf-8
" Vim script内でマルチバイト文字を使う場合の設定
scriptencoding utf-8
" 改行コードの自動判別. 左側が優先される
set fileformats=unix,dos,mac
" □や○文字が崩れる問題を解決
set ambiwidth=double
" クリップボードを共有
set clipboard+=unnamed
" タブ入力を複数の空白入力に置き換える
set expandtab
" 画面上でタブ文字が占める幅
set tabstop=2
" 改行時に前の行のインデントを継続する
set autoindent
" 改行時に前の行の構文をチェックし次の行のインデントを増減する
set smartindent
" smartindentで増減する幅
set shiftwidth=2
" 行番号を表示
set number
" インクリメンタルサーチ. 1文字入力毎に検索を行う
set incsearch
" 検索パターンに大文字小文字を区別しない
set ignorecase
" 検索パターンに大文字を含んでいたら大文字小文字を区別する
set smartcase
" 検索結果をハイライト"
set hlsearch
" バックスペースキーの有効化 https://vim-jp.org/vimdoc-ja/options.html#'backspace'
set backspace=indent,eol,start
" カーソルラインをハイライト
set cursorline
" 保存するコマンド履歴の数
set history=20
" 括弧の対応関係を一瞬表示する
set showmatch
" Vimの「%」を拡張する
source $VIMRUNTIME/macros/matchit.vim
" コマンドモードの補完
set wildmenu
" netrwのvで開く方向を右にする
let g:netrw_altv = 1
" netrwのoで開く方向を右にする
let g:netrw_alto = 1
" netrwのEnterでPと同じにする
let g:netrw_browse_split = 4
" ファイルタイプ検出してインデントを有効化 https://vim-jp.org/vimdoc-ja/filetype.html
filetype plugin indent on
" 色セット https://vim-jp.org/vimdoc-ja/syntax.html
syntax on
set background=dark
" コードの折り畳み関連
" 最初は展開されている状態にする
set foldmethod=indent
set foldcolumn=4
autocmd BufRead * normal zR
highlight Folded guibg=grey guifg=blue
highlight FoldColumn guibg=darkgrey guifg=white
" jj
inoremap <silent> jj <ESC>
" colorscheme deinのhookだとうまくいかない"
" colorscheme onedark
" colorscheme spaceduck
" colorscheme spacecamp
colorscheme PaperColor

let g:lightline#bufferline#show_number  = 1
let g:lightline#bufferline#shorten_path = 0

hi Pmenu ctermfg=145 ctermbg=239 guifg=#ABB2BF guibg=#3E4452
" hi Pmenu ctermfg=236 ctermbg=39 guifg=#2C323C guibg=#61AFEF
" hi PmenuSel ctermfg=39 ctermbg=236 guifg=#61AFEF guibg=#2C323Cj
.vim/rc/dein.toml
# プラグイン管理
[[plugins]]
repo = 'Shougo/dein.vim'

# 色
[[plugins]]
repo = 'sheerun/vim-polyglot'
[[plugins]]
repo = 'pineapplegiant/spaceduck'
hook_add = """
if exists('+termguicolors')
let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
set termguicolors
endif

" let g:lightline = {
"  \ 'colorscheme': 'spaceduck',
"  \ }
"""
[[plugins]]
repo = 'jaredgorski/spacecamp'
[[plugins]]
repo = 'NLKNguyen/papercolor-theme'
hook_add = """
let g:lightline = {
  \ 'colorscheme': 'PaperColor',
  \ }
"""
[[plugins]]
repo = 'joshdick/onedark.vim'
hook_add = """
" let g:lightline = {
"   \ 'colorscheme': 'onedark',
"   \ }
"""
[[plugins]]
repo = 'itchyny/lightline.vim'
# [[plugins]]
# repo = 'mengelbrecht/lightline-bufferline'

# LSPクライアント
[[plugins]]
repo = 'prabirshrestha/vim-lsp'
hook_add = """
highlight lspReference ctermfg=red guifg=red ctermbg=green guibg=green

function! s:on_lsp_buffer_enabled() abort
    setlocal omnifunc=lsp#complete
    setlocal signcolumn=yes
    if exists('+tagfunc') | setlocal tagfunc=lsp#tagfunc | endif
    nmap <buffer> gc <plug>(lsp-code-action)
    nmap <buffer> gC <plug>(lsp-code-action-float)
    nmap <buffer> gd <plug>(lsp-definition)
    nmap <buffer> gs <plug>(lsp-document-symbol-search)
    nmap <buffer> gS <plug>(lsp-workspace-symbol-search)
    nmap <buffer> gr <plug>(lsp-references)
    nmap <buffer> gi <plug>(lsp-implementation)
    nmap <buffer> gt <plug>(lsp-type-definition)
    nmap <buffer> <leader>rn <plug>(lsp-rename)
    nmap <buffer> [g <plug>(lsp-previous-diagnostic)
    nmap <buffer> ]g <plug>(lsp-next-diagnostic)
    nmap <buffer> K <plug>(lsp-hover)
    nnoremap <buffer> <expr><c-f> lsp#scroll(+4)
    nnoremap <buffer> <expr><c-d> lsp#scroll(-4)

    let g:lsp_format_sync_timeout = 1000
    autocmd! BufWritePre *.rs,*.go call execute('LspDocumentFormatSync')
endfunction

augroup lsp_install
    au!
    " call s:on_lsp_buffer_enabled only for languages that has the server registered.
    autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
augroup END
"""

# LSPの設定を楽にする
[[plugins]]
repo = 'mattn/vim-lsp-settings'
hook_add = """
let g:lsp_settings = {}
let g:lsp_settings['gopls'] = {
  \  'workspace_config': {
  \    'usePlaceholders': v:true,
  \    'analyses': {
  \      'fillstruct': v:true,
  \    },
  \  },
  \  'initialization_options': {
  \    'usePlaceholders': v:true,
  \    'analyses': {
  \      'fillstruct': v:true,
  \    },
  \  },
  \}
"""

# 補完
[[plugins]]
repo = 'prabirshrestha/asyncomplete.vim'

# 補完(LSPクライアント連携)
[[plugins]]
repo = 'prabirshrestha/asyncomplete-lsp.vim'

# ファイラ
[[plugins]]
repo = 'Shougo/defx.nvim'
hook_add = """
autocmd VimEnter * execute 'Defx'
autocmd BufWritePost * call defx#redraw()
autocmd BufEnter * call defx#redraw()
autocmd FileType defx call s:defx_my_settings()
function! s:defx_my_settings() abort
  " Define mappings
  nnoremap <silent><buffer><expr> <CR>
  \ defx#is_directory() ?
  \ defx#do_action('open_tree', 'toggle') :
  \ defx#do_action('drop')
  nnoremap <silent><buffer><expr> c
  \ defx#do_action('copy')
  nnoremap <silent><buffer><expr> m
  \ defx#do_action('move')
  nnoremap <silent><buffer><expr> p
  \ defx#do_action('paste')
  nnoremap <silent><buffer><expr> l
  \ defx#do_action('drop')
  nnoremap <silent><buffer><expr> E
  \ defx#do_action('drop', 'vsplit')
  nnoremap <silent><buffer><expr> P
  \ defx#do_action('preview')
  nnoremap <silent><buffer><expr> o
  \ defx#do_action('open_tree', 'toggle')
  nnoremap <silent><buffer><expr> K
  \ defx#do_action('new_directory')
  nnoremap <silent><buffer><expr> N
  \ defx#do_action('new_file')
  nnoremap <silent><buffer><expr> M
  \ defx#do_action('new_multiple_files')
  nnoremap <silent><buffer><expr> C
  \ defx#do_action('toggle_columns',
  \                'mark:indent:icon:filename:type:size:time')
  nnoremap <silent><buffer><expr> S
  \ defx#do_action('toggle_sort', 'time')
  nnoremap <silent><buffer><expr> d
  \ defx#do_action('remove')
  nnoremap <silent><buffer><expr> r
  \ defx#do_action('rename')
  nnoremap <silent><buffer><expr> !
  \ defx#do_action('execute_command')
  nnoremap <silent><buffer><expr> x
  \ defx#do_action('execute_system')
  nnoremap <silent><buffer><expr> yy
  \ defx#do_action('yank_path')
  nnoremap <silent><buffer><expr> .
  \ defx#do_action('toggle_ignored_files')
  nnoremap <silent><buffer><expr> ;
  \ defx#do_action('repeat')
  nnoremap <silent><buffer><expr> h
  \ defx#do_action('cd', ['..'])
  nnoremap <silent><buffer><expr> ~
  \ defx#do_action('cd')
  nnoremap <silent><buffer><expr> q
  \ defx#do_action('quit')
  nnoremap <silent><buffer><expr> <Space>
  \ defx#do_action('toggle_select') . 'j'
  nnoremap <silent><buffer><expr> *
  \ defx#do_action('toggle_select_all')
  nnoremap <silent><buffer><expr> j
  \ line('.') == line('$') ? 'gg' : 'j'
  nnoremap <silent><buffer><expr> k
  \ line('.') == 1 ? 'G' : 'k'
  nnoremap <silent><buffer><expr> <C-l>
  \ defx#do_action('redraw')
  nnoremap <silent><buffer><expr> <C-g>
  \ defx#do_action('print')
  nnoremap <silent><buffer><expr> cd
  \ defx#do_action('change_vim_cwd')
endfunction

function! Root(path) abort
  return fnamemodify(a:path, ':t')
endfunction

call defx#custom#source('file', {
     \ 'root': 'Root',
     \})

"""

# defxの依存
[[plugins]]
repo = 'roxma/nvim-yarp'
[[plugins]]
repo = 'roxma/vim-hug-neovim-rpc'

# defxのicon
[[plugins]]
repo = 'ryanoasis/vim-devicons'
[[plugins]]
repo = 'kristijanhusak/defx-icons'
hook_add = """
call defx#custom#option('_', {
  \ 'winwidth': 40,
  \ 'split': 'vertical',
  \ 'direction': 'topleft',
  \ 'show_ignored_files': 1,
  \ 'buffer_name': 'exproler',
  \ 'toggle': 1,
  \ 'resume': 1,
  \ 'columns': 'mark:git:indent:icons:filename',
  \ })
"""

[[plugins]]
repo = 'kristijanhusak/defx-git'
hook_add = """
call defx#custom#column('git', 'indicators', {
  \ 'Modified'  : '!',
  \ 'Staged'    : '✚',
  \ 'Untracked' : '✭',
  \ 'Renamed'   : '➜',
  \ 'Unmerged'  : '═',
  \ 'Ignored'   : '☒',
  \ 'Deleted'   : '✖',
  \ 'Unknown'   : '?'
  \ })
call defx#custom#column('git', 'column_length', 1)
nnoremap <buffer><silent> [c <Plug>(defx-git-prev)
nnoremap <buffer><silent> ]c <Plug>(defx-git-next)
nnoremap <buffer><silent> ]a <Plug>(defx-git-stage)
nnoremap <buffer><silent> ]r <Plug>(defx-git-reset)
nnoremap <buffer><silent> ]d <Plug>(defx-git-discard)
"""

[[plugins]]
repo = 'junegunn/fzf'
build = './install --bin'
merged = '0'

[[plugins]]
repo = 'junegunn/fzf.vim'
depends = 'fzf'
hook_add = '''
nnoremap <silent> <Leader>f :Files<CR>
nnoremap <silent> <Leader>F :GFiles?<CR>
nnoremap <silent> <Leader>b :Buffers<CR>
nnoremap <silent> <Leader>l :BLines<CR>
nnoremap <silent> <Leader>h :History<CR>
nnoremap <silent> <Leader>m :Mark<CR>
nnoremap <silent> <Leader>c :Commands<CR>
command! -bang -nargs=* Rg
  \ call fzf#vim#grep(
  \   'rg --line-number --no-heading '.shellescape(<q-args>), 0,
  \   fzf#vim#with_preview({'options': '--exact --reverse'}, 'right:50%:wrap'))
'''
.vim/rc/dein.toml
[[plugins]]
repo = 'mattn/vim-gomod'
on_if = 'expand("%:t") == "go.mod"'
このスクラップは4ヶ月前にクローズされました