if exists('g:loaded_autobrace') || &cp finish endif let g:loaded_autobrace = 1 let s:pair_chars = { \ '(': ')', \ '[': ']', \ '{': '}', \} let s:pair_cr_maps = { \ ')': "go_up()", \ ']': "go_up()", \ '}': "go_up()", \} let s:pair_bs_maps = { \ '"': "maybe_remove_adjacent_char('\"')", \ "'": "maybe_remove_adjacent_char(\"'\")", \ '(': "maybe_remove_empty_pair(')')", \ '[': "maybe_remove_empty_pair(']')", \ '{': "maybe_remove_empty_pair('}')", \ '': "maybe_collapse_pair()", \} function! s:move_cursor_left() return "\i" endfunction function! s:skip_closing_char(char) if s:nextchar() == a:char return "\la" else return a:char endif endfunction function! s:has_bs_mapping(char) return has_key(s:pair_bs_maps, a:char) endfunction function! s:run_bs_mapping(char) return eval(s:pair_bs_maps[a:char]) endfunction function! s:has_cr_mapping(char) return has_key(s:pair_cr_maps, a:char) endfunction function! s:run_cr_mapping(char) return eval(s:pair_cr_maps[a:char]) endfunction function! s:go_up() return "\\O" endfunction function! s:maybe_remove_adjacent_char(char) if s:nextchar() == a:char return "\\" else return "\" endif endfunction function! s:maybe_remove_empty_pair(char) let l:start = [line('.'), col('.')] let l:end = searchpos('[^ \t]', 'cnWz') if l:end == [0, 0] return "\" endif let l:next_nonblank = s:charat(l:end[0], l:end[1]) if l:next_nonblank != a:char return "\" endif let l:diff = [l:end[0] - l:start[0], l:end[1] - l:start[1]] if l:diff[0] == 0 return "\" . repeat("\", l:diff[1] + 1) elseif l:diff[0] == 1 return "\" . (l:diff[0] + 1) . "Ji" . "\\" else return "\" . (l:diff[0] + 1) . "Ji" . "\\\" endif endfunction function! s:maybe_collapse_pair() let l:prev_line_idx = line('.') - 1 if l:prev_line_idx < 1 return "\" endif let l:prev_line_char = s:charat(l:prev_line_idx, col([l:prev_line_idx, '$']) - 1) if l:prev_line_char !~ '[([{]' return "\" endif let l:end = searchpos('[^ \t]', 'cnWz') if l:end == [0, 0] return "\" endif let l:next_nonblank = s:charat(l:end[0], l:end[1]) if l:next_nonblank != s:pair_chars[l:prev_line_char] return "\" endif return "\\" . (l:end[0] - l:prev_line_idx + 1) . "Ji\" endfunction function! s:prevchar() return s:charat(line('.'), col('.') - 1) endfunction function! s:nextchar() return s:charat(line('.'), col('.')) endfunction function! s:charat(line, col) return getline(a:line)[a:col - 1] endfunction for [s:start, s:end] in [['(', ')'], ['{', '}'], ['[', ']']] exe "inoremap ".s:start. \ " ".s:start.s:end."=move_cursor_left()" exe "inoremap ".s:end. \ " =skip_closing_char('".s:end."')" endfor inoremap ' \ nextchar() == "'" \ ? "\=\skip_closing_char(\"'\")\" \ : col('.') == 1 \|\| match(prevchar(), '\W') != -1 \ ? "''\=\move_cursor_left()\" \ : "'" inoremap " \ nextchar() == '"' \ ? "\=\skip_closing_char('\"')\" \ : "\"\"\=\move_cursor_left()\" inoremap \ has_bs_mapping(prevchar()) \ ? "\=\run_bs_mapping(\prevchar())\" \ : "\" inoremap \ has_cr_mapping(nextchar()) \ ? "\=\run_cr_mapping(\nextchar())\" \ : "\"