2015-07-13 06:22:46 -04:00
|
|
|
" PathSep returns the appropriate OS specific path separator.
|
|
|
|
function! go#util#PathSep()
|
2016-06-26 07:12:36 -04:00
|
|
|
if go#util#IsWin()
|
|
|
|
return '\'
|
|
|
|
endif
|
|
|
|
return '/'
|
2015-07-13 06:22:46 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
" PathListSep returns the appropriate OS specific path list separator.
|
|
|
|
function! go#util#PathListSep()
|
2016-06-26 07:12:36 -04:00
|
|
|
if go#util#IsWin()
|
|
|
|
return ";"
|
|
|
|
endif
|
|
|
|
return ":"
|
2015-07-13 06:22:46 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
" LineEnding returns the correct line ending, based on the current fileformat
|
|
|
|
function! go#util#LineEnding()
|
2016-06-26 07:12:36 -04:00
|
|
|
if &fileformat == 'dos'
|
|
|
|
return "\r\n"
|
|
|
|
elseif &fileformat == 'mac'
|
|
|
|
return "\r"
|
|
|
|
endif
|
2015-07-13 06:22:46 -04:00
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
return "\n"
|
2015-07-13 06:22:46 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-07-03 07:53:59 -04:00
|
|
|
" Join joins any number of path elements into a single path, adding a
|
|
|
|
" Separator if necessary and returns the result
|
|
|
|
function! go#util#Join(...)
|
|
|
|
return join(a:000, go#util#PathSep())
|
|
|
|
endfunction
|
|
|
|
|
2015-07-13 06:22:46 -04:00
|
|
|
" IsWin returns 1 if current OS is Windows or 0 otherwise
|
|
|
|
function! go#util#IsWin()
|
2016-06-26 07:12:36 -04:00
|
|
|
let win = ['win16', 'win32', 'win64', 'win95']
|
|
|
|
for w in win
|
|
|
|
if (has(w))
|
|
|
|
return 1
|
|
|
|
endif
|
|
|
|
endfor
|
2016-02-20 08:13:10 -05:00
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
return 0
|
2015-07-13 06:22:46 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-08-02 08:48:32 -04:00
|
|
|
function! go#util#goarch()
|
2016-06-26 07:12:36 -04:00
|
|
|
return substitute(go#util#System('go env GOARCH'), '\n', '', 'g')
|
2016-05-14 07:57:54 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-08-02 08:48:32 -04:00
|
|
|
function! go#util#goos()
|
2016-06-26 07:12:36 -04:00
|
|
|
return substitute(go#util#System('go env GOOS'), '\n', '', 'g')
|
2016-05-14 07:57:54 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-08-02 08:48:32 -04:00
|
|
|
function! go#util#goroot()
|
2016-06-26 07:12:36 -04:00
|
|
|
return substitute(go#util#System('go env GOROOT'), '\n', '', 'g')
|
2016-05-14 07:57:54 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-08-02 08:48:32 -04:00
|
|
|
function! go#util#gopath()
|
2016-06-26 07:12:36 -04:00
|
|
|
return substitute(go#util#System('go env GOPATH'), '\n', '', 'g')
|
2016-05-14 07:57:54 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-08-02 08:48:32 -04:00
|
|
|
function! go#util#osarch()
|
|
|
|
return go#util#goos() . '_' . go#util#goarch()
|
2016-05-14 07:57:54 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
"Check if has vimproc
|
|
|
|
function! s:has_vimproc()
|
2016-06-26 07:12:36 -04:00
|
|
|
if !exists('g:go#use_vimproc')
|
|
|
|
if go#util#IsWin()
|
|
|
|
try
|
|
|
|
call vimproc#version()
|
|
|
|
let exists_vimproc = 1
|
|
|
|
catch
|
|
|
|
let exists_vimproc = 0
|
|
|
|
endtry
|
|
|
|
else
|
|
|
|
let exists_vimproc = 0
|
2016-05-14 07:57:54 -04:00
|
|
|
endif
|
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
let g:go#use_vimproc = exists_vimproc
|
|
|
|
endif
|
|
|
|
|
|
|
|
return g:go#use_vimproc
|
2016-05-14 07:57:54 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
if s:has_vimproc()
|
2016-06-26 07:12:36 -04:00
|
|
|
let s:vim_system = get(g:, 'gocomplete#system_function', 'vimproc#system2')
|
|
|
|
let s:vim_shell_error = get(g:, 'gocomplete#shell_error_function', 'vimproc#get_last_status')
|
2016-05-14 07:57:54 -04:00
|
|
|
else
|
2016-06-26 07:12:36 -04:00
|
|
|
let s:vim_system = get(g:, 'gocomplete#system_function', 'system')
|
|
|
|
let s:vim_shell_error = ''
|
2016-05-14 07:57:54 -04:00
|
|
|
endif
|
|
|
|
|
2016-08-02 08:48:32 -04:00
|
|
|
" System runs a shell command. It will reset the shell to /bin/sh for Unix-like
|
|
|
|
" systems if it is executable.
|
2016-05-14 07:57:54 -04:00
|
|
|
function! go#util#System(str, ...)
|
2016-08-02 08:48:32 -04:00
|
|
|
let l:shell = &shell
|
|
|
|
if !go#util#IsWin() && executable('/bin/sh')
|
|
|
|
let &shell = '/bin/sh'
|
|
|
|
endif
|
|
|
|
|
|
|
|
try
|
|
|
|
let l:output = call(s:vim_system, [a:str] + a:000)
|
|
|
|
return l:output
|
|
|
|
finally
|
|
|
|
let &shell = l:shell
|
|
|
|
endtry
|
2016-05-14 07:57:54 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! go#util#ShellError()
|
2016-06-26 07:12:36 -04:00
|
|
|
if empty(s:vim_shell_error)
|
|
|
|
return v:shell_error
|
|
|
|
endif
|
|
|
|
return call(s:vim_shell_error, [])
|
2016-05-14 07:57:54 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
2015-07-13 06:22:46 -04:00
|
|
|
" StripPath strips the path's last character if it's a path separator.
|
|
|
|
" example: '/foo/bar/' -> '/foo/bar'
|
|
|
|
function! go#util#StripPathSep(path)
|
2016-06-26 07:12:36 -04:00
|
|
|
let last_char = strlen(a:path) - 1
|
|
|
|
if a:path[last_char] == go#util#PathSep()
|
|
|
|
return strpart(a:path, 0, last_char)
|
|
|
|
endif
|
2015-07-13 06:22:46 -04:00
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
return a:path
|
2015-07-13 06:22:46 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-03-14 06:04:57 -04:00
|
|
|
" StripTrailingSlash strips the trailing slash from the given path list.
|
|
|
|
" example: ['/foo/bar/'] -> ['/foo/bar']
|
|
|
|
function! go#util#StripTrailingSlash(paths)
|
|
|
|
return map(copy(a:paths), 'go#util#StripPathSep(v:val)')
|
|
|
|
endfunction
|
|
|
|
|
2015-12-08 08:20:04 -05:00
|
|
|
" Shelljoin returns a shell-safe string representation of arglist. The
|
|
|
|
" {special} argument of shellescape() may optionally be passed.
|
|
|
|
function! go#util#Shelljoin(arglist, ...)
|
2016-06-26 07:12:36 -04:00
|
|
|
try
|
|
|
|
let ssl_save = &shellslash
|
|
|
|
set noshellslash
|
|
|
|
if a:0
|
|
|
|
return join(map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')'), ' ')
|
|
|
|
endif
|
2016-02-20 08:13:10 -05:00
|
|
|
|
2016-07-16 14:30:35 -04:00
|
|
|
return join(map(copy(a:arglist), 'shellescape(v:val)'), ' ')
|
|
|
|
finally
|
|
|
|
let &shellslash = ssl_save
|
|
|
|
endtry
|
2015-12-16 08:53:53 -05:00
|
|
|
endfunction
|
|
|
|
|
2016-05-14 07:57:54 -04:00
|
|
|
fu! go#util#Shellescape(arg)
|
2016-07-16 14:30:35 -04:00
|
|
|
if s:has_vimproc()
|
|
|
|
return vimproc#shellescape(a:arg)
|
|
|
|
endif
|
|
|
|
try
|
|
|
|
let ssl_save = &shellslash
|
|
|
|
set noshellslash
|
|
|
|
return shellescape(a:arg)
|
|
|
|
finally
|
|
|
|
let &shellslash = ssl_save
|
|
|
|
endtry
|
2016-05-14 07:57:54 -04:00
|
|
|
endf
|
|
|
|
|
2016-02-20 08:13:10 -05:00
|
|
|
" Shelllist returns a shell-safe representation of the items in the given
|
2015-12-16 08:53:53 -05:00
|
|
|
" arglist. The {special} argument of shellescape() may optionally be passed.
|
|
|
|
function! go#util#Shelllist(arglist, ...)
|
2016-07-16 14:30:35 -04:00
|
|
|
try
|
|
|
|
let ssl_save = &shellslash
|
|
|
|
set noshellslash
|
|
|
|
if a:0
|
|
|
|
return map(copy(a:arglist), 'shellescape(v:val, ' . a:1 . ')')
|
|
|
|
endif
|
|
|
|
return map(copy(a:arglist), 'shellescape(v:val)')
|
|
|
|
finally
|
|
|
|
let &shellslash = ssl_save
|
|
|
|
endtry
|
2015-12-16 08:53:53 -05:00
|
|
|
endfunction
|
|
|
|
|
2016-03-20 14:01:44 -04:00
|
|
|
" Returns the byte offset for line and column
|
|
|
|
function! go#util#Offset(line, col)
|
2016-07-16 14:30:35 -04:00
|
|
|
if &encoding != 'utf-8'
|
|
|
|
let sep = go#util#LineEnding()
|
|
|
|
let buf = a:line == 1 ? '' : (join(getline(1, a:line-1), sep) . sep)
|
|
|
|
let buf .= a:col == 1 ? '' : getline('.')[:a:col-2]
|
|
|
|
return len(iconv(buf, &encoding, 'utf-8'))
|
|
|
|
endif
|
|
|
|
return line2byte(a:line) + (a:col-2)
|
2016-03-20 14:01:44 -04:00
|
|
|
endfunction
|
|
|
|
"
|
|
|
|
" Returns the byte offset for the cursor
|
|
|
|
function! go#util#OffsetCursor()
|
2016-07-16 14:30:35 -04:00
|
|
|
return go#util#Offset(line('.'), col('.'))
|
2016-03-20 14:01:44 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-04-12 04:31:09 -04:00
|
|
|
" Windo is like the built-in :windo, only it returns to the window the command
|
|
|
|
" was issued from
|
|
|
|
function! go#util#Windo(command)
|
2016-07-16 14:30:35 -04:00
|
|
|
let s:currentWindow = winnr()
|
|
|
|
try
|
|
|
|
execute "windo " . a:command
|
|
|
|
finally
|
|
|
|
execute s:currentWindow. "wincmd w"
|
|
|
|
unlet s:currentWindow
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
" snippetcase converts the given word to given preferred snippet setting type
|
|
|
|
" case.
|
|
|
|
function! go#util#snippetcase(word)
|
|
|
|
let l:snippet_case = get(g:, 'go_snippet_case_type', "snakecase")
|
|
|
|
if l:snippet_case == "snakecase"
|
|
|
|
return go#util#snakecase(a:word)
|
|
|
|
elseif l:snippet_case == "camelcase"
|
|
|
|
return go#util#camelcase(a:word)
|
|
|
|
else
|
|
|
|
return a:word " do nothing
|
|
|
|
endif
|
2016-04-12 04:31:09 -04:00
|
|
|
endfunction
|
|
|
|
|
2016-07-16 14:30:35 -04:00
|
|
|
" snakecase converts a string to snake case. i.e: FooBar -> foo_bar
|
|
|
|
" Copied from tpope/vim-abolish
|
|
|
|
function! go#util#snakecase(word)
|
|
|
|
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
|
|
|
|
function! go#util#camelcase(word)
|
|
|
|
let word = substitute(a:word, '-', '_', 'g')
|
|
|
|
if word !~# '_' && word =~# '\l'
|
|
|
|
return substitute(word,'^.','\l&','')
|
|
|
|
else
|
|
|
|
return substitute(word,'\C\(_\)\=\(.\)','\=submatch(1)==""?tolower(submatch(2)) : toupper(submatch(2))','g')
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2016-08-02 08:48:32 -04:00
|
|
|
function! go#util#AddTags(line1, line2, ...)
|
|
|
|
" default is json
|
|
|
|
let l:keys = ["json"]
|
|
|
|
if a:0
|
|
|
|
let l:keys = a:000
|
|
|
|
endif
|
|
|
|
|
|
|
|
let l:line1 = a:line1
|
|
|
|
let l:line2 = a:line2
|
|
|
|
|
|
|
|
" If we're inside a struct and just call this function let us add the tags
|
|
|
|
" to all fields
|
|
|
|
" TODO(arslan): I don't like using patterns. Check if we can move it to
|
|
|
|
" `motion` and do it via AST based position
|
|
|
|
let ln1 = searchpair('struct {', '', '}', 'bcnW')
|
|
|
|
if ln1 == 0
|
|
|
|
echon "vim-go: " | echohl ErrorMsg | echon "cursor is outside the struct" | echohl None
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
|
|
|
" searchpair only returns a single position
|
|
|
|
let ln2 = search('}', "cnW")
|
|
|
|
|
|
|
|
" if no range is given we apply for the whole struct
|
|
|
|
if l:line1 == l:line2
|
|
|
|
let l:line1 = ln1 + 1
|
|
|
|
let l:line2 = ln2 - 1
|
|
|
|
endif
|
|
|
|
|
|
|
|
for line in range(l:line1, l:line2)
|
|
|
|
" get the field name (word) that are not part of a commented line
|
|
|
|
let l:matched = matchstr(getline(line), '\(\/\/.*\)\@<!\w\+')
|
|
|
|
if empty(l:matched)
|
|
|
|
continue
|
|
|
|
endif
|
|
|
|
|
|
|
|
let word = go#util#snippetcase(l:matched)
|
|
|
|
let tags = map(copy(l:keys), 'printf("%s:%s", v:val,"\"'. word .'\"")')
|
|
|
|
let updated_line = printf("%s `%s`", getline(line), join(tags, " "))
|
|
|
|
|
|
|
|
" finally, update the line inplace
|
|
|
|
call setline(line, updated_line)
|
|
|
|
endfor
|
|
|
|
endfunction
|
2016-07-16 14:30:35 -04:00
|
|
|
|
2015-12-16 08:53:53 -05:00
|
|
|
" TODO(arslan): I couldn't parameterize the highlight types. Check if we can
|
|
|
|
" simplify the following functions
|
|
|
|
|
|
|
|
function! go#util#EchoSuccess(msg)
|
2016-08-02 08:48:32 -04:00
|
|
|
redraw | echon "vim-go: " | echohl Function | echon a:msg | echohl None
|
2015-12-08 08:20:04 -05:00
|
|
|
endfunction
|
2015-12-16 08:53:53 -05:00
|
|
|
|
|
|
|
function! go#util#EchoError(msg)
|
2016-08-02 08:48:32 -04:00
|
|
|
redraw | echon "vim-go: " | echohl ErrorMsg | echon a:msg | echohl None
|
2015-12-16 08:53:53 -05:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! go#util#EchoWarning(msg)
|
2016-08-02 08:48:32 -04:00
|
|
|
redraw | echon "vim-go: " | echohl WarningMsg | echon a:msg | echohl None
|
2015-12-16 08:53:53 -05:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! go#util#EchoProgress(msg)
|
2016-08-02 08:48:32 -04:00
|
|
|
redraw | echon "vim-go: " | echohl Identifier | echon a:msg | echohl None
|
2015-12-16 08:53:53 -05:00
|
|
|
endfunction
|
|
|
|
|
2016-06-26 07:12:36 -04:00
|
|
|
" vim: sw=2 ts=2 et
|