mirror of
https://github.com/junegunn/limelight.vim.git
synced 2025-11-16 23:13:40 -05:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acec9cbb35 |
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@@ -1 +0,0 @@
|
||||
github: junegunn
|
||||
30
.github/workflows/test.yml
vendored
30
.github/workflows/test.yml
vendored
@@ -1,30 +0,0 @@
|
||||
---
|
||||
name: Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Vim
|
||||
run: sudo apt-get install vim
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
git clone https://github.com/junegunn/vader.vim.git
|
||||
git clone https://github.com/junegunn/seoul256.vim.git
|
||||
vim -Nu <(cat << VIMRC
|
||||
set rtp+=vader.vim
|
||||
set rtp+=seoul256.vim
|
||||
set rtp+=.
|
||||
VIMRC) -c 'silent Vader! test/*' > /dev/null
|
||||
13
.travis.yml
Normal file
13
.travis.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
language: vim
|
||||
|
||||
before_script: |
|
||||
git clone https://github.com/junegunn/vader.vim.git
|
||||
git clone https://github.com/junegunn/seoul256.vim.git
|
||||
|
||||
script: |
|
||||
vim -Nu <(cat << VIMRC
|
||||
set rtp+=vader.vim
|
||||
set rtp+=seoul256.vim
|
||||
set rtp+=.
|
||||
VIMRC) -c 'silent Vader! test/*' > /dev/null
|
||||
|
||||
21
LICENSE
21
LICENSE
@@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2021 Junegunn Choi
|
||||
|
||||
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.
|
||||
51
README.md
51
README.md
@@ -1,7 +1,6 @@
|
||||
limelight.vim 
|
||||
limelight.vim 
|
||||
=============
|
||||
|
||||
|
||||
Hyperfocus-writing in Vim.
|
||||
|
||||

