From 543be33b13756eabc02cd91ef141c1d3fb216446 Mon Sep 17 00:00:00 2001 From: Israel Chauca Fuentes Date: Mon, 22 Jul 2013 20:52:05 -0400 Subject: [PATCH] Better handling of nested quotes. Closes #134. --- autoload/delimitMate.vim | 31 +++++++++++++++++++++++++++---- doc/delimitMate.txt | 7 +++++-- test/autoclose_quotes.txt | 8 ++++++++ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/autoload/delimitMate.vim b/autoload/delimitMate.vim index 88afe50..2554b03 100644 --- a/autoload/delimitMate.vim +++ b/autoload/delimitMate.vim @@ -111,6 +111,22 @@ function! delimitMate#IsEmptyPair(str) "{{{ return 0 endfunction "}}} +function! delimitMate#RightQ(char) "{{{ + let i = 0 + while delimitMate#GetCharFromCursor(i) ==# a:char + let i += 1 + endwhile + return i +endfunction "}}} + +function! delimitMate#LeftQ(char) "{{{ + let i = 0 + while delimitMate#GetCharFromCursor(i - 1) ==# a:char + let i -= 1 + endwhile + return i * -1 +endfunction "}}} + function! delimitMate#GetCharFromCursor(...) "{{{ let idx = col('.') - 1 if !a:0 || (a:0 && a:1 >= 0) @@ -334,10 +350,17 @@ function! delimitMate#QuoteDelim(char) "{{{ endif let char_at = delimitMate#GetCharFromCursor(0) let char_before = delimitMate#GetCharFromCursor(-1) - if char_at == a:char && - \ index(s:g('nesting_quotes'), a:char) < 0 - " Get out of the string. - return "\" + let nesting_on = index(s:g('nesting_quotes'), a:char) > -1 + let left_q = nesting_on ? delimitMate#LeftQ(a:char) : 0 + if nesting_on && left_q > 1 + " Nesting quotes. + let right_q = delimitMate#RightQ(a:char) + let quotes = right_q > left_q + 1 ? 0 : left_q - right_q + 2 + let lefts = quotes - 1 + return repeat(a:char, quotes) . repeat("\", lefts) + elseif char_at == a:char + " Inside an empty pair, jump out + return a:char . "\" elseif delimitMate#IsSmartQuote(a:char) " Seems like a smart quote, insert a single char. return a:char diff --git a/doc/delimitMate.txt b/doc/delimitMate.txt index 437c546..6eb6d9a 100644 --- a/doc/delimitMate.txt +++ b/doc/delimitMate.txt @@ -182,8 +182,10 @@ e.g.: > Values: A list of quotes. ~ Default: [] ~ -Quotes listed here will not be able to jump out of the empty pair, thus -allowing the autoclosed quotes to be nested. +When adding a third quote listed in this option is inserted, three quotes will +be inserted to the right of the cursor and the cursor will stay in the middle. +If more quotes are inserted the number of quotes on both sides of the cursor +will stay balanced. e.g.: > let delimitMate_nesting_quotes = ['"','`'] au FileType python let b:delimitMate_nesting_quotes = ['"'] @@ -714,6 +716,7 @@ This script was inspired by the auto-completion of delimiters on TextMate. - Add delimitMate_eol_marker. - Reduce the number of mappings. - Stop using setline(). + - Better handling of nested quotes. |---------|------------|-----------------------------------------------------| 2.6 2011-01-14 * - Add smart_matchpairs feature. - Add mapping to jump over contiguous delimiters. diff --git a/test/autoclose_quotes.txt b/test/autoclose_quotes.txt index 68f540f..e843ea8 100644 --- a/test/autoclose_quotes.txt +++ b/test/autoclose_quotes.txt @@ -30,6 +30,7 @@ let g:delimitMate_autoclose = 1 # Handle backspace gracefully. set backspace= "'\a\x" "'x'" +set backspace=2 set cpo=ces$ "'x" "'x'" # Make sure smart quote works beyond first column. @@ -40,3 +41,10 @@ set cpo=ces$ "}\'" "''}" "'\abc '" "'abc '" "''abc '" "''abc ''" +# Nesting quotes: +let g:delimitMate_nesting_quotes = split(g:delimitMate_quotes, '\s\+') +"'''x" "'''x'''" +"''''x" "''''x''''" +"''x" "''x" +"'x" "'x'" +unlet g:delimitMate_nesting_quotes