diff --git a/CHANGELOG.md b/CHANGELOG.md index fa0d9cbf7f..79abc5f385 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,8 +24,11 @@ IMPROVEMENTS: * Syntax highlighting for variable declarations and assignments (disabled by default) [[GH-1426]](https://github.com/fatih/vim-go/pull/1426) and [[GH-1458]](https://github.com/fatih/vim-go/pull/1458). - -* Add support for `:GoDecls[Dir]` in [unite.vim](https://github.com/Shougo/unite.vim) [[GH-1391]](https://github.com/fatih/vim-go/pull/1391). +* Add support for `:GoDecls[Dir]` in [unite.vim](https://github.com/Shougo/unite.vim) + [[GH-1391]](https://github.com/fatih/vim-go/pull/1391). +* Add support for [fzf.vim](https://github.com/junegunn/fzf.vim) in + `GoDecls[Dir]`. + [[GH-1437]](https://github.com/fatih/vim-go/pull/1437). * Support relative imports for `:GoImpl` [[GH-1322]](https://github.com/fatih/vim-go/pull/1322). * A new `g:go_list_type_commands` setting is added to individually set the list type for each command [[GH-1415]](https://github.com/fatih/vim-go/pull/1415). As en example: diff --git a/autoload/fzf/decls.vim b/autoload/fzf/decls.vim new file mode 100644 index 0000000000..4f8125f7a8 --- /dev/null +++ b/autoload/fzf/decls.vim @@ -0,0 +1,154 @@ +function! s:code(group, attr) abort + let code = synIDattr(synIDtrans(hlID(a:group)), a:attr, "cterm") + if code =~ '^[0-9]\+$' + return code + endif +endfunction + +function! s:color(str, group) abort + let fg = s:code(a:group, "fg") + let bg = s:code(a:group, "bg") + let bold = s:code(a:group, "bold") + let italic = s:code(a:group, "italic") + let reverse = s:code(a:group, "reverse") + let underline = s:code(a:group, "underline") + let color = (empty(fg) ? "" : ("38;5;".fg)) . + \ (empty(bg) ? "" : (";48;5;".bg)) . + \ (empty(bold) ? "" : ";1") . + \ (empty(italic) ? "" : ";3") . + \ (empty(reverse) ? "" : ";7") . + \ (empty(underline) ? "" : ";4") + return printf("\x1b[%sm%s\x1b[m", color, a:str) +endfunction + +function! s:sink(str) abort + if len(a:str) < 2 + return + endif + let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' + let dir = getcwd() + try + " we jump to the file directory so we can get the fullpath via fnamemodify + " below + execute cd . fnameescape(s:current_dir) + + let vals = matchlist(a:str[1], '|\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)|') + + " i.e: main.go + let filename = vals[1] + let line = vals[2] + let col = vals[3] + + " i.e: /Users/fatih/vim-go/main.go + let filepath = fnamemodify(filename, ":p") + + let cmd = get({'ctrl-x': 'split', + \ 'ctrl-v': 'vertical split', + \ 'ctrl-t': 'tabe'}, a:str[0], 'e') + execute cmd fnameescape(filepath) + call cursor(line, col) + silent! norm! zvzz + finally + "jump back to old dir + execute cd . fnameescape(dir) + endtry +endfunction + +function! s:source(mode,...) abort + let s:current_dir = expand('%:p:h') + let ret_decls = [] + + let bin_path = go#path#CheckBinPath('motion') + if empty(bin_path) + return + endif + let command = printf("%s -format vim -mode decls", bin_path) + let command .= " -include ". get(g:, "go_decls_includes", "func,type") + + call go#cmd#autowrite() + + if a:mode == 0 + " current file mode + let fname = expand("%:p") + if a:0 && !empty(a:1) + let fname = a:1 + endif + + let command .= printf(" -file %s", shellescape(fname)) + else + " all functions mode + if a:0 && !empty(a:1) + let s:current_dir = a:1 + endif + + let command .= printf(" -dir %s", shellescape(s:current_dir)) + endif + + let out = go#util#System(command) + if go#util#ShellError() != 0 + call go#util#EchoError(out) + return + endif + + if exists("l:tmpname") + call delete(l:tmpname) + endif + + let result = eval(out) + if type(result) != 4 || !has_key(result, 'decls') + return + endif + + let decls = result.decls + + " find the maximum function name + let max_len = 0 + for decl in decls + if len(decl.ident)> max_len + let max_len = len(decl.ident) + endif + endfor + + for decl in decls + " paddings + let space = " " + for i in range(max_len - len(decl.ident)) + let space .= " " + endfor + + let pos = printf("|%s:%s:%s|", + \ fnamemodify(decl.filename, ":t"), + \ decl.line, + \ decl.col + \) + call add(ret_decls, printf("%s\t%s %s\t%s", + \ s:color(decl.ident . space, "Function"), + \ s:color(decl.keyword, "Keyword"), + \ s:color(pos, "SpecialComment"), + \ s:color(decl.full, "Comment"), + \)) + endfor + + return ret_decls +endfunc + +function! fzf#decls#cmd(...) abort + let normal_fg = s:code("Normal", "fg") + let normal_bg = s:code("Normal", "bg") + let cursor_fg = s:code("CursorLine", "fg") + let cursor_bg = s:code("CursorLine", "bg") + let colors = printf(" --color %s%s%s%s%s", + \ &background, + \ empty(normal_fg) ? "" : (",fg:".normal_fg), + \ empty(normal_bg) ? "" : (",bg:".normal_bg), + \ empty(cursor_fg) ? "" : (",fg+:".cursor_fg), + \ empty(cursor_bg) ? "" : (",bg+:".cursor_bg), + \) + call fzf#run(fzf#wrap('GoDecls', { + \ 'source': call('source', a:000), + \ 'options': '-n 1 --ansi --prompt "GoDecls> " --expect=ctrl-t,ctrl-v,ctrl-x'.colors, + \ 'sink*': function('s:sink') + \ })) +endfunction + +" vim: sw=2 ts=2 et diff --git a/autoload/go/decls.vim b/autoload/go/decls.vim new file mode 100644 index 0000000000..493bbd3763 --- /dev/null +++ b/autoload/go/decls.vim @@ -0,0 +1,21 @@ +if !exists('g:go_decls_mode') + let g:go_decls_mode = '' +endif + +function! go#decls#Decls(mode, ...) abort + if g:go_decls_mode == 'ctrlp' + call ctrlp#init(call("ctrlp#decls#cmd", [a:mode] + a:000)) + elseif g:go_decls_mode == 'fzf' + call call("fzf#decls#cmd", [a:mode] + a:000) + else + if globpath(&rtp, 'plugin/ctrlp.vim') != "" + call ctrlp#init(call("ctrlp#decls#cmd", [a:mode] + a:000)) + elseif globpath(&rtp, 'plugin/fzf.vim') != "" + call call("fzf#decls#cmd", [a:mode] + a:000) + else + call go#util#EchoError("neither ctrlp.vim nor fzf.vim are installed. Please install either one") + end + end +endfunction + +" vim: sw=2 ts=2 et diff --git a/doc/vim-go.txt b/doc/vim-go.txt index 92bdd0e670..349cb0067c 100644 --- a/doc/vim-go.txt +++ b/doc/vim-go.txt @@ -144,6 +144,8 @@ The following plugins are supported for use with vim-go: https://github.com/jodosha/vim-godebug * Interactive |:GoDecls| and |:GoDeclsDir|: + https://github.com/ctrlpvim/ctrlp.vim or + https://github.com/junegunn/fzf.vim or https://github.com/Shougo/unite.vim ============================================================================== @@ -668,25 +670,25 @@ CTRL-t *:GoDecls* :GoDecls [file] - Only enabled if `ctrlp.vim` is installed. If run shows all function and - type declarations for the current file. If [file] is non empty it parses - the given file. + Show all function and type declarations for the current file. If + [file] is non empty it parses the given file. + Requires `ctrlp.vim` or `fzf`; it will autodetect the plugin if installed, + but you can use |'g:go_decls_mode'| to force using one or the other. By default `type` and `func` declarations are shown. This can be changed - via |'g:go_decls_includes'|. + via |'g:go_decls_includes'|. Also see |unite-decls|. *:GoDeclsDir* :GoDeclsDir [dir] - Only enabled if `ctrlp.vim` is installed. If run shows all function and - type declarations for the current directory. If [dir] is given it parses - the given directory. + Show all function and type declarations for the current directory. If + [dir] is given it parses the given directory. *unite-decls* :Unite decls[:file or dir] - Only enabled if `unite.vim` is installed. If run shows declarations for - all functions and types on the current file or directory. If [:file or - dir] is non empty, it parses the given one. + Only enabled if `unite.vim` is installed. Show declarations for all + functions and types on the current file or directory. If [:file or dir] + is non empty, it parses the given one. > " show declarations on the parent directory of the current file :Unite decls @@ -1634,12 +1636,20 @@ By default the template file specified by |'g:go_template_file'| is used. < *'g:go_decls_includes'* -Only useful if `ctrlp.vim` or `unite.vim` are installed. This sets which -declarations to show for |:GoDecls| (`ctrp.vim`) and |unite-decls| +Only useful if `ctrlp.vim`, `unite.vim` or `fzf` are installed. This sets +which declarations to show for |:GoDecls| (`ctrp.vim`) and |unite-decls| (`unite.vim`). It is a Comma delimited list Possible options are: {func,type}. The default is: > let g:go_decls_includes = 'func,type' +< + *'g:go_decls_mode'* + +Define the tool to be used for |:GoDecls|. Valid options are `ctrlp.vim`, +`fzf`, or an empty string; in which case it will try to autodetect either +`ctrlp.vim` or `fzf`. +> + let g:go_decls_mode = '' < *'g:go_echo_command_info'* diff --git a/ftplugin/go/commands.vim b/ftplugin/go/commands.vim index bdb26d3976..5b32450b57 100644 --- a/ftplugin/go/commands.vim +++ b/ftplugin/go/commands.vim @@ -82,18 +82,9 @@ command! -nargs=* -complete=customlist,go#package#Complete GoErrCheck call go#li " -- alternate command! -bang GoAlternate call go#alternate#Switch(0, '') -" -- ctrlp -if globpath(&rtp, 'plugin/ctrlp.vim') != "" - command! -nargs=? -complete=file GoDecls call ctrlp#init(ctrlp#decls#cmd(0, )) - command! -nargs=? -complete=dir GoDeclsDir call ctrlp#init(ctrlp#decls#cmd(1, )) -else - function! s:ctrlp_warning() - call go#util#EchoError("ctrlp.vim plugin is not installed. Please install from: https://github.com/ctrlpvim/ctrlp.vim") - endfunction - - command! -nargs=? -complete=file GoDecls call ctrlp_warning() - command! -nargs=? -complete=file GoDeclsDir call ctrlp_warning() -endif +" -- decls +command! -nargs=? -complete=file GoDecls call go#decls#Decls(0, ) +command! -nargs=? -complete=dir GoDeclsDir call go#decls#Decls(1, ) " -- impl command! -nargs=* -buffer -complete=customlist,go#impl#Complete GoImpl call go#impl#Impl()