Some checks failed
		
		
	
	Detach Plugins / check (FlyGrep.vim) (push) Has been cancelled
				
			Detach Plugins / check (GitHub.vim) (push) Has been cancelled
				
			Detach Plugins / check (JavaUnit.vim) (push) Has been cancelled
				
			Detach Plugins / check (SourceCounter.vim) (push) Has been cancelled
				
			Detach Plugins / check (cpicker.nvim) (push) Has been cancelled
				
			Detach Plugins / check (dein-ui.vim) (push) Has been cancelled
				
			Detach Plugins / check (git.vim) (push) Has been cancelled
				
			Detach Plugins / check (iedit.vim) (push) Has been cancelled
				
			Detach Plugins / check (scrollbar.vim) (push) Has been cancelled
				
			Detach Plugins / check (vim-chat) (push) Has been cancelled
				
			Detach Plugins / check (vim-cheat) (push) Has been cancelled
				
			Detach Plugins / check (vim-todo) (push) Has been cancelled
				
			Detach Plugins / check (xmake.vim) (push) Has been cancelled
				
			test / Linux (nvim, nightly) (push) Has been cancelled
				
			test / Linux (nvim, v0.3.8) (push) Has been cancelled
				
			test / Linux (nvim, v0.4.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.4.2) (push) Has been cancelled
				
			test / Linux (nvim, v0.4.3) (push) Has been cancelled
				
			test / Linux (nvim, v0.4.4) (push) Has been cancelled
				
			test / Linux (nvim, v0.5.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.5.1) (push) Has been cancelled
				
			test / Linux (nvim, v0.6.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.6.1) (push) Has been cancelled
				
			test / Linux (nvim, v0.7.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.7.2) (push) Has been cancelled
				
			test / Linux (nvim, v0.8.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.8.1) (push) Has been cancelled
				
			test / Linux (nvim, v0.8.2) (push) Has been cancelled
				
			test / Linux (nvim, v0.8.3) (push) Has been cancelled
				
			test / Linux (nvim, v0.9.0) (push) Has been cancelled
				
			test / Linux (nvim, v0.9.1) (push) Has been cancelled
				
			test / Linux (true, vim, v7.4.052) (push) Has been cancelled
				
			test / Linux (true, vim, v7.4.1689) (push) Has been cancelled
				
			test / Linux (true, vim, v7.4.629) (push) Has been cancelled
				
			test / Linux (true, vim, v8.0.0027) (push) Has been cancelled
				
			test / Linux (true, vim, v8.0.0183) (push) Has been cancelled
				
			test / Linux (vim, nightly) (push) Has been cancelled
				
			test / Linux (vim, v8.0.0184) (push) Has been cancelled
				
			test / Linux (vim, v8.0.1453) (push) Has been cancelled
				
			test / Linux (vim, v8.1.2269) (push) Has been cancelled
				
			test / Linux (vim, v8.2.2434) (push) Has been cancelled
				
			test / Linux (vim, v8.2.3995) (push) Has been cancelled
				
			test / Windows (nvim, nightly) (push) Has been cancelled
				
			test / Windows (nvim, v0.3.8) (push) Has been cancelled
				
			test / Windows (nvim, v0.4.2) (push) Has been cancelled
				
			test / Windows (nvim, v0.4.3) (push) Has been cancelled
				
			test / Windows (nvim, v0.4.4) (push) Has been cancelled
				
			test / Windows (nvim, v0.5.0) (push) Has been cancelled
				
			test / Windows (nvim, v0.5.1) (push) Has been cancelled
				
			test / Windows (nvim, v0.6.0) (push) Has been cancelled
				
			test / Windows (nvim, v0.6.1) (push) Has been cancelled
				
			test / Windows (nvim, v0.7.0) (push) Has been cancelled
				
			test / Windows (nvim, v0.7.2) (push) Has been cancelled
				
			test / Windows (nvim, v0.8.0) (push) Has been cancelled
				
			test / Windows (nvim, v0.8.1) (push) Has been cancelled
				
			test / Windows (nvim, v0.8.2) (push) Has been cancelled
				
			test / Windows (nvim, v0.8.3) (push) Has been cancelled
				
			test / Windows (nvim, v0.9.0) (push) Has been cancelled
				
			test / Windows (nvim, v0.9.1) (push) Has been cancelled
				
			test / Windows (vim, nightly) (push) Has been cancelled
				
			test / Windows (vim, v7.4.1185) (push) Has been cancelled
				
			test / Windows (vim, v7.4.1689) (push) Has been cancelled
				
			test / Windows (vim, v8.0.0027) (push) Has been cancelled
				
			test / Windows (vim, v8.0.1453) (push) Has been cancelled
				
			test / Windows (vim, v8.1.2269) (push) Has been cancelled
				
			test / Windows (vim, v8.2.2434) (push) Has been cancelled
				
			test / Windows (vim, v8.2.3995) (push) Has been cancelled
				
			docker / docker (push) Has been cancelled
				
			mirror / check (coding) (push) Has been cancelled
				
			mirror / check (gitee) (push) Has been cancelled
				
			mirror / check (gitlab) (push) Has been cancelled
				
			
		
			
				
	
	
		
			812 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			VimL
		
	
	
	
	
	
			
		
		
	
	
			812 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			VimL
		
	
	
	
	
	
scriptencoding utf-8
 | 
						|
let s:is_vim = !has('nvim')
 | 
						|
let s:nvim_50 = has('nvim-0.5.0')
 | 
						|
let s:nvim_60 = has('nvim-0.6.0')
 | 
						|
let s:clear_match_by_window = s:nvim_60 || s:is_vim
 | 
						|
let s:set_extmark = has('nvim') && exists('*nvim_buf_set_extmark')
 | 
						|
let s:namespace_map = {}
 | 
						|
let s:ns_id = 1
 | 
						|
let s:diagnostic_hlgroups = ['CocErrorHighlight', 'CocWarningHighlight', 'CocInfoHighlight', 'CocHintHighlight', 'CocDeprecatedHighlight', 'CocUnusedHighlight']
 | 
						|
