decls.vim 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. function! s:code(group, attr) abort
  2. let code = synIDattr(synIDtrans(hlID(a:group)), a:attr, "cterm")
  3. if code =~ '^[0-9]\+$'
  4. return code
  5. endif
  6. endfunction
  7. function! s:color(str, group) abort
  8. let fg = s:code(a:group, "fg")
  9. let bg = s:code(a:group, "bg")
  10. let bold = s:code(a:group, "bold")
  11. let italic = s:code(a:group, "italic")
  12. let reverse = s:code(a:group, "reverse")
  13. let underline = s:code(a:group, "underline")
  14. let color = (empty(fg) ? "" : ("38;5;".fg)) .
  15. \ (empty(bg) ? "" : (";48;5;".bg)) .
  16. \ (empty(bold) ? "" : ";1") .
  17. \ (empty(italic) ? "" : ";3") .
  18. \ (empty(reverse) ? "" : ";7") .
  19. \ (empty(underline) ? "" : ";4")
  20. return printf("\x1b[%sm%s\x1b[m", color, a:str)
  21. endfunction
  22. function! s:sink(str) abort
  23. if len(a:str) < 2
  24. return
  25. endif
  26. let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
  27. let dir = getcwd()
  28. try
  29. " we jump to the file directory so we can get the fullpath via fnamemodify
  30. " below
  31. execute cd . fnameescape(s:current_dir)
  32. let vals = matchlist(a:str[1], '|\(.\{-}\):\(\d\+\):\(\d\+\)\s*\(.*\)|')
  33. " i.e: main.go
  34. let filename = vals[1]
  35. let line = vals[2]
  36. let col = vals[3]
  37. " i.e: /Users/fatih/vim-go/main.go
  38. let filepath = fnamemodify(filename, ":p")
  39. let cmd = get({'ctrl-x': 'split',
  40. \ 'ctrl-v': 'vertical split',
  41. \ 'ctrl-t': 'tabe'}, a:str[0], 'e')
  42. execute cmd fnameescape(filepath)
  43. call cursor(line, col)
  44. silent! norm! zvzz
  45. finally
  46. "jump back to old dir
  47. execute cd . fnameescape(dir)
  48. endtry
  49. endfunction
  50. function! s:source(mode,...) abort
  51. let s:current_dir = expand('%:p:h')
  52. let ret_decls = []
  53. let bin_path = go#path#CheckBinPath('motion')
  54. if empty(bin_path)
  55. return
  56. endif
  57. let command = printf("%s -format vim -mode decls", bin_path)
  58. let command .= " -include ". get(g:, "go_decls_includes", "func,type")
  59. call go#cmd#autowrite()
  60. if a:mode == 0
  61. " current file mode
  62. let fname = expand("%:p")
  63. if a:0 && !empty(a:1)
  64. let fname = a:1
  65. endif
  66. let command .= printf(" -file %s", shellescape(fname))
  67. else
  68. " all functions mode
  69. if a:0 && !empty(a:1)
  70. let s:current_dir = a:1
  71. endif
  72. let command .= printf(" -dir %s", shellescape(s:current_dir))
  73. endif
  74. let out = go#util#System(command)
  75. if go#util#ShellError() != 0
  76. call go#util#EchoError(out)
  77. return
  78. endif
  79. let result = eval(out)
  80. if type(result) != 4 || !has_key(result, 'decls')
  81. return ret_decls
  82. endif
  83. let decls = result.decls
  84. " find the maximum function name
  85. let max_len = 0
  86. for decl in decls
  87. if len(decl.ident)> max_len
  88. let max_len = len(decl.ident)
  89. endif
  90. endfor
  91. for decl in decls
  92. " paddings
  93. let space = " "
  94. for i in range(max_len - len(decl.ident))
  95. let space .= " "
  96. endfor
  97. let pos = printf("|%s:%s:%s|",
  98. \ fnamemodify(decl.filename, ":t"),
  99. \ decl.line,
  100. \ decl.col
  101. \)
  102. call add(ret_decls, printf("%s\t%s %s\t%s",
  103. \ s:color(decl.ident . space, "Function"),
  104. \ s:color(decl.keyword, "Keyword"),
  105. \ s:color(pos, "SpecialComment"),
  106. \ s:color(decl.full, "Comment"),
  107. \))
  108. endfor
  109. return ret_decls
  110. endfunc
  111. function! fzf#decls#cmd(...) abort
  112. let normal_fg = s:code("Normal", "fg")
  113. let normal_bg = s:code("Normal", "bg")
  114. let cursor_fg = s:code("CursorLine", "fg")
  115. let cursor_bg = s:code("CursorLine", "bg")
  116. let colors = printf(" --color %s%s%s%s%s",
  117. \ &background,
  118. \ empty(normal_fg) ? "" : (",fg:".normal_fg),
  119. \ empty(normal_bg) ? "" : (",bg:".normal_bg),
  120. \ empty(cursor_fg) ? "" : (",fg+:".cursor_fg),
  121. \ empty(cursor_bg) ? "" : (",bg+:".cursor_bg),
  122. \)
  123. call fzf#run(fzf#wrap('GoDecls', {
  124. \ 'source': call('<sid>source', a:000),
  125. \ 'options': '-n 1 --ansi --prompt "GoDecls> " --expect=ctrl-t,ctrl-v,ctrl-x'.colors,
  126. \ 'sink*': function('s:sink')
  127. \ }))
  128. endfunction
  129. " vim: sw=2 ts=2 et