diff --git a/CHANGELOG.md b/CHANGELOG.md index 512f81609e..b082afd095 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## unplanned +FEATURES: + +* Add `:GoFillStruct` to fill a struct with all fields; uses + [`fillstruct`](https://github.com/davidrjenni/reftools/tree/master/cmd/fillstruct) + [[GH-1443]](https://github.com/fatih/vim-go/pull/1443). + IMPROVEMENTS: * `:GoAddTags` and `:GoRemoveTags` now continue to process if there are diff --git a/autoload/go/doc.vim b/autoload/go/doc.vim index 3acb6f5372..4a6a39ebcc 100644 --- a/autoload/go/doc.vim +++ b/autoload/go/doc.vim @@ -150,18 +150,8 @@ function! s:gogetdoc(json) abort let command = join(cmd, " ") if &modified - " gogetdoc supports the same archive format as guru for dealing with - " modified buffers. - " use the -modified flag - " write each archive entry on stdin as: - " filename followed by newline - " file size followed by newline - " file contents - let in = "" - let content = join(go#util#GetLines(), "\n") - let in = fname . "\n" . strlen(content) . "\n" . content let command .= " -modified" - let out = go#util#System(command, in) + let out = go#util#System(command, go#util#archive()) else let out = go#util#System(command) endif diff --git a/autoload/go/fillstruct.vim b/autoload/go/fillstruct.vim new file mode 100644 index 0000000000..890be5ba16 --- /dev/null +++ b/autoload/go/fillstruct.vim @@ -0,0 +1,57 @@ +function! go#fillstruct#FillStruct() abort + let binpath = go#path#CheckBinPath('fillstruct') + if empty(binpath) + return + endif + + let l:cmd = [binpath, + \ '-file', bufname(''), + \ '-offset', go#util#OffsetCursor()] + + " Read from stdin if modified. + if &modified + call add(l:cmd, '-modified') + let l:out = go#util#System(go#util#Shelljoin(l:cmd), go#util#archive()) + else + let l:out = go#util#System(go#util#Shelljoin(l:cmd)) + endif + + if go#util#ShellError() != 0 + call go#util#EchoError(l:out) + return + endif + + try + let l:json = json_decode(l:out) + catch + call go#util#EchoError(l:out) + return + endtry + + let l:code = split(l:json['code'], "\n") + let l:pos = getpos('.') + + try + " Add any code before/after the struct. + exe l:json['start'] . 'go' + let l:code[0] = getline('.')[:col('.')-1] . l:code[0] + exe l:json['end'] . 'go' + let l:code[len(l:code)-1] .= getline('.')[col('.'):] + + " Indent every line except the first one; makes it look nice. + let l:indent = repeat("\t", indent('.') / &ts) + for i in range(1, len(l:code)-1) + let l:code[l:i] = l:indent . l:code[i] + endfor + + " Out with the old ... + exe 'normal! ' . l:json['start'] . 'gov' . l:json['end'] . 'gox' + " ... in with the new. + call setline('.', l:code[0]) + call append('.', l:code[1:]) + finally + call setpos('.', l:pos) + endtry +endfunction + +" vim: sw=2 ts=2 et diff --git a/autoload/go/guru.vim b/autoload/go/guru.vim index 87eb4b2c0e..5369385a3b 100644 --- a/autoload/go/guru.vim +++ b/autoload/go/guru.vim @@ -34,8 +34,7 @@ function! s:guru_cmd(args) range abort let filename = fnamemodify(expand("%"), ':p:gs?\\?/?') if &modified - let content = join(go#util#GetLines(), "\n") - let result.stdin_content = filename . "\n" . strlen(content) . "\n" . content + let result.stdin_content = go#util#archive() call add(cmd, "-modified") endif diff --git a/autoload/go/util.vim b/autoload/go/util.vim index df47bd71ed..2884ca811d 100644 --- a/autoload/go/util.vim +++ b/autoload/go/util.vim @@ -296,6 +296,7 @@ function! go#util#EchoInfo(msg) call s:echo(a:msg, 'Debug') endfunction +" Get all lines in the buffer as a a list. function! go#util#GetLines() let buf = getline(1, '$') if &encoding != 'utf-8' @@ -309,4 +310,16 @@ function! go#util#GetLines() return buf endfunction +" Convert the current buffer to the "archive" format of +" golang.org/x/tools/go/buildutil: +" https://godoc.org/golang.org/x/tools/go/buildutil#ParseOverlayArchive +" +" > The archive consists of a series of files. Each file consists of a name, a +" > decimal file size and the file contents, separated by newlinews. No newline +" > follows after the file contents. +function! go#util#archive() + let l:buffer = join(go#util#GetLines(), "\n") + return expand("%:p:gs!\\!/!") . "\n" . strlen(l:buffer) . "\n" . l:buffer +endfunction + " vim: sw=2 ts=2 et diff --git a/doc/vim-go.txt b/doc/vim-go.txt index 2e98c0ca9e..92bdd0e670 100644 --- a/doc/vim-go.txt +++ b/doc/vim-go.txt @@ -796,6 +796,25 @@ CTRL-t Surname: "Smith", } < + *:GoFillStruct* +:GoFillStruct + + Use `fillstruct` to fill a struct literal with default values. Existing + values (if any) are preserved. The cursor must be on the struct you wish + to fill. + + For example: +> + addr := net.Address{Name: "Ford Prefect"} +< + Becomes: +> + addr := net.Address{ + Name: "Ford Prefect", + Email: "", + } +< + ============================================================================== MAPPINGS *go-mappings* diff --git a/ftplugin/go/commands.vim b/ftplugin/go/commands.vim index 66d4e5ba64..bdb26d3976 100644 --- a/ftplugin/go/commands.vim +++ b/ftplugin/go/commands.vim @@ -104,4 +104,7 @@ command! -nargs=0 GoTemplateAutoCreateToggle call go#template#ToggleAutoCreate() " -- keyify command! -nargs=0 GoKeyify call go#keyify#Keyify() +" -- fillstruct +command! -nargs=0 GoFillStruct call go#fillstruct#FillStruct() + " vim: sw=2 ts=2 et diff --git a/plugin/go.vim b/plugin/go.vim index 1eb5c27f56..04244470a5 100644 --- a/plugin/go.vim +++ b/plugin/go.vim @@ -22,6 +22,7 @@ let s:packages = [ \ "github.com/zmb3/gogetdoc", \ "github.com/josharian/impl", \ "github.com/dominikh/go-tools/cmd/keyify", + \ "github.com/davidrjenni/reftools/cmd/fillstruct", \ ] " These commands are available on any filetypes