From be08e358b9c80919812376848c5bcab0649489b5 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 8 Mar 2018 22:00:25 -0500 Subject: initial implementation --- plugin/autobrace.vim | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 plugin/autobrace.vim (limited to 'plugin/autobrace.vim') diff --git a/plugin/autobrace.vim b/plugin/autobrace.vim new file mode 100644 index 0000000..acb92b8 --- /dev/null +++ b/plugin/autobrace.vim @@ -0,0 +1,146 @@ +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())\" + \ : "\" -- cgit v1.2.3-54-g00ecf