33 Commits

Author SHA1 Message Date
Junegunn Choi
0c8cc7f503 Add vim doc
Some checks failed
Test / build (push) Has been cancelled
Close #79
2024-09-12 18:17:43 +09:00
Junegunn Choi
785c1e17fe Remove unnecessary commands 2024-04-30 09:50:21 +09:00
Junegunn Choi
fe76263e1f Set up GitHub Actions (#77) 2024-04-30 09:47:30 +09:00
Aaron
87b1bb6996 Add section on plugin installation (#76) 2024-04-30 09:37:25 +09:00
Junegunn Choi
86aaec1700 Create FUNDING.yml 2022-08-03 11:21:09 +09:00
Junegunn Choi
eebac6c4fc Add LICENSE 2021-11-18 10:27:08 +09:00
Junegunn Choi
4412a84d7f Fix test on Travis CI 2020-10-13 20:31:14 +09:00
Junegunn Choi
4eb5d756b3 Fix test 2020-10-13 20:28:18 +09:00
Junegunn Choi
2adb5e2cac Fix normal mode operator: <Plug>(Limelight)
Caused by #60
2020-10-13 20:26:22 +09:00
Tobias Witt
815c612250 Don't move the cursor to beginning of line on deactivating limelight (#60)
Calling functions in vim using a range with `<line1>,<line2>call ...`
makes vim move the cursor to the beginning of the line. This can cause
distraction when Limelight is used in conjunction with the insert mode
(e.g. when deactivating on `InsertLeave`).

This commit makes the `Limelight` command pass the range as parameters
to the `execute` function which removes that effect while
`Limelight`ening a range still works.
2020-09-07 14:09:35 +09:00
郑浩楠
26e913a2e0 Fix horizontal cursor position when moving vertically (#59)
Fix #43
2019-07-09 22:14:30 +09:00
Filipe Silva
106fb5749d Backward compatibility for old Neovim releases (#32) 2016-06-24 02:51:29 +09:00
Junegunn Choi
e93c8013bb Fix #30 - Add support for termguicolors 2016-05-17 22:27:08 +09:00
Junegunn Choi
be8c754eb1 Support truecolor Neovim 2016-04-12 01:40:12 +09:00
Junegunn Choi
153e3f7b78 Merge pull request #23 from regnat/master
Added error message when running neovim with true colors
2015-08-19 12:09:33 +09:00
Théophane Hufschmitt
7551f9cd79 Added error message when running neovim with true colors 2015-08-19 10:22:57 +08:00
Junegunn Choi
4d63759523 Add g:limelight_priority
Can be used not to overrule hlsearch. Close #21.
2015-07-30 23:45:15 +09:00
Junegunn Choi
487515a1de Customizable paragraph boundary
Close #20
2015-07-30 23:35:53 +09:00
Junegunn Choi
9f57165a38 Workaround for Vim bug: using Float as a String in gvim (#19)
Related:
https://github.com/junegunn/vim-easy-align/issues/27
2015-07-30 01:48:08 +09:00
Junegunn Choi
63c4d78128 Merge pull request #18 from pgdouyon/master
Exclude whitespace-only lines from Limelight range
2015-07-27 09:56:57 +09:00
Pierre Douyon
df66855282 Exclude whitespace-only lines from Limelight range 2015-07-26 20:21:56 -04:00
Junegunn Choi
dbe351f683 Update README 2015-07-07 03:01:22 +09:00
Junegunn Choi
fc8dfac390 Add <Plug> mappings for highlighting fixed range 2015-06-07 21:37:48 +09:00
Junegunn Choi
f282610943 Limelight for a visual range (#15) 2015-06-07 21:26:18 +09:00
Junegunn Choi
64d1b28b93 Add g:limelight_paragraph_span (#12) 2015-02-18 02:54:32 +09:00
Junegunn Choi
faa85b1d1f Move the code to autoload directory 2015-01-31 01:38:00 +09:00
Junegunn Choi
34493b4232 Fix error message (#10) 2014-12-24 17:36:31 +09:00
Junegunn Choi
53887b5839 Merge pull request #8 from duckwork/master
Add guisp=bg to LimelightDim group
2014-11-16 04:29:59 +09:00
Case Duckworth
9bb5fa43d5 Add guisp=bg to LimelightDim group 2014-11-15 10:38:54 -07:00
Junegunn Choi
171112a9f7 Fix typo (#5) 2014-08-18 19:15:50 +09:00
Junegunn Choi
ab4cb16bae Promote the use of GoyoEnter/GoyoLeave events 2014-08-11 03:45:14 +09:00
Junegunn Choi
5c164c916a Fix error message (#4) 2014-07-08 12:09:11 +09:00
Junegunn Choi
f6ee73b43f Add failing test case for invalid message (#4) 2014-07-08 12:09:03 +09:00
9 changed files with 523 additions and 323 deletions

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
github: junegunn

30
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
---
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

View File

@@ -1,13 +0,0 @@
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 Normal file
View File

@@ -0,0 +1,21 @@
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.

View File

@@ -1,6 +1,7 @@
limelight.vim ![travis-ci](https://travis-ci.org/junegunn/limelight.vim.svg?branch=master)
limelight.vim ![GitHub Actions](https://img.shields.io/github/actions/workflow/status/junegunn/limelight.vim/test.yml?branch=master)
=============
Hyperfocus-writing in Vim.
![](https://raw.github.com/junegunn/i/master/limelight.gif)
@@ -8,16 +9,36 @@ 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
@@ -35,21 +56,27 @@ 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
function! GoyoBefore()
Limelight
endfunction
function! GoyoAfter()
Limelight!
endfunction
let g:goyo_callbacks = [function('GoyoBefore'), function('GoyoAfter')]
autocmd! User GoyoEnter Limelight
autocmd! User GoyoLeave Limelight!
```
Acknowledgement

282
autoload/limelight.vim Normal file
View File

@@ -0,0 +1,282 @@
" 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

123
doc/limelight.txt Normal file
View File

@@ -0,0 +1,123 @@
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:

View File

@@ -1,4 +1,4 @@
" Copyright (c) 2014 Junegunn Choi
" Copyright (c) 2015 Junegunn Choi
"
" MIT License
"
@@ -21,300 +21,7 @@
" 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 = 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
command! -nargs=? -bar -bang -range Limelight call limelight#execute(<bang>0, <count> > 0, <line1>, <line2>, <f-args>)
nnoremap <silent> <Plug>(Limelight) :set opfunc=limelight#operator<CR>g@
xnoremap <silent> <Plug>(Limelight) :Limelight<CR>

View File

@@ -15,6 +15,16 @@ 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
@@ -88,8 +98,16 @@ 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
@@ -104,8 +122,11 @@ 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'
@@ -113,5 +134,6 @@ Execute (TODO: Color interpolation):
Execute (Cleanup):
delc AssertOn
delc AssertOff
unlet! msg
Restore
execute 'colo '.g:colors_name
silent! execute 'colo '.g:colors_name