mirror of
				https://github.com/amix/vimrc
				synced 2025-10-31 06:33:35 +08:00 
			
		
		
		
	Updated plugins, also experimenting with a new font
The font is IBM Plex Mono: https://ibm.github.io/type/
This commit is contained in:
		| @ -9,20 +9,17 @@ endfunction | ||||
| " default it tries to call simply 'go build', but it first tries to get all | ||||
| " dependent files for the current folder and passes it to go build. | ||||
| function! go#cmd#Build(bang, ...) abort | ||||
|   " expand all wildcards(i.e: '%' to the current file name) | ||||
|   let goargs = map(copy(a:000), "expand(v:val)") | ||||
|  | ||||
|   " escape all shell arguments before we pass it to make | ||||
|   if !has('nvim') | ||||
|     let goargs = go#util#Shelllist(goargs, 1) | ||||
|   endif | ||||
|   " create our command arguments. go build discards any results when it | ||||
|   " Create our command arguments. go build discards any results when it | ||||
|   " compiles multiple packages. So we pass the `errors` package just as an | ||||
|   " placeholder with the current folder (indicated with '.'). We also pass -i | ||||
|   " that tries to install the dependencies, this has the side effect that it | ||||
|   " caches the build results, so every other build is faster. | ||||
|   let args = ["build"]  + goargs + ["-i", ".", "errors"] | ||||
|   let args = | ||||
|         \ ["build"] + | ||||
|         \ map(copy(a:000), "expand(v:val)") + | ||||
|         \ ["-i", ".", "errors"] | ||||
|  | ||||
|   " Vim async. | ||||
|   if go#util#has_job() | ||||
|     if get(g:, 'go_echo_command_info', 1) | ||||
|       call go#util#EchoProgress("building dispatched ...") | ||||
| @ -31,50 +28,52 @@ function! go#cmd#Build(bang, ...) abort | ||||
|     call s:cmd_job({ | ||||
|           \ 'cmd': ['go'] + args, | ||||
|           \ 'bang': a:bang, | ||||
|           \ 'for': 'GoBuild', | ||||
|           \}) | ||||
|     return | ||||
|  | ||||
|   " Nvim async. | ||||
|   elseif has('nvim') | ||||
|     if get(g:, 'go_echo_command_info', 1) | ||||
|       call go#util#EchoProgress("building dispatched ...") | ||||
|     endif | ||||
|  | ||||
|     " if we have nvim, call it asynchronously and return early ;) | ||||
|     call go#jobcontrol#Spawn(a:bang, "build", args) | ||||
|     return | ||||
|   endif | ||||
|     call go#jobcontrol#Spawn(a:bang, "build", "GoBuild", args) | ||||
|  | ||||
|   let old_gopath = $GOPATH | ||||
|   let $GOPATH = go#path#Detect() | ||||
|   let default_makeprg = &makeprg | ||||
|   let &makeprg = "go " . join(args, ' ') | ||||
|  | ||||
|   let l:listtype = go#list#Type("quickfix") | ||||
|   " execute make inside the source folder so we can parse the errors | ||||
|   " correctly | ||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
|   let dir = getcwd() | ||||
|   try | ||||
|     execute cd . fnameescape(expand("%:p:h")) | ||||
|     if l:listtype == "locationlist" | ||||
|       silent! exe 'lmake!' | ||||
|     else | ||||
|       silent! exe 'make!' | ||||
|     endif | ||||
|     redraw! | ||||
|   finally | ||||
|     execute cd . fnameescape(dir) | ||||
|   endtry | ||||
|  | ||||
|   let errors = go#list#Get(l:listtype) | ||||
|   call go#list#Window(l:listtype, len(errors)) | ||||
|   if !empty(errors) && !a:bang | ||||
|     call go#list#JumpToFirst(l:listtype) | ||||
|   " Vim 7.4 without async | ||||
|   else | ||||
|     call go#util#EchoSuccess("[build] SUCCESS") | ||||
|   endif | ||||
|     let old_gopath = $GOPATH | ||||
|     let $GOPATH = go#path#Detect() | ||||
|     let default_makeprg = &makeprg | ||||
|     let &makeprg = "go " . join(go#util#Shelllist(args), ' ') | ||||
|  | ||||
|   let &makeprg = default_makeprg | ||||
|   let $GOPATH = old_gopath | ||||
|     let l:listtype = go#list#Type("GoBuild") | ||||
|     " execute make inside the source folder so we can parse the errors | ||||
|     " correctly | ||||
|     let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
|     let dir = getcwd() | ||||
|     try | ||||
|       execute cd . fnameescape(expand("%:p:h")) | ||||
|       if l:listtype == "locationlist" | ||||
|         silent! exe 'lmake!' | ||||
|       else | ||||
|         silent! exe 'make!' | ||||
|       endif | ||||
|       redraw! | ||||
|     finally | ||||
|       execute cd . fnameescape(dir) | ||||
|     endtry | ||||
|  | ||||
|     let errors = go#list#Get(l:listtype) | ||||
|     call go#list#Window(l:listtype, len(errors)) | ||||
|     if !empty(errors) && !a:bang | ||||
|       call go#list#JumpToFirst(l:listtype) | ||||
|     else | ||||
|       call go#util#EchoSuccess("[build] SUCCESS") | ||||
|     endif | ||||
|  | ||||
|     let &makeprg = default_makeprg | ||||
|     let $GOPATH = old_gopath | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
|  | ||||
| @ -149,7 +148,7 @@ function! go#cmd#Run(bang, ...) abort | ||||
|     let &makeprg = "go run " . go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1) | ||||
|   endif | ||||
|  | ||||
|   let l:listtype = go#list#Type("quickfix") | ||||
|   let l:listtype = go#list#Type("GoRun") | ||||
|  | ||||
|   if l:listtype == "locationlist" | ||||
|     exe 'lmake!' | ||||
| @ -186,6 +185,7 @@ function! go#cmd#Install(bang, ...) abort | ||||
|     call s:cmd_job({ | ||||
|           \ 'cmd': ['go', 'install'] + goargs, | ||||
|           \ 'bang': a:bang, | ||||
|           \ 'for': 'GoInstall', | ||||
|           \}) | ||||
|     return | ||||
|   endif | ||||
| @ -198,7 +198,7 @@ function! go#cmd#Install(bang, ...) abort | ||||
|   let goargs = go#util#Shelljoin(map(copy(a:000), "expand(v:val)"), 1) | ||||
|   let &makeprg = "go install " . goargs | ||||
|  | ||||
|   let l:listtype = go#list#Type("quickfix") | ||||
|   let l:listtype = go#list#Type("GoInstall") | ||||
|   " execute make inside the source folder so we can parse the errors | ||||
|   " correctly | ||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
| @ -243,7 +243,7 @@ function! go#cmd#Generate(bang, ...) abort | ||||
|     let &makeprg = "go generate " . goargs . ' ' . gofiles | ||||
|   endif | ||||
|  | ||||
|   let l:listtype = go#list#Type("quickfix") | ||||
|   let l:listtype = go#list#Type("GoGenerate") | ||||
|  | ||||
|   echon "vim-go: " | echohl Identifier | echon "generating ..."| echohl None | ||||
|   if l:listtype == "locationlist" | ||||
|  | ||||
| @ -53,6 +53,7 @@ function! go#coverage#Buffer(bang, ...) abort | ||||
|           \ 'cmd': ['go', 'test', '-coverprofile', l:tmpname] + a:000, | ||||
|           \ 'custom_cb': function('s:coverage_callback', [l:tmpname]), | ||||
|           \ 'bang': a:bang, | ||||
|           \ 'for': 'GoTest', | ||||
|           \ }) | ||||
|     return | ||||
|   endif | ||||
| @ -94,9 +95,9 @@ function! go#coverage#Clear() abort | ||||
|   if exists("s:toggle") | let s:toggle = 0 | endif | ||||
|  | ||||
|   " remove the autocmd we defined | ||||
|   if exists("#BufWinLeave#<buffer>") | ||||
|     autocmd! BufWinLeave <buffer> | ||||
|   endif | ||||
|   augroup vim-go-coverage | ||||
|     autocmd! | ||||
|   augroup end | ||||
| endfunction | ||||
|  | ||||
| " Browser creates a new cover profile with 'go test -coverprofile' and opens | ||||
| @ -108,6 +109,7 @@ function! go#coverage#Browser(bang, ...) abort | ||||
|           \ 'cmd': ['go', 'test', '-coverprofile', l:tmpname], | ||||
|           \ 'custom_cb': function('s:coverage_browser_callback', [l:tmpname]), | ||||
|           \ 'bang': a:bang, | ||||
|           \ 'for': 'GoTest', | ||||
|           \ }) | ||||
|     return | ||||
|   endif | ||||
| @ -256,7 +258,10 @@ function! go#coverage#overlay(file) abort | ||||
|   endfor | ||||
|  | ||||
|   " clear the matches if we leave the buffer | ||||
|   autocmd BufWinLeave <buffer> call go#coverage#Clear() | ||||
|   augroup vim-go-coverage | ||||
|     autocmd! | ||||
|     autocmd BufWinLeave <buffer> call go#coverage#Clear() | ||||
|   augroup end | ||||
|  | ||||
|   for m in matches | ||||
|     call matchaddpos(m.group, m.pos) | ||||
|  | ||||
| @ -168,7 +168,7 @@ function! go#def#jump_to_declaration(out, mode, bin_name) abort | ||||
|       endif | ||||
|  | ||||
|       " open the file and jump to line and column | ||||
|       exec cmd fnameescape(filename) | ||||
|       exec cmd fnameescape(fnamemodify(filename, ':.')) | ||||
|     endif | ||||
|   endif | ||||
|   call cursor(line, col) | ||||
|  | ||||
| @ -1,32 +1,37 @@ | ||||
| func Test_jump_to_declaration_guru() | ||||
|   let file_name = "test-fixtures/def/jump.go" | ||||
|   let lnum = 5 | ||||
|   let col = 6 | ||||
| func! Test_jump_to_declaration_guru() abort | ||||
|   try | ||||
|     let l:filename = 'def/jump.go' | ||||
|     let lnum = 5 | ||||
|     let col = 6 | ||||
|     let l:tmp = gotest#load_fixture(l:filename) | ||||
|  | ||||
|   let out = printf("%s:%d:%d: defined here as func main", file_name, lnum, col) | ||||
|   let bin_name = "guru" | ||||
|     let guru_out = printf("%s:%d:%d: defined here as func main", filename, lnum, col) | ||||
|     call go#def#jump_to_declaration(guru_out, "", 'guru') | ||||
|  | ||||
|   call go#def#jump_to_declaration(out, "", bin_name) | ||||
|  | ||||
|   call assert_equal(file_name, bufname("%")) | ||||
|   call assert_equal(lnum, getcurpos()[1]) | ||||
|   call assert_equal(col, getcurpos()[2]) | ||||
|     call assert_equal(filename, bufname("%")) | ||||
|     call assert_equal(lnum, getcurpos()[1]) | ||||
|     call assert_equal(col, getcurpos()[2]) | ||||
|   finally | ||||
|     call delete(l:tmp, 'rf') | ||||
|   endtry | ||||
| endfunc | ||||
|  | ||||
| func Test_jump_to_declaration_godef() | ||||
|   let file_name = "test-fixtures/def/jump.go" | ||||
|   let lnum = 5 | ||||
|   let col = 6 | ||||
| func! Test_jump_to_declaration_godef() abort | ||||
|   try | ||||
|     let filename = 'def/jump.go' | ||||
|     let lnum = 5 | ||||
|     let col = 6 | ||||
|     let l:tmp = gotest#load_fixture(l:filename) | ||||
|  | ||||
|   " note that the output of godef has two lines | ||||
|   let out = printf("%s:%d:%d\ndefined here as func main", file_name, lnum, col) | ||||
|   let bin_name = "godef" | ||||
|     let godef_out = printf("%s:%d:%d\ndefined here as func main", filename, lnum, col) | ||||
|     call go#def#jump_to_declaration(godef_out, "", 'godef') | ||||
|  | ||||
|   call go#def#jump_to_declaration(out, "", bin_name) | ||||
|  | ||||
|   call assert_equal(file_name, bufname("%")) | ||||
|   call assert_equal(lnum, getcurpos()[1]) | ||||
|   call assert_equal(col, getcurpos()[2]) | ||||
|     call assert_equal(filename, bufname("%")) | ||||
|     call assert_equal(lnum, getcurpos()[1]) | ||||
|     call assert_equal(col, getcurpos()[2]) | ||||
|   finally | ||||
|     call delete(l:tmp, 'rf') | ||||
|   endtry | ||||
| endfunc | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
| @ -5,11 +5,7 @@ | ||||
| let s:buf_nr = -1 | ||||
|  | ||||
| if !exists("g:go_doc_command") | ||||
|   let g:go_doc_command = "godoc" | ||||
| endif | ||||
|  | ||||
| if !exists("g:go_doc_options") | ||||
|   let g:go_doc_options = "" | ||||
|   let g:go_doc_command = ["godoc"] | ||||
| endif | ||||
|  | ||||
| function! go#doc#OpenBrowser(...) abort | ||||
| @ -60,12 +56,11 @@ endfunction | ||||
| function! go#doc#Open(newmode, mode, ...) abort | ||||
|   " With argument: run "godoc [arg]". | ||||
|   if len(a:000) | ||||
|     let bin_path = go#path#CheckBinPath('godoc') | ||||
|     if empty(bin_path) | ||||
|     if empty(go#path#CheckBinPath(g:go_doc_command[0])) | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|     let command = printf("%s %s", go#util#Shellescape(bin_path), join(a:000, ' ')) | ||||
|     let command = printf("%s %s", go#util#Shelljoin(g:go_doc_command), join(a:000, ' ')) | ||||
|     let out = go#util#System(command) | ||||
|   " Without argument: run gogetdoc on cursor position. | ||||
|   else | ||||
| @ -85,6 +80,7 @@ endfunction | ||||
|  | ||||
| function! s:GodocView(newposition, position, content) abort | ||||
|   " reuse existing buffer window if it exists otherwise create a new one | ||||
|   let is_visible = bufexists(s:buf_nr) && bufwinnr(s:buf_nr) != -1 | ||||
|   if !bufexists(s:buf_nr) | ||||
|     execute a:newposition | ||||
|     sil file `="[Godoc]"` | ||||
| @ -96,20 +92,23 @@ function! s:GodocView(newposition, position, content) abort | ||||
|     execute bufwinnr(s:buf_nr) . 'wincmd w' | ||||
|   endif | ||||
|  | ||||
|   if a:position == "split" | ||||
|     " cap window height to 20, but resize it for smaller contents | ||||
|     let max_height = get(g:, "go_doc_max_height", 20) | ||||
|     let content_height = len(split(a:content, "\n")) | ||||
|     if content_height > max_height | ||||
|       exe 'resize ' . max_height | ||||
|   " if window was not visible then resize it | ||||
|   if !is_visible | ||||
|     if a:position == "split" | ||||
|       " cap window height to 20, but resize it for smaller contents | ||||
|       let max_height = get(g:, "go_doc_max_height", 20) | ||||
|       let content_height = len(split(a:content, "\n")) | ||||
|       if content_height > max_height | ||||
|         exe 'resize ' . max_height | ||||
|       else | ||||
|         exe 'resize ' . content_height | ||||
|       endif | ||||
|     else | ||||
|       exe 'resize ' . content_height | ||||
|       " set a sane maximum width for vertical splits. In this case the minimum | ||||
|       " that fits the godoc for package http without extra linebreaks and line | ||||
|       " numbers on | ||||
|       exe 'vertical resize 84' | ||||
|     endif | ||||
|   else | ||||
|     " set a sane maximum width for vertical splits. In this case the minimum | ||||
|     " that fits the godoc for package http without extra linebreaks and line | ||||
|     " numbers on | ||||
|     exe 'vertical resize 84' | ||||
|   endif | ||||
|  | ||||
|   setlocal filetype=godoc | ||||
| @ -155,18 +154,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 | ||||
|  | ||||
| @ -127,17 +127,23 @@ function! go#fmt#update_file(source, target) | ||||
|   let &fileformat = old_fileformat | ||||
|   let &syntax = &syntax | ||||
|  | ||||
|   let l:listtype = go#list#Type("GoFmt") | ||||
|  | ||||
|   " the title information was introduced with 7.4-2200 | ||||
|   " https://github.com/vim/vim/commit/d823fa910cca43fec3c31c030ee908a14c272640 | ||||
|   if !has('patch-7.4-2200') | ||||
|     return | ||||
|   if has('patch-7.4.2200') | ||||
|     " clean up previous list | ||||
|     if l:listtype == "quickfix" | ||||
|       let l:list_title = getqflist({'title': 1}) | ||||
|     else | ||||
|       let l:list_title = getloclist(0, {'title': 1}) | ||||
|     endif | ||||
|   else | ||||
|     " can't check the title, so assume that the list was for go fmt. | ||||
|     let l:list_title = {'title': 'Format'} | ||||
|   endif | ||||
|  | ||||
|   " clean up previous location list | ||||
|   let l:list_title = getqflist({'title': 1}) | ||||
|   if has_key(l:list_title, "title") && l:list_title['title'] == "Format" | ||||
|     let l:listtype = go#list#Type("quickfix") | ||||
|     call go#list#Clean(l:listtype) | ||||
|     call go#list#Window(l:listtype) | ||||
|   endif | ||||
| @ -245,7 +251,7 @@ endfunction | ||||
| " show_errors opens a location list and shows the given errors. If the given | ||||
| " errors is empty, it closes the the location list | ||||
| function! s:show_errors(errors) abort | ||||
|   let l:listtype = go#list#Type("quickfix") | ||||
|   let l:listtype = go#list#Type("GoFmt") | ||||
|   if !empty(a:errors) | ||||
|     call go#list#Populate(l:listtype, a:errors, 'Format') | ||||
|     echohl Error | echomsg "Gofmt returned error" | echohl None | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| func Test_run_fmt() | ||||
| func! Test_run_fmt() abort | ||||
|   let actual_file = tempname() | ||||
|   call writefile(readfile("test-fixtures/fmt/hello.go"), actual_file) | ||||
|  | ||||
| @ -13,7 +13,7 @@ func Test_run_fmt() | ||||
|   call assert_equal(expected, actual) | ||||
| endfunc | ||||
|  | ||||
| func Test_update_file() | ||||
| func! Test_update_file() abort | ||||
|   let expected = join(readfile("test-fixtures/fmt/hello_golden.go"), "\n") | ||||
|   let source_file = tempname() | ||||
|   call writefile(readfile("test-fixtures/fmt/hello_golden.go"), source_file) | ||||
| @ -30,7 +30,7 @@ func Test_update_file() | ||||
|   call assert_equal(expected, actual) | ||||
| endfunc | ||||
|  | ||||
| func Test_goimports() | ||||
| func! Test_goimports() abort | ||||
|   let $GOPATH = 'test-fixtures/fmt/' | ||||
|   let actual_file = tempname() | ||||
|   call writefile(readfile("test-fixtures/fmt/src/imports/goimports.go"), actual_file) | ||||
| @ -45,3 +45,5 @@ func Test_goimports() | ||||
|  | ||||
|   call assert_equal(expected, actual) | ||||
| endfunc | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -112,7 +111,8 @@ function! s:sync_guru(args) abort | ||||
|  | ||||
|   if !has_key(a:args, 'disable_progress') | ||||
|     if a:args.needs_scope | ||||
|       call go#util#EchoProgress("analysing with scope ". result.scope . " ...") | ||||
|       call go#util#EchoProgress("analysing with scope ". result.scope . | ||||
|             \ " (see ':help go-guru-scope' if this doesn't work)...") | ||||
|     elseif a:args.mode !=# 'what' | ||||
|       " the query might take time, let us give some feedback | ||||
|       call go#util#EchoProgress("analysing ...") | ||||
| @ -150,7 +150,8 @@ function! s:async_guru(args) abort | ||||
|  | ||||
|   if !has_key(a:args, 'disable_progress') | ||||
|     if a:args.needs_scope | ||||
|       call go#util#EchoProgress("analysing with scope ". result.scope . " ...") | ||||
|       call go#util#EchoProgress("analysing with scope " . result.scope . | ||||
|             \ " (see ':help go-guru-scope' if this doesn't work)...") | ||||
|     endif | ||||
|   endif | ||||
|  | ||||
| @ -159,9 +160,10 @@ function! s:async_guru(args) abort | ||||
|     call add(messages, a:msg) | ||||
|   endfunction | ||||
|  | ||||
|   function! s:exit_cb(job, exitval) closure | ||||
|     let out = join(messages, "\n") | ||||
|   let status = {} | ||||
|   let exitval = 0 | ||||
|  | ||||
|   function! s:exit_cb(job, exitval) closure | ||||
|     let status = { | ||||
|           \ 'desc': 'last status', | ||||
|           \ 'type': statusline_type, | ||||
| @ -169,21 +171,27 @@ function! s:async_guru(args) abort | ||||
|           \ } | ||||
|  | ||||
|     if a:exitval | ||||
|       let exitval = a:exitval | ||||
|       let status.state = "failed" | ||||
|     endif | ||||
|  | ||||
|     call go#statusline#Update(status_dir, status) | ||||
|   endfunction | ||||
|  | ||||
|   function! s:close_cb(ch) closure | ||||
|     let out = join(messages, "\n") | ||||
|  | ||||
|     if has_key(a:args, 'custom_parse') | ||||
|       call a:args.custom_parse(a:exitval, out) | ||||
|       call a:args.custom_parse(exitval, out) | ||||
|     else | ||||
|       call s:parse_guru_output(a:exitval, out, a:args.mode) | ||||
|       call s:parse_guru_output(exitval, out, a:args.mode) | ||||
|     endif | ||||
|   endfunction | ||||
|  | ||||
|   let start_options = { | ||||
|         \ 'callback': funcref("s:callback"), | ||||
|         \ 'exit_cb': funcref("s:exit_cb"), | ||||
|         \ 'close_cb': funcref("s:close_cb"), | ||||
|         \ } | ||||
|  | ||||
|   if has_key(result, 'stdin_content') | ||||
| @ -521,28 +529,40 @@ function! s:same_ids_highlight(exit_val, output) abort | ||||
|   if get(g:, "go_auto_sameids", 0) | ||||
|     " re-apply SameIds at the current cursor position at the time the buffer | ||||
|     " is redisplayed: e.g. :edit, :GoRename, etc. | ||||
|     autocmd BufWinEnter <buffer> nested call go#guru#SameIds() | ||||
|     augroup vim-go-sameids | ||||
|       autocmd! | ||||
|       autocmd BufWinEnter <buffer> nested call go#guru#SameIds() | ||||
|     augroup end | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| " ClearSameIds returns 0 when it removes goSameId groups and non-zero if no | ||||
| " goSameId groups are found. | ||||
| function! go#guru#ClearSameIds() abort | ||||
|   let l:cleared = 0 | ||||
|  | ||||
|   let m = getmatches() | ||||
|   for item in m | ||||
|     if item['group'] == 'goSameId' | ||||
|       call matchdelete(item['id']) | ||||
|       let l:cleared = 1 | ||||
|     endif | ||||
|   endfor | ||||
|  | ||||
|   " remove the autocmds we defined | ||||
|   if exists("#BufWinEnter#<buffer>") | ||||
|     autocmd! BufWinEnter <buffer> | ||||
|   if !l:cleared | ||||
|     return 1 | ||||
|   endif | ||||
|  | ||||
|   " remove the autocmds we defined | ||||
|   augroup vim-go-sameids | ||||
|     autocmd! | ||||
|   augroup end | ||||
|  | ||||
|   return 0 | ||||
| endfunction | ||||
|  | ||||
| function! go#guru#ToggleSameIds() abort | ||||
|   if len(getmatches()) != 0 | ||||
|     call go#guru#ClearSameIds() | ||||
|   else | ||||
|   if go#guru#ClearSameIds() != 0 | ||||
|     call go#guru#SameIds() | ||||
|   endif | ||||
| endfunction | ||||
| @ -583,11 +603,12 @@ function! s:parse_guru_output(exit_val, output, title) abort | ||||
|  | ||||
|   let old_errorformat = &errorformat | ||||
|   let errformat = "%f:%l.%c-%[%^:]%#:\ %m,%f:%l:%c:\ %m" | ||||
|   call go#list#ParseFormat("locationlist", errformat, a:output, a:title) | ||||
|   let l:listtype = go#list#Type("_guru") | ||||
|   call go#list#ParseFormat(l:listtype, errformat, a:output, a:title) | ||||
|   let &errorformat = old_errorformat | ||||
|  | ||||
|   let errors = go#list#Get("locationlist") | ||||
|   call go#list#Window("locationlist", len(errors)) | ||||
|   let errors = go#list#Get(l:listtype) | ||||
|   call go#list#Window(l:listtype, len(errors)) | ||||
| endfun | ||||
|  | ||||
| function! go#guru#Scope(...) abort | ||||
|  | ||||
| @ -6,11 +6,13 @@ function! go#impl#Impl(...) abort | ||||
|  | ||||
|   let recv = "" | ||||
|   let iface = "" | ||||
|   let interactive = 0 | ||||
|  | ||||
|   let pos = getpos('.') | ||||
|  | ||||
|   if a:0 == 0 | ||||
|     " user didn't passed anything,  just called ':GoImpl' | ||||
|     let receiveType = expand("<cword>") | ||||
|     let recv = printf("%s *%s", tolower(receiveType)[0], receiveType) | ||||
|     " Interactive mode if user didn't pass any arguments. | ||||
|     let recv = s:getReceiver() | ||||
|     let iface = input("vim-go: generating method stubs for interface: ") | ||||
|     redraw! | ||||
|     if empty(iface) | ||||
| @ -20,8 +22,7 @@ function! go#impl#Impl(...) abort | ||||
|   elseif a:0 == 1 | ||||
|     " we assume the user only passed the interface type, | ||||
|     " i.e: ':GoImpl io.Writer' | ||||
|     let receiveType = expand("<cword>") | ||||
|     let recv = printf("%s *%s", tolower(receiveType)[0], receiveType) | ||||
|     let recv = s:getReceiver() | ||||
|     let iface = a:1 | ||||
|   elseif a:0 > 2 | ||||
|     " user passed receiver and interface type both, | ||||
| @ -33,20 +34,41 @@ function! go#impl#Impl(...) abort | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   let result = go#util#System(join(go#util#Shelllist([binpath, recv, iface], ' '))) | ||||
|   if go#util#ShellError() != 0 | ||||
|     call go#util#EchoError(result) | ||||
|     return | ||||
|   " Make sure we put the generated code *after* the struct. | ||||
|   if getline(".") =~ "struct " | ||||
|     normal! $% | ||||
|   endif | ||||
|  | ||||
|   if result ==# '' | ||||
|     return | ||||
|   end | ||||
|   try | ||||
|     let dirname = fnameescape(expand('%:p:h')) | ||||
|     let result = go#util#System(join(go#util#Shelllist([binpath, '-dir', dirname, recv, iface], ' '))) | ||||
|     let result = substitute(result, "\n*$", "", "") | ||||
|     if go#util#ShellError() != 0 | ||||
|       call go#util#EchoError(result) | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|   let pos = getpos('.') | ||||
|   put ='' | ||||
|   put =result | ||||
|   call setpos('.', pos) | ||||
|     if result ==# '' | ||||
|       return | ||||
|     end | ||||
|  | ||||
|     put ='' | ||||
|     put =result | ||||
|   finally | ||||
|     call setpos('.', pos) | ||||
|   endtry | ||||
| endfunction | ||||
|  | ||||
| function! s:getReceiver() | ||||
|   let receiveType = expand("<cword>") | ||||
|   if receiveType == "type" | ||||
|     normal! w | ||||
|     let receiveType = expand("<cword>") | ||||
|   elseif receiveType == "struct" | ||||
|     normal! ge | ||||
|     let receiveType = expand("<cword>") | ||||
|   endif | ||||
|   return printf("%s *%s", tolower(receiveType)[0], receiveType) | ||||
| endfunction | ||||
|  | ||||
| if exists('*uniq') | ||||
|  | ||||
| @ -10,12 +10,17 @@ function go#job#Spawn(args) | ||||
|         \ 'messages': [], | ||||
|         \ 'args': a:args.cmd, | ||||
|         \ 'bang': 0, | ||||
|         \ 'for': "_job", | ||||
|         \ } | ||||
|  | ||||
|   if has_key(a:args, 'bang') | ||||
|     let cbs.bang = a:args.bang | ||||
|   endif | ||||
|  | ||||
|   if has_key(a:args, 'for') | ||||
|     let cbs.for = a:args.for | ||||
|   endif | ||||
|  | ||||
|   " add final callback to be called if async job is finished | ||||
|   " The signature should be in form: func(job, exit_status, messages) | ||||
|   if has_key(a:args, 'custom_cb') | ||||
| @ -47,7 +52,7 @@ function go#job#Spawn(args) | ||||
|       call self.custom_cb(a:job, a:exitval, self.messages) | ||||
|     endif | ||||
|  | ||||
|     let l:listtype = go#list#Type("quickfix") | ||||
|     let l:listtype = go#list#Type(self.for) | ||||
|     if a:exitval == 0 | ||||
|       call go#list#Clean(l:listtype) | ||||
|       call go#list#Window(l:listtype) | ||||
| @ -69,8 +74,7 @@ function go#job#Spawn(args) | ||||
|  | ||||
|     if !len(errors) | ||||
|       " failed to parse errors, output the original content | ||||
|       call go#util#EchoError(join(self.messages, " ")) | ||||
|       call go#util#EchoError(self.dir) | ||||
|       call go#util#EchoError(self.messages + [self.dir]) | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|  | ||||
| @ -9,11 +9,11 @@ let s:handlers = {} | ||||
| " Spawn is a wrapper around s:spawn. It can be executed by other files and | ||||
| " scripts if needed. Desc defines the description for printing the status | ||||
| " during the job execution (useful for statusline integration). | ||||
| function! go#jobcontrol#Spawn(bang, desc, args) abort | ||||
| function! go#jobcontrol#Spawn(bang, desc, for, args) abort | ||||
|   " autowrite is not enabled for jobs | ||||
|   call go#cmd#autowrite() | ||||
|  | ||||
|   let job = s:spawn(a:bang, a:desc, a:args) | ||||
|   let job = s:spawn(a:bang, a:desc, a:for, a:args) | ||||
|   return job.id | ||||
| endfunction | ||||
|  | ||||
| @ -37,7 +37,7 @@ endfunction | ||||
| " a job is started a reference will be stored inside s:jobs. spawn changes the | ||||
| " GOPATH when g:go_autodetect_gopath is enabled. The job is started inside the | ||||
| " current files folder. | ||||
| function! s:spawn(bang, desc, args) abort | ||||
| function! s:spawn(bang, desc, for, args) abort | ||||
|   let status_type = a:args[0] | ||||
|   let status_dir = expand('%:p:h') | ||||
|   let started_at = reltime() | ||||
| @ -62,6 +62,7 @@ function! s:spawn(bang, desc, args) abort | ||||
|         \ 'status_type' : status_type, | ||||
|         \ 'status_dir' : status_dir, | ||||
|         \ 'started_at' : started_at, | ||||
|         \ 'for' : a:for, | ||||
|         \ } | ||||
|  | ||||
|   " modify GOPATH if needed | ||||
| @ -129,7 +130,7 @@ function! s:on_exit(job_id, exit_status, event) dict abort | ||||
|  | ||||
|   call s:callback_handlers_on_exit(s:jobs[a:job_id], a:exit_status, std_combined) | ||||
|  | ||||
|   let l:listtype = go#list#Type("quickfix") | ||||
|   let l:listtype = go#list#Type(self.for) | ||||
|   if a:exit_status == 0 | ||||
|     call go#list#Clean(l:listtype) | ||||
|     call go#list#Window(l:listtype) | ||||
|  | ||||
| @ -57,3 +57,5 @@ endfunction | ||||
| function! s:chomp(string) | ||||
|     return substitute(a:string, '\n\+$', '', '') | ||||
| endfunction | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
| @ -48,6 +48,13 @@ function! go#lint#Gometa(autosave, ...) abort | ||||
|       let cmd += ["--exclude=".exclude] | ||||
|     endfor | ||||
|  | ||||
|     " gometalinter has a --tests flag to tell its linters whether to run | ||||
|     " against tests. While not all of its linters respect this flag, for those | ||||
|     " that do, it means if we don't pass --tests, the linter won't run against | ||||
|     " test files. One example of a linter that will not run against tests if | ||||
|     " we do not specify this flag is errcheck. | ||||
|     let cmd += ["--tests"] | ||||
|  | ||||
|     " path | ||||
|     let cmd += [expand('%:p:h')] | ||||
|   else | ||||
| @ -60,7 +67,7 @@ function! go#lint#Gometa(autosave, ...) abort | ||||
|   " For async mode (s:lint_job), we want to override the default deadline only | ||||
|   " if we have a deadline configured. | ||||
|   " | ||||
|   " For sync mode (go#tool#ExecuteInDir), always explicitly pass the 5 seconds | ||||
|   " For sync mode (go#util#System), always explicitly pass the 5 seconds | ||||
|   " deadline if there is no other deadline configured. If a deadline is | ||||
|   " configured, then use it. | ||||
|  | ||||
| @ -87,9 +94,9 @@ function! go#lint#Gometa(autosave, ...) abort | ||||
|  | ||||
|   let meta_command = join(cmd, " ") | ||||
|  | ||||
|   let out = go#tool#ExecuteInDir(meta_command) | ||||
|   let out = go#util#System(meta_command) | ||||
|  | ||||
|   let l:listtype = "quickfix" | ||||
|   let l:listtype = go#list#Type("GoMetaLinter") | ||||
|   if go#util#ShellError() == 0 | ||||
|     redraw | echo | ||||
|     call go#list#Clean(l:listtype) | ||||
| @ -134,7 +141,7 @@ function! go#lint#Golint(...) abort | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   let l:listtype = "quickfix" | ||||
|   let l:listtype = go#list#Type("GoLint") | ||||
|   call go#list#Parse(l:listtype, out) | ||||
|   let errors = go#list#Get(l:listtype) | ||||
|   call go#list#Window(l:listtype, len(errors)) | ||||
| @ -152,7 +159,7 @@ function! go#lint#Vet(bang, ...) abort | ||||
|     let out = go#util#System('go tool vet ' . go#util#Shelljoin(a:000)) | ||||
|   endif | ||||
|  | ||||
|   let l:listtype = "quickfix" | ||||
|   let l:listtype = go#list#Type("GoVet") | ||||
|   if go#util#ShellError() != 0 | ||||
|     let errors = go#tool#ParseErrors(split(out, '\n')) | ||||
|     call go#list#Populate(l:listtype, errors, 'Vet') | ||||
| @ -192,7 +199,7 @@ function! go#lint#Errcheck(...) abort | ||||
|   let command =  go#util#Shellescape(bin_path) . ' -abspath ' . import_path | ||||
|   let out = go#tool#ExecuteInDir(command) | ||||
|  | ||||
|   let l:listtype = "quickfix" | ||||
|   let l:listtype = go#list#Type("GoErrCheck") | ||||
|   if go#util#ShellError() != 0 | ||||
|     let errformat = "%f:%l:%c:\ %m, %f:%l:%c\ %#%m" | ||||
|  | ||||
| @ -246,7 +253,7 @@ function s:lint_job(args) | ||||
|   " autowrite is not enabled for jobs | ||||
|   call go#cmd#autowrite() | ||||
|  | ||||
|   let l:listtype = go#list#Type("quickfix") | ||||
|   let l:listtype = go#list#Type("GoMetaLinter") | ||||
|   let l:errformat = '%f:%l:%c:%t%*[^:]:\ %m,%f:%l::%t%*[^:]:\ %m' | ||||
|  | ||||
|   function! s:callback(chan, msg) closure | ||||
|  | ||||
| @ -2,13 +2,16 @@ if !exists("g:go_list_type") | ||||
|   let g:go_list_type = "" | ||||
| endif | ||||
|  | ||||
| if !exists("g:go_list_type_commands") | ||||
|   let g:go_list_type_commands = {} | ||||
| endif | ||||
|  | ||||
| " Window opens the list with the given height up to 10 lines maximum. | ||||
| " Otherwise g:go_loclist_height is used.  | ||||
| " Otherwise g:go_loclist_height is used. | ||||
| " | ||||
| " If no or zero height is given it closes the window by default.   | ||||
| " If no or zero height is given it closes the window by default. | ||||
| " To prevent this, set g:go_list_autoclose = 0 | ||||
| function! go#list#Window(listtype, ...) abort | ||||
|   let l:listtype = go#list#Type(a:listtype) | ||||
|   " we don't use lwindow to close the location list as we need also the | ||||
|   " ability to resize the window. So, we are going to use lopen and lclose | ||||
|   " for a better user experience. If the number of errors in a current | ||||
| @ -17,7 +20,7 @@ function! go#list#Window(listtype, ...) abort | ||||
|   if !a:0 || a:1 == 0 | ||||
|     let autoclose_window = get(g:, 'go_list_autoclose', 1) | ||||
|     if autoclose_window | ||||
|       if l:listtype == "locationlist" | ||||
|       if a:listtype == "locationlist" | ||||
|         lclose | ||||
|       else | ||||
|         cclose | ||||
| @ -36,7 +39,7 @@ function! go#list#Window(listtype, ...) abort | ||||
|     endif | ||||
|   endif | ||||
|  | ||||
|   if l:listtype == "locationlist" | ||||
|   if a:listtype == "locationlist" | ||||
|     exe 'lopen ' . height | ||||
|   else | ||||
|     exe 'copen ' . height | ||||
| @ -44,20 +47,18 @@ function! go#list#Window(listtype, ...) abort | ||||
| endfunction | ||||
|  | ||||
|  | ||||
| " Get returns the current list of items from the location list | ||||
| " Get returns the current items from the list | ||||
| function! go#list#Get(listtype) abort | ||||
|   let l:listtype = go#list#Type(a:listtype) | ||||
|   if l:listtype == "locationlist" | ||||
|   if a:listtype == "locationlist" | ||||
|     return getloclist(0) | ||||
|   else | ||||
|     return getqflist() | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| " Populate populate the location list with the given items | ||||
| " Populate populate the list with the given items | ||||
| function! go#list#Populate(listtype, items, title) abort | ||||
|   let l:listtype = go#list#Type(a:listtype) | ||||
|   if l:listtype == "locationlist" | ||||
|   if a:listtype == "locationlist" | ||||
|     call setloclist(0, a:items, 'r') | ||||
|  | ||||
|     " The last argument ({what}) is introduced with 7.4.2200: | ||||
| @ -69,20 +70,15 @@ function! go#list#Populate(listtype, items, title) abort | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! go#list#PopulateWin(winnr, items) abort | ||||
|   call setloclist(a:winnr, a:items, 'r') | ||||
| endfunction | ||||
|  | ||||
| " Parse parses the given items based on the specified errorformat and | ||||
| " populates the location list. | ||||
| " populates the list. | ||||
| function! go#list#ParseFormat(listtype, errformat, items, title) abort | ||||
|   let l:listtype = go#list#Type(a:listtype) | ||||
|   " backup users errorformat, will be restored once we are finished | ||||
|   let old_errorformat = &errorformat | ||||
|  | ||||
|   " parse and populate the location list | ||||
|   let &errorformat = a:errformat | ||||
|   if l:listtype == "locationlist" | ||||
|   if a:listtype == "locationlist" | ||||
|     lgetexpr a:items | ||||
|     if has("patch-7.4.2200") | call setloclist(0, [], 'a', {'title': a:title}) | endif | ||||
|   else | ||||
| @ -95,10 +91,9 @@ function! go#list#ParseFormat(listtype, errformat, items, title) abort | ||||
| endfunction | ||||
|  | ||||
| " Parse parses the given items based on the global errorformat and | ||||
| " populates the location list. | ||||
| " populates the list. | ||||
| function! go#list#Parse(listtype, items) abort | ||||
|   let l:listtype = go#list#Type(a:listtype) | ||||
|   if l:listtype == "locationlist" | ||||
|   if a:listtype == "locationlist" | ||||
|     lgetexpr a:items | ||||
|   else | ||||
|     cgetexpr a:items | ||||
| @ -107,8 +102,7 @@ endfunction | ||||
|  | ||||
| " JumpToFirst jumps to the first item in the location list | ||||
| function! go#list#JumpToFirst(listtype) abort | ||||
|   let l:listtype = go#list#Type(a:listtype) | ||||
|   if l:listtype == "locationlist" | ||||
|   if a:listtype == "locationlist" | ||||
|     ll 1 | ||||
|   else | ||||
|     cc 1 | ||||
| @ -117,22 +111,57 @@ endfunction | ||||
|  | ||||
| " Clean cleans the location list | ||||
| function! go#list#Clean(listtype) abort | ||||
|   let l:listtype = go#list#Type(a:listtype) | ||||
|   if l:listtype == "locationlist" | ||||
|   if a:listtype == "locationlist" | ||||
|     lex [] | ||||
|   else | ||||
|     cex [] | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! go#list#Type(listtype) abort | ||||
| function! s:listtype(listtype) abort | ||||
|   if g:go_list_type == "locationlist" | ||||
|     return "locationlist" | ||||
|   elseif g:go_list_type == "quickfix" | ||||
|     return "quickfix" | ||||
|   else | ||||
|     return a:listtype | ||||
|   endif | ||||
|  | ||||
|   return a:listtype | ||||
| endfunction | ||||
|  | ||||
| " s:default_list_type_commands is the defaults that will be used for each of | ||||
| " the supported commands (see documentation for g:go_list_type_commands). When | ||||
| " defining a default, quickfix should be used if the command operates on | ||||
| " multiple files, while locationlist should be used if the command operates on a | ||||
| " single file or buffer. Keys that begin with an underscore are not supported | ||||
| " in g:go_list_type_commands. | ||||
| let s:default_list_type_commands = { | ||||
|       \ "GoBuild":      "quickfix", | ||||
|       \ "GoErrCheck":   "quickfix", | ||||
|       \ "GoFmt":        "locationlist", | ||||
|       \ "GoGenerate":   "quickfix", | ||||
|       \ "GoInstall":    "quickfix", | ||||
|       \ "GoLint":       "quickfix", | ||||
|       \ "GoMetaLinter": "quickfix", | ||||
|       \ "GoModifyTags": "locationlist", | ||||
|       \ "GoRename":     "quickfix", | ||||
|       \ "GoRun":        "quickfix", | ||||
|       \ "GoTest":       "quickfix", | ||||
|       \ "GoVet":        "quickfix", | ||||
|       \ "_guru":        "locationlist", | ||||
|       \ "_term":        "locationlist", | ||||
|       \ "_job":         "locationlist", | ||||
|   \ } | ||||
|  | ||||
| function! go#list#Type(for) abort | ||||
|   let l:listtype = s:listtype(get(s:default_list_type_commands, a:for)) | ||||
|   if l:listtype == "0" | ||||
|     call go#util#EchoError(printf( | ||||
|           \ "unknown list type command value found ('%s'). Please open a bug report in the vim-go repo.", | ||||
|           \ a:for)) | ||||
|     let l:listtype = "quickfix" | ||||
|   endif | ||||
|  | ||||
|   return get(g:go_list_type_commands, a:for, l:listtype) | ||||
| endfunction | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
| @ -80,6 +80,7 @@ function! go#package#FromPath(arg) abort | ||||
|   for dir in dirs | ||||
|     if len(dir) && match(path, dir) == 0 | ||||
|       let workspace = dir | ||||
|       break | ||||
|     endif | ||||
|   endfor | ||||
|  | ||||
| @ -87,10 +88,12 @@ function! go#package#FromPath(arg) abort | ||||
|     return -1 | ||||
|   endif | ||||
|  | ||||
|   let path = substitute(path, '/*$', '', '') | ||||
|   let workspace = substitute(workspace . '/src/', '/+', '', '') | ||||
|   if isdirectory(path) | ||||
|     return substitute(path, workspace . 'src/', '', '') | ||||
|     return substitute(path, workspace, '', '') | ||||
|   else | ||||
|     return substitute(substitute(path, workspace . 'src/', '', ''), | ||||
|     return substitute(substitute(path, workspace, '', ''), | ||||
|           \ '/' . fnamemodify(path, ':t'), '', '') | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| @ -73,7 +73,7 @@ function! go#path#Detect() abort | ||||
|   let gopath = go#path#Default() | ||||
|  | ||||
|   " don't lookup for godeps if autodetect is disabled. | ||||
|   if !get(g:, "go_autodetect_gopath", 1) | ||||
|   if !get(g:, "go_autodetect_gopath", 0) | ||||
|     return gopath | ||||
|   endif | ||||
|  | ||||
| @ -179,7 +179,6 @@ function! go#path#CheckBinPath(binpath) abort | ||||
|   " just get the basename | ||||
|   let basename = fnamemodify(binpath, ":t") | ||||
|   if !executable(basename) | ||||
|  | ||||
|     call go#util#EchoError(printf("could not find '%s'. Run :GoInstallBinaries to fix it", basename)) | ||||
|  | ||||
|     " restore back! | ||||
|  | ||||
| @ -70,24 +70,4 @@ function! s:get_visual_selection() abort | ||||
|   return join(lines, "\n") | ||||
| endfunction | ||||
|  | ||||
| " following two functions are from: https://github.com/mattn/gist-vim | ||||
| " thanks  @mattn | ||||
| function! s:get_browser_command() abort | ||||
|   let go_play_browser_command = get(g:, 'go_play_browser_command', '') | ||||
|   if go_play_browser_command == '' | ||||
|     if has('win32') || has('win64') | ||||
|       let go_play_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%' | ||||
|     elseif has('mac') || has('macunix') || has('gui_macvim') || go#util#System('uname') =~? '^darwin' | ||||
|       let go_play_browser_command = 'open %URL%' | ||||
|     elseif executable('xdg-open') | ||||
|       let go_play_browser_command = 'xdg-open %URL%' | ||||
|     elseif executable('firefox') | ||||
|       let go_play_browser_command = 'firefox %URL% &' | ||||
|     else | ||||
|       let go_play_browser_command = '' | ||||
|     endif | ||||
|   endif | ||||
|   return go_play_browser_command | ||||
| endfunction | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
| @ -2,17 +2,25 @@ if !exists("g:go_gorename_bin") | ||||
|   let g:go_gorename_bin = "gorename" | ||||
| endif | ||||
|  | ||||
| if !exists("g:go_gorename_prefill") | ||||
|   let g:go_gorename_prefill = 1 | ||||
| endif | ||||
| " Set the default value. A value of "1" is a shortcut for this, for | ||||
| " compatibility reasons. | ||||
| function! s:default() abort | ||||
|   if !exists("g:go_gorename_prefill") || g:go_gorename_prefill == 1 | ||||
|     let g:go_gorename_prefill = 'expand("<cword>") =~# "^[A-Z]"' . | ||||
|           \ '? go#util#pascalcase(expand("<cword>"))' . | ||||
|           \ ': go#util#camelcase(expand("<cword>"))' | ||||
|   endif | ||||
| endfunction | ||||
| call s:default() | ||||
|  | ||||
| function! go#rename#Rename(bang, ...) abort | ||||
|   call s:default() | ||||
|  | ||||
|   let to_identifier = "" | ||||
|   if a:0 == 0 | ||||
|     let from = expand("<cword>") | ||||
|     let ask = printf("vim-go: rename '%s' to: ", from) | ||||
|     if g:go_gorename_prefill | ||||
|       let to_identifier = input(ask, from) | ||||
|     let ask = printf("vim-go: rename '%s' to: ", expand("<cword>")) | ||||
|     if g:go_gorename_prefill != '' | ||||
|       let to_identifier = input(ask, eval(g:go_gorename_prefill)) | ||||
|     else | ||||
|       let to_identifier = input(ask) | ||||
|     endif | ||||
| @ -24,7 +32,7 @@ function! go#rename#Rename(bang, ...) abort | ||||
|     let to_identifier = a:1 | ||||
|   endif | ||||
|  | ||||
|   "return with a warning if the bin doesn't exist | ||||
|   " return with a warning if the bin doesn't exist | ||||
|   let bin_path = go#path#CheckBinPath(g:go_gorename_bin) | ||||
|   if empty(bin_path) | ||||
|     return | ||||
| @ -117,7 +125,7 @@ function s:parse_errors(exit_val, bang, out) | ||||
|   silent! checktime | ||||
|   let &autoread = current_autoread | ||||
|  | ||||
|   let l:listtype = "quickfix" | ||||
|   let l:listtype = go#list#Type("GoRename") | ||||
|   if a:exit_val != 0 | ||||
|     call go#util#EchoError("FAILED") | ||||
|     let errors = go#tool#ParseErrors(a:out) | ||||
| @ -127,7 +135,7 @@ function s:parse_errors(exit_val, bang, out) | ||||
|       call go#list#JumpToFirst(l:listtype) | ||||
|     elseif empty(errors) | ||||
|       " failed to parse errors, output the original content | ||||
|       call go#util#EchoError(join(a:out, "")) | ||||
|       call go#util#EchoError(a:out) | ||||
|     endif | ||||
|  | ||||
|     return | ||||
| @ -146,4 +154,13 @@ function s:parse_errors(exit_val, bang, out) | ||||
|   silent execute ":e" | ||||
| endfunction | ||||
|  | ||||
| " Commandline completion: original, unexported camelCase, and exported | ||||
| " CamelCase. | ||||
| function! go#rename#Complete(lead, cmdline, cursor) | ||||
|   let l:word = expand('<cword>') | ||||
|   return filter(uniq(sort( | ||||
|         \ [l:word, go#util#camelcase(l:word), go#util#pascalcase(l:word)])), | ||||
|         \ 'strpart(v:val, 0, len(a:lead)) == a:lead') | ||||
| endfunction | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
| @ -95,12 +95,12 @@ func s:write_out(out) abort | ||||
|  | ||||
|   if has_key(result, 'errors') | ||||
|     let l:winnr = winnr() | ||||
|     let l:listtype = go#list#Type("quickfix") | ||||
|     let l:listtype = go#list#Type("GoModifyTags") | ||||
|     call go#list#ParseFormat(l:listtype, "%f:%l:%c:%m", result['errors'], "gomodifytags") | ||||
|     call go#list#Window(l:listtype, len(result['errors'])) | ||||
|  | ||||
|     "prevent jumping to quickfix list | ||||
|     exe l:winnr . "wincmd w"  | ||||
|     exe l:winnr . "wincmd w" | ||||
|   endif | ||||
| endfunc | ||||
|  | ||||
| @ -210,3 +210,5 @@ func s:create_cmd(args) abort | ||||
|  | ||||
|   return {'cmd': cmd} | ||||
| endfunc | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
| @ -1,28 +1,22 @@ | ||||
| func Test_add_tags() | ||||
|   let input_file = tempname() | ||||
|   call writefile(readfile("test-fixtures/tags/add_all_input.go"), input_file) | ||||
|  | ||||
|   let expected = join(readfile("test-fixtures/tags/add_all_golden.go"), "\n") | ||||
|  | ||||
|   " run for offset 40, which is inside the struct | ||||
|   call go#tags#run(0, 0, 40, "add", input_file, 1) | ||||
|  | ||||
|   let actual = join(readfile(input_file), "\n") | ||||
|  | ||||
|   call assert_equal(expected, actual) | ||||
| func! Test_add_tags() abort | ||||
|   try | ||||
|     let l:tmp = gotest#load_fixture('tags/add_all_input.go') | ||||
|     silent call go#tags#run(0, 0, 40, "add", bufname(''), 1) | ||||
|     call gotest#assert_fixture('tags/add_all_golden.go') | ||||
|   finally | ||||
|     call delete(l:tmp, 'rf') | ||||
|   endtry | ||||
| endfunc | ||||
|  | ||||
|  | ||||
| func Test_remove_tags() | ||||
|   let input_file = tempname() | ||||
|   call writefile(readfile("test-fixtures/tags/remove_all_input.go"), input_file) | ||||
|  | ||||
|   let expected = join(readfile("test-fixtures/tags/remove_all_golden.go"), "\n") | ||||
|  | ||||
|   " run for offset 40, which is inside the struct | ||||
|   call go#tags#run(0, 0, 40, "remove", input_file, 1) | ||||
|  | ||||
|   let actual = join(readfile(input_file), "\n") | ||||
|  | ||||
|   call assert_equal(expected, actual) | ||||
| func! Test_remove_tags() abort | ||||
|   try | ||||
|     let l:tmp = gotest#load_fixture('tags/remove_all_input.go') | ||||
|     silent call go#tags#run(0, 0, 40, "remove", bufname(''), 1) | ||||
|     call gotest#assert_fixture('tags/remove_all_golden.go') | ||||
|   finally | ||||
|     call delete(l:tmp, 'rf') | ||||
|   endtry | ||||
| endfunc | ||||
|  | ||||
| " vim:ts=2:sts=2:sw=2:et | ||||
|  | ||||
| @ -77,6 +77,7 @@ function! go#term#newmode(bang, cmd, mode) abort | ||||
|   call jobresize(id, width, height) | ||||
|  | ||||
|   let s:jobs[id] = job | ||||
|   stopinsert | ||||
|   return id | ||||
| endfunction | ||||
|  | ||||
| @ -104,7 +105,7 @@ function! s:on_exit(job_id, exit_status, event) dict abort | ||||
|   endif | ||||
|   let job = s:jobs[a:job_id] | ||||
|  | ||||
|   let l:listtype = "locationlist" | ||||
|   let l:listtype = go#list#Type("_term") | ||||
|  | ||||
|   " usually there is always output so never branch into this clause | ||||
|   if empty(job.stdout) | ||||
|  | ||||
| @ -6,9 +6,13 @@ function! go#test#Test(bang, compile, ...) abort | ||||
|  | ||||
|   " don't run the test, only compile it. Useful to capture and fix errors. | ||||
|   if a:compile | ||||
|     " we're going to tell to run a test function that doesn't exist. This | ||||
|     " triggers a build of the test file itself but no tests will run. | ||||
|     call extend(args, ["-run", "499EE4A2-5C85-4D35-98FC-7377CD87F263"]) | ||||
|     let testfile = tempname() . ".vim-go.test" | ||||
|     call extend(args, ["-c", "-o", testfile]) | ||||
|   endif | ||||
|  | ||||
|   if exists('g:go_build_tags') | ||||
|     let tags = get(g:, 'go_build_tags') | ||||
|     call extend(args, ["-tags", tags]) | ||||
|   endif | ||||
|  | ||||
|   if a:0 | ||||
| @ -33,9 +37,9 @@ function! go#test#Test(bang, compile, ...) abort | ||||
|  | ||||
|   if get(g:, 'go_echo_command_info', 1) | ||||
|     if a:compile | ||||
|       echon "vim-go: " | echohl Identifier | echon "compiling tests ..." | echohl None | ||||
|       call go#util#EchoProgress("compiling tests ...") | ||||
|     else | ||||
|       echon "vim-go: " | echohl Identifier | echon "testing ..." | echohl None | ||||
|       call go#util#EchoProgress("testing...") | ||||
|     endif | ||||
|   endif | ||||
|  | ||||
| @ -57,7 +61,7 @@ function! go#test#Test(bang, compile, ...) abort | ||||
|     if get(g:, 'go_term_enabled', 0) | ||||
|       let id = go#term#new(a:bang, ["go"] + args) | ||||
|     else | ||||
|       let id = go#jobcontrol#Spawn(a:bang, "test", args) | ||||
|       let id = go#jobcontrol#Spawn(a:bang, "test", "GoTest", args) | ||||
|     endif | ||||
|  | ||||
|     return id | ||||
| @ -69,7 +73,7 @@ function! go#test#Test(bang, compile, ...) abort | ||||
|   let command = "go " . join(args, ' ') | ||||
|   let out = go#tool#ExecuteInDir(command) | ||||
|  | ||||
|   let l:listtype = "quickfix" | ||||
|   let l:listtype = go#list#Type("GoTest") | ||||
|  | ||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
|   let dir = getcwd() | ||||
| @ -87,15 +91,15 @@ function! go#test#Test(bang, compile, ...) abort | ||||
|       " failed to parse errors, output the original content | ||||
|       call go#util#EchoError(out) | ||||
|     endif | ||||
|     echon "vim-go: " | echohl ErrorMsg | echon "[test] FAIL" | echohl None | ||||
|     call go#util#EchoError("[test] FAIL") | ||||
|   else | ||||
|     call go#list#Clean(l:listtype) | ||||
|     call go#list#Window(l:listtype) | ||||
|  | ||||
|     if a:compile | ||||
|       echon "vim-go: " | echohl Function | echon "[test] SUCCESS" | echohl None | ||||
|       call go#util#EchoSuccess("[test] SUCCESS") | ||||
|     else | ||||
|       echon "vim-go: " | echohl Function | echon "[test] PASS" | echohl None | ||||
|       call go#util#EchoSuccess("[test] PASS") | ||||
|     endif | ||||
|   endif | ||||
|   execute cd . fnameescape(dir) | ||||
| @ -172,12 +176,12 @@ function s:test_job(args) abort | ||||
|     if get(g:, 'go_echo_command_info', 1) | ||||
|       if a:exitval == 0 | ||||
|         if a:args.compile_test | ||||
|           call go#util#EchoSuccess("SUCCESS") | ||||
|           call go#util#EchoSuccess("[test] SUCCESS") | ||||
|         else | ||||
|           call go#util#EchoSuccess("PASS") | ||||
|           call go#util#EchoSuccess("[test] PASS") | ||||
|         endif | ||||
|       else | ||||
|         call go#util#EchoError("FAILED") | ||||
|         call go#util#EchoError("[test] FAIL") | ||||
|       endif | ||||
|     endif | ||||
|  | ||||
| @ -188,7 +192,7 @@ function s:test_job(args) abort | ||||
|  | ||||
|     call go#statusline#Update(status_dir, status) | ||||
|  | ||||
|     let l:listtype = go#list#Type("quickfix") | ||||
|     let l:listtype = go#list#Type("GoTest") | ||||
|     if a:exitval == 0 | ||||
|       call go#list#Clean(l:listtype) | ||||
|       call go#list#Window(l:listtype) | ||||
| @ -222,9 +226,9 @@ endfunction | ||||
|  | ||||
| " show_errors parses the given list of lines of a 'go test' output and returns | ||||
| " a quickfix compatible list of errors. It's intended to be used only for go | ||||
| " test output.  | ||||
| " test output. | ||||
| function! s:show_errors(args, exit_val, messages) abort | ||||
|   let l:listtype = go#list#Type("quickfix") | ||||
|   let l:listtype = go#list#Type("GoTest") | ||||
|  | ||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
|   try | ||||
| @ -237,7 +241,7 @@ function! s:show_errors(args, exit_val, messages) abort | ||||
|  | ||||
|   if !len(errors) | ||||
|     " failed to parse errors, output the original content | ||||
|     call go#util#EchoError(join(a:messages, " ")) | ||||
|     call go#util#EchoError(a:messages) | ||||
|     call go#util#EchoError(a:args.dir) | ||||
|     return | ||||
|   endif | ||||
| @ -253,28 +257,85 @@ endfunction | ||||
|  | ||||
| function! s:parse_errors(lines) abort | ||||
|   let errors = [] | ||||
|   let paniced = 0 " signals whether all remaining lines should be included in errors. | ||||
|   let test = '' | ||||
|  | ||||
|   " NOTE(arslan): once we get JSON output everything will be easier :) | ||||
|   " https://github.com/golang/go/issues/2981 | ||||
|   for line in a:lines | ||||
|     let fatalerrors = matchlist(line, '^\(fatal error:.*\)$') | ||||
|     let tokens = matchlist(line, '^\s*\(.\{-}\.go\):\(\d\+\):\s*\(.*\)') | ||||
|  | ||||
|     let fatalerrors = matchlist(line, '^\(\(fatal error\|panic\):.*\)$') | ||||
|     if !empty(fatalerrors) | ||||
|       call add(errors, {"text": fatalerrors[1]}) | ||||
|     elseif !empty(tokens) | ||||
|       let paniced = 1 | ||||
|       call add(errors, {"text": line}) | ||||
|       continue | ||||
|     endif | ||||
|  | ||||
|     if !paniced | ||||
|       " Matches failure lines. These lines always have zero or more leading spaces followed by '-- FAIL: ', following by the test name followed by a space the duration of the test in parentheses | ||||
|       " e.g.: | ||||
|       "   '--- FAIL: TestSomething (0.00s)' | ||||
|       let failure = matchlist(line, '^ *--- FAIL: \(.*\) (.*)$') | ||||
|       if get(g:, 'go_test_prepend_name', 0) | ||||
|         if !empty(failure) | ||||
|           let test = failure[1] . ': ' | ||||
|           continue | ||||
|         endif | ||||
|       endif | ||||
|     endif | ||||
|  | ||||
|     let tokens = [] | ||||
|     if paniced | ||||
|       " Matches lines in stacktraces produced by panic. The lines always have | ||||
|       " one or more leading tabs, followed by the path to the file. The file | ||||
|       " path is followed by a colon and then the line number within the file | ||||
|       " where the panic occurred. After that there's a space and hexadecimal | ||||
|       " number. | ||||
|       " | ||||
|       " e.g.: | ||||
|       "   '\t/usr/local/go/src/time.go:1313 +0x5d' | ||||
|       let tokens = matchlist(line, '^\t\+\(.\{-}\.go\):\(\d\+\) \(+0x.*\)') | ||||
|     else | ||||
|       " matches lines produced by `go test`. All lines produced by `go test` | ||||
|       " that we're interested in start with zero or more spaces (increasing | ||||
|       " depth of subtests is represented by a similar increase in the number | ||||
|       " of spaces at the start of output lines. Top level tests start with | ||||
|       " zero leading spaces). Lines that indicate test status (e.g. RUN, FAIL, | ||||
|       " PASS) start after the spaces. Lines that indicate test failure | ||||
|       " location or test log message location (e.g.  "testing.T".Log) begin | ||||
|       " with the appropriate number of spaces for the current test level, | ||||
|       " followed by a tab, a filename , a colon, the line number, another | ||||
|       " colon, a space, and the failure or log message. | ||||
|       " | ||||
|       " e.g.: | ||||
|       "   '\ttime_test.go:30: Likely problem: the time zone files have not been installed.' | ||||
|       let tokens = matchlist(line, '^ *\t\+\(.\{-}\.go\):\(\d\+\):\s*\(.*\)') | ||||
|     endif | ||||
|  | ||||
|     if !empty(tokens) " Check whether the line may refer to a file. | ||||
|       " strip endlines of form ^M | ||||
|       let out = substitute(tokens[3], '\r$', '', '') | ||||
|       let file = fnamemodify(tokens[1], ':p') | ||||
|  | ||||
|       " Preserve the line when the filename is not readable. This is an | ||||
|       " unusual case, but possible; any test that produces lines that match | ||||
|       " the pattern used in the matchlist assigned to tokens is a potential | ||||
|       " source of this condition. For instance, github.com/golang/mock/gomock | ||||
|       " will sometimes produce lines that satisfy this condition. | ||||
|       if !filereadable(file) | ||||
|         call add(errors, {"text": test . line}) | ||||
|         continue | ||||
|       endif | ||||
|  | ||||
|       call add(errors, { | ||||
|             \ "filename" : fnamemodify(tokens[1], ':p'), | ||||
|             \ "filename" : file, | ||||
|             \ "lnum"     : tokens[2], | ||||
|             \ "text"     : out, | ||||
|             \ "text"     : test . out, | ||||
|             \ }) | ||||
|     elseif paniced | ||||
|       call add(errors, {"text": line}) | ||||
|     elseif !empty(errors) | ||||
|       " Preserve indented lines. | ||||
|       " This comes up especially with multi-line test output. | ||||
|       if match(line, '^\s') >= 0 | ||||
|       " Preserve indented lines. This comes up especially with multi-line test output. | ||||
|       if match(line, '^ *\t\+') >= 0 | ||||
|         call add(errors, {"text": line}) | ||||
|       endif | ||||
|     endif | ||||
| @ -284,4 +345,3 @@ function! s:parse_errors(lines) abort | ||||
| endfunction | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
| " | ||||
|  | ||||
| @ -162,6 +162,18 @@ function! go#tool#FilterValids(items) abort | ||||
| endfunction | ||||
|  | ||||
| function! go#tool#ExecuteInDir(cmd) abort | ||||
|   " Verify that the directory actually exists. If the directory does not | ||||
|   " exist, then assume that the a:cmd should not be executed. Callers expect | ||||
|   " to check v:shell_error (via go#util#ShellError()), so execute a command | ||||
|   " that will return an error as if a:cmd was run and exited with an error. | ||||
|   " This helps avoid errors when working with plugins that use virtual files | ||||
|   " that don't actually exist on the file system (e.g. vim-fugitive's | ||||
|   " GitDiff). | ||||
|   if !isdirectory(expand("%:p:h")) | ||||
|     let [out, err] = go#util#Exec(["false"]) | ||||
|     return '' | ||||
|   endif | ||||
|  | ||||
|   let old_gopath = $GOPATH | ||||
|   let old_goroot = $GOROOT | ||||
|   let $GOPATH = go#path#Detect() | ||||
| @ -194,7 +206,6 @@ function! go#tool#Exists(importpath) abort | ||||
|     return 0 | ||||
| endfunction | ||||
|  | ||||
|  | ||||
| " following two functions are from: https://github.com/mattn/gist-vim | ||||
| " thanks  @mattn | ||||
| function! s:get_browser_command() abort | ||||
| @ -202,12 +213,14 @@ function! s:get_browser_command() abort | ||||
|     if go_play_browser_command == '' | ||||
|         if go#util#IsWin() | ||||
|             let go_play_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%' | ||||
|         elseif has('mac') || has('macunix') || has('gui_macvim') || go#util#System('uname') =~? '^darwin' | ||||
|         elseif go#util#IsMac() | ||||
|             let go_play_browser_command = 'open %URL%' | ||||
|         elseif executable('xdg-open') | ||||
|             let go_play_browser_command = 'xdg-open %URL%' | ||||
|         elseif executable('firefox') | ||||
|             let go_play_browser_command = 'firefox %URL% &' | ||||
|         elseif executable('chromium') | ||||
|             let go_play_browser_command = 'chromium %URL% &' | ||||
|         else | ||||
|             let go_play_browser_command = '' | ||||
|         endif | ||||
|  | ||||
| @ -43,6 +43,14 @@ function! go#util#IsWin() abort | ||||
|   return 0 | ||||
| endfunction | ||||
|  | ||||
| " IsMac returns 1 if current OS is macOS or 0 otherwise. | ||||
| function! go#util#IsMac() abort | ||||
|   return has('mac') || | ||||
|         \ has('macunix') || | ||||
|         \ has('gui_macvim') || | ||||
|         \ go#util#System('uname') =~? '^darwin' | ||||
| endfunction | ||||
|  | ||||
|  " Checks if using: | ||||
|  " 1) Windows system, | ||||
|  " 2) And has cygpath executable, | ||||
| @ -110,25 +118,22 @@ function! go#util#osarch() abort | ||||
|   return go#util#env("goos") . '_' . go#util#env("goarch") | ||||
| endfunction | ||||
|  | ||||
| " System runs a shell command. If possible, it will temporary set | ||||
| " the shell to /bin/sh for Unix-like systems providing a Bourne | ||||
| " POSIX like environment. | ||||
| function! go#util#System(str, ...) abort | ||||
| " Run a shell command. | ||||
| " | ||||
| " It will temporary set the shell to /bin/sh for Unix-like systems if possible, | ||||
| " so that we always use a standard POSIX-compatible Bourne shell (and not e.g. | ||||
| " csh, fish, etc.) See #988 and #1276. | ||||
| function! s:system(cmd, ...) abort | ||||
|   " Preserve original shell and shellredir values | ||||
|   let l:shell = &shell | ||||
|   let l:shellredir = &shellredir | ||||
|  | ||||
|   " Use a Bourne POSIX like shell. Some parts of vim-go expect | ||||
|   " commands to be executed using bourne semantics #988 and #1276. | ||||
|   " Alter shellredir to match bourne. Especially important if login shell | ||||
|   " is set to any of the csh or zsh family #1276. | ||||
|   if !go#util#IsWin() && executable('/bin/sh') | ||||
|       set shell=/bin/sh shellredir=>%s\ 2>&1 | ||||
|   endif | ||||
|  | ||||
|   try | ||||
|     let l:output = call('system', [a:str] + a:000) | ||||
|     return l:output | ||||
|     return call('system', [a:cmd] + a:000) | ||||
|   finally | ||||
|     " Restore original values | ||||
|     let &shell = l:shell | ||||
| @ -136,6 +141,31 @@ function! go#util#System(str, ...) abort | ||||
|   endtry | ||||
| endfunction | ||||
|  | ||||
| " System runs a shell command "str". Every arguments after "str" is passed to | ||||
| " stdin. | ||||
| function! go#util#System(str, ...) abort | ||||
|   return call('s:system', [a:str] + a:000) | ||||
| endfunction | ||||
|  | ||||
| " Exec runs a shell command "cmd", which must be a list, one argument per item. | ||||
| " Every list entry will be automatically shell-escaped | ||||
| " Every other argument is passed to stdin. | ||||
| function! go#util#Exec(cmd, ...) abort | ||||
|   if len(a:cmd) == 0 | ||||
|     call go#util#EchoError("go#util#Exec() called with empty a:cmd") | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   " CheckBinPath will show a warning for us. | ||||
|   let l:bin = go#path#CheckBinPath(a:cmd[0]) | ||||
|   if empty(l:bin) | ||||
|     return ["", 1] | ||||
|   endif | ||||
|  | ||||
|   let l:out = call('s:system', [go#util#Shelljoin([l:bin] + a:cmd[1:])] + a:000) | ||||
|   return [l:out, go#util#ShellError()] | ||||
| endfunction | ||||
|  | ||||
| function! go#util#ShellError() abort | ||||
|   return v:shell_error | ||||
| endfunction | ||||
| @ -242,50 +272,71 @@ endfunction | ||||
| " snakecase converts a string to snake case. i.e: FooBar -> foo_bar | ||||
| " Copied from tpope/vim-abolish | ||||
| function! go#util#snakecase(word) abort | ||||
|   let word = substitute(a:word,'::','/','g') | ||||
|   let word = substitute(word,'\(\u\+\)\(\u\l\)','\1_\2','g') | ||||
|   let word = substitute(word,'\(\l\|\d\)\(\u\)','\1_\2','g') | ||||
|   let word = substitute(word,'[.-]','_','g') | ||||
|   let word = substitute(a:word, '::', '/', 'g') | ||||
|   let word = substitute(word, '\(\u\+\)\(\u\l\)', '\1_\2', 'g') | ||||
|   let word = substitute(word, '\(\l\|\d\)\(\u\)', '\1_\2', 'g') | ||||
|   let word = substitute(word, '[.-]', '_', 'g') | ||||
|   let word = tolower(word) | ||||
|   return word | ||||
| endfunction | ||||
|  | ||||
| " camelcase converts a string to camel case. i.e: FooBar -> fooBar | ||||
| " Copied from tpope/vim-abolish | ||||
| " camelcase converts a string to camel case. e.g. FooBar or foo_bar will become | ||||
| " fooBar. | ||||
| " Copied from tpope/vim-abolish. | ||||
| function! go#util#camelcase(word) abort | ||||
|   let word = substitute(a:word, '-', '_', 'g') | ||||
|   if word !~# '_' && word =~# '\l' | ||||
|     return substitute(word,'^.','\l&','') | ||||
|     return substitute(word, '^.', '\l&', '') | ||||
|   else | ||||
|     return substitute(word,'\C\(_\)\=\(.\)','\=submatch(1)==""?tolower(submatch(2)) : toupper(submatch(2))','g') | ||||
|     return substitute(word, '\C\(_\)\=\(.\)', '\=submatch(1)==""?tolower(submatch(2)) : toupper(submatch(2))','g') | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| " TODO(arslan): I couldn't parameterize the highlight types. Check if we can | ||||
| " simplify the following functions | ||||
| " pascalcase converts a string to 'PascalCase'. e.g. fooBar or foo_bar will | ||||
| " become FooBar. | ||||
| function! go#util#pascalcase(word) abort | ||||
|   let word = go#util#camelcase(a:word) | ||||
|   return toupper(word[0]) . word[1:] | ||||
| endfunction | ||||
|  | ||||
| " Echo a message to the screen and highlight it with the group in a:hi. | ||||
| " | ||||
| " NOTE(arslan): echon doesn't work well with redraw, thus echo doesn't print | ||||
| " even though we order it. However echom seems to be work fine. | ||||
| " The message can be a list or string; every line with be :echomsg'd separately. | ||||
| function! s:echo(msg, hi) | ||||
|   let l:msg = [] | ||||
|   if type(a:msg) != type([]) | ||||
|     let l:msg = split(a:msg, "\n") | ||||
|   else | ||||
|     let l:msg = a:msg | ||||
|   endif | ||||
|  | ||||
|   " Tabs display as ^I or <09>, so manually expand them. | ||||
|   let l:msg = map(l:msg, 'substitute(v:val, "\t", "        ", "")') | ||||
|  | ||||
|   exe 'echohl ' . a:hi | ||||
|   for line in l:msg | ||||
|     echom "vim-go: " . line | ||||
|   endfor | ||||
|   echohl None | ||||
| endfunction | ||||
|  | ||||
| function! go#util#EchoSuccess(msg) | ||||
|   redraw | echohl Function | echom "vim-go: " . a:msg | echohl None | ||||
|   call s:echo(a:msg, 'Function') | ||||
| endfunction | ||||
|  | ||||
| function! go#util#EchoError(msg) | ||||
|   redraw | echohl ErrorMsg | echom "vim-go: " . a:msg | echohl None | ||||
|   call s:echo(a:msg, 'ErrorMsg') | ||||
| endfunction | ||||
|  | ||||
| function! go#util#EchoWarning(msg) | ||||
|   redraw | echohl WarningMsg | echom "vim-go: " . a:msg | echohl None | ||||
|   call s:echo(a:msg, 'WarningMsg') | ||||
| endfunction | ||||
|  | ||||
| function! go#util#EchoProgress(msg) | ||||
|   redraw | echohl Identifier | echom "vim-go: " . a:msg | echohl None | ||||
|   call s:echo(a:msg, 'Identifier') | ||||
| endfunction | ||||
|  | ||||
| function! go#util#EchoInfo(msg) | ||||
|   redraw | echohl Debug | echom "vim-go: " . a:msg | echohl None | ||||
|   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' | ||||
| @ -299,4 +350,49 @@ 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 | ||||
|  | ||||
|  | ||||
| " Make a named temporary directory which starts with "prefix". | ||||
| " | ||||
| " Unfortunately Vim's tempname() is not portable enough across various systems; | ||||
| " see: https://github.com/mattn/vim-go/pull/3#discussion_r138084911 | ||||
| function! go#util#tempdir(prefix) abort | ||||
|   " See :help tempfile | ||||
|   if go#util#IsWin() | ||||
|     let l:dirs = [$TMP, $TEMP, 'c:\tmp', 'c:\temp'] | ||||
|   else | ||||
|     let l:dirs = [$TMPDIR, '/tmp', './', $HOME] | ||||
|   endif | ||||
|  | ||||
|   let l:dir = '' | ||||
|   for l:d in dirs | ||||
|     if !empty(l:d) && filewritable(l:d) == 2 | ||||
|       let l:dir = l:d | ||||
|       break | ||||
|     endif | ||||
|   endfor | ||||
|  | ||||
|   if l:dir == '' | ||||
|     echoerr 'Unable to find directory to store temporary directory in' | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   " Not great randomness, but "good enough" for our purpose here. | ||||
|   let l:rnd = sha256(printf('%s%s', localtime(), fnamemodify(bufname(''), ":p"))) | ||||
|   let l:tmp = printf("%s/%s%s", l:dir, a:prefix, l:rnd) | ||||
|   call mkdir(l:tmp, 'p', 0700) | ||||
|   return l:tmp | ||||
| endfunction | ||||
|  | ||||
| " vim: sw=2 ts=2 et | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 amix
					amix