" Maximum count to highlight each time.
 | 
						|
let g:coc_highlight_maximum_count = get(g:, 'coc_highlight_maximum_count', 100)
 | 
						|
let s:term = &termguicolors == 0 && !has('gui_running')
 | 
						|
 | 
						|
if has('nvim-0.5.0') && s:clear_match_by_window == 0
 | 
						|
  try
 | 
						|
    call getmatches(0)
 | 
						|
    let s:clear_match_by_window = 1
 | 
						|
  catch /^Vim\%((\a\+)\)\=:E118/
 | 
						|
    " ignored
 | 
						|
  endtry
 | 
						|
endif
 | 
						|
 | 
						|
" Update buffer region by region.
 | 
						|
function! coc#highlight#buffer_update(bufnr, key, highlights, ...) abort
 | 
						|
  if !bufloaded(a:bufnr)
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  if empty(a:highlights)
 | 
						|
    call coc#highlight#clear_highlight(a:bufnr, a:key, 0, -1)
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let priority = get(a:, 1, v:null)
 | 
						|
  let changedtick = getbufvar(a:bufnr, 'changedtick', 0)
 | 
						|
  if type(get(a:, 2, v:null)) == 0 && changedtick > a:2
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let hls = map(copy(a:highlights), "{'hlGroup':v:val[0],'lnum':v:val[1],'colStart':v:val[2],'colEnd':v:val[3],'combine':get(v:val,4,1),'start_incl':get(v:val,5,0),'end_incl':get(v:val,6,0)}")
 | 
						|
  if len(hls) <= g:coc_highlight_maximum_count
 | 
						|
    call coc#highlight#update_highlights(a:bufnr, a:key, hls, 0, -1, priority)
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let linecount = coc#compat#buf_line_count(a:bufnr)
 | 
						|
  let groups = s:group_hls(hls, linecount)
 | 
						|
  call s:update_highlights_timer(a:bufnr, changedtick, a:key, priority, groups, 0)
 | 
						|
endfunction
 | 
						|
 | 
						|
" Update highlights by check exists highlights.
 | 
						|
" 0 based, end exclusive start and end
 | 
						|
function! coc#highlight#update_highlights(bufnr, key, highlights, ...) abort
 | 
						|
  let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
 | 
						|
  if !bufloaded(bufnr)
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let start = get(a:, 1, 0)
 | 
						|
  let end = get(a:, 2, -1)
 | 
						|
  if end == 0
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let linecount = coc#compat#buf_line_count(a:bufnr)
 | 
						|
  if end >= linecount
 | 
						|
    let end = -1
 | 
						|
  endif
 | 
						|
  if empty(a:highlights)
 | 
						|
    call coc#highlight#clear_highlight(bufnr, a:key, start, end)
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let priority = get(a:, 3, v:null)
 | 
						|
  let total = len(a:highlights)
 | 
						|
  " index list that exists with current highlights
 | 
						|
  let exists = []
 | 
						|
  let ns = coc#highlight#create_namespace(a:key)
 | 
						|
  if has('nvim-0.5.0') || exists('*prop_list')
 | 
						|
    let endLnum = end < 0 ? linecount - 1 : end - 1
 | 
						|
    let firstLnum = a:highlights[0]['lnum']
 | 
						|
    if firstLnum > start
 | 
						|
      call coc#highlight#clear_highlight(bufnr, a:key, start, firstLnum)
 | 
						|
      let start = firstLnum
 | 
						|
    endif
 | 
						|
    let lastLnum = a:highlights[total - 1]['lnum']
 | 
						|
    if lastLnum < endLnum
 | 
						|
      call coc#highlight#clear_highlight(bufnr, a:key, lastLnum + 1, endLnum + 1)
 | 
						|
      let endLnum = lastLnum
 | 
						|
    endif
 | 
						|
    let current = coc#highlight#get_highlights(bufnr, a:key, start, endLnum)
 | 
						|
    let currIndex = 0
 | 
						|
    if !empty(current)
 | 
						|
      for [lnum, items] in s:to_group(current)
 | 
						|
        let indexes = []
 | 
						|
        let currIndexes = range(0, len(items) - 1)
 | 
						|
        let removeIndexes = []
 | 
						|
        while currIndex != total
 | 
						|
          let hi = a:highlights[currIndex]
 | 
						|
          if hi['lnum'] == lnum
 | 
						|
            let findIndex = -1
 | 
						|
            for idx in currIndexes
 | 
						|
              let item = items[idx]
 | 
						|
              if hi['hlGroup'] ==# item[0] && hi['colStart'] == item[2] && hi['colEnd'] == item[3]
 | 
						|
                call add(indexes, currIndex)
 | 
						|
                let findIndex = idx
 | 
						|
                break
 | 
						|
              elseif item[2] > hi['colStart']
 | 
						|
                break
 | 
						|
              endif
 | 
						|
            endfor
 | 
						|
            if findIndex != -1
 | 
						|
              call filter(currIndexes, 'v:val != '.findIndex)
 | 
						|
            endif
 | 
						|
          elseif hi['lnum'] > lnum
 | 
						|
            break
 | 
						|
          endif
 | 
						|
          let currIndex = currIndex + 1
 | 
						|
        endwhile
 | 
						|
        for idx in currIndexes
 | 
						|
          if s:is_vim
 | 
						|
            call prop_remove({'bufnr': bufnr, 'id': items[idx][4]})
 | 
						|
          else
 | 
						|
            call nvim_buf_del_extmark(bufnr, ns, items[idx][4])
 | 
						|
          endif
 | 
						|
        endfor
 | 
						|
        call extend(exists, indexes)
 | 
						|
      endfor
 | 
						|
    endif
 | 
						|
  else
 | 
						|
    call coc#highlight#clear_highlight(bufnr, a:key, start, end)
 | 
						|
  endif
 | 
						|
  let indexes = range(0, total - 1)
 | 
						|
  if !empty(exists)
 | 
						|
    let indexes = filter(indexes, 'index(exists, v:val) == -1')
 | 
						|
  endif
 | 
						|
  for idx in indexes
 | 
						|
    let hi = a:highlights[idx]
 | 
						|
    let opts = {
 | 
						|
        \ 'combine': get(hi, 'combine', 0),
 | 
						|
        \ 'start_incl': get(hi, 'start_incl', 0),
 | 
						|
        \ 'end_incl': get(hi, 'end_incl', 0),
 | 
						|
        \ }
 | 
						|
    if type(priority) == 0
 | 
						|
      let opts['priority'] = s:get_priority(a:key, hi['hlGroup'], priority)
 | 
						|
    endif
 | 
						|
    call coc#highlight#add_highlight(bufnr, ns, hi['hlGroup'], hi['lnum'], hi['colStart'], hi['colEnd'], opts)
 | 
						|
  endfor
 | 
						|
