github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/cmd/oracle/oracle.vim (about) 1 " -*- text -*- 2 " oracle.vim -- Vim integration for the Go oracle. 3 " 4 " Load with (e.g.) :source oracle.vim 5 " Call with (e.g.) :GoOracleDescribe 6 " while cursor or selection is over syntax of interest. 7 " Run :copen to show the quick-fix file. 8 " 9 " This is an absolutely rudimentary integration of the Go Oracle into 10 " Vim's quickfix mechanism and it needs a number of usability 11 " improvements before it can be practically useful to Vim users. 12 " Voluntary contributions welcomed! 13 " 14 " TODO(adonovan): 15 " - reject buffers with no filename. 16 " - hide all filenames in quickfix buffer. 17 18 " Get the path to the Go oracle executable. 19 func! s:go_oracle_bin() 20 let [ext, sep] = (has('win32') || has('win64') ? ['.exe', ';'] : ['', ':']) 21 let go_oracle = globpath(join(split($GOPATH, sep), ','), '/bin/oracle' . ext) 22 if go_oracle == '' 23 let go_oracle = globpath($GOROOT, '/bin/oracle' . ext) 24 endif 25 return go_oracle 26 endfunction 27 28 let s:go_oracle = s:go_oracle_bin() 29 30 func! s:qflist(output) 31 let qflist = [] 32 " Parse GNU-style 'file:line.col-line.col: message' format. 33 let mx = '^\(\a:[\\/][^:]\+\|[^:]\+\):\(\d\+\):\(\d\+\):\(.*\)$' 34 for line in split(a:output, "\n") 35 let ml = matchlist(line, mx) 36 " Ignore non-match lines or warnings 37 if ml == [] || ml[4] =~ '^ warning:' 38 continue 39 endif 40 let item = { 41 \ 'filename': ml[1], 42 \ 'text': ml[4], 43 \ 'lnum': ml[2], 44 \ 'col': ml[3], 45 \} 46 let bnr = bufnr(fnameescape(ml[1])) 47 if bnr != -1 48 let item['bufnr'] = bnr 49 endif 50 call add(qflist, item) 51 endfor 52 call setqflist(qflist) 53 cwindow 54 endfun 55 56 func! s:getpos(l, c) 57 if &encoding != 'utf-8' 58 let buf = a:l == 1 ? '' : (join(getline(1, a:l-1), "\n") . "\n") 59 let buf .= a:c == 1 ? '' : getline('.')[:a:c-2] 60 return len(iconv(buf, &encoding, 'utf-8')) 61 endif 62 return line2byte(a:l) + (a:c-2) 63 endfun 64 65 func! s:RunOracle(mode, selected) range abort 66 let fname = expand('%:p') 67 let sname = get(g:, 'go_oracle_scope_file', fname) 68 if a:selected != -1 69 let pos1 = s:getpos(line("'<"), col("'<")) 70 let pos2 = s:getpos(line("'>"), col("'>")) 71 let cmd = printf('%s -pos=%s:#%d,#%d %s %s', 72 \ s:go_oracle, 73 \ shellescape(fname), pos1, pos2, a:mode, shellescape(sname)) 74 else 75 let pos = s:getpos(line('.'), col('.')) 76 let cmd = printf('%s -pos=%s:#%d %s %s', 77 \ s:go_oracle, 78 \ shellescape(fname), pos, a:mode, shellescape(sname)) 79 endif 80 call s:qflist(system(cmd)) 81 endfun 82 83 " Describe the expression at the current point. 84 command! -range=% GoOracleDescribe 85 \ call s:RunOracle('describe', <count>) 86 87 " Show possible callees of the function call at the current point. 88 command! -range=% GoOracleCallees 89 \ call s:RunOracle('callees', <count>) 90 91 " Show the set of callers of the function containing the current point. 92 command! -range=% GoOracleCallers 93 \ call s:RunOracle('callers', <count>) 94 95 " Show the callgraph of the current program. 96 command! -range=% GoOracleCallgraph 97 \ call s:RunOracle('callgraph', <count>) 98 99 " Describe the 'implements' relation for types in the 100 " package containing the current point. 101 command! -range=% GoOracleImplements 102 \ call s:RunOracle('implements', <count>) 103 104 " Enumerate the set of possible corresponding sends/receives for 105 " this channel receive/send operation. 106 command! -range=% GoOracleChannelPeers 107 \ call s:RunOracle('peers', <count>)