decls.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. # ============================================================================
  2. # FILE: decls.py
  3. # AUTHOR: delphinus <delphinus@remora.cx>
  4. # License: MIT license
  5. # ============================================================================
  6. import os
  7. import subprocess
  8. import json
  9. import denite.util
  10. from .base import Base
  11. DECLS_SYNTAX_HIGHLIGHT = [
  12. {'name': 'FilePath', 're': r'[^:]*\ze:', 'link': 'Comment'},
  13. {'name': 'Line', 're': r'\d\+\ze :', 'link': 'LineNr'},
  14. {'name': 'WholeFunction', 're': r'\vfunc %(\([^)]+\) )?[^(]+'},
  15. {'name': 'Function', 'parent': 'WholeFunction',
  16. 're': r'\S\+\ze(', 'link': 'Function'},
  17. {'name': 'WholeType', 're': r'type \S\+'},
  18. {'name': 'Type', 'parent': 'WholeType',
  19. 're': r'\v( )@<=\S+', 'link': 'Type'},
  20. {'name': 'Separator', 're': r':', 'conceal': True},
  21. {'name': 'SeparatorFunction', 'parent': 'WholeFunction',
  22. 're': r'func ', 'conceal': True},
  23. {'name': 'SeparatorType', 'parent': 'WholeType',
  24. 're': r'type ', 'conceal': True},
  25. ]
  26. class Source(Base):
  27. def __init__(self, vim):
  28. super().__init__(vim)
  29. self.name = 'decls'
  30. self.kind = 'file'
  31. def gather_candidates(self, context):
  32. bin_path = self.vim.call('go#path#CheckBinPath', 'motion')
  33. if bin_path == '':
  34. return []
  35. expand = context['args'][0] if context['args'] else '%:p:h'
  36. target = self.vim.funcs.expand(expand)
  37. if os.path.isdir(target):
  38. mode = 'dir'
  39. elif os.path.isfile(target):
  40. mode = 'file'
  41. else:
  42. return []
  43. if self.vim.funcs.exists('g:go_decls_includes'):
  44. include = self.vim.eval('g:go_decls_includes')
  45. else:
  46. include = 'func,type'
  47. command = [bin_path, '-mode', 'decls', '-include', include,
  48. '-' + mode, target]
  49. try:
  50. cmd = subprocess.run(command, stdout=subprocess.PIPE, check=True)
  51. except subprocess.CalledProcessError as err:
  52. denite.util.error(self.vim,
  53. 'command returned invalid response: ' + str(err))
  54. return []
  55. txt = cmd.stdout.decode('utf-8')
  56. output = json.loads(txt, encoding='utf-8')
  57. def make_candidates(row):
  58. name = self.vim.funcs.fnamemodify(row['filename'], ':~:.')
  59. return {
  60. 'word': '{0} :{1} :{2}'.format(name, row['line'], row['full']),
  61. 'action__path': row['filename'],
  62. 'action__line': row['line'],
  63. 'action__col': row['col'],
  64. }
  65. return list(map(make_candidates, output['decls']))
  66. def highlight(self):
  67. for syn in DECLS_SYNTAX_HIGHLIGHT:
  68. containedin = self.syntax_name
  69. containedin += '_' + syn['parent'] if 'parent' in syn else ''
  70. conceal = ' conceal' if 'conceal' in syn else ''
  71. self.vim.command(
  72. 'syntax match {0}_{1} /{2}/ contained containedin={3}{4}'
  73. .format(self.syntax_name, syn['name'], syn['re'],
  74. containedin, conceal))
  75. if 'link' in syn:
  76. self.vim.command('highlight default link {0}_{1} {2}'.format(
  77. self.syntax_name, syn['name'], syn['link']))