endfunction
 | 
						|
 | 
						|
" Get list of highlights by range or all buffer.
 | 
						|
" 0 based line, start_col and end_col
 | 
						|
" 0 based start & end line, end inclusive.
 | 
						|
function! coc#highlight#get_highlights(bufnr, key, ...) abort
 | 
						|
  if !bufloaded(a:bufnr)
 | 
						|
    return v:null
 | 
						|
  endif
 | 
						|
  if !has_key(s:namespace_map, a:key)
 | 
						|
    return []
 | 
						|
  endif
 | 
						|
  let start = get(a:, 1, 0)
 | 
						|
  let end = get(a:, 2, -1)
 | 
						|
  if s:nvim_60
 | 
						|
    return v:lua.require('coc.highlight').getHighlights(a:bufnr, a:key, start, end)
 | 
						|
  elseif s:nvim_50
 | 
						|
    return luaeval(
 | 
						|
          \ 'require("coc.highlight").getHighlights(_A[1],_A[2],_A[3],_A[4])',
 | 
						|
          \ [a:bufnr, a:key, start, end]
 | 
						|
          \ )
 | 
						|
  endif
 | 
						|
  let res = []
 | 
						|
  let ns = s:namespace_map[a:key]
 | 
						|
  if exists('*prop_list')
 | 
						|
    let types = coc#api#get_types(ns)
 | 
						|
    if empty(types)
 | 
						|
      return res
 | 
						|
    endif
 | 
						|
    " Could filter by end_lnum and types
 | 
						|
    if has('patch-8.2.3652')
 | 
						|
      let endLnum = end == -1 ? -1 : end + 1
 | 
						|
      for prop in prop_list(start + 1, {'bufnr': a:bufnr, 'types': types, 'end_lnum': endLnum})
 | 
						|
        if prop['start'] == 0 || prop['end'] == 0
 | 
						|
          " multi line textprop are not supported, simply ignore it
 | 
						|
          continue
 | 
						|
        endif
 | 
						|
        let startCol = prop['col'] - 1
 | 
						|
        let endCol = startCol + prop['length']
 | 
						|
        call add(res, [s:prop_type_hlgroup(prop['type']), prop['lnum'] - 1, startCol, endCol, prop['id']])
 | 
						|
      endfor
 | 
						|
    else
 | 
						|
      if end == -1
 | 
						|
        let end = coc#compat#buf_line_count(a:bufnr)
 | 
						|
      else
 | 
						|
        let end = end + 1
 | 
						|
      endif
 | 
						|
      for line in range(start + 1, end)
 | 
						|
        for prop in prop_list(line, {'bufnr': a:bufnr})
 | 
						|
          if index(types, prop['type']) == -1 || prop['start'] == 0 || prop['end'] == 0
 | 
						|
            " multi line textprop are not supported, simply ignore it
 | 
						|
            continue
 | 
						|
          endif
 | 
						|
          let startCol = prop['col'] - 1
 | 
						|
          let endCol = startCol + prop['length']
 | 
						|
          call add(res, [s:prop_type_hlgroup(prop['type']), line - 1, startCol, endCol, prop['id']])
 | 
						|
        endfor
 | 
						|
      endfor
 | 
						|
    endif
 | 
						|
  else
 | 
						|
    throw 'Get highlights requires neovim 0.5.0 or vim support prop_list'
 | 
						|
  endif
 | 
						|
  return res
 | 
						|
endfunction
 | 
						|
 | 
						|
" Add multiple highlights to buffer.
 | 
						|
" type HighlightItem = [hlGroup, lnum, colStart, colEnd, combine?, start_incl?, end_incl?]
 | 
						|
function! coc#highlight#set(bufnr, key, highlights, priority) abort
 | 
						|
  if !bufloaded(a:bufnr)
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let ns = coc#highlight#create_namespace(a:key)
 | 
						|
  let g:c = 1
 | 
						|
  if s:nvim_60
 | 
						|
    call v:lua.require('coc.highlight').set(a:bufnr, ns, a:highlights, a:priority)
 | 
						|
  elseif s:nvim_50
 | 
						|
    call luaeval(
 | 
						|
          \ 'require("coc.highlight").set(_A[1],_A[2],_A[3],_A[4])',
 | 
						|
          \ [a:bufnr, ns, a:highlights, a:priority]
 | 
						|
          \ )
 | 
						|
  else
 | 
						|
    if len(a:highlights) > g:coc_highlight_maximum_count
 | 
						|
      call s:add_highlights_timer(a:bufnr, ns, a:highlights, a:priority)
 | 
						|
    else
 | 
						|
      call s:add_highlights(a:bufnr, ns, a:highlights, a:priority)
 | 
						|
    endif
 | 
						|
  endif
 | 
						|
endfunction
 | 
						|
 | 
						|
" Clear highlights by 0 based line numbers.
 | 
						|
