Created
September 6, 2021 16:25
-
-
Save kuuote/393e251b9036d843269710e2e74aebb3 to your computer and use it in GitHub Desktop.
Imitation of 3bmd's colorize
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" 括弧を収集 | |
function! s:collect() abort | |
let view = winsaveview() | |
let pairs = [] | |
call cursor([1, 1]) | |
if search('(\|)', 'cW') | |
call add(pairs, [getline('.')[col('.')-1], [line('.'), col('.')]]) | |
endif | |
while search('(\|)', 'W') | |
call add(pairs, [getline('.')[col('.')-1], [line('.'), col('.')]]) | |
endwhile | |
call winrestview(view) | |
return pairs | |
endfunction | |
" 括弧のリストを木構造に変換 | |
function! s:treeize(pairs) abort | |
let stack = [] | |
let root = {'children': [], 'start': -1} | |
let current = root | |
for p in a:pairs | |
if p[0] ==# '(' | |
call add(stack, current) | |
let current = {'children': [], 'start': p[1]} | |
else | |
if empty(stack) | |
continue | |
endif | |
let current.end = p[1] | |
let p = remove(stack, -1) | |
call add(p.children, current) | |
let current = p | |
endif | |
endfor | |
return root | |
endfunction | |
" 与えられた範囲がカーソルを含むかをチェックする | |
" 10000行以上あるとバグるけど知らん | |
function! s:check(start, end) abort | |
let c = line('.') * 10000 + col('.') | |
let s = a:start[0] * 10000 + a:start[1] | |
let e = a:end[0] * 10000 + a:end[1] | |
return s <= c && c <= e | |
endfunction | |
" ツリーの中からカーソルの位置を探索 | |
" カーソルを含む括弧の位置を外側から数えたリストを返す | |
function! s:find(tree) abort | |
let stack = [] | |
let current = a:tree.children | |
let idx = 0 | |
while idx < len(current) | |
let n = current[idx] | |
if s:check(n.start, n.end) | |
call add(stack, [n.start, n.end]) | |
let current = n.children | |
let idx = 0 | |
continue | |
endif | |
let idx += 1 | |
endwhile | |
return stack | |
endfunction | |
" ハイライトを消す | |
function! s:deletehls() abort | |
let b:colorize_hls = get(b:, 'colorize_hls', []) | |
for hl in b:colorize_hls | |
silent! call matchdelete(hl) | |
endfor | |
let b:colorize_hls = [] | |
endfunction | |
" matchaddposで描画 | |
function! s:paint(positions) abort | |
call s:deletehls() | |
let hls = b:colorize_hls | |
for i in range(len(a:positions)) | |
let [s, e] = a:positions[i] | |
let color = 'Colorize' .. i % 6 | |
if s[0] == e[0] | |
call add(hls, matchaddpos(color, [[s[0], s[1], e[1] - s[1] + 1]])) | |
else | |
let ls = line('w0') | |
let le = line('w$') | |
call add(hls, matchaddpos(color, [[s[0], s[1], 10000]])) | |
for l in range(s[0] + 1, e[0] - 1) | |
if ls <= l && l <= le | |
call add(hls, matchaddpos(color, [[l]])) | |
endif | |
endfor | |
call add(hls, matchaddpos(color, [[e[0], 1, e[1]]])) | |
endif | |
endfor | |
endfunction | |
function! s:repaint() abort | |
let pos = [line('.'), col('.')] | |
if get(b:, 'colorize_position', []) == pos | |
return | |
endif | |
let b:colorize_position = pos | |
if get(b:, 'colorize_changedtick', -1) != b:changedtick | |
let b:colorize_tree = s:treeize(s:collect()) | |
let b:colorize_changedtick = b:changedtick | |
endif | |
call s:paint(s:find(b:colorize_tree)) | |
endfunction | |
function! s:enable() abort | |
augroup colorize | |
autocmd! * <buffer> | |
autocmd BufWinLeave <buffer> call s:deletehls() | |
autocmd BufWinEnter,CursorMoved <buffer> call s:repaint() | |
augroup END | |
call s:repaint() | |
endfunction | |
function! s:disable() abort | |
augroup colorize | |
autocmd! * <buffer> | |
augroup END | |
call s:deletehls() | |
endfunction | |
function! s:def_highlight() abort | |
hi! default Colorize0 ctermbg=159 guibg=#BAFFFF | |
hi! default Colorize1 ctermbg=224 guibg=#FFCACA | |
hi! default Colorize2 ctermbg=229 guibg=#FFFFBA | |
hi! default Colorize3 ctermbg=189 guibg=#CACAFF | |
hi! default Colorize4 ctermbg=194 guibg=#CAFFCA | |
hi! default Colorize5 ctermbg=219 guibg=#FFBAFF | |
endfunction | |
autocmd ColorScheme * call s:def_highlight() | |
call s:def_highlight() | |
command! ColorizeEnable call s:enable() | |
command! ColorizeDisable call s:disable() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment