| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- " Copyright (c) 2015 Junegunn Choi
- "
- " MIT License
- "
- " Permission is hereby granted, free of charge, to any person obtaining
- " a copy of this software and associated documentation files (the
- " "Software"), to deal in the Software without restriction, including
- " without limitation the rights to use, copy, modify, merge, publish,
- " distribute, sublicense, and/or sell copies of the Software, and to
- " permit persons to whom the Software is furnished to do so, subject to
- " the following conditions:
- "
- " The above copyright notice and this permission notice shall be
- " included in all copies or substantial portions of the Software.
- "
- " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- " EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- " NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- " LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- " OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- " WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- if exists('g:loaded_limelight')
- finish
- endif
- let g:loaded_limelight = 1
- let s:cpo_save = &cpo
- set cpo&vim
- let s:default_coeff = str2float('0.5')
- let s:invalid_coefficient = 'Invalid coefficient. Expected: 0.0 ~ 1.0'
- function! s:unsupported()
- let var = 'g:limelight_conceal_'.(has('gui_running') ? 'gui' : 'cterm').'fg'
- if exists(var)
- return 'Cannot calculate background color.'
- else
- return 'Unsupported color scheme. '.var.' required.'
- endif
- endfunction
- function! s:getpos()
- let bop = get(g:, 'limelight_bop', '^\s*$\n\zs')
- let eop = get(g:, 'limelight_eop', '^\s*$')
- let span = max([0, get(g:, 'limelight_paragraph_span', 0) - s:empty(getline('.'))])
- let pos = exists('*getcurpos')? getcurpos() : getpos('.')
- for i in range(0, span)
- let start = searchpos(bop, i == 0 ? 'cbW' : 'bW')[0]
- endfor
- call setpos('.', pos)
- for _ in range(0, span)
- let end = searchpos(eop, 'W')[0]
- endfor
- call setpos('.', pos)
- return [start, end]
- endfunction
- function! s:empty(line)
- return (a:line =~# '^\s*$')
- endfunction
- function! s:limelight()
- if !empty(get(w:, 'limelight_range', []))
- return
- endif
- if !exists('w:limelight_prev')
- let w:limelight_prev = [0, 0, 0, 0]
- endif
- let curr = [line('.'), line('$')]
- if curr ==# w:limelight_prev[0 : 1]
- return
- endif
- let paragraph = s:getpos()
- if paragraph ==# w:limelight_prev[2 : 3]
- return
- endif
- call s:clear_hl()
- call call('s:hl', paragraph)
- let w:limelight_prev = extend(curr, paragraph)
- endfunction
- function! s:hl(startline, endline)
- let w:limelight_match_ids = get(w:, 'limelight_match_ids', [])
- let priority = get(g:, 'limelight_priority', 10)
- call add(w:limelight_match_ids, matchadd('LimelightDim', '\%<'.a:startline.'l', priority))
- if a:endline > 0
- call add(w:limelight_match_ids, matchadd('LimelightDim', '\%>'.a:endline.'l', priority))
- endif
- endfunction
- function! s:clear_hl()
- while exists('w:limelight_match_ids') && !empty(w:limelight_match_ids)
- silent! call matchdelete(remove(w:limelight_match_ids, -1))
- endwhile
- endfunction
- function! s:hex2rgb(str)
- let str = substitute(a:str, '^#', '', '')
- return [eval('0x'.str[0:1]), eval('0x'.str[2:3]), eval('0x'.str[4:5])]
- endfunction
- let s:gray_converter = {
- \ 0: 231,
- \ 7: 254,
- \ 15: 256,
- \ 16: 231,
- \ 231: 256
- \ }
- function! s:gray_contiguous(col)
- let val = get(s:gray_converter, a:col, a:col)
- if val < 231 || val > 256
- throw s:unsupported()
- endif
- return val
- endfunction
- function! s:gray_ansi(col)
- return a:col == 231 ? 0 : (a:col == 256 ? 231 : a:col)
- endfunction
- function! s:coeff(coeff)
- let coeff = a:coeff < 0 ?
- \ get(g:, 'limelight_default_coefficient', s:default_coeff) : a:coeff
- if coeff < 0 || coeff > 1
- throw 'Invalid g:limelight_default_coefficient. Expected: 0.0 ~ 1.0'
- endif
- return coeff
- endfunction
- function! s:dim(coeff)
- let synid = synIDtrans(hlID('Normal'))
- let fg = synIDattr(synid, 'fg#')
- let bg = synIDattr(synid, 'bg#')
- if has('gui_running') || has('termguicolors') && &termguicolors || has('nvim') && $NVIM_TUI_ENABLE_TRUE_COLOR
- if a:coeff < 0 && exists('g:limelight_conceal_guifg')
- let dim = g:limelight_conceal_guifg
- elseif empty(fg) || empty(bg)
- throw s:unsupported()
- else
- let coeff = s:coeff(a:coeff)
- let fg_rgb = s:hex2rgb(fg)
- let bg_rgb = s:hex2rgb(bg)
- let dim_rgb = [
- \ bg_rgb[0] * coeff + fg_rgb[0] * (1 - coeff),
- \ bg_rgb[1] * coeff + fg_rgb[1] * (1 - coeff),
- \ bg_rgb[2] * coeff + fg_rgb[2] * (1 - coeff)]
- let dim = '#'.join(map(dim_rgb, 'printf("%x", float2nr(v:val))'), '')
- endif
- execute printf('hi LimelightDim guifg=%s guisp=bg', dim)
- elseif &t_Co == 256
- if a:coeff < 0 && exists('g:limelight_conceal_ctermfg')
- let dim = g:limelight_conceal_ctermfg
- elseif fg <= -1 || bg <= -1
- throw s:unsupported()
- else
- let coeff = s:coeff(a:coeff)
- let fg = s:gray_contiguous(fg)
- let bg = s:gray_contiguous(bg)
- let dim = s:gray_ansi(float2nr(bg * coeff + fg * (1 - coeff)))
- endif
- if type(dim) == 1
- execute printf('hi LimelightDim ctermfg=%s', dim)
- else
- execute printf('hi LimelightDim ctermfg=%d', dim)
- endif
- else
- throw 'Unsupported terminal. Sorry.'
- endif
- endfunction
- function! s:error(msg)
- echohl ErrorMsg
- echo a:msg
- echohl None
- endfunction
- function! s:parse_coeff(coeff)
- let t = type(a:coeff)
- if t == 1
- if a:coeff =~ '^ *[0-9.]\+ *$'
- let c = str2float(a:coeff)
- else
- throw s:invalid_coefficient
- endif
- elseif index([0, 5], t) >= 0
- let c = t
- else
- throw s:invalid_coefficient
- endif
- return c
- endfunction
- function! s:on(range, ...)
- try
- let s:limelight_coeff = a:0 > 0 ? s:parse_coeff(a:1) : -1
- call s:dim(s:limelight_coeff)
- catch
- return s:error(v:exception)
- endtry
- let w:limelight_range = a:range
- if !empty(a:range)
- call s:clear_hl()
- call call('s:hl', a:range)
- endif
- augroup limelight
- let was_on = exists('#limelight#CursorMoved')
- autocmd!
- if empty(a:range) || was_on
- autocmd CursorMoved,CursorMovedI * call s:limelight()
- endif
- autocmd ColorScheme * try
- \| call s:dim(s:limelight_coeff)
- \| catch
- \| call s:off()
- \| throw v:exception
- \| endtry
- augroup END
- " FIXME: We cannot safely remove this group once Limelight started
- augroup limelight_cleanup
- autocmd!
- autocmd WinEnter * call s:cleanup()
- augroup END
- doautocmd CursorMoved
- endfunction
- function! s:off()
- call s:clear_hl()
- augroup limelight
- autocmd!
- augroup END
- augroup! limelight
- unlet! w:limelight_prev w:limelight_match_ids w:limelight_range
- endfunction
- function! s:is_on()
- return exists('#limelight')
- endfunction
- function! s:cleanup()
- if !s:is_on()
- call s:clear_hl()
- end
- endfunction
- function! limelight#execute(bang, visual, line1, line2, ...)
- let range = a:visual ? [a:line1, a:line2] : []
- if a:bang
- if a:0 > 0 && a:1 =~ '^!' && !s:is_on()
- if len(a:1) > 1
- call s:on(range, a:1[1:-1])
- else
- call s:on(range)
- endif
- else
- call s:off()
- endif
- elseif a:0 > 0
- call s:on(range, a:1)
- else
- call s:on(range)
- endif
- endfunction
- function! limelight#operator(...)
- call limelight#execute(0, 1, line("'["), line("']"))
- endfunction
- let &cpo = s:cpo_save
- unlet s:cpo_save
|