function! coc#highlight#clear(bufnr, key, lnums) abort
 | 
						|
  if !bufloaded(a:bufnr) || empty(a:lnums)
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let ns = coc#highlight#create_namespace(a:key)
 | 
						|
  for lnum in a:lnums
 | 
						|
    if has('nvim')
 | 
						|
      call nvim_buf_clear_namespace(a:bufnr, ns, lnum, lnum + 1)
 | 
						|
    else
 | 
						|
      call coc#api#exec('buf_clear_namespace', [a:bufnr, ns, lnum, lnum + 1])
 | 
						|
    endif
 | 
						|
  endfor
 | 
						|
  " clear highlights in invalid line.
 | 
						|
  if has('nvim')
 | 
						|
    let linecount = nvim_buf_line_count(a:bufnr)
 | 
						|
    call nvim_buf_clear_namespace(a:bufnr, ns, linecount, -1)
 | 
						|
  endif
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#del_markers(bufnr, key, ids) abort
 | 
						|
  if !bufloaded(a:bufnr)
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let ns = coc#highlight#create_namespace(a:key)
 | 
						|
  for id in a:ids
 | 
						|
    if s:is_vim
 | 
						|
      call prop_remove({'bufnr': a:bufnr, 'id': id})
 | 
						|
    else
 | 
						|
      call nvim_buf_del_extmark(a:bufnr, ns, id)
 | 
						|
    endif
 | 
						|
  endfor
 | 
						|
endfunction
 | 
						|
 | 
						|
" highlight LSP range, opts contains 'combine' 'priority' 'start_incl' 'end_incl'
 | 
						|
function! coc#highlight#ranges(bufnr, key, hlGroup, ranges, ...) abort
 | 
						|
  let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
 | 
						|
  if !bufloaded(bufnr) || !exists('*getbufline')
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let opts = get(a:, 1, {})
 | 
						|
  let synmaxcol = getbufvar(a:bufnr, '&synmaxcol', 1000)
 | 
						|
  if synmaxcol == 0
 | 
						|
    let synmaxcol = 1000
 | 
						|
  endif
 | 
						|
  let synmaxcol = min([synmaxcol, 1000])
 | 
						|
  let srcId = coc#highlight#create_namespace(a:key)
 | 
						|
  for range in a:ranges
 | 
						|
    let start = range['start']
 | 
						|
    let end = range['end']
 | 
						|
    for lnum in range(start['line'] + 1, end['line'] + 1)
 | 
						|
      let arr = getbufline(bufnr, lnum)
 | 
						|
      let line = empty(arr) ? '' : arr[0]
 | 
						|
      if empty(line)
 | 
						|
        continue
 | 
						|
      endif
 | 
						|
      if start['character'] > synmaxcol || end['character'] > synmaxcol
 | 
						|
        continue
 | 
						|
      endif
 | 
						|
      let colStart = lnum == start['line'] + 1 ? coc#string#byte_index(line, start['character']) : 0
 | 
						|
      let colEnd = lnum == end['line'] + 1 ? coc#string#byte_index(line, end['character']) : strlen(line)
 | 
						|
      if colStart == colEnd
 | 
						|
        continue
 | 
						|
      endif
 | 
						|
      call coc#highlight#add_highlight(bufnr, srcId, a:hlGroup, lnum - 1, colStart, colEnd, opts)
 | 
						|
    endfor
 | 
						|
  endfor
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#add_highlight(bufnr, src_id, hl_group, line, col_start, col_end, ...) abort
 | 
						|
  let opts = get(a:, 1, {})
 | 
						|
  let priority = get(opts, 'priority', v:null)
 | 
						|
  if !s:is_vim
 | 
						|
    if s:set_extmark && a:src_id != -1
 | 
						|
      " get(opts, 'start_incl', 0) ? v:true : v:false,
 | 
						|
      try
 | 
						|
        call nvim_buf_set_extmark(a:bufnr, a:src_id, a:line, a:col_start, {
 | 
						|
              \ 'end_col': a:col_end,
 | 
						|
              \ 'hl_group': a:hl_group,
 | 
						|
              \ 'hl_mode': get(opts, 'combine', 1) ? 'combine' : 'replace',
 | 
						|
              \ 'right_gravity': v:true,
 | 
						|
              \ 'end_right_gravity': v:false,
 | 
						|
              \ 'priority': type(priority) == 0 ?  min([priority, 4096]) : 4096,
 | 
						|
              \ })
 | 
						|
      catch /^Vim\%((\a\+)\)\=:E5555/
 | 
						|
        " the end_col could be invalid, ignore this error
 | 
						|
      endtry
 | 
						|
    else
 | 
						|
      call nvim_buf_add_highlight(a:bufnr, a:src_id, a:hl_group, a:line, a:col_start, a:col_end)
 | 
						|
    endif
 | 
						|
  else
 | 
						|
    call coc#api#exec('buf_add_highlight', [a:bufnr, a:src_id, a:hl_group, a:line, a:col_start, a:col_end, opts])
 | 
						|
  endif
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#clear_highlight(bufnr, key, start_line, end_line) abort
 | 
						|
  let bufnr = a:bufnr == 0 ? bufnr('%') : a:bufnr
 | 
						|
  if !bufloaded(bufnr)
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let src_id = coc#highlight#create_namespace(a:key)
 | 
						|
  if has('nvim')
 | 
						|
    call nvim_buf_clear_namespace(a:bufnr, src_id, a:start_line, a:end_line)
 | 
						|
  else
 | 
						|
    call coc#api#exec('buf_clear_namespace', [a:bufnr, src_id, a:start_line, a:end_line])
 | 
						|
  endif
 | 
						|
endfunction
 | 
						|
 | 
						|
" highlight buffer in winid with CodeBlock &HighlightItems
 | 
						|
" export interface HighlightItem {
 | 
						|
"   lnum: number // 0 based
 | 
						|
"   hlGroup: string
 | 
						|
"   colStart: number // 0 based
 | 
						|
"   colEnd: number
 | 
						|
" }
 | 
						|
" export interface CodeBlock {
 | 
						|
"   filetype?: string
 | 
						|
"   hlGroup?: string
 | 
						|
"   startLine: number // 0 based
 | 
						|
"   endLine: number
 | 
						|
" }
 | 
						|
