All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
2 " Author: w0rp <devw0rp@gmail.com>
3 " Description: This module implements error/warning highlighting.
5 if !hlexists('ALEError')
6 highlight link ALEError SpellBad
9 if !hlexists('ALEStyleError')
10 highlight link ALEStyleError ALEError
13 if !hlexists('ALEWarning')
14 highlight link ALEWarning SpellCap
17 if !hlexists('ALEStyleWarning')
18 highlight link ALEStyleWarning ALEWarning
21 if !hlexists('ALEInfo')
22 highlight link ALEInfo ALEWarning
25 " The maximum number of items for the second argument of matchaddpos()
26 let s:MAX_POS_VALUES = 8
27 let s:MAX_COL_SIZE = 1073741824 " pow(2, 30)
29 let s:has_nvim_highlight = exists('*nvim_buf_add_highlight') && exists('*nvim_buf_clear_namespace')
31 if s:has_nvim_highlight
32 let s:ns_id = nvim_create_namespace('ale_highlight')
35 " Wrappers are necessary to test this functionality by faking the calls in tests.
36 function! ale#highlight#nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start, col_end) abort
37 " Ignore all errors for adding highlights.
39 call nvim_buf_add_highlight(a:buffer, a:ns_id, a:hl_group, a:line, a:col_start, a:col_end)
44 function! ale#highlight#nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end) abort
45 call nvim_buf_clear_namespace(a:buffer, a:ns_id, a:line_start, a:line_end)
48 function! ale#highlight#CreatePositions(line, col, end_line, end_col) abort
49 if a:line >= a:end_line
50 " For single lines, just return the one position.
51 return [[[a:line, a:col, a:end_col - a:col + 1]]]
54 " Get positions from the first line at the first column, up to a large
55 " integer for highlighting up to the end of the line, followed by
56 " the lines in-between, for highlighting entire lines, and
57 " a highlight for the last line, up to the end column.
59 \ [[a:line, a:col, s:MAX_COL_SIZE]]
60 \ + range(a:line + 1, a:end_line - 1)
61 \ + [[a:end_line, 1, a:end_col]]
64 \ range(0, len(l:all_positions) - 1, s:MAX_POS_VALUES),
65 \ 'l:all_positions[v:val : v:val + s:MAX_POS_VALUES - 1]',
69 " Given a loclist for current items to highlight, remove all highlights
70 " except these which have matching loclist item entries.
72 function! ale#highlight#RemoveHighlights() abort
73 if s:has_nvim_highlight
74 call ale#highlight#nvim_buf_clear_namespace(bufnr(''), s:ns_id, 0, -1)
76 for l:match in getmatches()
77 if l:match.group =~? '\v^ALE(Style)?(Error|Warning|Info)(Line)?$'
78 call matchdelete(l:match.id)
84 " Same semantics of matchaddpos but will use nvim_buf_add_highlight if
85 " available. This involves iterating over the position list, switching from
86 " 1-based indexing to 0-based indexing, and translating the multiple ways
87 " that position can be specified for matchaddpos into line + col_start +
89 function! s:matchaddpos(group, pos_list) abort
90 if s:has_nvim_highlight
91 for l:pos in a:pos_list
92 let l:line = type(l:pos) == v:t_number
96 if type(l:pos) == v:t_number || len(l:pos) == 1
98 let l:col_end = s:MAX_COL_SIZE
100 let l:col_start = l:pos[1] - 1
101 let l:col_end = l:col_start + get(l:pos, 2, 1)
104 call ale#highlight#nvim_buf_add_highlight(
114 call matchaddpos(a:group, a:pos_list)
118 function! s:highlight_line(bufnr, lnum, group) abort
119 call s:matchaddpos(a:group, [a:lnum])
122 function! s:highlight_range(bufnr, range, group) abort
123 " Set all of the positions, which are chunked into Lists which
124 " are as large as will be accepted by matchaddpos.
126 \ ale#highlight#CreatePositions(
132 \ 's:matchaddpos(a:group, v:val)'
136 function! ale#highlight#UpdateHighlights() abort
137 let l:item_list = get(b:, 'ale_enabled', 1) && g:ale_enabled
138 \ ? get(b:, 'ale_highlight_items', [])
141 call ale#highlight#RemoveHighlights()
143 for l:item in l:item_list
144 if l:item.type is# 'W'
145 if get(l:item, 'sub_type', '') is# 'style'
146 let l:group = 'ALEStyleWarning'
148 let l:group = 'ALEWarning'
150 elseif l:item.type is# 'I'
151 let l:group = 'ALEInfo'
152 elseif get(l:item, 'sub_type', '') is# 'style'
153 let l:group = 'ALEStyleError'
155 let l:group = 'ALEError'
159 \ 'lnum': l:item.lnum,
161 \ 'end_lnum': get(l:item, 'end_lnum', l:item.lnum),
162 \ 'end_col': get(l:item, 'end_col', l:item.col)
165 call s:highlight_range(l:item.bufnr, l:range, l:group)
168 " If highlights are enabled and signs are not enabled, we should still
169 " offer line highlights by adding a separate set of highlights.
171 let l:available_groups = {
172 \ 'ALEWarningLine': hlexists('ALEWarningLine'),
173 \ 'ALEInfoLine': hlexists('ALEInfoLine'),
174 \ 'ALEErrorLine': hlexists('ALEErrorLine'),
177 for l:item in l:item_list
178 if l:item.type is# 'W'
179 let l:group = 'ALEWarningLine'
180 elseif l:item.type is# 'I'
181 let l:group = 'ALEInfoLine'
183 let l:group = 'ALEErrorLine'
186 if l:available_groups[l:group]
187 call s:highlight_line(l:item.bufnr, l:item.lnum, l:group)
193 function! ale#highlight#BufferHidden(buffer) abort
194 " Remove highlights right away when buffers are hidden.
195 " They will be restored later when buffers are entered.
196 call ale#highlight#RemoveHighlights()
199 augroup ALEHighlightBufferGroup
201 autocmd BufEnter * call ale#highlight#UpdateHighlights()
202 autocmd BufHidden * call ale#highlight#BufferHidden(expand('<abuf>'))
205 function! ale#highlight#SetHighlights(buffer, loclist) abort
206 let l:new_list = getbufvar(a:buffer, 'ale_enabled', 1) && g:ale_enabled
207 \ ? filter(copy(a:loclist), 'v:val.bufnr == a:buffer && v:val.col > 0')
210 " Set the list in the buffer variable.
211 call setbufvar(str2nr(a:buffer), 'ale_highlight_items', l:new_list)
213 let l:exclude_list = ale#Var(a:buffer, 'exclude_highlights')
215 if !empty(l:exclude_list)
216 call filter(l:new_list, 'empty(ale#util#GetMatches(v:val.text, l:exclude_list))')
219 " Update highlights for the current buffer, which may or may not
220 " be the buffer we just set highlights for.
221 call ale#highlight#UpdateHighlights()