mirror of
				https://github.com/amix/vimrc
				synced 2025-10-31 06:33:35 +08:00 
			
		
		
		
	Updated plugins
This commit is contained in:
		| @ -1,7 +1,7 @@ | ||||
| ## unplanned | ||||
|  | ||||
| BACKWARDS INCOMPATABILITIES: | ||||
| * g:go_highlight_fuction_arguments is renamed to g:go_highlight_function_parameters | ||||
| * g:go_highlight_function_arguments is renamed to g:go_highlight_function_parameters | ||||
|   [[GH-2117]](https://github.com/fatih/vim-go/pull/2117) | ||||
|  | ||||
| IMPROVEMENTS: | ||||
| @ -23,6 +23,20 @@ IMPROVEMENTS: | ||||
|   [[GH-2101]](https://github.com/fatih/vim-go/pull/2101) | ||||
| * Report errors in quickfix when Delve fails to start (e.g. compiler errors). | ||||
|   [[GH-2111]](https://github.com/fatih/vim-go/pull/2111) | ||||
| * Support undo_ftplugin, make most autocmd's buffer-local, and only do the bare | ||||
|   minimum based on file names alone. | ||||
|   [[GH-2108]](https://github.com/fatih/vim-go/pull/2108) | ||||
| * Write a message when `:GoInfo` can't display any results when `g:go_info_mode='gocode'`. | ||||
|   [[GH-2122]](https://github.com/fatih/vim-go/pull/2122) | ||||
| * Highlight fields followed by an operator when `g:go_highlight_fields` is set. | ||||
|   [[GH-1907]](https://github.com/fatih/vim-go/pull/1907) | ||||
| * Skip autosave actions when the buffer is not a readable file. | ||||
|   [[GH-2143]](https://github.com/fatih/vim-go/pull/2143) | ||||
| * Run `godef` from the current buffer's directory to make sure it works with modules. | ||||
|   [[GH-2150]](https://github.com/fatih/vim-go/pull/2150) | ||||
| * Add a function, `go#tool#DescribeBalloon`, to show information in a balloon | ||||
|   with `'balloonexpr`. (Vim8 only). | ||||
|   [[GH-1975]](https://github.com/fatih/vim-go/pull/1975) | ||||
|  | ||||
| BUG FIXES: | ||||
| * Fix opening of non-existent file from `:GoDeclsDir` when the current | ||||
| @ -43,6 +57,15 @@ BUG FIXES: | ||||
|   [[GH-2109]](https://github.com/fatih/vim-go/pull/2109) | ||||
| * Highlight return parameter types when g:go_highlight_function_arguments is set. | ||||
|   [[GH-2116]](https://github.com/fatih/vim-go/pull/2116) | ||||
| * Fix lockup in Neovim when trying to run `:GoDebugTest` when there are no tests. | ||||
|   [[GH-2125]](https://github.com/fatih/vim-go/pull/2125) | ||||
| * Keep track of breakpoints correctly when buffer is edited after breakpoints | ||||
|   are set. | ||||
|   [[GH-2126]](https://github.com/fatih/vim-go/pull/2126) | ||||
| * Fix race conditions in `:GoDebugStop`. | ||||
|   [[GH-2127]](https://github.com/fatih/vim-go/pull/2127) | ||||
| * Fix jumping to module or package using godef. | ||||
|   [[GH-2141]](https://github.com/fatih/vim-go/pull/2141) | ||||
|  | ||||
| ## 1.19 - (November 4, 2018) | ||||
|  | ||||
| @ -238,7 +261,7 @@ BUG FIXES: | ||||
| FEATURES: | ||||
|  | ||||
| * **Debugger support!** Add integrated support for the | ||||
|   [`delve`](https://github.com/derekparker/delve) debugger. Use | ||||
|   [`delve`](https://github.com/go-delve/delve) debugger. Use | ||||
|   `:GoInstallBinaries` to install `dlv`, and see `:help go-debug` to get | ||||
|   started. | ||||
|   [[GH-1390]](https://github.com/fatih/vim-go/pull/1390) | ||||
|  | ||||
| @ -177,7 +177,7 @@ function! go#cmd#Run(bang, ...) abort | ||||
|   endtry | ||||
|  | ||||
|   let items = go#list#Get(l:listtype) | ||||
|   let errors = go#tool#FilterValids(items) | ||||
|   let errors = go#util#FilterValids(items) | ||||
|  | ||||
|   call go#list#Populate(l:listtype, errors, &makeprg) | ||||
|   call go#list#Window(l:listtype, len(errors)) | ||||
|  | ||||
| @ -197,16 +197,18 @@ function! s:info_filter(echo, result) abort | ||||
|   let wordMatch = substitute(wordMatch, "'", "''", "g") | ||||
|   let filtered = filter(l:candidates, "v:val.info =~ '".wordMatch."'") | ||||
|  | ||||
|   if len(l:filtered) != 1 | ||||
|     return "" | ||||
|   if len(l:filtered) == 0 | ||||
|     return "no matches" | ||||
|   elseif len(l:filtered) > 1 | ||||
|     return "ambiguous match" | ||||
|   endif | ||||
|  | ||||
|   return l:filtered[0].info | ||||
| endfunction | ||||
|  | ||||
| function! s:info_complete(echo, result) abort | ||||
|   if a:echo && !empty(a:result) | ||||
|     echo "vim-go: " | echohl Function | echon a:result | echohl None | ||||
|   if a:echo | ||||
|     call go#util#ShowInfo(a:result) | ||||
|   endif | ||||
|  | ||||
|   return a:result | ||||
|  | ||||
| @ -440,6 +440,11 @@ function! go#config#FoldEnable(...) abort | ||||
|   return get(g:, 'go_fold_enable', ['block', 'import', 'varconst', 'package_comment']) | ||||
| endfunction | ||||
|  | ||||
| function! go#config#EchoGoInfo() abort | ||||
|   return get(g:, "go_echo_go_info", 1) | ||||
| endfunction | ||||
|  | ||||
|  | ||||
| " Set the default value. A value of "1" is a shortcut for this, for | ||||
| " compatibility reasons. | ||||
| if exists("g:go_gorename_prefill") && g:go_gorename_prefill == 1 | ||||
|  | ||||
| @ -112,7 +112,7 @@ function! go#coverage#Browser(bang, ...) abort | ||||
|   let id = call('go#test#Test', args) | ||||
|  | ||||
|   if go#util#ShellError() == 0 | ||||
|     call go#tool#ExecuteInDir(['go', 'tool', 'cover', '-html=' . l:tmpname]) | ||||
|     call go#util#ExecInDir(['go', 'tool', 'cover', '-html=' . l:tmpname]) | ||||
|   endif | ||||
|  | ||||
|   call delete(l:tmpname) | ||||
| @ -284,7 +284,7 @@ endfunction | ||||
|  | ||||
| function! s:coverage_browser_callback(coverfile, job, exit_status, data) | ||||
|   if a:exit_status == 0 | ||||
|     call go#tool#ExecuteInDir(['go', 'tool', 'cover', '-html=' . a:coverfile]) | ||||
|     call go#util#ExecInDir(['go', 'tool', 'cover', '-html=' . a:coverfile]) | ||||
|   endif | ||||
|  | ||||
|   call delete(a:coverfile) | ||||
|  | ||||
| @ -8,7 +8,6 @@ if !exists('s:state') | ||||
|   let s:state = { | ||||
|       \ 'rpcid': 1, | ||||
|       \ 'running': 0, | ||||
|       \ 'breakpoint': {}, | ||||
|       \ 'currentThread': {}, | ||||
|       \ 'localVars': {}, | ||||
|       \ 'functionArgs': {}, | ||||
| @ -101,6 +100,9 @@ function! s:call_jsonrpc(method, ...) abort | ||||
|       call chansend(l:ch, l:req_json) | ||||
|       while len(s:state.data) == 0 | ||||
|         sleep 50m | ||||
|         if get(s:state, 'ready', 0) == 0 | ||||
|           return | ||||
|         endif | ||||
|       endwhile | ||||
|       let resp_json = s:state.data[0] | ||||
|       let s:state.data = s:state.data[1:] | ||||
| @ -235,7 +237,11 @@ function! s:stop() abort | ||||
|  | ||||
|   if has_key(s:state, 'job') | ||||
|     call go#job#Wait(s:state['job']) | ||||
|     call remove(s:state, 'job') | ||||
|  | ||||
|     " while waiting, the s:complete may have already removed job from s:state. | ||||
|     if has_key(s:state, 'job') | ||||
|       call remove(s:state, 'job') | ||||
|     endif | ||||
|   endif | ||||
|  | ||||
|   if has_key(s:state, 'ready') | ||||
| @ -250,16 +256,6 @@ function! s:stop() abort | ||||
| endfunction | ||||
|  | ||||
| function! go#debug#Stop() abort | ||||
|   " TODO(bc): don't remove breakpoints that were set before debugging started | ||||
|   " (see out_cb). | ||||
|   " Remove signs. | ||||
|   for k in keys(s:state['breakpoint']) | ||||
|     let bt = s:state['breakpoint'][k] | ||||
|     if bt.id >= 0 | ||||
|       silent exe 'sign unplace ' . bt.id | ||||
|     endif | ||||
|   endfor | ||||
|  | ||||
|   " Remove all commands and add back the default commands. | ||||
|   for k in map(split(execute('command GoDebug'), "\n")[1:], 'matchstr(v:val, "^\\s*\\zs\\S\\+")') | ||||
|     exe 'delcommand' k | ||||
| @ -286,8 +282,8 @@ function! go#debug#Stop() abort | ||||
|   silent! exe bufwinnr(bufnr('__GODEBUG_OUTPUT__')) 'wincmd c' | ||||
|  | ||||
|   if has('balloon_eval') | ||||
|     set noballooneval | ||||
|     set balloonexpr= | ||||
|     let &noballooneval=s:ballooneval | ||||
|     let &balloonexpr=s:balloonexpr | ||||
|   endif | ||||
|  | ||||
|   augroup vim-go-debug | ||||
| @ -413,18 +409,8 @@ function! s:expand_var() abort | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:start_cb(res) abort | ||||
|   if empty(a:res) || !has_key(a:res, 'result') | ||||
|     return | ||||
|   endif | ||||
|   for bt in a:res.result.Breakpoints | ||||
|     if bt.id >= 0 | ||||
|       let s:state['breakpoint'][bt.id] = bt | ||||
|       exe 'sign place '. bt.id .' line=' . bt.line . ' name=godebugbreakpoint file=' . bt.file | ||||
|     endif | ||||
|   endfor | ||||
|  | ||||
|   let oldbuf = bufnr('%') | ||||
| function! s:start_cb() abort | ||||
|   let l:winid = win_getid() | ||||
|   silent! only! | ||||
|  | ||||
|   let winnum = bufwinnr(bufnr('__GODEBUG_STACKTRACE__')) | ||||
| @ -480,11 +466,14 @@ function! s:start_cb(res) abort | ||||
|   nnoremap <silent> <Plug>(go-debug-print)      :<C-u>call go#debug#Print(expand('<cword>'))<CR> | ||||
|  | ||||
|   if has('balloon_eval') | ||||
|     let s:balloonexpr=&balloonexpr | ||||
|     let s:ballooneval=&ballooneval | ||||
|  | ||||
|     set balloonexpr=go#debug#BalloonExpr() | ||||
|     set ballooneval | ||||
|   endif | ||||
|  | ||||
|   exe bufwinnr(oldbuf) 'wincmd w' | ||||
|   call win_gotoid(l:winid) | ||||
|  | ||||
|   augroup vim-go-debug | ||||
|     autocmd! * <buffer> | ||||
| @ -560,15 +549,14 @@ function! s:out_cb(ch, msg) abort | ||||
|     " future messages. | ||||
|     let s:state['ready'] = 1 | ||||
|  | ||||
|     " Tell dlv about the breakpoints that the user added before delve started. | ||||
|     let l:breaks = copy(s:state.breakpoint) | ||||
|     let s:state['breakpoint'] = {} | ||||
|     for l:bt in values(l:breaks) | ||||
|       call go#debug#Breakpoint(bt.line) | ||||
|     " replace all the breakpoints set before delve started so that the ids won't overlap. | ||||
|     let l:breakpoints = s:list_breakpoints() | ||||
|     for l:bt in s:list_breakpoints() | ||||
|       exe 'sign unplace '. l:bt.id | ||||
|       call go#debug#Breakpoint(l:bt.line, l:bt.file) | ||||
|     endfor | ||||
|  | ||||
|     let res = s:call_jsonrpc('RPCServer.ListBreakpoints') | ||||
|     call s:start_cb(res) | ||||
|     call s:start_cb() | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| @ -753,13 +741,12 @@ endfunction | ||||
|  | ||||
| function! s:eval(arg) abort | ||||
|   try | ||||
|     let res = s:call_jsonrpc('RPCServer.State') | ||||
|     let goroutineID = res.result.State.currentThread.goroutineID | ||||
|     let res = s:call_jsonrpc('RPCServer.Eval', { | ||||
|     let l:res = s:call_jsonrpc('RPCServer.State') | ||||
|     let l:res = s:call_jsonrpc('RPCServer.Eval', { | ||||
|           \ 'expr':  a:arg, | ||||
|           \ 'scope': {'GoroutineID': goroutineID} | ||||
|           \ 'scope': {'GoroutineID': l:res.result.State.currentThread.goroutineID} | ||||
|       \ }) | ||||
|     return s:eval_tree(res.result.Variable, 0) | ||||
|     return s:eval_tree(l:res.result.Variable, 0) | ||||
|   catch | ||||
|     call go#util#EchoError(v:exception) | ||||
|     return '' | ||||
| @ -809,12 +796,11 @@ endfunction | ||||
|  | ||||
| function! go#debug#Set(symbol, value) abort | ||||
|   try | ||||
|     let res = s:call_jsonrpc('RPCServer.State') | ||||
|     let goroutineID = res.result.State.currentThread.goroutineID | ||||
|     let l:res = s:call_jsonrpc('RPCServer.State') | ||||
|     call s:call_jsonrpc('RPCServer.Set', { | ||||
|           \ 'symbol': a:symbol, | ||||
|           \ 'value':  a:value, | ||||
|           \ 'scope':  {'GoroutineID': goroutineID} | ||||
|           \ 'scope':  {'GoroutineID': l:res.result.State.currentThread.goroutineID} | ||||
|     \ }) | ||||
|   catch | ||||
|     call go#util#EchoError(v:exception) | ||||
| @ -825,8 +811,8 @@ endfunction | ||||
|  | ||||
| function! s:update_stacktrace() abort | ||||
|   try | ||||
|     let res = s:call_jsonrpc('RPCServer.Stacktrace', {'id': s:groutineID(), 'depth': 5}) | ||||
|     call s:show_stacktrace(res) | ||||
|     let l:res = s:call_jsonrpc('RPCServer.Stacktrace', {'id': s:groutineID(), 'depth': 5}) | ||||
|     call s:show_stacktrace(l:res) | ||||
|   catch | ||||
|     call go#util#EchoError(v:exception) | ||||
|   endtry | ||||
| @ -856,7 +842,7 @@ function! go#debug#Stack(name) abort | ||||
|   endif | ||||
|  | ||||
|   " Add a breakpoint to the main.Main if the user didn't define any. | ||||
|   if len(s:state['breakpoint']) is 0 | ||||
|   if len(s:list_breakpoints()) is 0 | ||||
|     if go#debug#Breakpoint() isnot 0 | ||||
|       let s:state.running = 0 | ||||
|       return | ||||
| @ -888,23 +874,15 @@ function! go#debug#Restart() abort | ||||
|   try | ||||
|     call s:stop() | ||||
|  | ||||
|     let l:breaks = s:state['breakpoint'] | ||||
|     let s:state = { | ||||
|         \ 'rpcid': 1, | ||||
|         \ 'running': 0, | ||||
|         \ 'breakpoint': {}, | ||||
|         \ 'currentThread': {}, | ||||
|         \ 'localVars': {}, | ||||
|         \ 'functionArgs': {}, | ||||
|         \ 'message': [], | ||||
|         \} | ||||
|  | ||||
|     " Preserve breakpoints. | ||||
|     for bt in values(l:breaks) | ||||
|       " TODO: should use correct filename | ||||
|       exe 'sign unplace '. bt.id .' file=' . bt.file | ||||
|       call go#debug#Breakpoint(bt.line) | ||||
|     endfor | ||||
|     call call('go#debug#Start', s:start_args) | ||||
|   catch | ||||
|     call go#util#EchoError(v:exception) | ||||
| @ -919,47 +897,45 @@ endfunction | ||||
| " Toggle breakpoint. Returns 0 on success and 1 on failure. | ||||
| function! go#debug#Breakpoint(...) abort | ||||
|   let l:filename = fnamemodify(expand('%'), ':p:gs!\\!/!') | ||||
|   let l:linenr = line('.') | ||||
|  | ||||
|   " Get line number from argument. | ||||
|   if len(a:000) > 0 | ||||
|     let linenr = str2nr(a:1) | ||||
|     if linenr is 0 | ||||
|     let l:linenr = str2nr(a:1) | ||||
|     if l:linenr is 0 | ||||
|       call go#util#EchoError('not a number: ' . a:1) | ||||
|       return 0 | ||||
|     endif | ||||
|   else | ||||
|     let linenr = line('.') | ||||
|     if len(a:000) > 1 | ||||
|       let l:filename = a:2 | ||||
|     endif | ||||
|   endif | ||||
|  | ||||
|   try | ||||
|     " Check if we already have a breakpoint for this line. | ||||
|     let found = {} | ||||
|     for k in keys(s:state.breakpoint) | ||||
|       let bt = s:state.breakpoint[k] | ||||
|       if bt.file == l:filename && bt.line == linenr | ||||
|         let found = bt | ||||
|     let l:found = {} | ||||
|     for l:bt in s:list_breakpoints() | ||||
|       if l:bt.file is# l:filename && l:bt.line is# l:linenr | ||||
|         let l:found = l:bt | ||||
|         break | ||||
|       endif | ||||
|     endfor | ||||
|  | ||||
|     " Remove breakpoint. | ||||
|     if type(found) == v:t_dict && !empty(found) | ||||
|       call remove(s:state['breakpoint'], bt.id) | ||||
|       exe 'sign unplace '. found.id .' file=' . found.file | ||||
|     if type(l:found) == v:t_dict && !empty(l:found) | ||||
|       exe 'sign unplace '. l:found.id .' file=' . l:found.file | ||||
|       if s:isActive() | ||||
|         let res = s:call_jsonrpc('RPCServer.ClearBreakpoint', {'id': found.id}) | ||||
|         let res = s:call_jsonrpc('RPCServer.ClearBreakpoint', {'id': l:found.id}) | ||||
|       endif | ||||
|     " Add breakpoint. | ||||
|     else | ||||
|       if s:isActive() | ||||
|         let res = s:call_jsonrpc('RPCServer.CreateBreakpoint', {'Breakpoint': {'file': l:filename, 'line': linenr}}) | ||||
|         let bt = res.result.Breakpoint | ||||
|         exe 'sign place '. bt.id .' line=' . bt.line . ' name=godebugbreakpoint file=' . bt.file | ||||
|         let s:state['breakpoint'][bt.id] = bt | ||||
|         let l:res = s:call_jsonrpc('RPCServer.CreateBreakpoint', {'Breakpoint': {'file': l:filename, 'line': l:linenr}}) | ||||
|         let l:bt = res.result.Breakpoint | ||||
|         exe 'sign place '. l:bt.id .' line=' . l:bt.line . ' name=godebugbreakpoint file=' . l:bt.file | ||||
|       else | ||||
|         let id = len(s:state['breakpoint']) + 1 | ||||
|         let s:state['breakpoint'][id] = {'id': id, 'file': l:filename, 'line': linenr} | ||||
|         exe 'sign place '. id .' line=' . linenr . ' name=godebugbreakpoint file=' . l:filename | ||||
|         let l:id = len(s:list_breakpoints()) + 1 | ||||
|         exe 'sign place ' . l:id . ' line=' . l:linenr . ' name=godebugbreakpoint file=' . l:filename | ||||
|       endif | ||||
|     endif | ||||
|   catch | ||||
| @ -970,8 +946,40 @@ function! go#debug#Breakpoint(...) abort | ||||
|   return 0 | ||||
| endfunction | ||||
|  | ||||
| function! s:list_breakpoints() | ||||
|   " :sign place | ||||
|   " --- Signs --- | ||||
|   " Signs for a.go: | ||||
|   "     line=15  id=2  name=godebugbreakpoint | ||||
|   "     line=16  id=1  name=godebugbreakpoint | ||||
|   " Signs for a_test.go: | ||||
|   "     line=6  id=3  name=godebugbreakpoint | ||||
|  | ||||
|   let l:signs = [] | ||||
|   let l:file = '' | ||||
|   for l:line in split(execute('sign place'), '\n')[1:] | ||||
|     if l:line =~# '^Signs for ' | ||||
|       let l:file = l:line[10:-2] | ||||
|       continue | ||||
|     endif | ||||
|  | ||||
|     if l:line !~# 'name=godebugbreakpoint' | ||||
|       continue | ||||
|     endif | ||||
|  | ||||
|     let l:sign = matchlist(l:line, '\vline\=(\d+) +id\=(\d+)') | ||||
|     call add(l:signs, { | ||||
|           \ 'id': l:sign[2], | ||||
|           \ 'file': fnamemodify(l:file, ':p'), | ||||
|           \ 'line': str2nr(l:sign[1]), | ||||
|     \ }) | ||||
|   endfor | ||||
|  | ||||
|   return l:signs | ||||
| endfunction | ||||
|  | ||||
| sign define godebugbreakpoint text=> texthl=GoDebugBreakpoint | ||||
| sign define godebugcurline text== linehl=GoDebugCurrent texthl=GoDebugCurrent | ||||
| sign define godebugcurline    text== texthl=GoDebugCurrent    linehl=GoDebugCurrent | ||||
|  | ||||
| " restore Vi compatibility settings | ||||
| let &cpo = s:cpo_save | ||||
|  | ||||
| @ -89,6 +89,7 @@ function! s:debug(...) abort | ||||
|     call assert_false(exists(':GoDebugStop')) | ||||
|  | ||||
|   finally | ||||
|     call go#debug#Breakpoint(6) | ||||
|     call delete(l:tmp, 'rf') | ||||
|   endtry | ||||
| endfunction | ||||
|  | ||||
| @ -22,9 +22,9 @@ function! go#def#Jump(mode) abort | ||||
|     if &modified | ||||
|       let l:stdin_content = join(go#util#GetLines(), "\n") | ||||
|       call add(l:cmd, "-i") | ||||
|       let [l:out, l:err] = go#util#Exec(l:cmd, l:stdin_content) | ||||
|       let [l:out, l:err] = go#util#ExecInDir(l:cmd, l:stdin_content) | ||||
|     else | ||||
|       let [l:out, l:err] = go#util#Exec(l:cmd) | ||||
|       let [l:out, l:err] = go#util#ExecInDir(l:cmd) | ||||
|     endif | ||||
|   elseif bin_name == 'guru' | ||||
|     let cmd = [go#path#CheckBinPath(bin_name)] | ||||
| @ -61,9 +61,9 @@ function! go#def#Jump(mode) abort | ||||
|     endif | ||||
|  | ||||
|     if &modified | ||||
|       let [l:out, l:err] = go#util#Exec(l:cmd, stdin_content) | ||||
|       let [l:out, l:err] = go#util#ExecInDir(l:cmd, l:stdin_content) | ||||
|     else | ||||
|       let [l:out, l:err] = go#util#Exec(l:cmd) | ||||
|       let [l:out, l:err] = go#util#ExecInDir(l:cmd) | ||||
|     endif | ||||
|   else | ||||
|     call go#util#EchoError('go_def_mode value: '. bin_name .' is not valid. Valid values are: [godef, guru]') | ||||
| @ -106,10 +106,24 @@ function! go#def#jump_to_declaration(out, mode, bin_name) abort | ||||
|     let parts = split(out, ':') | ||||
|   endif | ||||
|  | ||||
|   if len(parts) == 0 | ||||
|     call go#util#EchoError('go jump_to_declaration '. a:bin_name .' output is not valid.') | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   let line = 1 | ||||
|   let col = 1 | ||||
|   let ident = 0 | ||||
|   let filename = parts[0] | ||||
|   let line = parts[1] | ||||
|   let col = parts[2] | ||||
|   let ident = parts[3] | ||||
|   if len(parts) > 1 | ||||
|     let line = parts[1] | ||||
|   endif | ||||
|   if len(parts) > 2 | ||||
|     let col = parts[2] | ||||
|   endif | ||||
|   if len(parts) > 3 | ||||
|     let ident = parts[3] | ||||
|   endif | ||||
|  | ||||
|   " Remove anything newer than the current position, just like basic | ||||
|   " vim tag support | ||||
|  | ||||
| @ -35,7 +35,7 @@ function! go#doc#OpenBrowser(...) abort | ||||
|       let godoc_url .= "#" . name | ||||
|     endif | ||||
|  | ||||
|     call go#tool#OpenBrowser(godoc_url) | ||||
|     call go#util#OpenBrowser(godoc_url) | ||||
|     return | ||||
|   endif | ||||
|  | ||||
| @ -49,7 +49,7 @@ function! go#doc#OpenBrowser(...) abort | ||||
|  | ||||
|   " example url: https://godoc.org/github.com/fatih/set#Set | ||||
|   let godoc_url = go#config#DocUrl() . "/" . pkg . "#" . exported_name | ||||
|   call go#tool#OpenBrowser(godoc_url) | ||||
|   call go#util#OpenBrowser(godoc_url) | ||||
| endfunction | ||||
|  | ||||
| function! go#doc#Open(newmode, mode, ...) abort | ||||
|  | ||||
| @ -18,6 +18,7 @@ function! s:guru_cmd(args) range abort | ||||
|   let format = a:args.format | ||||
|   let needs_scope = a:args.needs_scope | ||||
|   let selected = a:args.selected | ||||
|   let postype = get(a:args, 'postype', 'cursor') | ||||
|  | ||||
|   let result = {} | ||||
|  | ||||
| @ -61,12 +62,16 @@ function! s:guru_cmd(args) range abort | ||||
|     call extend(cmd, ["-scope", l:scope]) | ||||
|   endif | ||||
|  | ||||
|   let pos = printf("#%s", go#util#OffsetCursor()) | ||||
|   if selected != -1 | ||||
|     " means we have a range, get it | ||||
|     let pos1 = go#util#Offset(line("'<"), col("'<")) | ||||
|     let pos2 = go#util#Offset(line("'>"), col("'>")) | ||||
|     let pos = printf("#%s,#%s", pos1, pos2) | ||||
|   if postype == 'balloon' | ||||
|     let pos = printf("#%s", go#util#Offset(v:beval_lnum, v:beval_col)) | ||||
|   else | ||||
|     let pos = printf("#%s", go#util#OffsetCursor()) | ||||
|     if selected != -1 | ||||
|       " means we have a range, get it | ||||
|       let pos1 = go#util#Offset(line("'<"), col("'<")) | ||||
|       let pos2 = go#util#Offset(line("'>"), col("'>")) | ||||
|       let pos = printf("#%s,#%s", pos1, pos2) | ||||
|     endif | ||||
|   endif | ||||
|  | ||||
|   let l:filename = fnamemodify(expand("%"), ':p:gs?\\?/?') . ':' . pos | ||||
| @ -282,7 +287,7 @@ function! go#guru#DescribeInfo(showstatus) abort | ||||
|         return | ||||
|       endif | ||||
|  | ||||
|       let info  = val["type"] | ||||
|       let info = val["type"] | ||||
|     elseif detail == "type" | ||||
|       if !has_key(result, 'type') | ||||
|         call go#util#EchoError("type key is missing. Please open a bug report on vim-go repo.") | ||||
| @ -295,7 +300,7 @@ function! go#guru#DescribeInfo(showstatus) abort | ||||
|         return | ||||
|       endif | ||||
|  | ||||
|       let info  = type["type"] | ||||
|       let info = type["type"] | ||||
|     elseif detail == "package" | ||||
|       if !has_key(result, 'package') | ||||
|         call go#util#EchoError("package key is missing. Please open a bug report on vim-go repo.") | ||||
| @ -316,7 +321,7 @@ function! go#guru#DescribeInfo(showstatus) abort | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|     echo "vim-go: " | echohl Function | echon info | echohl None | ||||
|     call go#util#ShowInfo(info) | ||||
|   endfunction | ||||
|  | ||||
|   let args = { | ||||
| @ -590,6 +595,141 @@ function! go#guru#Scope(...) abort | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! go#guru#DescribeBalloon() abort | ||||
|   " don't even try if async isn't available. | ||||
|   if !go#util#has_job() | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   " json_encode() and friends are introduced with this patch (7.4.1304) | ||||
|   " vim: https://groups.google.com/d/msg/vim_dev/vLupTNhQhZ8/cDGIk0JEDgAJ | ||||
|   " nvim: https://github.com/neovim/neovim/pull/4131 | ||||
|   if !exists("*json_decode") | ||||
|     call go#util#EchoError("requires 'json_decode'. Update your Vim/Neovim version.") | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   function! s:describe_balloon(exit_val, output, mode) | ||||
|     if a:exit_val != 0 | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|     if a:output[0] !=# '{' | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|     if empty(a:output) || type(a:output) != type("") | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|     let l:result = json_decode(a:output) | ||||
|     if type(l:result) != type({}) | ||||
|       call go#util#EchoError(printf('malformed output from guru: %s', a:output)) | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|     let l:info = [] | ||||
|     if has_key(l:result, 'desc') | ||||
|       if l:result['desc'] != 'identifier' | ||||
|         let l:info = add(l:info, l:result['desc']) | ||||
|       endif | ||||
|     endif | ||||
|  | ||||
|     if has_key(l:result, 'detail') | ||||
|       let l:detail = l:result['detail'] | ||||
|  | ||||
|       " guru gives different information based on the detail mode. Let try to | ||||
|       " extract the most useful information | ||||
|  | ||||
|       if l:detail == 'value' | ||||
|         if !has_key(l:result, 'value') | ||||
|           call go#util#EchoError('value key is missing. Please open a bug report on vim-go repo.') | ||||
|           return | ||||
|         endif | ||||
|  | ||||
|         let l:val = l:result['value'] | ||||
|         if !has_key(l:val, 'type') | ||||
|           call go#util#EchoError('type key is missing (value.type). Please open a bug report on vim-go repo.') | ||||
|           return | ||||
|         endif | ||||
|  | ||||
|         let l:info = add(l:info, printf('type: %s', l:val['type'])) | ||||
|         if has_key(l:val, 'value') | ||||
|           let l:info = add(l:info, printf('value: %s', l:val['value'])) | ||||
|         endif | ||||
|       elseif l:detail == 'type' | ||||
|         if !has_key(l:result, 'type') | ||||
|           call go#util#EchoError('type key is missing. Please open a bug report on vim-go repo.') | ||||
|           return | ||||
|         endif | ||||
|  | ||||
|         let l:type = l:result['type'] | ||||
|         if !has_key(l:type, 'type') | ||||
|           call go#util#EchoError('type key is missing (type.type). Please open a bug report on vim-go repo.') | ||||
|           return | ||||
|         endif | ||||
|  | ||||
|         let l:info = add(l:info, printf('type: %s', l:type['type'])) | ||||
|  | ||||
|         if has_key(l:type, 'methods') | ||||
|           let l:info = add(l:info, 'methods:') | ||||
|           for l:m in l:type.methods | ||||
|             let l:info = add(l:info, printf("\t%s", l:m['name'])) | ||||
|           endfor | ||||
|         endif | ||||
|       elseif l:detail == 'package' | ||||
|         if !has_key(l:result, 'package') | ||||
|           call go#util#EchoError('package key is missing. Please open a bug report on vim-go repo.') | ||||
|           return | ||||
|         endif | ||||
|  | ||||
|         let l:package = result['package'] | ||||
|         if !has_key(l:package, 'path') | ||||
|           call go#util#EchoError('path key is missing (package.path). Please open a bug report on vim-go repo.') | ||||
|           return | ||||
|         endif | ||||
|  | ||||
|         let l:info = add(l:info, printf('package: %s', l:package["path"])) | ||||
|       elseif l:detail == 'unknown' | ||||
|         " the description is already included in l:info, and there's no other | ||||
|         " information on unknowns. | ||||
|       else | ||||
|         call go#util#EchoError(printf('unknown detail mode (%s) found. Please open a bug report on vim-go repo', l:detail)) | ||||
|         return | ||||
|       endif | ||||
|     endif | ||||
|  | ||||
|     if has('balloon_eval') | ||||
|       call balloon_show(join(l:info, "\n")) | ||||
|       return | ||||
|     endif | ||||
|  | ||||
|     call balloon_show(l:info) | ||||
|   endfunction | ||||
|  | ||||
|  | ||||
|   " change the active window to the window where the cursor is. | ||||
|   let l:winid = win_getid(winnr()) | ||||
|   call win_gotoid(v:beval_winid) | ||||
|  | ||||
|   let l:args = { | ||||
|         \ 'mode': 'describe', | ||||
|         \ 'format': 'json', | ||||
|         \ 'selected': -1, | ||||
|         \ 'needs_scope': 0, | ||||
|         \ 'custom_parse': function('s:describe_balloon'), | ||||
|         \ 'disable_progress': 1, | ||||
|         \ 'postype': 'balloon', | ||||
|         \ } | ||||
|  | ||||
|   call s:async_guru(args) | ||||
|  | ||||
|   " make the starting window active again | ||||
|   call win_gotoid(l:winid) | ||||
|  | ||||
|   return '' | ||||
| endfunction | ||||
|  | ||||
| " restore Vi compatibility settings | ||||
| let &cpo = s:cpo_save | ||||
| unlet s:cpo_save | ||||
|  | ||||
| @ -7,7 +7,7 @@ let s:templatepath = go#util#Join(expand('<sfile>:p:h:h:h'), '.github', 'ISSUE_T | ||||
| function! go#issue#New() abort | ||||
|   let body = substitute(s:issuebody(), '[^A-Za-z0-9_.~-]', '\="%".printf("%02X",char2nr(submatch(0)))', 'g') | ||||
|   let url = "https://github.com/fatih/vim-go/issues/new?body=" . l:body | ||||
|   call go#tool#OpenBrowser(l:url) | ||||
|   call go#util#OpenBrowser(l:url) | ||||
| endfunction | ||||
|  | ||||
| function! s:issuebody() abort | ||||
|  | ||||
| @ -420,7 +420,7 @@ endfunction | ||||
|  | ||||
| function! go#job#Wait(job) abort | ||||
|   if has('nvim') | ||||
|     call jobwait(a:job) | ||||
|     call jobwait([a:job]) | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|  | ||||
| @ -66,7 +66,7 @@ function! go#package#ImportPath() abort | ||||
|     return s:import_paths[dir] | ||||
|   endif | ||||
|  | ||||
|   let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list']) | ||||
|   let [l:out, l:err] = go#util#ExecInDir(['go', 'list']) | ||||
|   if l:err != 0 | ||||
|     return -1 | ||||
|   endif | ||||
|  | ||||
| @ -35,7 +35,7 @@ function! go#play#Share(count, line1, line2) abort | ||||
|   endif | ||||
|  | ||||
|   if go#config#PlayOpenBrowser() | ||||
|     call go#tool#OpenBrowser(url) | ||||
|     call go#util#OpenBrowser(url) | ||||
|   endif | ||||
|  | ||||
|   echo "vim-go: snippet uploaded: ".url | ||||
|  | ||||
| @ -39,7 +39,7 @@ function! go#rename#Rename(bang, ...) abort | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   let [l:out, l:err] = go#tool#ExecuteInDir(l:cmd) | ||||
|   let [l:out, l:err] = go#util#ExecInDir(l:cmd) | ||||
|   call s:parse_errors(l:err, a:bang, split(l:out, '\n')) | ||||
| endfunction | ||||
|  | ||||
| @ -89,7 +89,7 @@ function s:parse_errors(exit_val, bang, out) | ||||
|  | ||||
|   let l:listtype = go#list#Type("GoRename") | ||||
|   if a:exit_val != 0 | ||||
|     let errors = go#tool#ParseErrors(a:out) | ||||
|     let errors = go#util#ParseErrors(a:out) | ||||
|     call go#list#Populate(l:listtype, errors, 'Rename') | ||||
|     call go#list#Window(l:listtype, len(errors)) | ||||
|     if !empty(errors) && !a:bang | ||||
|  | ||||
| @ -84,8 +84,8 @@ function! s:on_exit(job_id, exit_status, event) dict abort | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   let errors = go#tool#ParseErrors(self.stdout) | ||||
|   let errors = go#tool#FilterValids(errors) | ||||
|   let errors = go#util#ParseErrors(self.stdout) | ||||
|   let errors = go#util#FilterValids(errors) | ||||
|  | ||||
|   if !empty(errors) | ||||
|     " close terminal; we don't need it anymore | ||||
|  | ||||
| @ -64,7 +64,7 @@ function! go#test#Test(bang, compile, ...) abort | ||||
|  | ||||
|   let l:cmd = ['go'] + l:args | ||||
|  | ||||
|   let [l:out, l:err] = go#tool#ExecuteInDir(l:cmd) | ||||
|   let [l:out, l:err] = go#util#ExecInDir(l:cmd) | ||||
|   " TODO(bc): When the output is JSON, the JSON should be run through a | ||||
|   " filter to produce lines that are more easily described by errorformat. | ||||
|  | ||||
|  | ||||
| @ -40,7 +40,7 @@ function! go#tool#Files(...) abort | ||||
|     endif | ||||
|   endfor | ||||
|  | ||||
|   let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:combined]) | ||||
|   let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:combined]) | ||||
|   return split(l:out, '\n') | ||||
| endfunction | ||||
|  | ||||
| @ -50,7 +50,7 @@ function! go#tool#Deps() abort | ||||
|   else | ||||
|     let format = "{{range $f := .Deps}}{{$f}}\n{{end}}" | ||||
|   endif | ||||
|   let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:format]) | ||||
|   let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:format]) | ||||
|   return split(l:out, '\n') | ||||
| endfunction | ||||
|  | ||||
| @ -61,14 +61,14 @@ function! go#tool#Imports() abort | ||||
|   else | ||||
|     let format = "{{range $f := .Imports}}{{$f}}{{printf \"\\n\"}}{{end}}" | ||||
|   endif | ||||
|   let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:format]) | ||||
|   let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', l:format]) | ||||
|   if l:err != 0 | ||||
|     echo out | ||||
|     return imports | ||||
|   endif | ||||
|  | ||||
|   for package_path in split(out, '\n') | ||||
|     let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', '{{.Name}}', l:package_path]) | ||||
|     let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', '{{.Name}}', l:package_path]) | ||||
|     if l:err != 0 | ||||
|       echo out | ||||
|       return imports | ||||
| @ -92,7 +92,7 @@ function! go#tool#Info(showstatus) abort | ||||
| endfunction | ||||
|  | ||||
| function! go#tool#PackageName() abort | ||||
|   let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', '{{.Name}}']) | ||||
|   let [l:out, l:err] = go#util#ExecInDir(['go', 'list', '-tags', go#config#BuildTags(), '-f', '{{.Name}}']) | ||||
|   if l:err != 0 | ||||
|       return -1 | ||||
|   endif | ||||
| @ -100,92 +100,10 @@ function! go#tool#PackageName() abort | ||||
|   return split(out, '\n')[0] | ||||
| endfunction | ||||
|  | ||||
| function! go#tool#ParseErrors(lines) abort | ||||
|   let errors = [] | ||||
|  | ||||
|   for line in a:lines | ||||
|     let fatalerrors = matchlist(line, '^\(fatal error:.*\)$') | ||||
|     let tokens = matchlist(line, '^\s*\(.\{-}\):\(\d\+\):\s*\(.*\)') | ||||
|  | ||||
|     if !empty(fatalerrors) | ||||
|       call add(errors, {"text": fatalerrors[1]}) | ||||
|     elseif !empty(tokens) | ||||
|       " strip endlines of form ^M | ||||
|       let out = substitute(tokens[3], '\r$', '', '') | ||||
|  | ||||
|       call add(errors, { | ||||
|             \ "filename" : fnamemodify(tokens[1], ':p'), | ||||
|             \ "lnum"     : tokens[2], | ||||
|             \ "text"     : out, | ||||
|             \ }) | ||||
|     elseif !empty(errors) | ||||
|       " Preserve indented lines. | ||||
|       " This comes up especially with multi-line test output. | ||||
|       if match(line, '^\s') >= 0 | ||||
|         call add(errors, {"text": substitute(line, '\r$', '', '')}) | ||||
|       endif | ||||
|     endif | ||||
|   endfor | ||||
|  | ||||
|   return errors | ||||
| endfunction | ||||
|  | ||||
| " FilterValids filters the given items with only items that have a valid | ||||
| " filename. Any non valid filename is filtered out. | ||||
| function! go#tool#FilterValids(items) abort | ||||
|   " Remove any nonvalid filename from the location list to avoid opening an | ||||
|   " empty buffer. See https://github.com/fatih/vim-go/issues/287 for | ||||
|   " details. | ||||
|   let filtered = [] | ||||
|   let is_readable = {} | ||||
|  | ||||
|   for item in a:items | ||||
|     if has_key(item, 'bufnr') | ||||
|       let filename = bufname(item.bufnr) | ||||
|     elseif has_key(item, 'filename') | ||||
|       let filename = item.filename | ||||
|     else | ||||
|       " nothing to do, add item back to the list | ||||
|       call add(filtered, item) | ||||
|       continue | ||||
|     endif | ||||
|  | ||||
|     if !has_key(is_readable, filename) | ||||
|       let is_readable[filename] = filereadable(filename) | ||||
|     endif | ||||
|     if is_readable[filename] | ||||
|       call add(filtered, item) | ||||
|     endif | ||||
|   endfor | ||||
|  | ||||
|   for k in keys(filter(is_readable, '!v:val')) | ||||
|     echo "vim-go: " | echohl Identifier | echon "[run] Dropped " | echohl Constant | echon  '"' . k . '"' | ||||
|     echohl Identifier | echon " from location list (nonvalid filename)" | echohl None | ||||
|   endfor | ||||
|  | ||||
|   return filtered | ||||
| endfunction | ||||
|  | ||||
| function! go#tool#ExecuteInDir(cmd) abort | ||||
|   if !isdirectory(expand("%:p:h")) | ||||
|     return ['', 1] | ||||
|   endif | ||||
|  | ||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
|   let dir = getcwd() | ||||
|   try | ||||
|     execute cd . fnameescape(expand("%:p:h")) | ||||
|     let [l:out, l:err] = go#util#Exec(a:cmd) | ||||
|   finally | ||||
|     execute cd . fnameescape(l:dir) | ||||
|   endtry | ||||
|   return [l:out, l:err] | ||||
| endfunction | ||||
|  | ||||
| " Exists checks whether the given importpath exists or not. It returns 0 if | ||||
| " the importpath exists under GOPATH. | ||||
| function! go#tool#Exists(importpath) abort | ||||
|     let [l:out, l:err] = go#tool#ExecuteInDir(['go', 'list', a:importpath]) | ||||
|     let [l:out, l:err] = go#util#ExecInDir(['go', 'list', a:importpath]) | ||||
|     if l:err != 0 | ||||
|         return -1 | ||||
|     endif | ||||
| @ -193,28 +111,8 @@ function! go#tool#Exists(importpath) abort | ||||
|     return 0 | ||||
| endfunction | ||||
|  | ||||
| function! go#tool#OpenBrowser(url) abort | ||||
|     let l:cmd = go#config#PlayBrowserCommand() | ||||
|     if len(l:cmd) == 0 | ||||
|         redraw | ||||
|         echohl WarningMsg | ||||
|         echo "It seems that you don't have general web browser. Open URL below." | ||||
|         echohl None | ||||
|         echo a:url | ||||
|         return | ||||
|     endif | ||||
|  | ||||
|     " if setting starts with a !. | ||||
|     if l:cmd =~ '^!' | ||||
|         let l:cmd = substitute(l:cmd, '%URL%', '\=escape(shellescape(a:url), "#")', 'g') | ||||
|         silent! exec l:cmd | ||||
|     elseif cmd =~ '^:[A-Z]' | ||||
|         let l:cmd = substitute(l:cmd, '%URL%', '\=escape(a:url,"#")', 'g') | ||||
|         exec l:cmd | ||||
|     else | ||||
|         let l:cmd = substitute(l:cmd, '%URL%', '\=shellescape(a:url)', 'g') | ||||
|         call go#util#System(l:cmd) | ||||
|     endif | ||||
| function! go#tool#DescribeBalloon() | ||||
|   return go#guru#DescribeBalloon() | ||||
| endfunction | ||||
|  | ||||
| " restore Vi compatibility settings | ||||
|  | ||||
| @ -5,7 +5,7 @@ set cpo&vim | ||||
| func! Test_ExecuteInDir() abort | ||||
|   let l:tmp = gotest#write_file('a/a.go', ['package a']) | ||||
|   try | ||||
|     let l:out = go#tool#ExecuteInDir(['pwd']) | ||||
|     let l:out = go#util#ExecInDir(['pwd']) | ||||
|     call assert_equal([l:tmp . "/src/a\n", 0], l:out) | ||||
|   finally | ||||
|     call delete(l:tmp, 'rf') | ||||
| @ -17,7 +17,7 @@ func! Test_ExecuteInDir_nodir() abort | ||||
|   exe ':e ' . l:tmp . '/new-dir/a' | ||||
|  | ||||
|   try | ||||
|     let l:out = go#tool#ExecuteInDir(['pwd']) | ||||
|     let l:out = go#util#ExecInDir(['pwd']) | ||||
|     call assert_equal(['', 1], l:out) | ||||
|   finally | ||||
|     call delete(l:tmp, 'rf') | ||||
|  | ||||
| @ -196,6 +196,22 @@ function! go#util#Exec(cmd, ...) abort | ||||
|   return call('s:exec', [[l:bin] + a:cmd[1:]] + a:000) | ||||
| endfunction | ||||
|  | ||||
| function! go#util#ExecInDir(cmd, ...) abort | ||||
|   if !isdirectory(expand("%:p:h")) | ||||
|     return ['', 1] | ||||
|   endif | ||||
|  | ||||
|   let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' | ||||
|   let dir = getcwd() | ||||
|   try | ||||
|     execute cd . fnameescape(expand("%:p:h")) | ||||
|     let [l:out, l:err] = call('go#util#Exec', [a:cmd] + a:000) | ||||
|   finally | ||||
|     execute cd . fnameescape(l:dir) | ||||
|   endtry | ||||
|   return [l:out, l:err] | ||||
| endfunction | ||||
|  | ||||
| function! s:exec(cmd, ...) abort | ||||
|   let l:bin = a:cmd[0] | ||||
|   let l:cmd = go#util#Shelljoin([l:bin] + a:cmd[1:]) | ||||
| @ -441,6 +457,104 @@ function! go#util#HasDebug(flag) | ||||
|   return index(go#config#Debug(), a:flag) >= 0 | ||||
| endfunction | ||||
|  | ||||
| function! go#util#OpenBrowser(url) abort | ||||
|     let l:cmd = go#config#PlayBrowserCommand() | ||||
|     if len(l:cmd) == 0 | ||||
|         redraw | ||||
|         echohl WarningMsg | ||||
|         echo "It seems that you don't have general web browser. Open URL below." | ||||
|         echohl None | ||||
|         echo a:url | ||||
|         return | ||||
|     endif | ||||
|  | ||||
|     " if setting starts with a !. | ||||
|     if l:cmd =~ '^!' | ||||
|         let l:cmd = substitute(l:cmd, '%URL%', '\=escape(shellescape(a:url), "#")', 'g') | ||||
|         silent! exec l:cmd | ||||
|     elseif cmd =~ '^:[A-Z]' | ||||
|         let l:cmd = substitute(l:cmd, '%URL%', '\=escape(a:url,"#")', 'g') | ||||
|         exec l:cmd | ||||
|     else | ||||
|         let l:cmd = substitute(l:cmd, '%URL%', '\=shellescape(a:url)', 'g') | ||||
|         call go#util#System(l:cmd) | ||||
|     endif | ||||
| endfunction | ||||
|  | ||||
| function! go#util#ParseErrors(lines) abort | ||||
|   let errors = [] | ||||
|  | ||||
|   for line in a:lines | ||||
|     let fatalerrors = matchlist(line, '^\(fatal error:.*\)$') | ||||
|     let tokens = matchlist(line, '^\s*\(.\{-}\):\(\d\+\):\s*\(.*\)') | ||||
|  | ||||
|     if !empty(fatalerrors) | ||||
|       call add(errors, {"text": fatalerrors[1]}) | ||||
|     elseif !empty(tokens) | ||||
|       " strip endlines of form ^M | ||||
|       let out = substitute(tokens[3], '\r$', '', '') | ||||
|  | ||||
|       call add(errors, { | ||||
|             \ "filename" : fnamemodify(tokens[1], ':p'), | ||||
|             \ "lnum"     : tokens[2], | ||||
|             \ "text"     : out, | ||||
|             \ }) | ||||
|     elseif !empty(errors) | ||||
|       " Preserve indented lines. | ||||
|       " This comes up especially with multi-line test output. | ||||
|       if match(line, '^\s') >= 0 | ||||
|         call add(errors, {"text": substitute(line, '\r$', '', '')}) | ||||
|       endif | ||||
|     endif | ||||
|   endfor | ||||
|  | ||||
|   return errors | ||||
| endfunction | ||||
|  | ||||
| " FilterValids filters the given items with only items that have a valid | ||||
| " filename. Any non valid filename is filtered out. | ||||
| function! go#util#FilterValids(items) abort | ||||
|   " Remove any nonvalid filename from the location list to avoid opening an | ||||
|   " empty buffer. See https://github.com/fatih/vim-go/issues/287 for | ||||
|   " details. | ||||
|   let filtered = [] | ||||
|   let is_readable = {} | ||||
|  | ||||
|   for item in a:items | ||||
|     if has_key(item, 'bufnr') | ||||
|       let filename = bufname(item.bufnr) | ||||
|     elseif has_key(item, 'filename') | ||||
|       let filename = item.filename | ||||
|     else | ||||
|       " nothing to do, add item back to the list | ||||
|       call add(filtered, item) | ||||
|       continue | ||||
|     endif | ||||
|  | ||||
|     if !has_key(is_readable, filename) | ||||
|       let is_readable[filename] = filereadable(filename) | ||||
|     endif | ||||
|     if is_readable[filename] | ||||
|       call add(filtered, item) | ||||
|     endif | ||||
|   endfor | ||||
|  | ||||
|   for k in keys(filter(is_readable, '!v:val')) | ||||
|     echo "vim-go: " | echohl Identifier | echon "[run] Dropped " | echohl Constant | echon  '"' . k . '"' | ||||
|     echohl Identifier | echon " from location list (nonvalid filename)" | echohl None | ||||
|   endfor | ||||
|  | ||||
|   return filtered | ||||
| endfunction | ||||
|  | ||||
| function! go#util#ShowInfo(info) | ||||
|   if empty(a:info) | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   echo "vim-go: " | echohl Function | echon a:info | echohl None | ||||
| endfunction | ||||
|  | ||||
| " restore Vi compatibility settings | ||||
| let &cpo = s:cpo_save | ||||
| unlet s:cpo_save | ||||
|  | ||||
| @ -783,7 +783,7 @@ CTRL-t | ||||
|                                                                *:GoRemoveTags* | ||||
| :[range]GoRemoveTags [key],[option] [key1],[option1] ... | ||||
|  | ||||
|     Rmove field tags for the fields of a struct. If called inside a struct it | ||||
|     Remove field tags for the fields of a struct. If called inside a struct it | ||||
|     automatically remove all field tags. An error message is given if it's | ||||
|     called outside a struct definition or if the file is not correctly | ||||
|     formatted | ||||
| @ -1176,6 +1176,12 @@ cleaned for each package after `60` seconds. This can be changed with the | ||||
| Returns the description of the identifer under the cursor. Can be used to plug | ||||
| into the statusline. | ||||
|  | ||||
|  | ||||
|                                                    *go#tool#DescribeBalloon()* | ||||
|  | ||||
| Suitable to be used as an expression to show the evaluation balloon. See `help | ||||
| balloonexpr`. | ||||
|  | ||||
| ============================================================================== | ||||
| SETTINGS                                                        *go-settings* | ||||
|  | ||||
| @ -1303,7 +1309,7 @@ fails. By default the location list is shown. > | ||||
|  | ||||
| Use this option to enable fmt's experimental mode. This experimental mode is | ||||
| superior to the current mode as it fully saves the undo history, so undo/redo | ||||
| doesn't break. However it's slows (creates/deletes a file for every save) and | ||||
| doesn't break. However, it's slow (creates/deletes a file for every save) and | ||||
| it's causing problems on some Vim versions. By default it's disabled. > | ||||
|  | ||||
|   let g:go_fmt_experimental = 0 | ||||
|  | ||||
| @ -4,45 +4,19 @@ | ||||
| let s:cpo_save = &cpo | ||||
| set cpo&vim | ||||
|  | ||||
| " We take care to preserve the user's fileencodings and fileformats, | ||||
| " because those settings are global (not buffer local), yet we want | ||||
| " to override them for loading Go files, which are defined to be UTF-8. | ||||
| let s:current_fileformats = '' | ||||
| let s:current_fileencodings = '' | ||||
|  | ||||
| " define fileencodings to open as utf-8 encoding even if it's ascii. | ||||
| function! s:gofiletype_pre(type) | ||||
|   let s:current_fileformats = &g:fileformats | ||||
|   let s:current_fileencodings = &g:fileencodings | ||||
|   set fileencodings=utf-8 fileformats=unix | ||||
|   let &l:filetype = a:type | ||||
| endfunction | ||||
|  | ||||
| " restore fileencodings as others | ||||
| function! s:gofiletype_post() | ||||
|   let &g:fileformats = s:current_fileformats | ||||
|   let &g:fileencodings = s:current_fileencodings | ||||
| endfunction | ||||
|  | ||||
| " Note: should not use augroup in ftdetect (see :help ftdetect) | ||||
| au BufNewFile *.go setfiletype go | if &modifiable | setlocal fileencoding=utf-8 fileformat=unix | endif | ||||
| au BufRead *.go call s:gofiletype_pre("go") | ||||
| au BufReadPost *.go call s:gofiletype_post() | ||||
|  | ||||
| au BufNewFile *.s setfiletype asm | if &modifiable | setlocal fileencoding=utf-8 fileformat=unix | endif | ||||
| au BufRead *.s call s:gofiletype_pre("asm") | ||||
| au BufReadPost *.s call s:gofiletype_post() | ||||
|  | ||||
| au BufRead,BufNewFile *.tmpl set filetype=gohtmltmpl | ||||
| au BufRead,BufNewFile *.go setfiletype go | ||||
| au BufRead,BufNewFile *.s setfiletype asm | ||||
| au BufRead,BufNewFile *.tmpl setfiletype gohtmltmpl | ||||
|  | ||||
| " remove the autocommands for modsim3, and lprolog files so that their | ||||
| " highlight groups, syntax, etc. will not be loaded. *.MOD is included, so | ||||
| " that on case insensitive file systems the module2 autocmds will not be | ||||
| " executed. | ||||
| au! BufNewFile,BufRead *.mod,*.MOD | ||||
| au! BufRead,BufNewFile *.mod,*.MOD | ||||
| " Set the filetype if the first non-comment and non-blank line starts with | ||||
| " 'module <path>'. | ||||
| au BufNewFile,BufRead go.mod call s:gomod() | ||||
| au BufRead,BufNewFile go.mod call s:gomod() | ||||
|  | ||||
| fun! s:gomod() | ||||
|   for l:i in range(1, line('$')) | ||||
| @ -52,7 +26,7 @@ fun! s:gomod() | ||||
|     endif | ||||
|  | ||||
|     if l:l =~# '^module .\+' | ||||
|       set filetype=gomod | ||||
|       setfiletype gomod | ||||
|     endif | ||||
|  | ||||
|     break | ||||
|  | ||||
| @ -9,7 +9,8 @@ let b:did_ftplugin = 1 | ||||
| let s:cpo_save = &cpo | ||||
| set cpo&vim | ||||
|  | ||||
| let b:undo_ftplugin = "setl fo< com< cms<" | ||||
| let b:undo_ftplugin = "setl fo< com< cms< | ||||
|       \ | exe 'au! vim-go-asm-buffer * <buffer>'" | ||||
|  | ||||
| setlocal formatoptions-=t | ||||
|  | ||||
| @ -20,6 +21,15 @@ setlocal noexpandtab | ||||
|  | ||||
| command! -nargs=0 AsmFmt call go#asmfmt#Format() | ||||
|  | ||||
| " Autocommands | ||||
| " ============================================================================ | ||||
|  | ||||
| augroup vim-go-asm-buffer | ||||
|   autocmd! * <buffer> | ||||
|  | ||||
|   autocmd BufWritePre <buffer> call go#auto#asmfmt_autosave() | ||||
| augroup end | ||||
|  | ||||
| " restore Vi compatibility settings | ||||
| let &cpo = s:cpo_save | ||||
| unlet s:cpo_save | ||||
|  | ||||
| @ -13,7 +13,8 @@ let b:did_ftplugin = 1 | ||||
| let s:cpo_save = &cpo | ||||
| set cpo&vim | ||||
|  | ||||
| let b:undo_ftplugin = "setl fo< com< cms<" | ||||
| let b:undo_ftplugin = "setl fo< com< cms< | ||||
|       \ | exe 'au! vim-go-buffer * <buffer>'" | ||||
|  | ||||
| setlocal formatoptions-=t | ||||
|  | ||||
| @ -72,73 +73,42 @@ if go#config#AutoTypeInfo() || go#config#AutoSameids() | ||||
|   let &l:updatetime= get(g:, "go_updatetime", 800) | ||||
| endif | ||||
|  | ||||
| " NOTE(arslan): experimental, disabled by default, doesn't work well. No | ||||
| " documentation as well. If anyone feels adventurous, enable the following and | ||||
| " try to search for Go identifiers ;) | ||||
| " Autocommands | ||||
| " ============================================================================ | ||||
| " | ||||
| " if get(g:, "go_sameid_search_enabled", 0) | ||||
| "   autocmd FileType go nnoremap <buffer> <silent> * :<c-u>call Sameids_search(0)<CR> | ||||
| "   autocmd FileType go nnoremap <buffer> <silent> # :<c-u>call Sameids_search(1)<CR> | ||||
| "   autocmd FileType go nnoremap <buffer> <silent> n :<c-u>call Sameids_repeat(0)<CR> | ||||
| "   autocmd FileType go nnoremap <buffer> <silent> N :<c-u>call Sameids_repeat(1)<CR> | ||||
| "   autocmd FileType go cabbrev nohlsearch <C-r>=Sameids_nohlsearch()<CR> | ||||
| " endif | ||||
| augroup vim-go-buffer | ||||
|   autocmd! * <buffer> | ||||
|  | ||||
| " " mode 0: next 1: prev | ||||
| " function! Sameids_repeat(mode) | ||||
| "   let matches = getmatches() | ||||
| "   if empty(matches) | ||||
| "     return | ||||
| "   endif | ||||
| "   let cur_offset = go#util#OffsetCursor() | ||||
|   autocmd CursorHold <buffer> call go#auto#auto_type_info() | ||||
|   autocmd CursorHold <buffer> call go#auto#auto_sameids() | ||||
|  | ||||
| "   " reverse list to make it easy to find the prev occurrence | ||||
| "   if a:mode | ||||
| "    call reverse(matches) | ||||
| "   endif | ||||
|   " Echo the identifier information when completion is done. Useful to see | ||||
|   " the signature of a function, etc... | ||||
|   if exists('##CompleteDone') | ||||
|     autocmd CompleteDone <buffer> call go#auto#echo_go_info() | ||||
|   endif | ||||
|  | ||||
| "   for m in matches | ||||
| "     if !has_key(m, "group") | ||||
| "       return | ||||
| "     endif | ||||
|   autocmd BufWritePre <buffer> call go#auto#fmt_autosave() | ||||
|   autocmd BufWritePost <buffer> call go#auto#metalinter_autosave() | ||||
|  | ||||
| "     if m.group != "goSameId" | ||||
| "       return | ||||
| "     endif | ||||
|   " clear SameIds when the buffer is unloaded so that loading another buffer | ||||
|   " in the same window doesn't highlight the most recently matched | ||||
|   " identifier's positions. | ||||
|   autocmd BufWinEnter <buffer> call go#guru#ClearSameIds() | ||||
|  | ||||
| "     let offset = go#util#Offset(m.pos1[0], m.pos1[1]) | ||||
|  | ||||
| "     if a:mode && cur_offset > offset | ||||
| "       call cursor(m.pos1[0], m.pos1[1]) | ||||
| "       return | ||||
| "     elseif !a:mode && cur_offset < offset | ||||
| "       call cursor(m.pos1[0], m.pos1[1]) | ||||
| "       return | ||||
| "     endif | ||||
| "   endfor | ||||
|  | ||||
| "   " reached start/end, jump to the end/start | ||||
| "   let initial_match = matches[0] | ||||
| "   if !has_key(initial_match, "group") | ||||
| "     return | ||||
| "   endif | ||||
|  | ||||
| "   if initial_match.group != "goSameId" | ||||
| "     return | ||||
| "   endif | ||||
|  | ||||
| "   call cursor(initial_match.pos1[0], initial_match.pos1[1]) | ||||
| " endfunction | ||||
|  | ||||
| " function! Sameids_search(mode) | ||||
| "   call go#guru#SameIds() | ||||
| "   call Sameids_repeat(a:mode) | ||||
| " endfunction | ||||
|  | ||||
| " function! Sameids_nohlsearch() | ||||
| "   call go#guru#ClearSameIds() | ||||
| "   return "nohlsearch" | ||||
| " endfunction | ||||
|   autocmd BufEnter <buffer> | ||||
|         \  if go#config#AutodetectGopath() && !exists('b:old_gopath') | ||||
|         \|   let b:old_gopath = exists('$GOPATH') ? $GOPATH : -1 | ||||
|         \|   let $GOPATH = go#path#Detect() | ||||
|         \| endif | ||||
|   autocmd BufLeave <buffer> | ||||
|         \  if exists('b:old_gopath') | ||||
|         \|   if b:old_gopath isnot -1 | ||||
|         \|     let $GOPATH = b:old_gopath | ||||
|         \|   endif | ||||
|         \|   unlet b:old_gopath | ||||
|         \| endif | ||||
| augroup end | ||||
|  | ||||
| " restore Vi compatibility settings | ||||
| let &cpo = s:cpo_save | ||||
|  | ||||
| @ -9,13 +9,23 @@ let b:did_ftplugin = 1 | ||||
| let s:cpo_save = &cpo | ||||
| set cpo&vim | ||||
|  | ||||
| let b:undo_ftplugin = "setl fo< com< cms<" | ||||
| let b:undo_ftplugin = "setl fo< com< cms< | ||||
|       \ | exe 'au! vim-go-gomod-buffer * <buffer>'" | ||||
|  | ||||
| setlocal formatoptions-=t | ||||
|  | ||||
| setlocal comments=s1:/*,mb:*,ex:*/,:// | ||||
| setlocal commentstring=//\ %s | ||||
|  | ||||
| " Autocommands | ||||
| " ============================================================================ | ||||
|  | ||||
| augroup vim-go-gomod-buffer | ||||
|   autocmd! * <buffer> | ||||
|  | ||||
|   autocmd BufWritePre <buffer> call go#auto#modfmt_autosave() | ||||
| augroup end | ||||
|  | ||||
| " restore Vi compatibility settings | ||||
| let &cpo = s:cpo_save | ||||
| unlet s:cpo_save | ||||
|  | ||||
| @ -47,7 +47,7 @@ call s:checkVersion() | ||||
| " needed by the user with GoInstallBinaries. | ||||
| let s:packages = { | ||||
|       \ 'asmfmt':        ['github.com/klauspost/asmfmt/cmd/asmfmt'], | ||||
|       \ 'dlv':           ['github.com/derekparker/delve/cmd/dlv'], | ||||
|       \ 'dlv':           ['github.com/go-delve/delve/cmd/dlv'], | ||||
|       \ 'errcheck':      ['github.com/kisielk/errcheck'], | ||||
|       \ 'fillstruct':    ['github.com/davidrjenni/reftools/cmd/fillstruct'], | ||||
|       \ 'gocode':        ['github.com/mdempsky/gocode', {'windows': ['-ldflags', '-H=windowsgui']}], | ||||
| @ -212,110 +212,37 @@ endfunction | ||||
| " Autocommands | ||||
| " ============================================================================ | ||||
| " | ||||
| function! s:echo_go_info() | ||||
|   if !get(g:, "go_echo_go_info", 1) | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   if !exists('v:completed_item') || empty(v:completed_item) | ||||
|     return | ||||
|   endif | ||||
|   let item = v:completed_item | ||||
| " We take care to preserve the user's fileencodings and fileformats, | ||||
| " because those settings are global (not buffer local), yet we want | ||||
| " to override them for loading Go files, which are defined to be UTF-8. | ||||
| let s:current_fileformats = '' | ||||
| let s:current_fileencodings = '' | ||||
|  | ||||
|   if !has_key(item, "info") | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   if empty(item.info) | ||||
|     return | ||||
|   endif | ||||
|  | ||||
|   redraws! | echo "vim-go: " | echohl Function | echon item.info | echohl None | ||||
| " define fileencodings to open as utf-8 encoding even if it's ascii. | ||||
| function! s:gofiletype_pre() | ||||
|   let s:current_fileformats = &g:fileformats | ||||
|   let s:current_fileencodings = &g:fileencodings | ||||
|   set fileencodings=utf-8 fileformats=unix | ||||
| endfunction | ||||
|  | ||||
| function! s:auto_type_info() | ||||
|   " GoInfo automatic update | ||||
|   if get(g:, "go_auto_type_info", 0) | ||||
|     call go#tool#Info(0) | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:auto_sameids() | ||||
|   " GoSameId automatic update | ||||
|   if get(g:, "go_auto_sameids", 0) | ||||
|     call go#guru#SameIds(0) | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:fmt_autosave() | ||||
|   " Go code formatting on save | ||||
|   if get(g:, "go_fmt_autosave", 1) | ||||
|     call go#fmt#Format(-1) | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:asmfmt_autosave() | ||||
|   " Go asm formatting on save | ||||
|   if get(g:, "go_asmfmt_autosave", 0) | ||||
|     call go#asmfmt#Format() | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:modfmt_autosave() | ||||
|   " go.mod code formatting on save | ||||
|   if get(g:, "go_mod_fmt_autosave", 1) | ||||
|     call go#mod#Format() | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:metalinter_autosave() | ||||
|   " run gometalinter on save | ||||
|   if get(g:, "go_metalinter_autosave", 0) | ||||
|     call go#lint#Gometa(0, 1) | ||||
|   endif | ||||
| endfunction | ||||
|  | ||||
| function! s:template_autocreate() | ||||
|   " create new template from scratch | ||||
|   if get(g:, "go_template_autocreate", 1) && &modifiable | ||||
|     call go#template#create() | ||||
|   endif | ||||
| " restore fileencodings as others | ||||
| function! s:gofiletype_post() | ||||
|   let &g:fileformats = s:current_fileformats | ||||
|   let &g:fileencodings = s:current_fileencodings | ||||
| endfunction | ||||
|  | ||||
| augroup vim-go | ||||
|   autocmd! | ||||
|  | ||||
|   autocmd CursorHold *.go call s:auto_type_info() | ||||
|   autocmd CursorHold *.go call s:auto_sameids() | ||||
|   autocmd BufNewFile *.go if &modifiable | setlocal fileencoding=utf-8 fileformat=unix | endif | ||||
|   autocmd BufNewFile *.go call go#auto#template_autocreate() | ||||
|   autocmd BufRead *.go call s:gofiletype_pre() | ||||
|   autocmd BufReadPost *.go call s:gofiletype_post() | ||||
|  | ||||
|   " Echo the identifier information when completion is done. Useful to see | ||||
|   " the signature of a function, etc... | ||||
|   if exists('##CompleteDone') | ||||
|     autocmd CompleteDone *.go call s:echo_go_info() | ||||
|   endif | ||||
|  | ||||
|   autocmd BufWritePre *.go call s:fmt_autosave() | ||||
|   autocmd BufWritePre *.mod call s:modfmt_autosave() | ||||
|   autocmd BufWritePre *.s call s:asmfmt_autosave() | ||||
|   autocmd BufWritePost *.go call s:metalinter_autosave() | ||||
|   autocmd BufNewFile *.go call s:template_autocreate() | ||||
|   " clear SameIds when the buffer is unloaded so that loading another buffer | ||||
|   " in the same window doesn't highlight the most recently matched | ||||
|   " identifier's positions. | ||||
|   autocmd BufWinEnter *.go call go#guru#ClearSameIds() | ||||
|  | ||||
|   autocmd BufEnter *.go | ||||
|         \  if go#config#AutodetectGopath() && !exists('b:old_gopath') | ||||
|         \|   let b:old_gopath = exists('$GOPATH') ? $GOPATH : -1 | ||||
|         \|   let $GOPATH = go#path#Detect() | ||||
|         \| endif | ||||
|   autocmd BufLeave *.go | ||||
|         \  if exists('b:old_gopath') | ||||
|         \|   if b:old_gopath isnot -1 | ||||
|         \|     let $GOPATH = b:old_gopath | ||||
|         \|   endif | ||||
|         \|   unlet b:old_gopath | ||||
|         \| endif | ||||
|   autocmd BufNewFile *.s if &modifiable | setlocal fileencoding=utf-8 fileformat=unix | endif | ||||
|   autocmd BufRead *.s call s:gofiletype_pre() | ||||
|   autocmd BufReadPost *.s call s:gofiletype_post() | ||||
| augroup end | ||||
|  | ||||
| " restore Vi compatibility settings | ||||
|  | ||||
| @ -72,7 +72,7 @@ hi def link     goComment           Comment | ||||
| hi def link     goTodo              Todo | ||||
|  | ||||
| if go#config#HighlightGenerateTags() | ||||
|   syn match       goGenerateVariables contained /\(\$GOARCH\|\$GOOS\|\$GOFILE\|\$GOLINE\|\$GOPACKAGE\|\$DOLLAR\)\>/ | ||||
|   syn match       goGenerateVariables contained /\%(\$GOARCH\|\$GOOS\|\$GOFILE\|\$GOLINE\|\$GOPACKAGE\|\$DOLLAR\)\>/ | ||||
|   syn region      goGenerate          start="^\s*//go:generate" end="$" contains=goGenerateVariables | ||||
|   hi def link     goGenerate          PreProc | ||||
|   hi def link     goGenerateVariables Special | ||||
| @ -113,7 +113,7 @@ if go#config#HighlightFormatStrings() | ||||
|   " 5. Match [n] or nothing before a verb | ||||
|   " 6. Match a formatting verb | ||||
|   syn match       goFormatSpecifier   /\ | ||||
|         \([^%]\(%%\)*\)\ | ||||
|         \%([^%]\%(%%\)*\)\ | ||||
|         \@<=%[-#0 +]*\ | ||||
|         \%(\%(\%(\[\d\+\]\)\=\*\)\|\d\+\)\=\ | ||||
|         \%(\.\%(\%(\%(\[\d\+\]\)\=\*\)\|\d\+\)\=\)\=\ | ||||
| @ -159,7 +159,7 @@ else | ||||
| endif | ||||
|  | ||||
| " Single-line var, const, and import. | ||||
| syn match       goSingleDecl        /\(import\|var\|const\) [^(]\@=/ contains=goImport,goVar,goConst | ||||
| syn match       goSingleDecl        /\%(import\|var\|const\) [^(]\@=/ contains=goImport,goVar,goConst | ||||
|  | ||||
| " Integers | ||||
| syn match       goDecimalInt        "\<-\=\d\+\%([Ee][-+]\=\d\+\)\=\>" | ||||
| @ -190,7 +190,7 @@ hi def link     goImaginaryFloat    Float | ||||
|  | ||||
| " Spaces after "[]" | ||||
| if go#config#HighlightArrayWhitespaceError() | ||||
|   syn match goSpaceError display "\(\[\]\)\@<=\s\+" | ||||
|   syn match goSpaceError display "\%(\[\]\)\@<=\s\+" | ||||
| endif | ||||
|  | ||||
| " Spacing errors around the 'chan' keyword | ||||
| @ -199,24 +199,24 @@ if go#config#HighlightChanWhitespaceError() | ||||
|   " | ||||
|   " \(\<chan\>\)\@<!<-  (only pick arrow when it doesn't come after a chan) | ||||
|   " this prevents picking up 'chan<- chan<-' but not '<- chan' | ||||
|   syn match goSpaceError display "\(\(\<chan\>\)\@<!<-\)\@<=\s\+\(\<chan\>\)\@=" | ||||
|   syn match goSpaceError display "\%(\%(\<chan\>\)\@<!<-\)\@<=\s\+\%(\<chan\>\)\@=" | ||||
|  | ||||
|   " send-only annotation on chan type | ||||
|   " | ||||
|   " \(<-\)\@<!\<chan\>  (only pick chan when it doesn't come after an arrow) | ||||
|   " this prevents picking up '<-chan <-chan' but not 'chan <-' | ||||
|   syn match goSpaceError display "\(\(<-\)\@<!\<chan\>\)\@<=\s\+\(<-\)\@=" | ||||
|   syn match goSpaceError display "\%(\%(<-\)\@<!\<chan\>\)\@<=\s\+\%(<-\)\@=" | ||||
|  | ||||
|   " value-ignoring receives in a few contexts | ||||
|   syn match goSpaceError display "\(\(^\|[={(,;]\)\s*<-\)\@<=\s\+" | ||||
|   syn match goSpaceError display "\%(\%(^\|[={(,;]\)\s*<-\)\@<=\s\+" | ||||
| endif | ||||
|  | ||||
| " Extra types commonly seen | ||||
| if go#config#HighlightExtraTypes() | ||||
|   syn match goExtraType /\<bytes\.\(Buffer\)\>/ | ||||
|   syn match goExtraType /\<context\.\(Context\)\>/ | ||||
|   syn match goExtraType /\<io\.\(Reader\|ReadSeeker\|ReadWriter\|ReadCloser\|ReadWriteCloser\|Writer\|WriteCloser\|Seeker\)\>/ | ||||
|   syn match goExtraType /\<reflect\.\(Kind\|Type\|Value\)\>/ | ||||
|   syn match goExtraType /\<bytes\.\%(Buffer\)\>/ | ||||
|   syn match goExtraType /\<context\.\%(Context\)\>/ | ||||
|   syn match goExtraType /\<io\.\%(Reader\|ReadSeeker\|ReadWriter\|ReadCloser\|ReadWriteCloser\|Writer\|WriteCloser\|Seeker\)\>/ | ||||
|   syn match goExtraType /\<reflect\.\%(Kind\|Type\|Value\)\>/ | ||||
|   syn match goExtraType /\<unsafe\.Pointer\>/ | ||||
| endif | ||||
|  | ||||
| @ -265,20 +265,20 @@ hi def link     goOperator          Operator | ||||
| " Functions; | ||||
| if go#config#HighlightFunctions() || go#config#HighlightFunctionParameters() | ||||
|   syn match goDeclaration       /\<func\>/ nextgroup=goReceiver,goFunction,goSimpleParams skipwhite skipnl | ||||
|   syn match goReceiverVar       /\w\+\ze\s\+\(\w\|\*\)/ nextgroup=goPointerOperator,goReceiverType skipwhite skipnl contained | ||||
|   syn match goReceiverVar       /\w\+\ze\s\+\%(\w\|\*\)/ nextgroup=goPointerOperator,goReceiverType skipwhite skipnl contained | ||||
|   syn match goPointerOperator   /\*/ nextgroup=goReceiverType contained skipwhite skipnl | ||||
|   syn match goFunction          /\w\+/ nextgroup=goSimpleParams contained skipwhite skipnl | ||||
|   syn match goReceiverType      /\w\+/ contained | ||||
| if go#config#HighlightFunctionParameters() | ||||
|   syn match goSimpleParams     /(\(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType nextgroup=goFunctionReturn skipwhite skipnl | ||||
|   syn match goFunctionReturn   /(\(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType skipwhite skipnl | ||||
|   syn match goParamName        /\w\+\(\s*,\s*\w\+\)*\ze\s\+\(\w\|\.\|\*\|\[\)/ contained nextgroup=goParamType skipwhite skipnl | ||||
|   syn match goParamType     /\([^,)]\|\_s\)\+,\?/ contained nextgroup=goParamName skipwhite skipnl | ||||
|                         \ contains=goVarArgs,goType,goSignedInts,goUnsignedInts,goFloats,goComplexes,goDeclType,goBlock | ||||
|   hi def link   goReceiverVar    goParamName | ||||
|   hi def link   goParamName      Identifier | ||||
| endif | ||||
|   syn match goReceiver          /(\s*\w\+\(\s\+\*\?\s*\w\+\)\?\s*)\ze\s*\w/ contained nextgroup=goFunction contains=goReceiverVar skipwhite skipnl | ||||
|   if go#config#HighlightFunctionParameters() | ||||
|     syn match goSimpleParams      /(\%(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType nextgroup=goFunctionReturn skipwhite skipnl | ||||
|     syn match goFunctionReturn   /(\%(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType skipwhite skipnl | ||||
|     syn match goParamName        /\w\+\%(\s*,\s*\w\+\)*\ze\s\+\%(\w\|\.\|\*\|\[\)/ contained nextgroup=goParamType skipwhite skipnl | ||||
|     syn match goParamType        /\%([^,)]\|\_s\)\+,\?/ contained nextgroup=goParamName skipwhite skipnl | ||||
|                           \ contains=goVarArgs,goType,goSignedInts,goUnsignedInts,goFloats,goComplexes,goDeclType,goBlock | ||||
|     hi def link   goReceiverVar    goParamName | ||||
|     hi def link   goParamName      Identifier | ||||
|   endif | ||||
|   syn match goReceiver          /(\s*\w\+\%(\s\+\*\?\s*\w\+\)\?\s*)\ze\s*\w/ contained nextgroup=goFunction contains=goReceiverVar skipwhite skipnl | ||||
| else | ||||
|   syn keyword goDeclaration func | ||||
| endif | ||||
| @ -292,7 +292,20 @@ hi def link     goFunctionCall      Type | ||||
|  | ||||
| " Fields; | ||||
| if go#config#HighlightFields() | ||||
|   syn match goField                 /\.\w\+\([.\ \n\r\:\)\[,]\)\@=/hs=s+1 | ||||
|   " 1. Match a sequence of word characters coming after a '.' | ||||
|   " 2. Require the following but dont match it: ( \@= see :h E59) | ||||
|   "    - The symbols: / - + * %   OR | ||||
|   "    - The symbols: [] {} <> )  OR | ||||
|   "    - The symbols: \n \r space OR | ||||
|   "    - The symbols: , : . | ||||
|   " 3. Have the start of highlight (hs) be the start of matched | ||||
|   "    pattern (s) offsetted one to the right (+1) (see :h E401) | ||||
|   syn match       goField   /\.\w\+\ | ||||
|         \%(\%([\/\-\+*%]\)\|\ | ||||
|         \%([\[\]{}<\>\)]\)\|\ | ||||
|         \%([\!=\^|&]\)\|\ | ||||
|         \%([\n\r\ ]\)\|\ | ||||
|         \%([,\:.]\)\)\@=/hs=s+1 | ||||
| endif | ||||
| hi def link    goField              Identifier | ||||
|  | ||||
| @ -301,7 +314,7 @@ if go#config#HighlightTypes() | ||||
|   syn match goTypeConstructor      /\<\w\+{\@=/ | ||||
|   syn match goTypeDecl             /\<type\>/ nextgroup=goTypeName skipwhite skipnl | ||||
|   syn match goTypeName             /\w\+/ contained nextgroup=goDeclType skipwhite skipnl | ||||
|   syn match goDeclType             /\<\(interface\|struct\)\>/ skipwhite skipnl | ||||
|   syn match goDeclType             /\<\%(interface\|struct\)\>/ skipwhite skipnl | ||||
|   hi def link     goReceiverType      Type | ||||
| else | ||||
|   syn keyword goDeclType           struct interface | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Amir Salihefendic
					Amir Salihefendic