function! coc#highlight#add_highlights(winid, codes, highlights) abort
 | 
						|
  if get(g:, 'coc_node_env', '') ==# 'test'
 | 
						|
    call setwinvar(a:winid, 'highlights', a:highlights)
 | 
						|
  endif
 | 
						|
  " clear highlights
 | 
						|
  call coc#compat#execute(a:winid, 'syntax clear')
 | 
						|
  let bufnr = winbufnr(a:winid)
 | 
						|
  call coc#highlight#clear_highlight(bufnr, -1, 0, -1)
 | 
						|
  if !empty(a:codes)
 | 
						|
    call coc#highlight#highlight_lines(a:winid, a:codes)
 | 
						|
  endif
 | 
						|
  if !empty(a:highlights)
 | 
						|
    for item in a:highlights
 | 
						|
      let hlGroup = item['hlGroup']
 | 
						|
      let opts = hlGroup =~# 'Search$' ? {'priority': 999, 'combine': 1} : {}
 | 
						|
      call coc#highlight#add_highlight(bufnr, -1, hlGroup, item['lnum'], item['colStart'], item['colEnd'])
 | 
						|
    endfor
 | 
						|
  endif
 | 
						|
endfunction
 | 
						|
 | 
						|
 | 
						|
" Add highlights to line groups of winid, support hlGroup and filetype
 | 
						|
" config should have startLine, endLine (0 based, end excluded) and filetype or hlGroup
 | 
						|
" endLine should > startLine and endLine is excluded
 | 
						|
"
 | 
						|
" export interface CodeBlock {
 | 
						|
"   filetype?: string
 | 
						|
"   hlGroup?: string
 | 
						|
"   startLine: number // 0 based
 | 
						|
"   endLine: number
 | 
						|
" }
 | 
						|
function! coc#highlight#highlight_lines(winid, blocks) abort
 | 
						|
  let region_id = 1
 | 
						|
  let defined = []
 | 
						|
  let cmds = []
 | 
						|
  for config in a:blocks
 | 
						|
    let start = config['startLine'] + 1
 | 
						|
    let end = config['endLine'] == -1 ? len(getbufline(winbufnr(a:winid), 1, '$')) + 1 : config['endLine'] + 1
 | 
						|
    let filetype = get(config, 'filetype', '')
 | 
						|
    let hlGroup = get(config, 'hlGroup', '')
 | 
						|
    if !empty(hlGroup)
 | 
						|
      call add(cmds, 'syntax region '.hlGroup.' start=/\%'.start.'l/ end=/\%'.end.'l/')
 | 
						|
    else
 | 
						|
      let filetype = matchstr(filetype, '\v^\w+')
 | 
						|
      if empty(filetype) || filetype == 'txt' || index(get(g:, 'coc_markdown_disabled_languages', []), filetype) != -1
 | 
						|
        continue
 | 
						|
      endif
 | 
						|
      if index(defined, filetype) == -1
 | 
						|
        call add(cmds, 'syntax include @'.toupper(filetype).' syntax/'.filetype.'.vim')
 | 
						|
        call add(cmds, 'unlet! b:current_syntax')
 | 
						|
        call add(defined, filetype)
 | 
						|
      endif
 | 
						|
      call add(cmds, 'syntax region CodeBlock'.region_id.' start=/\%'.start.'l/ end=/\%'.end.'l/ contains=@'.toupper(filetype).' keepend')
 | 
						|
      let region_id = region_id + 1
 | 
						|
    endif
 | 
						|
  endfor
 | 
						|
  if !empty(cmds)
 | 
						|
    call coc#compat#execute(a:winid, cmds, 'silent!')
 | 
						|
  endif
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#compose(fg, bg) abort
 | 
						|
  let fgId = synIDtrans(hlID(a:fg))
 | 
						|
  let bgId = synIDtrans(hlID(a:bg))
 | 
						|
  let isGuiReversed = synIDattr(fgId, 'reverse', 'gui') !=# '1' || synIDattr(bgId, 'reverse', 'gui') !=# '1'
 | 
						|
  let guifg = isGuiReversed ? synIDattr(fgId, 'fg', 'gui') : synIDattr(fgId, 'bg', 'gui')
 | 
						|
  let guibg = isGuiReversed ? synIDattr(bgId, 'bg', 'gui') : synIDattr(bgId, 'fg', 'gui')
 | 
						|
  let isCtermReversed = synIDattr(fgId, 'reverse', 'cterm') !=# '1' || synIDattr(bgId, 'reverse', 'cterm') !=# '1'
 | 
						|
  let ctermfg = isCtermReversed ? synIDattr(fgId, 'fg', 'cterm') : synIDattr(fgId, 'bg', 'cterm')
 | 
						|
  let ctermbg = isCtermReversed ? synIDattr(bgId, 'bg', 'cterm') : synIDattr(bgId, 'fg', 'cterm')
 | 
						|
  let bold = synIDattr(fgId, 'bold') ==# '1'
 | 
						|
  let italic = synIDattr(fgId, 'italic') ==# '1'
 | 
						|
  let underline = synIDattr(fgId, 'underline') ==# '1'
 | 
						|
  let cmd = ''
 | 
						|
  if !empty(guifg)
 | 
						|
    let cmd .= ' guifg=' . guifg
 | 
						|
  endif
 | 
						|
  if !empty(ctermfg)
 | 
						|
    let cmd .= ' ctermfg=' . ctermfg
 | 
						|
  elseif guifg =~# '^#'
 | 
						|
    let cmd .= ' ctermfg=' . coc#color#rgb2term(strpart(guifg, 1))
 | 
						|
  endif
 | 
						|
  if !empty(guibg)
 | 
						|
    let cmd .= ' guibg=' . guibg
 | 
						|
  endif
 | 
						|
  if !empty(ctermbg)
 | 
						|
    let cmd .= ' ctermbg=' . ctermbg
 | 
						|
  elseif guibg =~# '^#'
 | 
						|
    let cmd .= ' ctermbg=' . coc#color#rgb2term(strpart(guibg, 1))
 | 
						|
  endif
 | 
						|
  if bold
 | 
						|
    let cmd .= ' cterm=bold gui=bold'
 | 
						|
  elseif italic
 | 
						|
    let cmd .= ' cterm=italic gui=italic'
 | 
						|
  elseif underline
 | 
						|
    let cmd .= ' cterm=underline gui=underline'
 | 
						|
  endif
 | 
						|
  return cmd
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#valid(hlGroup) abort
 | 
						|
  return hlexists(a:hlGroup) && execute('hi '.a:hlGroup, 'silent!') !~# ' cleared$'
 | 
						|