|
||||
@@ -9,36 +8,16 @@ Hyperfocus-writing in Vim.
|
||||
Best served with [Goyo.vim](https://github.com/junegunn/goyo.vim).
|
||||
Works on 256-color terminal or on GVim.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Use your favorite plugin manager.
|
||||
|
||||
- [vim-plug](https://github.com/junegunn/vim-plug)
|
||||
1. Add `Plug 'junegunn/limelight.vim'` to your Vim configuration file
|
||||
2. Run `:source %`
|
||||
3. Run `:PlugInstall`
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
- `Limelight [0.0 ~ 1.0]`
|
||||
- `Limelight [{}|()] [0.0 ~ 1.0]`
|
||||
- Turn Limelight on
|
||||
- `Limelight!`
|
||||
- Turn Limelight off
|
||||
- `Limelight!! [0.0 ~ 1.0]`
|
||||
- `Limelight!! [{}|()] [0.0 ~ 1.0]`
|
||||
- Toggle Limelight
|
||||
|
||||
### Limelight for a selected range
|
||||
|
||||
You can invoke `:Limelight` for a visual range. There are also `<Plug>`
|
||||
mappings for normal and visual mode for the purpose.
|
||||
|
||||
```vim
|
||||
nmap <Leader>l <Plug>(Limelight)
|
||||
xmap <Leader>l <Plug>(Limelight)
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
For some color schemes, Limelight may not be able to calculate the color for
|
||||
@@ -56,27 +35,21 @@ let g:limelight_conceal_guifg = '#777777'
|
||||
|
||||
" Default: 0.5
|
||||
let g:limelight_default_coefficient = 0.7
|
||||
|
||||
" Number of preceding/following paragraphs to include (default: 0)
|
||||
let g:limelight_paragraph_span = 1
|
||||
|
||||
" Beginning/end of paragraph
|
||||
" When there's no empty line between the paragraphs
|
||||
" and each paragraph starts with indentation
|
||||
let g:limelight_bop = '^\s'
|
||||
let g:limelight_eop = '\ze\n^\s'
|
||||
|
||||
" Highlighting priority (default: 10)
|
||||
" Set it to -1 not to overrule hlsearch
|
||||
let g:limelight_priority = -1
|
||||
```
|
||||
|
||||
Goyo.vim integration
|
||||
--------------------
|
||||
|
||||
```vim
|
||||
autocmd! User GoyoEnter Limelight
|
||||
autocmd! User GoyoLeave Limelight!
|
||||
function! GoyoBefore()
|
||||
Limelight
|
||||
endfunction
|
||||
|
||||
function! GoyoAfter()
|
||||
Limelight!
|
||||
endfunction
|
||||
|
||||
let g:goyo_callbacks = [function('GoyoBefore'), function('GoyoAfter')]
|
||||
```
|
||||
|
||||
Acknowledgement
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
" 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
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
limelight-vim.txt limelight-vim Last change: September 12 2024
|
||||
LIMELIGHT-VIM - TABLE OF CONTENTS *limelight-vim* *limelight-vim-toc*
|
||||
==============================================================================
|
||||
|
||||
limelight.vim |limelight-vim|
|
||||
Installation |limelight-vim-installation|
|
||||
Usage |limelight-vim-usage|
|
||||
Limelight for a selected range |limelight-vim-limelight-for-a-selected-range|
|
||||
Options |limelight-vim-options|
|
||||
Goyo.vim integration |limelight-vim-goyo-vim-integration|
|
||||
Acknowledgement |limelight-vim-acknowledgement|
|
||||
License |limelight-vim-license|
|
||||
|
||||
LIMELIGHT.VIM
|
||||
==============================================================================
|
||||
|
||||
Hyperfocus-writing in Vim.
|
||||
|
||||
Best served with {Goyo.vim}{1}. Works on 256-color terminal or on GVim.
|
||||
|
||||
{1} https://github.com/junegunn/goyo.vim
|
||||
|
||||
|
||||
INSTALLATION *limelight-vim-installation*
|
||||
==============================================================================
|
||||
|
||||
Use your favorite plugin manager.
|
||||
|
||||
*:PlugInstall*
|
||||
|
||||
- {vim-plug}{2}
|
||||
1. Add `Plug 'junegunn/limelight.vim'` to your Vim configuration file
|
||||
2. Run `:source %`
|
||||
3. Run `:PlugInstall`
|
||||
|
||||
{2} https://github.com/junegunn/vim-plug
|
||||
|
||||
|
||||
USAGE *limelight-vim-usage*
|
||||
==============================================================================
|
||||
|
||||
- `Limelight [0.0 ~ 1.0]`
|
||||
- Turn Limelight on
|
||||
- `Limelight!`
|
||||
- Turn Limelight off
|
||||
- `Limelight!! [0.0 ~ 1.0]`
|
||||
- Toggle Limelight
|
||||
|
||||
|
||||
< Limelight for a selected range >____________________________________________~
|
||||
*limelight-vim-limelight-for-a-selected-range*
|
||||
|
||||
*:Limelight*
|
||||
|
||||
You can invoke `:Limelight` for a visual range. There are also <Plug> mappings
|
||||
for normal and visual mode for the purpose.
|
||||
|
||||
*<Plug>(Limelight)*
|
||||
>
|
||||
nmap <Leader>l <Plug>(Limelight)
|
||||
xmap <Leader>l <Plug>(Limelight)
|
||||
<
|
||||
|
||||
< Options >___________________________________________________________________~
|
||||
*limelight-vim-options*
|
||||
|
||||
*g:limelight_conceal_ctermfg* *g:limelight_conceal_guifg*
|
||||
|
||||
For some color schemes, Limelight may not be able to calculate the color for
|
||||
dimming down the surrounding paragraphs. In that case, you need to define
|
||||
`g:limelight_conceal_ctermfg` or `g:limelight_conceal_guifg`.
|
||||
|
||||
*g:limelight_priority* *g:limelight_eop* *g:limelight_bop*
|
||||
*g:limelight_paragraph_span* *g:limelight_default_coefficient*
|
||||
>
|
||||
" Color name (:help cterm-colors) or ANSI code
|
||||
let g:limelight_conceal_ctermfg = 'gray'
|
||||
let g:limelight_conceal_ctermfg = 240
|
||||
|
||||
" Color name (:help gui-colors) or RGB color
|
||||
let g:limelight_conceal_guifg = 'DarkGray'
|
||||
let g:limelight_conceal_guifg = '#777777'
|
||||
|
||||
" Default: 0.5
|
||||
let g:limelight_default_coefficient = 0.7
|
||||
|
||||
" Number of preceding/following paragraphs to include (default: 0)
|
||||
let g:limelight_paragraph_span = 1
|
||||
|
||||
" Beginning/end of paragraph
|
||||
" When there's no empty line between the paragraphs
|
||||
" and each paragraph starts with indentation
|
||||
let g:limelight_bop = '^\s'
|
||||
let g:limelight_eop = '\ze\n^\s'
|
||||
|
||||
" Highlighting priority (default: 10)
|
||||
" Set it to -1 not to overrule hlsearch
|
||||
let g:limelight_priority = -1
|
||||
<
|
||||
|
||||
GOYO.VIM INTEGRATION *limelight-vim-goyo-vim-integration*
|
||||
==============================================================================
|
||||
>
|
||||
autocmd! User GoyoEnter Limelight
|
||||
autocmd! User GoyoLeave Limelight!
|
||||
<
|
||||
|
||||
ACKNOWLEDGEMENT *limelight-vim-acknowledgement*
|
||||
==============================================================================
|
||||
|
||||
Thanks to {@Cutuchiqueno}{3} for {suggesting the idea}{4}.
|
||||
|
||||
{3} https://github.com/Cutuchiqueno
|
||||
{4} https://github.com/junegunn/goyo.vim/issues/34
|
||||
|
||||
|
||||
LICENSE *limelight-vim-license*
|
||||
==============================================================================
|
||||
|
||||
MIT
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:sw=2:ts=2:ft=help:norl:nowrap:
|
||||
@@ -1,4 +1,4 @@
|
||||
" Copyright (c) 2015 Junegunn Choi
|
||||
" Copyright (c) 2014 Junegunn Choi
|
||||
"
|
||||
" MIT License
|
||||
"
|
||||
@@ -21,7 +21,300 @@
|
||||
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
command! -nargs=? -bar -bang -range Limelight call limelight#execute(<bang>0, <count> > 0, <line1>, <line2>, <f-args>)
|
||||
if exists('g:loaded_limelight')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_limelight = 1
|
||||
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:default_coeff = 0.5
|
||||
let s:unsupported =
|
||||
\ 'Unsupported color scheme. g:limelight_conceal_' .
|
||||
\ (has('gui_running') ? 'gui' : 'cterm') . 'fg required.'
|
||||
let s:invalid_coefficient = 'Invalid coefficient. Expected: 0.0 ~ 1.0'
|
||||
|
||||
function! s:limelight()
|
||||
if !exists('w:limelight_prev')
|
||||
let w:limelight_prev = [0, 0, 0, 0]
|
||||
endif
|
||||
if !exists('w:limelight_match_ids')
|
||||
let w:limelight_match_ids = []
|
||||
endif
|
||||
|
||||
let curr = [line('.'), line('$')]
|
||||
if curr ==# w:limelight_prev[0 : 1] && empty(s:params)
|
||||
return
|
||||
endif
|
||||
|
||||
let range = s:find_range()
|
||||
if range ==# w:limelight_prev[2 : 3]
|
||||
return
|
||||
endif
|
||||
|
||||
call s:clear_hl()
|
||||
if range[0] > 0
|
||||
call add(w:limelight_match_ids, matchadd('LimelightDim', '\%<'.range[0].'l'))
|
||||
endif
|
||||
if range[1] > 0
|
||||
call add(w:limelight_match_ids, matchadd('LimelightDim', '\%>'.range[1].'l'))
|
||||
endif
|
||||
let w:limelight_prev = extend(curr, range)
|
||||
endfunction
|
||||
|
||||
function! s:find_range()
|
||||
if empty(s:params)
|
||||
return s:find_paragraph()
|
||||
else
|
||||
return s:find_enclosing_block()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:find_paragraph()
|
||||
return [searchpos('^$', 'bnW')[0], searchpos('^$', 'nW')[0]]
|
||||
endfunction
|
||||
|
||||
function! s:find_begin(pair)
|
||||
let filtered =
|
||||
\ filter(
|
||||
\ map(items({ 'bcnW': 'nW', 'bnW': 'cnW' }),
|
||||
\ '[searchpair(a:pair[0], "", a:pair[1], v:val[0]), v:val[1], a:pair]'),
|
||||
\ 'v:val[0] > 0')
|
||||
if empty(filtered)
|
||||
return [0, '', []]
|
||||
else
|
||||
return s:max_by_1st(filtered)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:find_enclosing_block()
|
||||
let begins =
|
||||
\ filter(map(copy(s:params), 's:find_begin(v:val)'), 'v:val[0] > 0')
|
||||
if empty(begins)
|
||||
return [0, 0]
|
||||
else
|
||||
let [begin, flag, pair] = s:max_by_1st(begins)
|
||||
let end = searchpair(pair[0], '', pair[1], flag)
|
||||
if end == 0
|
||||
return [0, 0]
|
||||
endif
|
||||
return [begin, end]
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:max_by_1st(list)
|
||||
let max = a:list[0]
|
||||
for item in a:list
|
||||
if item[0] > max[0]
|
||||
let max = item
|
||||
endif
|
||||
endfor
|
||||
return max
|
||||
endfunction
|
||||
|
||||
function! s:clear_hl()
|
||||
while !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')
|
||||
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', 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:on(coeff, params)
|
||||
try
|
||||
call s:dim(a:coeff)
|
||||
catch
|
||||
return s:error(v:exception)
|
||||
endtry
|
||||
|
||||
augroup limelight
|
||||
autocmd!
|
||||
autocmd CursorMoved,CursorMovedI * call s:limelight()
|
||||
autocmd ColorScheme * try
|
||||
\| call s:dim(s:limelight_coeff)
|
||||
\| call s:limelight()
|
||||
\| 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
|
||||
|
||||
let s:params = a:params
|
||||
|
||||
doautocmd CursorMoved
|
||||
endfunction
|
||||
|
||||
function! s:off()
|
||||
if exists('w:limelight_match_ids')
|
||||
call s:clear_hl()
|
||||
endif
|
||||
augroup limelight
|
||||
autocmd!
|
||||
augroup END
|
||||
augroup! limelight
|
||||
unlet! w:limelight_prev w:limelight_match_ids
|
||||
endfunction
|
||||
|
||||
function! s:is_on()
|
||||
return exists('#limelight')
|
||||
endfunction
|
||||
|
||||
function! s:transform_params(params)
|
||||
let ret = []
|
||||
for param in a:params
|
||||
if len(param) == 2
|
||||
call add(ret, [param[0], param[1]])
|
||||
elseif param =~ '/'
|
||||
call add(ret, split(param, '/')[0:1])
|
||||
else
|
||||
throw 'Invalid pair: ' . param
|
||||
endif
|
||||
endfor
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:parse_args(args)
|
||||
if empty(a:args)
|
||||
return [0, -1, []]
|
||||
else
|
||||
let toggle = a:args[0][0] == '!'
|
||||
let args = copy(a:args)
|
||||
let args[0] = substitute(a:args[0], '^!', '', '')
|
||||
let args = filter(args, 'len(v:val) > 0')
|
||||
|
||||
let params = []
|
||||
let coeff = -1
|
||||
for arg in args
|
||||
if arg =~ '^[0-9.-]\+$'
|
||||
let coeff = str2float(arg)
|
||||
if coeff < 0 || coeff > 1
|
||||
throw s:invalid_coefficient
|
||||
endif
|
||||
else
|
||||
call add(params, arg)
|
||||
endif
|
||||
endfor
|
||||
return [toggle, coeff, s:transform_params(params)]
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:do(bang, ...)
|
||||
try
|
||||
let [toggle, coeff, params] = s:parse_args(a:000)
|
||||
catch
|
||||
return s:error(v:exception)
|
||||
endtry
|
||||
|
||||
if a:bang
|
||||
if toggle
|
||||
if s:is_on()
|
||||
call s:off()
|
||||
else
|
||||
call s:on(coeff, params)
|
||||
endif
|
||||
else
|
||||
call s:off()
|
||||
endif
|
||||
else
|
||||
call s:on(coeff, params)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:cleanup()
|
||||
if !s:is_on() && exists('w:limelight_match_ids')
|
||||
call s:clear_hl()
|
||||
end
|
||||
endfunction
|
||||
|
||||
command! -nargs=* -bar -bang Limelight call s:do('<bang>' == '!', <f-args>)
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
nnoremap <silent> <Plug>(Limelight) :set opfunc=limelight#operator<CR>g@
|
||||
xnoremap <silent> <Plug>(Limelight) :Limelight<CR>
|
||||
|
||||
@@ -15,16 +15,6 @@ Before:
|
||||
unlet! g:limelight_default_coefficient
|
||||
\ g:limelight_conceal_guifg g:limelight_conceal_ctermfg
|
||||
|
||||
Execute (Invalid argument type):
|
||||
Limelight 'hello'
|
||||
AssertOff
|
||||
|
||||
Limelight {}
|
||||
AssertOff
|
||||
|
||||
Limelight []
|
||||
AssertOff
|
||||
|
||||
Execute (Invalid argument range):
|
||||
Limelight 1.2
|
||||
AssertOff
|
||||
@@ -98,16 +88,8 @@ Execute (Unsupported. but g:limelight_conceal_???fg defined):
|
||||
Limelight!
|
||||
AssertOff
|
||||
else
|
||||
if exists('&termguicolors')
|
||||
set notermguicolors
|
||||
endif
|
||||
colo default
|
||||
let &t_Co = 256
|
||||
|
||||
" Cannot enable it without g:limelight_conceal_ctermfg
|
||||
Limelight
|
||||
AssertOff
|
||||
|
||||
let g:limelight_conceal_ctermfg = 240
|
||||
Limelight
|
||||
AssertOn
|
||||
@@ -122,11 +104,8 @@ Execute (Unsupported. but g:limelight_conceal_???fg defined):
|
||||
endif
|
||||
|
||||
" However, you're still not allowed to pass argument to Limelight command
|
||||
redir => msg
|
||||
Limelight 0.5
|
||||
redir END
|
||||
AssertOff
|
||||
Assert msg !~ 'g:limelight_conceal_', 'Invalid message: '.msg
|
||||
|
||||
Execute (TODO: Color interpolation):
|
||||
Assert 0, 'TODO'
|
||||
@@ -134,6 +113,5 @@ Execute (TODO: Color interpolation):
|
||||
Execute (Cleanup):
|
||||
delc AssertOn
|
||||
delc AssertOff
|
||||
unlet! msg
|
||||
Restore
|
||||
silent! execute 'colo '.g:colors_name
|
||||
execute 'colo '.g:colors_name
|
||||
|
||||
Reference in New Issue
Block a user