" Vim global plugin for short description
" Maintainer:	Jan Pobrislo <ccx@webprojekty.cz>
" Version:	0.2
" Description:	Long description.
" Last Change:	2015-08-27
" License:	Vim License (see :help license)
" Location:	plugin/prism.vim
" Website:	https://webprojekty.cz/ccx/bzr/vim-prism
"
" See prism.txt for help.  This can be accessed by doing:
"
" :helptags ~/.vim/doc
" :help prism

let g:prism_version = '0.2'

" Allow use of line continuation.
let s:save_cpo = &cpo
set cpo&vim

" load guard
if exists("g:loaded_prism")
  let &cpo = s:save_cpo
  finish
endif
let g:loaded_prism = 1

if !exists('g:prism_enabled')
  let g:prism_enabled = 1
endif

if !exists('g:prism_dark_colors')
  let g:prism_dark_colors = [ 31, 35, 113, 137, 130, 172, 191, 132, 140, 147 ]
endif

if !exists('g:prism_light_colors')
let g:prism_light_colors = [
    \ 'red',
    \ 'darkyellow',
    \ 'darkgreen',
    \ 'blue',
    \ 'darkmagenta',
    \ 'red',
    \ 'darkyellow',
    \ 'darkgreen',
    \ 'blue',
    \ 'darkmagenta' ]
endif

command! PrismEnable let g:prism_enabled = 1 <Bar> exe 'set ft='.&ft
command! PrismDisable let g:prism_enabled = 0 <Bar> exe 'set ft='.&ft

" set up colors and return their count
fun! s:PrismScheme()
  let l:n = 0
	if &bg == "dark"
		for colorid in g:prism_dark_colors
			exe 'hi default   hlLevel'.l:n.' ctermfg='.colorid
			let l:n = l:n + 1
		endfor
		return len(g:prism_dark_colors)
	else
		for colorid in g:prism_light_colors
			exe 'hi default   hlLevel'.l:n.' ctermfg='.colorid
			let l:n = l:n + 1
		endfor
		return len(g:prism_light_colors)
	endif
endfun

" produce contains= string for round/square/curly variations of given depth
fun! s:con(depth)
	return 'contains=prism'.a:depth.'r,prism'.a:depth.'s,prism'.a:depth.'c'
endfun

" create syntax rules for bracketed regions, on top of existing syntax rules
" call this from after/syntax/filetype.vim
fun! Prism(depth, contains, containedin)
	if !g:prism_enabled
		return
	endif

	if a:depth
		let l:depth = min([a:depth, s:PrismScheme() - 1])
	else
		let l:depth = s:PrismScheme() - 1
	endif

	if !empty(a:contains) && a:contains !~ '^,'
		let l:contains = ','.a:contains
	else
		let l:contains = a:contains
	endif

	if !empty(a:containedin) && a:containedin !~ '^containedin='
		let l:containedin = 'containedin='.a:containedin
	else
		let l:containedin = a:containedin
	endif

	exe 'syn region prism0r  transparent matchgroup=hlLevel0  start=/(/  end=/)/  '.s:con(1).l:contains.' '.l:containedin
	exe 'syn region prism0c  transparent matchgroup=hlLevel0  start=/{/  end=/}/  '.s:con(1).l:contains.' '.l:containedin
	exe 'syn region prism0s  transparent matchgroup=hlLevel0  start=/\[/ end=/\]/ '.s:con(1).l:contains.' '.l:containedin
	for n in range(1, l:depth - 1)
		exe 'syn region  prism'.n.'r  transparent matchgroup=hlLevel'.n.'  start=/(/  end=/)/  contained '.s:con(n+1).l:contains
		exe 'syn region  prism'.n.'c  transparent matchgroup=hlLevel'.n.'  start=/{/  end=/}/  contained '.s:con(n+1).l:contains
		exe 'syn region  prism'.n.'s  transparent matchgroup=hlLevel'.n.'  start=/\[/ end=/\]/ contained '.s:con(n+1).l:contains
	endfor
	exe 'syn region  prism'.l:depth.'r  transparent matchgroup=hlLevel'.l:depth.'  start=/(/  end=/)/  contained '.s:con(0).l:contains
	exe 'syn region  prism'.l:depth.'c  transparent matchgroup=hlLevel'.l:depth.'  start=/{/  end=/}/  contained '.s:con(0).l:contains
	exe 'syn region  prism'.l:depth.'s  transparent matchgroup=hlLevel'.l:depth.'  start=/\[/ end=/\]/ contained '.s:con(0).l:contains
endfun

" Returns string that closes all open brackets at the point of cursor
fun! PrismClose()
	let l:result = ''
	for id in synstack(line("."), col("."))
		let l:name = synIDattr(id, "name")
		if l:name[:4] == 'prism'
			let l:type = name[strlen(name)-1]
			if l:type == 'r'
				let l:result = ')' . l:result
			elseif l:type == 's'
				let l:result = ']' . l:result
			elseif l:type == 'c'
				let l:result = '}' . l:result
			endif
		endif
	endfor
	return l:result
endfun

" Returns string that closes innermost open bracket at the point of cursor
fun! PrismCloseInner()
	let l:result = ''
	for id in synstack(line("."), col("."))
		let l:name = synIDattr(id, "name")
		if l:name[:4] == 'prism'
			let l:type = name[strlen(name)-1]
			if l:type == 'r'
				let l:result = ')'
			elseif l:type == 's'
				let l:result = ']'
			elseif l:type == 'c'
				let l:result = '}'
			endif
		endif
	endfor
	return l:result
endfun

"reset &cpo back to users setting
let &cpo = s:save_cpo

" vim: sw=4 sts=4 ts=4 noet