endfunction
 | 
						|
 | 
						|
" Compose hlGroups with foreground and background colors.
 | 
						|
function! coc#highlight#compose_hlgroup(fgGroup, bgGroup) abort
 | 
						|
  let hlGroup = 'Fg'.a:fgGroup.'Bg'.a:bgGroup
 | 
						|
  if a:fgGroup ==# a:bgGroup
 | 
						|
    return a:fgGroup
 | 
						|
  endif
 | 
						|
  if coc#highlight#valid(hlGroup)
 | 
						|
    return hlGroup
 | 
						|
  endif
 | 
						|
  let cmd = coc#highlight#compose(a:fgGroup, a:bgGroup)
 | 
						|
  if empty(cmd)
 | 
						|
      return 'Normal'
 | 
						|
  endif
 | 
						|
  execute 'silent hi ' . hlGroup . cmd
 | 
						|
  return hlGroup
 | 
						|
endfunction
 | 
						|
 | 
						|
" hlGroup id, key => 'fg' | 'bg', kind => 'cterm' | 'gui'
 | 
						|
function! coc#highlight#get_color(id, key, kind) abort
 | 
						|
  if synIDattr(a:id, 'reverse', a:kind) !=# '1'
 | 
						|
    return synIDattr(a:id, a:key, a:kind)
 | 
						|
  endif
 | 
						|
  return  synIDattr(a:id, a:key ==# 'bg' ? 'fg' : 'bg', a:kind)
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#get_hl_command(id, key, cterm, gui) abort
 | 
						|
  let cterm = coc#highlight#get_color(a:id, a:key, 'cterm')
 | 
						|
  let gui = coc#highlight#get_color(a:id, a:key, 'gui')
 | 
						|
  let cmd = ' cterm'.a:key.'=' . (empty(cterm) ? a:cterm : cterm)
 | 
						|
  let cmd .= ' gui'.a:key.'=' . (empty(gui) ? a:gui : gui)
 | 
						|
  return cmd
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#reversed(id) abort
 | 
						|
  let gui = has('gui_running') || &termguicolors == 1
 | 
						|
  if synIDattr(synIDtrans(a:id), 'reverse', gui ? 'gui' : 'cterm') == '1'
 | 
						|
    return 1
 | 
						|
  endif
 | 
						|
  return 0
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#get_contrast(group1, group2) abort
 | 
						|
  let normal = coc#highlight#get_hex_color(synIDtrans(hlID('Normal')), 'bg', '#000000')
 | 
						|
  let bg1 = coc#highlight#get_hex_color(synIDtrans(hlID(a:group1)), 'bg', normal)
 | 
						|
  let bg2 = coc#highlight#get_hex_color(synIDtrans(hlID(a:group2)), 'bg', normal)
 | 
						|
  return coc#color#hex_contrast(bg1, bg2)
 | 
						|
endfunction
 | 
						|
 | 
						|
" Darken or lighten background
 | 
						|
function! coc#highlight#create_bg_command(group, amount) abort
 | 
						|
  let id = synIDtrans(hlID(a:group))
 | 
						|
  let normal = coc#highlight#get_hex_color(synIDtrans(hlID('Normal')), 'bg', &background ==# 'dark' ? '#282828' : '#fefefe')
 | 
						|
  let bg = coc#highlight#get_hex_color(id, 'bg', normal)
 | 
						|
  let hex = a:amount > 0 ? coc#color#darken(bg, a:amount) : coc#color#lighten(bg, -a:amount)
 | 
						|
 | 
						|
  let ctermbg = coc#color#rgb2term(strpart(hex, 1))
 | 
						|
  if s:term && !s:check_ctermbg(id, ctermbg) && abs(a:amount) < 20.0
 | 
						|
    return coc#highlight#create_bg_command(a:group, a:amount * 2)
 | 
						|
  endif
 | 
						|
  return 'ctermbg=' . ctermbg.' guibg=' . hex
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#get_hex_color(id, kind, fallback) abort
 | 
						|
  let attr = coc#highlight#get_color(a:id, a:kind, s:term ? 'cterm' : 'gui')
 | 
						|
  let hex = s:to_hex_color(attr, s:term)
 | 
						|
  if empty(hex) && !s:term
 | 
						|
    let attr = coc#highlight#get_color(a:id, a:kind, 'cterm')
 | 
						|
    let hex = s:to_hex_color(attr, 1)
 | 
						|
  endif
 | 
						|
  return empty(hex) ? a:fallback : hex
 | 
						|
endfunction
 | 
						|
 | 
						|
function! s:check_ctermbg(id, cterm) abort
 | 
						|
  let attr = coc#highlight#get_color(a:id, 'bg', 'cterm')
 | 
						|
  if empty(attr)
 | 
						|
    let attr = coc#highlight#get_color(synIDtrans(hlID('Normal')), 'bg', 'cterm')
 | 
						|
  endif
 | 
						|
  if attr ==# a:cterm
 | 
						|
    return 0
 | 
						|
  endif
 | 
						|
  return 1
 | 
						|
endfunction
 | 
						|
 | 
						|
function! s:to_hex_color(color, term) abort
 | 
						|
  if empty(a:color)
 | 
						|
    return ''
 | 
						|
  endif
 | 
						|
  if a:color =~# '^#\x\+$'
 | 
						|
    return a:color
 | 
						|
  endif
 | 
						|
  if a:term && a:color =~# '^\d\+$'
 | 
						|
    return coc#color#term2rgb(a:color)
 | 
						|
  endif
 | 
						|
  let hex = coc#color#nameToHex(tolower(a:color), a:term)
 | 
						|
  return empty(hex) ? '' : hex
 | 
						|
endfunction
 | 
						|
 | 
						|
" add matches for winid, use 0 for current window.
 | 
						|
function! coc#highlight#match_ranges(winid, bufnr, ranges, hlGroup, priority) abort
 | 
						|
  let winid = a:winid == 0 ? win_getid() : a:winid
 | 
						|
  let bufnr = a:bufnr == 0 ? winbufnr(winid) : a:bufnr
 | 
						|
  if empty(getwininfo(winid)) || (a:bufnr != 0 && winbufnr(a:winid) != a:bufnr)
 | 
						|
    " not valid
 | 
						|
    return []
 | 
						|
  endif
 | 
						|
  if !s:clear_match_by_window
 | 
						|
    let curr = win_getid()
 | 
						|
    noa call win_gotoid(winid)
 | 
						|
  endif
 | 
						|
  let ids = []
 | 
						|
  for range in a:ranges
 | 
						|
    let pos = []
 | 
						|
    let start = range['start']
 | 
						|
    let end = range['end']
 | 
						|
    for lnum in range(start['line'] + 1, end['line'] + 1)
 | 
						|
      let arr = getbufline(bufnr, lnum)
 | 
						|
      let line = empty(arr) ? '' : arr[0]
 | 
						|
      if empty(line)
 | 
						|
        continue
 | 
						|
      endif
 | 
						|
      let colStart = lnum == start['line'] + 1 ? coc#string#byte_index(line, start['character']) + 1 : 1
 | 
						|
      let colEnd = lnum == end['line'] + 1 ? coc#string#byte_index(line, end['character']) + 1 : strlen(line) + 1
 | 
						|
      if colStart == colEnd
 | 
						|
        continue
 | 
						|
      endif
 | 
						|
      call add(pos, [lnum, colStart, colEnd - colStart])
 | 
						|
    endfor
 | 
						|
    if !empty(pos)
 | 
						|
      let opts = s:clear_match_by_window ? {'window': a:winid} : {}
 | 
						|
      let i = 1
 | 
						|
      let l = []
 | 
						|
      for p in pos
 | 
						|
        call add(l, p)
 | 
						|
        if i % 8 == 0
 | 
						|
          let id = matchaddpos(a:hlGroup, l, a:priority, -1, opts)
 | 
						|
          call add(ids, id)
 | 
						|
          let l = []
 | 
						|
        endif
 | 
						|
        let i += 1
 | 
						|
      endfor
 | 
						|
      if !empty(l)
 | 
						|
        let id = matchaddpos(a:hlGroup, l, a:priority, -1, opts)
 | 
						|
        call add(ids, id)
 | 
						|
      endif
 | 
						|
    endif
 | 
						|
  endfor
 | 
						|
  if !s:clear_match_by_window
 | 
						|
    noa call win_gotoid(curr)
 | 
						|
  endif
 | 
						|
  return ids
 | 
						|
endfunction
 | 
						|
 | 
						|
" Clear matches by hlGroup regexp.
 | 
						|
function! coc#highlight#clear_match_group(winid, match) abort
 | 
						|
  let winid = a:winid == 0 ? win_getid() : a:winid
 | 
						|
  if empty(getwininfo(winid))
 | 
						|
    " not valid
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  if s:clear_match_by_window
 | 
						|
    let arr = filter(getmatches(winid), 'v:val["group"] =~# "'.a:match.'"')
 | 
						|
    for item in arr
 | 
						|
      call matchdelete(item['id'], winid)
 | 
						|
    endfor
 | 
						|
  else
 | 
						|
    let curr = win_getid()
 | 
						|
    let switch = exists('*nvim_set_current_win') && curr != winid
 | 
						|
    if switch
 | 
						|
      noa call nvim_set_current_win(a:winid)
 | 
						|
    endif
 | 
						|
    if win_getid() == winid
 | 
						|
      let arr = filter(getmatches(), 'v:val["group"] =~# "'.a:match.'"')
 | 
						|
      for item in arr
 | 
						|
        call matchdelete(item['id'])
 | 
						|
      endfor
 | 
						|
    endif
 | 
						|
    if switch
 | 
						|
      noa call nvim_set_current_win(curr)
 | 
						|
    endif
 | 
						|
  endif
 | 
						|
endfunction
 | 
						|
 | 
						|
" Clear matches by match ids, use 0 for current win.
 | 
						|
function! coc#highlight#clear_matches(winid, ids)
 | 
						|
  let winid = a:winid == 0 ? win_getid() : a:winid
 | 
						|
  if empty(getwininfo(winid))
 | 
						|
    " not valid
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  if s:clear_match_by_window
 | 
						|
    for id in a:ids
 | 
						|
      try
 | 
						|
        call matchdelete(id, winid)
 | 
						|
      catch /^Vim\%((\a\+)\)\=:E803/
 | 
						|
        " ignore
 | 
						|
      endtry
 | 
						|
    endfor
 | 
						|
  else
 | 
						|
    let curr = win_getid()
 | 
						|
    let switch = exists('*nvim_set_current_win') && curr != winid
 | 
						|
    if switch
 | 
						|
      noa call nvim_set_current_win(a:winid)
 | 
						|
    endif
 | 
						|
    if win_getid() == winid
 | 
						|
      for id in a:ids
 | 
						|
        try
 | 
						|
          call matchdelete(id)
 | 
						|
        catch /^Vim\%((\a\+)\)\=:E803/
 | 
						|
          " ignore
 | 
						|
        endtry
 | 
						|
      endfor
 | 
						|
    endif
 | 
						|
    if switch
 | 
						|
      noa call nvim_set_current_win(curr)
 | 
						|
    endif
 | 
						|
  endif
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#clear_all() abort
 | 
						|
  for src_id in values(s:namespace_map)
 | 
						|
    for bufnr in map(getbufinfo({'bufloaded': 1}), 'v:val["bufnr"]')
 | 
						|
      if has('nvim')
 | 
						|
        call nvim_buf_clear_namespace(bufnr, src_id, 0, -1)
 | 
						|
      else
 | 
						|
        call coc#api#exec('buf_clear_namespace', [bufnr, src_id, 0, -1])
 | 
						|
      endif
 | 
						|
    endfor
 | 
						|
  endfor
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#create_namespace(key) abort
 | 
						|
  if type(a:key) == 0
 | 
						|
    return a:key
 | 
						|
  endif
 | 
						|
  if has_key(s:namespace_map, a:key)
 | 
						|
    return s:namespace_map[a:key]
 | 
						|
  endif
 | 
						|
  if has('nvim')
 | 
						|
    let s:namespace_map[a:key] = nvim_create_namespace('coc-'.a:key)
 | 
						|
  else
 | 
						|
    let s:namespace_map[a:key] = s:ns_id
 | 
						|
    let s:ns_id = s:ns_id + 1
 | 
						|
  endif
 | 
						|
  return s:namespace_map[a:key]
 | 
						|
endfunction
 | 
						|
 | 
						|
function! coc#highlight#get_syntax_name(lnum, col)
 | 
						|
  return synIDattr(synIDtrans(synID(a:lnum,a:col,1)),"name")
 | 
						|
endfunction
 | 
						|
 | 
						|
function! s:prop_type_hlgroup(type) abort
 | 
						|
  return substitute(a:type, '_\d\+$', '', '')
 | 
						|
endfunction
 | 
						|
 | 
						|
function! s:update_highlights_timer(bufnr, changedtick, key, priority, groups, idx) abort
 | 
						|
  if getbufvar(a:bufnr, 'changedtick', 0) != a:changedtick
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  let group = get(a:groups, a:idx, v:null)
 | 
						|
  if empty(group)
 | 
						|
    return
 | 
						|
  endif
 | 
						|
  if empty(group['highlights'])
 | 
						|
    call coc#highlight#clear_highlight(a:bufnr, a:key, group['start'], group['end'])
 | 
						|
  else
 | 
						|
    call coc#highlight#update_highlights(a:bufnr, a:key, group['highlights'], group['start'], group['end'], a:priority)
 | 
						|
  endif
 | 
						|
  if a:idx < len(a:groups) - 1
 | 
						|
    call timer_start(50, { -> s:update_highlights_timer(a:bufnr, a:changedtick, a:key, a:priority, a:groups, a:idx + 1)})
 | 
						|
  endif
 | 
						|
endfunction
 | 
						|
 | 
						|
function! s:add_highlights_timer(bufnr, ns, highlights, priority) abort
 | 
						|
  let hls = []
 | 
						|
  let next = []
 | 
						|
  for i in range(0, len(a:highlights) - 1)
 | 
						|
    if i < g:coc_highlight_maximum_count
 | 
						|
      call add(hls, a:highlights[i])
 | 
						|
    else
 | 
						|
      call add(next, a:highlights[i])
 | 
						|
    endif
 | 
						|
  endfor
 | 
						|
  call s:add_highlights(a:bufnr, a:ns, hls, a:priority)
 | 
						|
  if len(next)
 | 
						|
    call timer_start(30, {->s:add_highlights_timer(a:bufnr, a:ns, next, a:priority)})
 | 
						|
  endif
 | 
						|
endfunction
 | 
						|
 | 
						|
function! s:add_highlights(bufnr, ns, highlights, priority) abort
 | 
						|
  for item in a:highlights
 | 
						|
    let opts = {
 | 
						|
          \ 'priority': a:priority,
 | 
						|
          \ 'combine': get(item, 4, 1) ? 1 : 0,
 | 
						|
          \ 'start_incl': get(item, 5, 0) ? 1 : 0,
 | 
						|
          \ 'end_incl':  get(item, 6, 0) ? 1 : 0,
 | 
						|
          \ }
 | 
						|
    call coc#highlight#add_highlight(a:bufnr, a:ns, item[0], item[1], item[2], item[3], opts)
 | 
						|
  endfor
 | 
						|
endfunction
 | 
						|
 | 
						|
function! s:to_group(items) abort
 | 
						|
  let res = []
 | 
						|
  let before = v:null
 | 
						|
  for item in a:items
 | 
						|
    if empty(before) || before[0] != item[1]
 | 
						|
      let before = [item[1], [item]]
 | 
						|
      call add(res, before)
 | 
						|
    else
 | 
						|
      call add(before[1], item)
 | 
						|
    endif
 | 
						|
  endfor
 | 
						|
  return res
 | 
						|
endfunction
 | 
						|
 | 
						|
function! s:get_priority(key, hlGroup, priority) abort
 | 
						|
  if a:hlGroup ==# 'CocListSearch'
 | 
						|
    return 2048
 | 
						|
  endif
 | 
						|
  if a:hlGroup ==# 'CocSearch'
 | 
						|
    return 999
 | 
						|
  endif
 | 
						|
  if strpart(a:key, 0, 10) !=# 'diagnostic'
 | 
						|
    return a:priority
 | 
						|
  endif
 | 
						|
  return a:priority - index(s:diagnostic_hlgroups, a:hlGroup)
 | 
						|
endfunction
 | 
						|
 | 
						|
function! s:group_hls(hls, linecount) abort
 | 
						|
  " start, end, highlights
 | 
						|
  let groups = []
 | 
						|
  if empty(a:hls)
 | 
						|
    call add(groups, {'start': 0, 'end': a:linecount, 'highlights': []})
 | 
						|
    return groups
 | 
						|
  endif
 | 
						|
  let start = 0
 | 
						|
  let highlights = []
 | 
						|
  let lastLnum = -1
 | 
						|
  for item in a:hls
 | 
						|
    let lnum = item['lnum']
 | 
						|
    if lnum >= a:linecount
 | 
						|
      break
 | 
						|
    endif
 | 
						|
    if len(highlights) < g:coc_highlight_maximum_count || lnum == lastLnum
 | 
						|
      call add(highlights, item)
 | 
						|
      let lastLnum = lnum
 | 
						|
    else
 | 
						|
      call add(groups, {'start': start, 'end': lastLnum + 1, 'highlights': highlights})
 | 
						|
      let highlights = []
 | 
						|
      let start = lastLnum + 1
 | 
						|
      call add(highlights, item)
 | 
						|
      let lastLnum = lnum
 | 
						|
    endif
 | 
						|
  endfor
 | 
						|
  call add(groups, {'start': start, 'end': a:linecount, 'highlights': highlights})
 | 
						|
  return groups
 | 
						|
endfunction
 |