1
0

signs.vim 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. if exists('g:loaded_syntastic_notifier_signs') || !exists('g:loaded_syntastic_plugin')
  2. finish
  3. endif
  4. let g:loaded_syntastic_notifier_signs = 1
  5. " Initialisation {{{1
  6. " start counting sign ids at 5000, start here to hopefully avoid conflicting
  7. " with any other code that places signs (not sure if this precaution is
  8. " actually needed)
  9. let s:first_sign_id = 5000
  10. let s:next_sign_id = s:first_sign_id
  11. let g:SyntasticSignsNotifier = {}
  12. let s:setup_done = 0
  13. " }}}1
  14. " Public methods {{{1
  15. function! g:SyntasticSignsNotifier.New() abort " {{{2
  16. let newObj = copy(self)
  17. if !s:setup_done
  18. call self._setup()
  19. let s:setup_done = 1
  20. lockvar s:setup_done
  21. endif
  22. return newObj
  23. endfunction " }}}2
  24. function! g:SyntasticSignsNotifier.enabled() abort " {{{2
  25. return has('signs') && syntastic#util#var('enable_signs')
  26. endfunction " }}}2
  27. function! g:SyntasticSignsNotifier.refresh(loclist) abort " {{{2
  28. call syntastic#log#debug(g:_SYNTASTIC_DEBUG_NOTIFICATIONS, 'signs: refresh')
  29. let old_signs = copy(self._bufSignIds())
  30. if self.enabled()
  31. call self._signErrors(a:loclist)
  32. endif
  33. call self._removeSigns(old_signs)
  34. endfunction " }}}2
  35. " }}}1
  36. " Private methods {{{1
  37. " One time setup: define our own sign types and highlighting
  38. function! g:SyntasticSignsNotifier._setup() abort " {{{2
  39. if has('signs')
  40. if !hlexists('SyntasticErrorSign')
  41. highlight link SyntasticErrorSign error
  42. endif
  43. if !hlexists('SyntasticWarningSign')
  44. highlight link SyntasticWarningSign todo
  45. endif
  46. if !hlexists('SyntasticStyleErrorSign')
  47. highlight link SyntasticStyleErrorSign SyntasticErrorSign
  48. endif
  49. if !hlexists('SyntasticStyleWarningSign')
  50. highlight link SyntasticStyleWarningSign SyntasticWarningSign
  51. endif
  52. if !hlexists('SyntasticStyleErrorLine')
  53. highlight link SyntasticStyleErrorLine SyntasticErrorLine
  54. endif
  55. if !hlexists('SyntasticStyleWarningLine')
  56. highlight link SyntasticStyleWarningLine SyntasticWarningLine
  57. endif
  58. " define the signs used to display syntax and style errors/warns
  59. execute 'sign define SyntasticError text=' . g:syntastic_error_symbol .
  60. \ ' texthl=SyntasticErrorSign linehl=SyntasticErrorLine'
  61. execute 'sign define SyntasticWarning text=' . g:syntastic_warning_symbol .
  62. \ ' texthl=SyntasticWarningSign linehl=SyntasticWarningLine'
  63. execute 'sign define SyntasticStyleError text=' . g:syntastic_style_error_symbol .
  64. \ ' texthl=SyntasticStyleErrorSign linehl=SyntasticStyleErrorLine'
  65. execute 'sign define SyntasticStyleWarning text=' . g:syntastic_style_warning_symbol .
  66. \ ' texthl=SyntasticStyleWarningSign linehl=SyntasticStyleWarningLine'
  67. endif
  68. endfunction " }}}2
  69. " Place signs by all syntax errors in the buffer
  70. function! g:SyntasticSignsNotifier._signErrors(loclist) abort " {{{2
  71. let loclist = a:loclist
  72. if !loclist.isEmpty()
  73. let buf = bufnr('')
  74. if !bufloaded(buf)
  75. " signs can be placed only in loaded buffers
  76. return
  77. endif
  78. " errors come first, so that they are not masked by warnings
  79. let issues = copy(loclist.errors())
  80. call extend(issues, loclist.warnings())
  81. call filter(issues, 'v:val["bufnr"] == buf')
  82. let seen = {}
  83. for i in issues
  84. if i['lnum'] > 0 && !has_key(seen, i['lnum'])
  85. let seen[i['lnum']] = 1
  86. let sign_severity = i['type'] ==? 'W' ? 'Warning' : 'Error'
  87. let sign_subtype = get(i, 'subtype', '')
  88. let sign_type = 'Syntastic' . sign_subtype . sign_severity
  89. execute 'sign place ' . s:next_sign_id . ' line=' . i['lnum'] . ' name=' . sign_type . ' buffer=' . i['bufnr']
  90. call add(self._bufSignIds(), s:next_sign_id)
  91. let s:next_sign_id += 1
  92. endif
  93. endfor
  94. endif
  95. endfunction " }}}2
  96. " Remove the signs with the given ids from this buffer
  97. function! g:SyntasticSignsNotifier._removeSigns(ids) abort " {{{2
  98. if has('signs')
  99. for s in reverse(copy(a:ids))
  100. execute 'sign unplace ' . s
  101. call remove(self._bufSignIds(), index(self._bufSignIds(), s))
  102. endfor
  103. endif
  104. endfunction " }}}2
  105. " Get all the ids of the SyntaxError signs in the buffer
  106. function! g:SyntasticSignsNotifier._bufSignIds() abort " {{{2
  107. if !exists('b:syntastic_private_sign_ids')
  108. let b:syntastic_private_sign_ids = []
  109. endif
  110. return b:syntastic_private_sign_ids
  111. endfunction " }}}2
  112. " }}}1
  113. " vim: set sw=4 sts=4 et fdm=marker: