Skip to content

Instantly share code, notes, and snippets.

@kuuote
Created September 6, 2021 16:25
Show Gist options
  • Save kuuote/393e251b9036d843269710e2e74aebb3 to your computer and use it in GitHub Desktop.
Save kuuote/393e251b9036d843269710e2e74aebb3 to your computer and use it in GitHub Desktop.
Imitation of 3bmd's colorize
" 括弧を収集
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