diff --git a/Makefile b/Makefile index 90fc063..00a4403 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,21 @@ PLUGIN=delimitMate install: - cp -f doc/* ~/.vim/doc/${PLUGIN}.txt - cp -f plugin/* ~/.vim/plugin/${PLUGIN}.vim + cp -f doc/${PLUGIN}.txt ~/.vim/doc/${PLUGIN}.txt + cp -f plugin/${PLUGIN}.vim ~/.vim/plugin/${PLUGIN}.vim + cp -f autoload/${PLUGIN}.vim ~/.vim/autoload/${PLUGIN}.vim doc_update: install /usr/bin/vim -u NONE -c ':helptags ~/.vim/doc' -c ':q' zip: - zip -r ${PLUGIN}.zip doc plugin + zip -r ${PLUGIN}.zip doc plugin autoload zip ${PLUGIN}.zip -d \*.sw\? vimball: install echo doc/${PLUGIN}.txt > vimball.txt echo plugin/${PLUGIN}.vim >> vimball.txt + echo autoload/${PLUGIN}.vim >> vimball.txt /usr/bin/vim -c 'e vimball.txt' -c '%MkVimball! ${PLUGIN}' -c 'q' gzip: vimball diff --git a/autoload/delimitMate.vim b/autoload/delimitMate.vim new file mode 100644 index 0000000..eeb8a15 --- /dev/null +++ b/autoload/delimitMate.vim @@ -0,0 +1,428 @@ +" ============================================================================ +" File: autoload/delimitMate.vim +" Version: 2.1 +" Description: This plugin provides auto-completion for quotes, parens, etc. +" Maintainer: Israel Chauca F. +" Manual: Read ":help delimitMate". + +" Utilities {{{ +function! delimitMate#ShouldJump() "{{{ + let col = col('.') + let lcol = col('$') + let char = getline('.')[col - 1] + let nchar = getline('.')[col] + let uchar = getline(line('.') + 1)[0] + + for cdel in b:delimitMate_right_delims + b:delimitMate_quotes_list + if char == cdel + " Closing delimiter on the right. + return 1 + endif + endfor + + if b:delimitMate_expand_space && char == " " + for cdel in b:delimitMate_right_delims + b:delimitMate_quotes_list + if nchar == cdel + " Closing delimiter with space expansion. + return 1 + endif + endfor + endif + + if b:delimitMate_expand_cr && char == "" + for cdel in b:delimitMate_right_delims + b:delimitMate_quotes_list + if uchar == cdel + " Closing delimiter with CR expansion. + return 1 + endif + endfor + endif + + return 0 +endfunction "}}} + +function! delimitMate#IsBlockVisual() " {{{ + if visualmode() == "" + return 1 + endif + " Store unnamed register values for later use in delimitMate#RestoreRegister(). + let b:save_reg = getreg('"') + let b:save_reg_mode = getregtype('"') + + if len(getline('.')) == 0 + " This for proper wrap of empty lines. + let @" = "\n" + endif + return 0 +endfunction " }}} + +function! delimitMate#IsEmptyPair(str) "{{{ + for pair in b:delimitMate_matchpairs_list + if a:str == join( split( pair, ':' ),'' ) + return 1 + endif + endfor + for quote in b:delimitMate_quotes_list + if a:str == quote . quote + return 1 + endif + endfor + return 0 +endfunction "}}} + +function! delimitMate#IsCRExpansion() " {{{ + let nchar = getline(line('.')-1)[-1:] + let schar = getline(line('.')+1)[-1:] + let isEmpty = getline('.') == "" + if index(b:delimitMate_left_delims, nchar) > -1 && + \ index(b:delimitMate_left_delims, nchar) == index(b:delimitMate_right_delims, schar) && + \ isEmpty + return 1 + elseif index(b:delimitMate_quotes_list, nchar) > -1 && + \ index(b:delimitMate_quotes_list, nchar) == index(b:delimitMate_quotes_list, schar) && + \ isEmpty + return 1 + else + return 0 + endif +endfunction " }}} delimitMate#IsCRExpansion() + +function! delimitMate#IsSpaceExpansion() " {{{ + let line = getline('.') + let col = col('.')-2 + if col > 0 + let pchar = line[col - 1] + let nchar = line[col + 2] + let isSpaces = (line[col] == line[col+1] && line[col] == " ") + + if index(b:delimitMate_left_delims, pchar) > -1 && + \ index(b:delimitMate_left_delims, pchar) == index(b:delimitMate_right_delims, nchar) && + \ isSpaces + return 1 + elseif index(b:delimitMate_quotes_list, pchar) > -1 && + \ index(b:delimitMate_quotes_list, pchar) == index(b:delimitMate_quotes_list, nchar) && + \ isSpaces + return 1 + endif + endif + return 0 +endfunction " }}} IsSpaceExpansion() + +function! delimitMate#WithinEmptyPair() "{{{ + let cur = strpart( getline('.'), col('.')-2, 2 ) + return delimitMate#IsEmptyPair( cur ) +endfunction "}}} + +function! delimitMate#WriteBefore(str) "{{{ + let len = len(a:str) + let line = getline('.') + let col = col('.')-2 + if col < 0 + call setline('.',line[(col+len+1):]) + else + call setline('.',line[:(col)].line[(col+len+1):]) + endif + return a:str +endfunction " }}} + +function! delimitMate#WriteAfter(str) "{{{ + let len = len(a:str) + let line = getline('.') + let col = col('.')-2 + if (col) < 0 + call setline('.',a:str.line) + else + call setline('.',line[:(col)].a:str.line[(col+len):]) + endif + return '' +endfunction " }}} + +function! delimitMate#RestoreRegister() " {{{ + " Restore unnamed register values store in delimitMate#IsBlockVisual(). + call setreg('"', b:save_reg, b:save_reg_mode) + echo "" +endfunction " }}} + +function! delimitMate#GetCurrentSyntaxRegion() "{{{ + return synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name') +endfunction " }}} + +function! delimitMate#GetCurrentSyntaxRegionIf(char) "{{{ + let col = col('.') + let origin_line = getline('.') + let changed_line = strpart(origin_line, 0, col - 1) . a:char . strpart(origin_line, col - 1) + call setline('.', changed_line) + let region = synIDattr(synIDtrans(synID(line('.'), col, 1)), 'name') + call setline('.', origin_line) + return region +endfunction "}}} + +function! delimitMate#IsForbidden(char) "{{{ + let result = index(b:delimitMate_excluded_regions_list, delimitMate#GetCurrentSyntaxRegion()) >= 0 + if result + return result + endif + let region = delimitMate#GetCurrentSyntaxRegionIf(a:char) + let result = index(b:delimitMate_excluded_regions_list, region) >= 0 + "return result || region == 'Comment' + return result +endfunction "}}} +" }}} + +" Doers {{{ +function! delimitMate#JumpIn(char) " {{{ + let line = getline('.') + let col = col('.')-2 + if (col) < 0 + call setline('.',a:char.line) + else + "echom string(col).':'.line[:(col)].'|'.line[(col+1):] + call setline('.',line[:(col)].a:char.line[(col+1):]) + endif + return '' +endfunction " }}} + +function! delimitMate#JumpOut(char) "{{{ + let line = getline('.') + let col = col('.')-2 + if line[col+1] == a:char + call setline('.',line[:(col)].line[(col+2):]) + endif + return a:char +endfunction " }}} + +function! delimitMate#JumpAny() " {{{ + " Let's get the character on the right. + let char = getline('.')[col('.')-1] + if char == " " + " Space expansion. + let char = char . getline('.')[col('.')] . "\" + elseif char == "" + " CR expansion. + let char = "\" . getline(line('.') + 1)[0] . "\" + endif + return char . "\" +endfunction " delimitMate#JumpAny() }}} + +function! delimitMate#SkipDelim(char) "{{{ + let cur = strpart( getline('.'), col('.')-2, 3 ) + if cur[0] == "\\" + " Escaped character + return a:char + elseif cur[1] == a:char + " Exit pair + return delimitMate#WriteBefore(a:char) + "elseif cur[1] == ' ' && cur[2] == a:char + "" I'm leaving this in case someone likes it. Jump an space and delimiter. + "return "\\" + elseif delimitMate#IsEmptyPair( cur[0] . a:char ) + " Add closing delimiter and jump back to the middle. + return delimitMate#WriteAfter(a:char) + else + " Nothing special here, return the same character. + return a:char + endif +endfunction "}}} + +function! delimitMate#QuoteDelim(char) "{{{ + let line = getline('.') + let col = col('.') - 2 + if line[col] == "\\" + " Seems like a escaped character, insert one quotation mark. + return a:char + elseif line[col + 1] == a:char + " Get out of the string. + return delimitMate#WriteBefore(a:char) + elseif (line[col] =~ '[a-zA-Z0-9]' && a:char == "'") || + \(line[col] =~ '[a-zA-Z0-9]' && b:delimitMate_smart_quotes) + " Seems like an apostrophe or a closing, insert a single quote. + return a:char + elseif (line[col] == a:char && line[col + 1 ] != a:char) && b:delimitMate_smart_quotes + " Seems like we have an unbalanced quote, insert one quotation mark and jump to the middle. + return delimitMate#WriteAfter(a:char) + else + " Insert a pair and jump to the middle. + call delimitMate#WriteAfter(a:char) + return a:char + endif +endfunction "}}} + +function! delimitMate#MapMsg(msg) "{{{ + redraw + echomsg a:msg + return "" +endfunction "}}} + +function! delimitMate#ExpandReturn() "{{{ + if delimitMate#WithinEmptyPair() && + \ b:delimitMate_expand_cr + " Expand: + return "\a\x\\k$\"_xa" + else + return "\" + endif +endfunction "}}} + +function! delimitMate#ExpandSpace() "{{{ + if delimitMate#WithinEmptyPair() && + \ b:delimitMate_expand_space + " Expand: + return delimitMate#WriteAfter(' ') . "\" + else + return "\" + endif +endfunction "}}} + +function! delimitMate#BS() " {{{ + if delimitMate#WithinEmptyPair() + return "\\\" + elseif b:delimitMate_expand_cr && + \ (delimitMate#IsCRExpansion() != 0 || delimitMate#IsSpaceExpansion()) + return "\\" + else + return "\" + endif +endfunction " }}} delimitMate#BS() + +" }}} + +" Mappers: {{{ +function! delimitMate#NoAutoClose() "{{{ + " inoremap ) =delimitMate#SkipDelim('\)') + for delim in b:delimitMate_right_delims + b:delimitMate_quotes_list + exec 'inoremap ' . delim . ' =delimitMate#SkipDelim("' . escape(delim,'"') . '")' + endfor +endfunction "}}} + +function! delimitMate#AutoClose() "{{{ + " Add matching pair and jump to the midle: + " inoremap ( () + let i = 0 + while i < len(b:delimitMate_matchpairs_list) + let ld = b:delimitMate_left_delims[i] + let rd = b:delimitMate_right_delims[i] + exec 'inoremap ' . ld . ' ' . ld . '=delimitMate#JumpIn("' . rd . '")' + "exec 'inoremap ' . ld . ' ' '=delimitMate#JumpIn("' . ld . '")' + let i += 1 + endwhile + + " Exit from inside the matching pair: + for delim in b:delimitMate_right_delims + exec 'inoremap ' . delim . ' =delimitMate#JumpOut("\' . delim . '")' + endfor + + " Add matching quote and jump to the midle, or exit if inside a pair of matching quotes: + " inoremap " =delimitMate#QuoteDelim("\"") + for delim in b:delimitMate_quotes_list + exec 'inoremap ' . delim . ' =delimitMate#QuoteDelim("\' . delim . '")' + endfor + + " Try to fix the use of apostrophes (de-activated by default): + " inoremap n't n't + for map in b:delimitMate_apostrophes_list + exec "inoremap " . map . " " . map + endfor +endfunction "}}} + +function! delimitMate#VisualMaps() " {{{ + let VMapMsg = "delimitMate: delimitMate is disabled on blockwise visual mode." + let vleader = b:delimitMate_visual_leader + " Wrap the selection with matching pairs, but do nothing if blockwise visual mode is active: + let i = 0 + while i < len(b:delimitMate_matchpairs_list) + " Map left delimiter: + let ld = b:delimitMate_left_delims[i] + let rd = b:delimitMate_right_delims[i] + exec 'vnoremap ' . vleader . ld . ' delimitMate#IsBlockVisual() ? delimitMate#MapMsg("' . VMapMsg . '") : "s' . ld . '\\"' . rd . '\:call delimitMate#RestoreRegister()"' + + " Map right delimiter: + exec 'vnoremap ' . vleader . rd . ' delimitMate#IsBlockVisual() ? delimitMate#MapMsg("' . VMapMsg . '") : "s' . ld . '\\"' . rd . '\:call delimitMate#RestoreRegister()"' + let i += 1 + endwhile + + " Wrap the selection with matching quotes, but do nothing if blockwise visual mode is active: + for quote in b:delimitMate_quotes_list + " vnoremap \' delimitMate#IsBlockVisual() ? delimitMate#MapMsg("Message") : "s'\\"'\:call delimitMate#RestoreRegister()" + exec 'vnoremap ' . vleader . quote . ' delimitMate#IsBlockVisual() ? delimitMate#MapMsg("' . VMapMsg . '") : "s' . escape(quote,'"') .'\\"' . escape(quote,'"') . '\:call delimitMate#RestoreRegister()"' + endfor +endfunction "}}} + +function! delimitMate#ExtraMappings() "{{{ + " If pair is empty, delete both delimiters: + inoremap =delimitMate#BS() + + " If pair is empty, delete closing delimiter: + inoremap delimitMate#WithinEmptyPair() ? "\" : "\" + + " Expand return if inside an empty pair: + if b:delimitMate_expand_cr != 0 + inoremap delimitMate#WithinEmptyPair() ? "\=delimitMate#ExpandReturn()\" : "\" + endif + + " Expand space if inside an empty pair: + if b:delimitMate_expand_space != 0 + inoremap delimitMate#WithinEmptyPair() ? "\=delimitMate#ExpandSpace()\" : "\" + endif + + " Jump out ot any empty pair: + if b:delimitMate_tab2exit + inoremap delimitMate#ShouldJump() ? delimitMate#JumpAny() : "\" + endif +endfunction "}}} +"}}} + +" Tools: {{{ +function! delimitMate#TestMappings() "{{{ + if b:delimitMate_autoclose + for i in range(len(b:delimitMate_left_delims)) + exec "normal GGAOpen & close: " . b:delimitMate_left_delims[i]. "|" + exec "normal A\Delete: " . b:delimitMate_left_delims[i] . "\|" + exec "normal A\Exit: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "|" + exec "normal A\Space: " . b:delimitMate_left_delims[i] . " |" + exec "normal A\Delete space: " . b:delimitMate_left_delims[i] . " \|" + exec "normal GGA\Visual-L: v\v" . b:delimitMate_visual_leader . b:delimitMate_left_delims[i] + exec "normal A\Visual-R: v\v" . b:delimitMate_visual_leader . b:delimitMate_right_delims[i] + exec "normal A\Car return: " . b:delimitMate_left_delims[i] . "\|" + exec "normal GGA\Delete car return: " . b:delimitMate_left_delims[i] . "\\|\GGA\\" + endfor + for i in range(len(b:delimitMate_quotes_list)) + exec "normal GGAOpen & close: " . b:delimitMate_quotes_list[i] . "|" + exec "normal A\Delete: " + exec "normal A". b:delimitMate_quotes_list[i] + exec "normal a\|" + exec "normal A\Exit: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|" + exec "normal A\Space: " . b:delimitMate_quotes_list[i] . " |" + exec "normal A\Delete space: " . b:delimitMate_quotes_list[i] . " \|" + exec "normal GGA\Visual: v\v" . b:delimitMate_visual_leader . b:delimitMate_quotes_list[i] + exec "normal A\Car return: " . b:delimitMate_quotes_list[i] . "\|" + exec "normal GGA\Delete car return: " . b:delimitMate_quotes_list[i] . "\\|\GGA\\" + endfor + else + for i in range(len(b:delimitMate_left_delims)) + exec "normal GGAOpen & close: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "|" + exec "normal A\Delete: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "\|" + exec "normal A\Exit: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . b:delimitMate_right_delims[i] . "|" + exec "normal A\Space: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . " |" + exec "normal A\Delete space: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . " \|" + exec "normal GGA\Visual-L: v\v" . b:delimitMate_visual_leader . b:delimitMate_left_delims[i] + exec "normal A\Visual-R: v\v" . b:delimitMate_visual_leader . b:delimitMate_right_delims[i] + exec "normal A\Car return: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "\|" + exec "normal GGA\Delete car return: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "\\|\GGA\\" + endfor + for i in range(len(b:delimitMate_quotes_list)) + exec "normal GGAOpen & close: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|" + exec "normal A\Delete: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "\|" + exec "normal A\Exit: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|" + exec "normal A\Space: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . " |" + exec "normal A\Delete space: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . " \|" + exec "normal GGA\Visual: v\v" . b:delimitMate_visual_leader . b:delimitMate_quotes_list[i] + exec "normal A\Car return: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "\|" + exec "normal GGA\Delete car return: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "\\|\GGA\\" + endfor + endif + exec "normal \i" +endfunction "}}} + +"}}} + +" vim:foldmethod=marker:foldcolumn=4 diff --git a/plugin/delimitMate.vim b/plugin/delimitMate.vim index d249e3d..a611570 100644 --- a/plugin/delimitMate.vim +++ b/plugin/delimitMate.vim @@ -55,54 +55,18 @@ function! s:Init() "{{{ " delimitMate_matchpairs {{{ if !exists("b:delimitMate_matchpairs") && !exists("g:delimitMate_matchpairs") - if s:ValidMatchpairs(&matchpairs) == 1 - let s:matchpairs_temp = &matchpairs - else - echoerr "delimitMate: There seems to be a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if this is a bug." - finish - endif + let s:matchpairs_temp = &matchpairs elseif exists("b:delimitMate_matchpairs") - if s:ValidMatchpairs(b:delimitMate_matchpairs) || b:delimitMate_matchpairs == "" - let s:matchpairs_temp = b:delimitMate_matchpairs - else - echoerr "delimitMate: Invalid format in 'b:delimitMate_matchpairs', falling back to matchpairs. Fix the error and use the command :DelimitMateReload to try again." - if s:ValidMatchpairs(&matchpairs) == 1 - let s:matchpairs_temp = &matchpairs - else - echoerr "delimitMate: There seems to be a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if this is a bug." - let s:matchpairs_temp = "" - endif - endif + let s:matchpairs_temp = b:delimitMate_matchpairs else - if s:ValidMatchpairs(g:delimitMate_matchpairs) || g:delimitMate_matchpairs == "" - let s:matchpairs_temp = g:delimitMate_matchpairs - else - echoerr "delimitMate: Invalid format in 'g:delimitMate_matchpairs', falling back to matchpairs. Fix the error and use the command :DelimitMateReload to try again." - if s:ValidMatchpairs(&matchpairs) == 1 - let s:matchpairs_temp = &matchpairs - else - echoerr "delimitMate: There seems to be a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if this is a bug." - let s:matchpairs_temp = "" - endif - endif - + let s:matchpairs_temp = g:delimitMate_matchpairs endif " }}} " delimitMate_quotes {{{ if exists("b:delimitMate_quotes") - if b:delimitMate_quotes =~ '^\(\S\)\(\s\S\)*$' || b:delimitMate_quotes == "" - let s:quotes = split(b:delimitMate_quotes) - else - let s:quotes = split("\" ' `") - echoerr "delimitMate: There is a problem with the format of 'b:delimitMate_quotes', it should be a string of single characters separated by spaces. Falling back to default values." - endif + let s:quotes = split(b:delimitMate_quotes) elseif exists("g:delimitMate_quotes") - if g:delimitMate_quotes =~ '^\(\S\)\(\s\S\)*$' || g:delimitMate_quotes == "" - let s:quotes = split(g:delimitMate_quotes) - else - let s:quotes = split("\" ' `") - echoerr "delimitMate: There is a problem with the format of 'g:delimitMate_quotes', it should be a string of single characters separated by spaces. Falling back to default values." - endif + let s:quotes = split(g:delimitMate_quotes) else let s:quotes = split("\" ' `") endif @@ -178,461 +142,20 @@ function! s:Init() "{{{ let b:delimitMate_matchpairs_list = split(s:matchpairs_temp, ',') let b:delimitMate_left_delims = split(s:matchpairs_temp, ':.,\=') let b:delimitMate_right_delims = split(s:matchpairs_temp, ',\=.:') - let s:VMapMsg = "delimitMate: delimitMate is disabled on blockwise visual mode." call s:UnMap() if b:delimitMate_autoclose - call s:AutoClose() + call delimitMate#AutoClose() else - call s:NoAutoClose() + call delimitMate#NoAutoClose() endif - call s:VisualMaps() - call s:ExtraMappings() + call delimitMate#VisualMaps() + call delimitMate#ExtraMappings() endfunction "}}} Init() "}}} -" Utilities: {{{ -function! s:ValidMatchpairs(str) "{{{ - if a:str !~ '^.:.\(,.:.\)*$' - return 0 - endif - for pair in split(a:str,',') - if strpart(pair, 0, 1) == strpart(pair, 2, 1) || strlen(pair) != 3 - return 0 - endif - endfor - return 1 -endfunction "}}} - -function! DelimitMate_ShouldJump() "{{{ - let col = col('.') - let lcol = col('$') - let char = getline('.')[col - 1] - let nchar = getline('.')[col] - let uchar = getline(line('.') + 1)[0] - - for cdel in b:delimitMate_right_delims + b:delimitMate_quotes_list - if char == cdel - " Closing delimiter on the right. - return 1 - endif - endfor - - if b:delimitMate_expand_space && char == " " - for cdel in b:delimitMate_right_delims + b:delimitMate_quotes_list - if nchar == cdel - " Closing delimiter with space expansion. - return 1 - endif - endfor - endif - - if b:delimitMate_expand_cr && char == "" - for cdel in b:delimitMate_right_delims + b:delimitMate_quotes_list - if uchar == cdel - " Closing delimiter with CR expansion. - return 1 - endif - endfor - endif - - return 0 -endfunction "}}} - -function! s:IsBlockVisual() " {{{ - if visualmode() == "" - return 1 - endif - " Store unnamed register values for later use in s:RestoreRegister(). - let s:save_reg = getreg('"') - let s:save_reg_mode = getregtype('"') - - if len(getline('.')) == 0 - " This for proper wrap of empty lines. - let @" = "\n" - endif - return 0 -endfunction " }}} - -function! s:IsEmptyPair(str) "{{{ - for pair in b:delimitMate_matchpairs_list - if a:str == join( split( pair, ':' ),'' ) - return 1 - endif - endfor - for quote in b:delimitMate_quotes_list - if a:str == quote . quote - return 1 - endif - endfor - return 0 -endfunction "}}} - -function! s:IsCRExpansion() " {{{ - let nchar = getline(line('.')-1)[-1:] - let schar = getline(line('.')+1)[-1:] - let isEmpty = getline('.') == "" - if index(b:delimitMate_left_delims, nchar) > -1 && - \ index(b:delimitMate_left_delims, nchar) == index(b:delimitMate_right_delims, schar) && - \ isEmpty - return 1 - elseif index(b:delimitMate_quotes_list, nchar) > -1 && - \ index(b:delimitMate_quotes_list, nchar) == index(b:delimitMate_quotes_list, schar) && - \ isEmpty - return 1 - else - return 0 - endif -endfunction " }}} s:IsCRExpansion() - -function! s:IsSpaceExpansion() " {{{ - let line = getline('.') - let col = col('.')-2 - if col > 0 - let pchar = line[col - 1] - let nchar = line[col + 2] - let isSpaces = (line[col] == line[col+1] && line[col] == " ") - - if index(b:delimitMate_left_delims, pchar) > -1 && - \ index(b:delimitMate_left_delims, pchar) == index(b:delimitMate_right_delims, nchar) && - \ isSpaces - return 1 - elseif index(b:delimitMate_quotes_list, pchar) > -1 && - \ index(b:delimitMate_quotes_list, pchar) == index(b:delimitMate_quotes_list, nchar) && - \ isSpaces - return 1 - endif - endif - return 0 -endfunction " }}} IsSpaceExpansion() - -function! DelimitMate_WithinEmptyPair() "{{{ - let cur = strpart( getline('.'), col('.')-2, 2 ) - return s:IsEmptyPair( cur ) -endfunction "}}} - -function! s:WriteBefore(str) "{{{ - let len = len(a:str) - let line = getline('.') - let col = col('.')-2 - if col < 0 - call setline('.',line[(col+len+1):]) - else - call setline('.',line[:(col)].line[(col+len+1):]) - endif - return a:str -endfunction " }}} - -function! s:WriteAfter(str) "{{{ - let len = len(a:str) - let line = getline('.') - let col = col('.')-2 - if (col) < 0 - call setline('.',a:str.line) - else - call setline('.',line[:(col)].a:str.line[(col+len):]) - endif - return '' -endfunction " }}} - -function! s:RestoreRegister() " {{{ - " Restore unnamed register values store in s:IsBlockVisual(). - call setreg('"', s:save_reg, s:save_reg_mode) - echo "" -endfunction " }}} - -function! s:GetCurrentSyntaxRegion() "{{{ - return synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name') -endfunction " }}} - -function! s:GetCurrentSyntaxRegionIf(char) "{{{ - let col = col('.') - let origin_line = getline('.') - let changed_line = strpart(origin_line, 0, col - 1) . a:char . strpart(origin_line, col - 1) - call setline('.', changed_line) - let region = synIDattr(synIDtrans(synID(line('.'), col, 1)), 'name') - call setline('.', origin_line) - return region -endfunction "}}} - -function! s:IsForbidden(char) "{{{ - let result = index(b:delimitMate_excluded_regions_list, s:GetCurrentSyntaxRegion()) >= 0 - if result - return result - endif - let region = s:GetCurrentSyntaxRegionIf(a:char) - let result = index(b:delimitMate_excluded_regions_list, region) >= 0 - "return result || region == 'Comment' - return result -endfunction "}}} - -" }}} - -" Doers: {{{ -function! s:JumpIn(char) " {{{ - if s:IsForbidden(b:delimitMate_left_delims[index(b:delimitMate_right_delims, a:char)]) - echom 1 - return a:char - endif - call s:WriteAfter(b:delimitMate_right_delims[index(b:delimitMate_left_delims, a:char)]) - return a:char -endfunction " }}} - -function! s:JumpOut(char) "{{{ - if s:IsForbidden(a:char) - return a:char - endif - let line = getline('.') - let col = col('.') - 2 - if line[col + 1] == a:char - return a:char . "\" - endif - return a:char -endfunction " }}} - -function! DelimitMate_JumpAny() " {{{ - " Let's get the character on the right. - let char = getline('.')[col('.')-1] - if char == " " - " Space expansion. - let char = char . getline('.')[col('.')] . "\" - elseif char == "" - " CR expansion. - let char = "\" . getline(line('.') + 1)[0] . "\" - endif - return char . "\" -endfunction " DelimitMate_JumpAny() }}} - -function! s:SkipDelim(char) "{{{ - if s:IsForbidden(a:char) - return a:char - endif - let cur = strpart( getline('.'), col('.')-2, 3 ) - if cur[0] == "\\" - " Escaped character - return a:char - elseif cur[1] == a:char - " Exit pair - return s:WriteBefore(a:char) - "elseif cur[1] == ' ' && cur[2] == a:char - "" I'm leaving this in case someone likes it. Jump an space and delimiter. - "return "\\" - elseif s:IsEmptyPair( cur[0] . a:char ) - " Add closing delimiter and jump back to the middle. - return s:WriteAfter(a:char) - else - " Nothing special here, return the same character. - return a:char - endif -endfunction "}}} - -function! s:QuoteDelim(char) "{{{ - if s:IsForbidden(a:char) - return a:char - endif - let line = getline('.') - let col = col('.') - 2 - if line[col] == "\\" - " Seems like a escaped character, insert one quotation mark. - return a:char - elseif line[col + 1] == a:char - " Get out of the string. - return s:WriteBefore(a:char) - elseif (line[col] =~ '[a-zA-Z0-9]' && a:char == "'") || - \(line[col] =~ '[a-zA-Z0-9]' && b:delimitMate_smart_quotes) - " Seems like an apostrophe or a closing, insert a single quote. - return a:char - elseif (line[col] == a:char && line[col + 1 ] != a:char) && b:delimitMate_smart_quotes - " Seems like we have an unbalanced quote, insert one quotation mark and jump to the middle. - return s:WriteAfter(a:char) - else - " Insert a pair and jump to the middle. - call s:WriteAfter(a:char) - return a:char - endif -endfunction "}}} - -function! s:MapMsg(msg) "{{{ - redraw - echomsg a:msg - return "" -endfunction "}}} - -function! DelimitMate_ExpandReturn() "{{{ - if DelimitMate_WithinEmptyPair() && - \ b:delimitMate_expand_cr && - \ s:IsForbidden('') == 0 - " Expand: - return "\a\x\\k$\"_xa" - else - return "\" - endif -endfunction "}}} - -function! DelimitMate_ExpandSpace() "{{{ - if DelimitMate_WithinEmptyPair() && - \ b:delimitMate_expand_space && - \ s:IsForbidden('') == 0 - " Expand: - return s:WriteAfter(' ') . "\" - else - return "\" - endif -endfunction "}}} - -function! DelimitMate_BS() " {{{ - let IsF = s:IsForbidden('') - if DelimitMate_WithinEmptyPair() && IsF == 0 - return "\\\" - elseif b:delimitMate_expand_cr && - \ IsF == 0 && - \ (IsCRExpansion() != 0 || IsSpaceExpansion()) - return "\\" - else - return "\" - endif -endfunction " }}} DelimitMate_BS() - -"}}} - -" Mappings: {{{ -function! s:NoAutoClose() "{{{ - " inoremap ) =SkipDelim('\)') - for delim in b:delimitMate_right_delims + b:delimitMate_quotes_list - exec 'inoremap ' . delim . ' =SkipDelim("' . escape(delim,'"') . '")' - endfor -endfunction "}}} - -function! s:AutoClose() "{{{ - " Add matching pair and jump to the midle: - " inoremap ( () - let i = 0 - while i < len(b:delimitMate_matchpairs_list) - let ld = b:delimitMate_left_delims[i] - let rd = b:delimitMate_right_delims[i] - "exec 'inoremap ' . ld . ' ' . ld . '=JumpIn("' . rd . '")' - exec 'inoremap ' . ld . ' ' '=JumpIn("' . ld . '")' - let i += 1 - endwhile - - " Exit from inside the matching pair: - for delim in b:delimitMate_right_delims - exec 'inoremap ' . delim . ' =JumpOut("\' . delim . '")' - endfor - - " Add matching quote and jump to the midle, or exit if inside a pair of matching quotes: - " inoremap " =QuoteDelim("\"") - for delim in b:delimitMate_quotes_list - exec 'inoremap ' . delim . ' =QuoteDelim("\' . delim . '")' - endfor - - " Try to fix the use of apostrophes (de-activated by default): - " inoremap n't n't - for map in b:delimitMate_apostrophes_list - exec "inoremap " . map . " " . map - endfor - -endfunction "}}} - -function! s:VisualMaps() " {{{ - let vleader = b:delimitMate_visual_leader - " Wrap the selection with matching pairs, but do nothing if blockwise visual mode is active: - let i = 0 - while i < len(b:delimitMate_matchpairs_list) - " Map left delimiter: - let ld = b:delimitMate_left_delims[i] - let rd = b:delimitMate_right_delims[i] - exec 'vnoremap ' . vleader . ld . ' IsBlockVisual() ? MapMsg("' . s:VMapMsg . '") : "s' . ld . '\\"' . rd . '\:call RestoreRegister()"' - - " Map right delimiter: - exec 'vnoremap ' . vleader . rd . ' IsBlockVisual() ? MapMsg("' . s:VMapMsg . '") : "s' . ld . '\\"' . rd . '\:call RestoreRegister()"' - let i += 1 - endwhile - - " Wrap the selection with matching quotes, but do nothing if blockwise visual mode is active: - for quote in b:delimitMate_quotes_list - " vnoremap \' IsBlockVisual() ? MapMsg("Message") : "s'\\"'\:call RestoreRegister()" - exec 'vnoremap ' . vleader . quote . ' IsBlockVisual() ? MapMsg("' . s:VMapMsg . '") : "s' . escape(quote,'"') .'\\"' . escape(quote,'"') . '\:call RestoreRegister()"' - endfor -endfunction "}}} - -function! s:ExtraMappings() "{{{ - " If pair is empty, delete both delimiters: - inoremap =DelimitMate_BS() - - " If pair is empty, delete closing delimiter: - inoremap DelimitMate_WithinEmptyPair() ? "\" : "\" - - " Expand return if inside an empty pair: - if b:delimitMate_expand_cr != 0 - inoremap =DelimitMate_ExpandReturn() - endif - - " Expand space if inside an empty pair: - if b:delimitMate_expand_space != 0 - inoremap =DelimitMate_ExpandSpace() - endif - - " Jump out ot any empty pair: - if b:delimitMate_tab2exit - inoremap DelimitMate_ShouldJump() ? DelimitMate_JumpAny() : "\" - endif -endfunction "}}} -"}}} - " Tools: {{{ -function! s:TestMappings() "{{{ - if b:delimitMate_autoclose - for i in range(len(b:delimitMate_left_delims)) - exec "normal GGAOpen & close: " . b:delimitMate_left_delims[i]. "|" - exec "normal A\Delete: " . b:delimitMate_left_delims[i] . "\|" - exec "normal A\Exit: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "|" - exec "normal A\Space: " . b:delimitMate_left_delims[i] . " |" - exec "normal A\Delete space: " . b:delimitMate_left_delims[i] . " \|" - exec "normal GGA\Visual-L: v\v" . b:delimitMate_visual_leader . b:delimitMate_left_delims[i] - exec "normal A\Visual-R: v\v" . b:delimitMate_visual_leader . b:delimitMate_right_delims[i] - exec "normal A\Car return: " . b:delimitMate_left_delims[i] . "\|" - exec "normal GGA\Delete car return: " . b:delimitMate_left_delims[i] . "\\|\GGA\\" - endfor - for i in range(len(b:delimitMate_quotes_list)) - exec "normal GGAOpen & close: " . b:delimitMate_quotes_list[i] . "|" - exec "normal A\Delete: " - exec "normal A". b:delimitMate_quotes_list[i] - exec "normal a\|" - exec "normal A\Exit: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|" - exec "normal A\Space: " . b:delimitMate_quotes_list[i] . " |" - exec "normal A\Delete space: " . b:delimitMate_quotes_list[i] . " \|" - exec "normal GGA\Visual: v\v" . b:delimitMate_visual_leader . b:delimitMate_quotes_list[i] - exec "normal A\Car return: " . b:delimitMate_quotes_list[i] . "\|" - exec "normal GGA\Delete car return: " . b:delimitMate_quotes_list[i] . "\\|\GGA\\" - endfor - else - for i in range(len(b:delimitMate_left_delims)) - exec "normal GGAOpen & close: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "|" - exec "normal A\Delete: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "\|" - exec "normal A\Exit: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . b:delimitMate_right_delims[i] . "|" - exec "normal A\Space: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . " |" - exec "normal A\Delete space: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . " \|" - exec "normal GGA\Visual-L: v\v" . b:delimitMate_visual_leader . b:delimitMate_left_delims[i] - exec "normal A\Visual-R: v\v" . b:delimitMate_visual_leader . b:delimitMate_right_delims[i] - exec "normal A\Car return: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "\|" - exec "normal GGA\Delete car return: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "\\|\GGA\\" - endfor - for i in range(len(b:delimitMate_quotes_list)) - exec "normal GGAOpen & close: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|" - exec "normal A\Delete: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "\|" - exec "normal A\Exit: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|" - exec "normal A\Space: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . " |" - exec "normal A\Delete space: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . " \|" - exec "normal GGA\Visual: v\v" . b:delimitMate_visual_leader . b:delimitMate_quotes_list[i] - exec "normal A\Car return: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "\|" - exec "normal GGA\Delete car return: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "\\|\GGA\\" - endfor - endif - exec "normal \i" -endfunction "}}} - function! s:UnMap() " {{{ " No Autoclose Mappings: for char in b:delimitMate_right_delims + b:delimitMate_quotes_list @@ -700,10 +223,8 @@ function! s:UnMap() " {{{ endfunction " }}} s:ExtraMappings() function! s:TestMappingsDo() "{{{ - "DelimitMateReload if !exists("g:delimitMate_testing") - "call s:DelimitMateDo() - call s:TestMappings() + call delimitMate#TestMappings() else let temp_varsDM = [b:delimitMate_expand_space, b:delimitMate_expand_cr, b:delimitMate_autoclose] for i in [0,1] @@ -715,7 +236,7 @@ function! s:TestMappingsDo() "{{{ exec "normal i b:delimitMate_autoclose: " . b:delimitMate_autoclose . "\" exec "normal i b:delimitMate_expand_space: " . b:delimitMate_expand_space . "\" exec "normal i b:delimitMate_expand_cr: " . b:delimitMate_expand_cr . "\\" - call s:TestMappings() + call delimitMate#TestMappings() exec "normal i\" endfor endfor @@ -727,6 +248,7 @@ function! s:TestMappingsDo() "{{{ endif endfunction "}}} + function! s:DelimitMateDo() "{{{ if exists("g:delimitMate_excluded_ft") " Check if this file type is excluded: