├── .gitignore ├── Makefile ├── README.md ├── autoload └── delimitMate.vim ├── basic_vimrc ├── doc └── delimitMate.txt ├── plugin └── delimitMate.vim └── test ├── Makefile ├── README.md ├── _setup.vim ├── autoclose_matchpairs.txt ├── autoclose_matchpairs.vim ├── autoclose_quotes.txt ├── autoclose_quotes.vim ├── eol_marker.vim ├── expand_cr.txt ├── expand_cr.vim ├── expand_space.txt ├── expand_space.vim └── first_buffer_no_ft.vim /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw? 2 | *.un? 3 | *.vba 4 | *.vmb 5 | *.zip 6 | *.gz 7 | vimball.txt 8 | *.orig 9 | tags 10 | test/build 11 | test/*.tap 12 | test/*.msgout 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PLUGIN = $(wildcard plugin/*.vim) 2 | SOURCES = $(PLUGIN) 3 | LIB = $(wildcard autoload/*.vim) 4 | SOURCES += $(LIB) 5 | DOC = $(wildcard doc/*.txt) 6 | SOURCES += $(DOC) 7 | NAME = delimitMate 8 | VERSION = $(shell $(SED) -n -e '/Current \+release/{s/^ \+\([0-9.]\+\).*/\1/;p;}' $(firstword $(DOC))) 9 | FILENAME = $(NAME)-$(VERSION) 10 | DESTDIR = $(HOME)/.vim 11 | VIM = vim 12 | SED = $(shell command -v gsed || command -v sed) 13 | PERL = perl 14 | comma := , 15 | empty := 16 | space := $(empty) $(empty) 17 | 18 | .PHONY: version clean distclean undo release test install uninstall 19 | 20 | all: zip gzip 21 | dist: version all 22 | vimball: $(FILENAME).vmb 23 | zip: $(FILENAME).zip $(FILENAME).vmb.zip 24 | gzip: $(FILENAME).tar.gz $(FILENAME).vmb.gz 25 | 26 | clean: 27 | rm -f */*.orig *.~* .VimballRecord *.zip *.gz *.vmb 28 | 29 | distclean: clean 30 | -zsh -c 'setopt extendedglob; rm -f ^(README.md|Makefile|basic_vimrc)(.)' 31 | -zsh -c 'setopt extendedglob; rm -f .^(git|README.md|Makefile|basic_vimrc)*' 32 | 33 | undo: 34 | for i in */*.orig; do mv -f "$$i" "$${i%.*}"; done 35 | 36 | version: 37 | $(PERL) -i.orig -pne 'if (/^"\sVersion:/) {s/(\d+\.\S+)/$(VERSION)/}' $(PLUGIN) $(LIB) 38 | $(PERL) -i.orig -pne \ 39 | 'if (/let\sdelimitMate_version/) {s/"(\d+\.\S+)"/"$(VERSION)"/}' $(PLUGIN) 40 | $(PERL) -i.orig -pne 'if (/beasts/) {s/(v\d+\.\S+)/v$(VERSION)/}' $(DOC) 41 | $(PERL) -i.orig -MPOSIX -pne \ 42 | 'if (/^"\sModified:/) {$$now_string = strftime "%F", localtime; s/(\d+-\d+-\d+)/$$now_string/e}' \ 43 | $(PLUGIN) $(LIB) 44 | $(PERL) -i.orig -MPOSIX -pne \ 45 | 'if (/^\s+$(VERSION)\s+\d+-\d+-\d+\s+\*/) {$$now_string = strftime "%F", localtime; s/(\d+-\d+-\d+)/$$now_string/}' \ 46 | $(DOC) 47 | 48 | test: 49 | $(MAKE) -C test 50 | 51 | install: $(SOURCES) 52 | for dir in $(^D);\ 53 | do install -d -m 0755 $(DESTDIR)$(PREFIX)/$$dir;\ 54 | done;\ 55 | for file in $^;\ 56 | do install -m 0644 $$file $(DESTDIR)$(PREFIX)/$$file;\ 57 | done; 58 | 59 | uninstall: 60 | for file in $(SOURCES);\ 61 | do rm -f $(DESTDIR)$(PREFIX)/$$file;\ 62 | done; 63 | 64 | %.vmb: $(SOURCES) 65 | $(VIM) -N -es -u NORC \ 66 | -c 'call setline(1,["$(subst $(space),"$(comma)",$^)"])'\ 67 | -c "%MkVimball! $(basename $@) ." -c 'q!' 68 | 69 | %.vmb.zip: vimball 70 | zip $@ $(basename $@) 71 | 72 | %.zip: $(SOURCES) 73 | zip $@ $^ 74 | 75 | %.vmb.gz: vimball 76 | gzip -f < $(basename $@) > $@ 77 | 78 | %.tar.gz: $(SOURCES) 79 | tar -cvzf $@ $^ 80 | 81 | # vim:ts=2:sw=2 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This plug-in provides automatic closing of quotes, parenthesis, brackets, etc., besides some other related features that 2 | should make your time in insert mode a little bit easier, like syntax awareness (will not insert the closing delimiter 3 | in comments and other configurable regions), and expansions (off by default), and some more. 4 | 5 | Most of the features can be modified or disabled permanently, using global variables, or on a FileType basis, using 6 | :autocmd. 7 | -------------------------------------------------------------------------------- /autoload/delimitMate.vim: -------------------------------------------------------------------------------- 1 | " File: autoload/delimitMate.vim 2 | " Version: 2.7 3 | " Modified: 2013-07-15 4 | " Description: This plugin provides auto-completion for quotes, parens, etc. 5 | " Maintainer: Israel Chauca F. 6 | " Manual: Read ":help delimitMate". 7 | " ============================================================================ 8 | 9 | "let delimitMate_loaded = 1 10 | 11 | if !exists('s:options') 12 | let s:options = {} 13 | endif 14 | 15 | function! s:set(name, value) "{{{ 16 | let bufnr = bufnr('%') 17 | if !has_key(s:options, bufnr) 18 | let s:options[bufnr] = {} 19 | endif 20 | let s:options[bufnr][a:name] = a:value 21 | endfunction "}}} 22 | 23 | function! s:get(...) "{{{ 24 | let options = deepcopy(eval('s:options.' . bufnr('%'))) 25 | if a:0 26 | return options[a:1] 27 | endif 28 | return options 29 | endfunction "}}} 30 | 31 | function! s:exists(name, ...) "{{{ 32 | let scope = a:0 ? a:1 : 's' 33 | if scope == 's' 34 | let bufnr = bufnr('%') 35 | let name = 'options.' . bufnr . '.' . a:name 36 | else 37 | let name = 'delimitMate_' . a:name 38 | endif 39 | return exists(scope . ':' . name) 40 | endfunction "}}} 41 | 42 | function! s:is_jump(...) "{{{ 43 | " Returns 1 if the next character is a closing delimiter. 44 | let char = s:get_char(0) 45 | let list = s:get('right_delims') + s:get('quotes_list') 46 | 47 | " Closing delimiter on the right. 48 | if (!a:0 && index(list, char) > -1) 49 | \ || (a:0 && char == a:1) 50 | return 1 51 | endif 52 | 53 | " Closing delimiter with space expansion. 54 | let nchar = s:get_char(1) 55 | if !a:0 && s:get('expand_space') && char == " " 56 | if index(list, nchar) > -1 57 | return 2 58 | endif 59 | elseif a:0 && s:get('expand_space') && nchar == a:1 && char == ' ' 60 | return 3 61 | endif 62 | 63 | if !s:get('jump_expansion') 64 | return 0 65 | endif 66 | 67 | " Closing delimiter with CR expansion. 68 | let uchar = matchstr(getline(line('.') + 1), '^\s*\zs\S') 69 | if !a:0 && s:get('expand_cr') && char == "" 70 | if index(list, uchar) > -1 71 | return 4 72 | endif 73 | elseif a:0 && s:get('expand_cr') && uchar == a:1 74 | return 5 75 | endif 76 | return 0 77 | endfunction "}}} 78 | 79 | function! s:rquote(char) "{{{ 80 | let pos = matchstr(getline('.')[col('.') : ], escape(a:char, '[]*.^$\'), 1) 81 | let i = 0 82 | while s:get_char(i) ==# a:char 83 | let i += 1 84 | endwhile 85 | return i 86 | endfunction "}}} 87 | 88 | function! s:lquote(char) "{{{ 89 | let i = 0 90 | while s:get_char(i - 1) ==# a:char 91 | let i -= 1 92 | endwhile 93 | return i * -1 94 | endfunction "}}} 95 | 96 | function! s:get_char(...) "{{{ 97 | let idx = col('.') - 1 98 | if !a:0 || (a:0 && a:1 >= 0) 99 | " Get char from cursor. 100 | let line = getline('.')[idx :] 101 | let pos = a:0 ? a:1 : 0 102 | return matchstr(line, '^'.repeat('.', pos).'\zs.') 103 | endif 104 | " Get char behind cursor. 105 | let line = getline('.')[: idx - 1] 106 | let pos = 0 - (1 + a:1) 107 | return matchstr(line, '.\ze'.repeat('.', pos).'$') 108 | endfunction "s:get_char }}} 109 | 110 | function! s:is_cr_expansion(...) " {{{ 111 | let nchar = getline(line('.')-1)[-1:] 112 | let schar = matchstr(getline(line('.')+1), '^\s*\zs\S') 113 | let isEmpty = a:0 ? getline('.') =~ '^\s*$' : empty(getline('.')) 114 | if index(s:get('left_delims'), nchar) > -1 115 | \ && index(s:get('left_delims'), nchar) 116 | \ == index(s:get('right_delims'), schar) 117 | \ && isEmpty 118 | return 1 119 | elseif index(s:get('quotes_list'), nchar) > -1 120 | \ && index(s:get('quotes_list'), nchar) 121 | \ == index(s:get('quotes_list'), schar) 122 | \ && isEmpty 123 | return 1 124 | else 125 | return 0 126 | endif 127 | endfunction " }}} s:is_cr_expansion() 128 | 129 | function! s:is_space_expansion() " {{{ 130 | if col('.') > 2 131 | let pchar = s:get_char(-2) 132 | let nchar = s:get_char(1) 133 | let isSpaces = 134 | \ (s:get_char(-1) 135 | \ == s:get_char(0) 136 | \ && s:get_char(-1) == " ") 137 | 138 | if index(s:get('left_delims'), pchar) > -1 && 139 | \ index(s:get('left_delims'), pchar) 140 | \ == index(s:get('right_delims'), nchar) && 141 | \ isSpaces 142 | return 1 143 | elseif index(s:get('quotes_list'), pchar) > -1 && 144 | \ index(s:get('quotes_list'), pchar) 145 | \ == index(s:get('quotes_list'), nchar) && 146 | \ isSpaces 147 | return 1 148 | endif 149 | endif 150 | return 0 151 | endfunction " }}} IsSpaceExpansion() 152 | 153 | function! s:is_empty_matchpair() "{{{ 154 | " get char before the cursor. 155 | let open = s:get_char(-1) 156 | let idx = index(s:get('left_delims'), open) 157 | if idx == -1 158 | return 0 159 | endif 160 | let close = get(s:get('right_delims'), idx, '') 161 | return close ==# s:get_char(0) 162 | endfunction "}}} 163 | 164 | function! s:is_empty_quotes() "{{{ 165 | " get char before the cursor. 166 | let quote = s:get_char(-1) 167 | let idx = index(s:get('quotes_list'), quote) 168 | if idx == -1 169 | return 0 170 | endif 171 | return quote ==# s:get_char(0) 172 | endfunction "}}} 173 | 174 | function! s:cursor_idx() "{{{ 175 | let idx = len(split(getline('.')[: col('.') - 1], '\zs')) - 1 176 | return idx 177 | endfunction "delimitMate#CursorCol }}} 178 | 179 | function! s:get_syn_name() "{{{ 180 | let col = col('.') 181 | if col == col('$') 182 | let col = col - 1 183 | endif 184 | return synIDattr(synIDtrans(synID(line('.'), col, 1)), 'name') 185 | endfunction " }}} 186 | 187 | function! s:is_excluded_ft(ft) "{{{ 188 | if !exists("g:delimitMate_excluded_ft") 189 | return 0 190 | endif 191 | return index(split(g:delimitMate_excluded_ft, ','), a:ft, 0, 1) >= 0 192 | endfunction "}}} 193 | 194 | function! s:is_forbidden(char) "{{{ 195 | if s:is_excluded_ft(&filetype) 196 | return 1 197 | endif 198 | if !s:get('excluded_regions_enabled') 199 | return 0 200 | endif 201 | let region = s:get_syn_name() 202 | return index(s:get('excluded_regions_list'), region) >= 0 203 | endfunction "}}} 204 | 205 | function! s:balance_matchpairs(char) "{{{ 206 | " Returns: 207 | " = 0 => Parens balanced. 208 | " > 0 => More opening parens. 209 | " < 0 => More closing parens. 210 | 211 | let line = getline('.') 212 | let col = s:cursor_idx() - 1 213 | let col = col >= 0 ? col : 0 214 | let list = split(line, '\zs') 215 | let left = s:get('left_delims')[index(s:get('right_delims'), a:char)] 216 | let right = a:char 217 | let opening = 0 218 | let closing = 0 219 | 220 | " If the cursor is not at the beginning, count what's behind it. 221 | if col > 0 222 | " Find the first opening paren: 223 | let start = index(list, left) 224 | " Must be before cursor: 225 | let start = start < col ? start : col - 1 226 | " Now count from the first opening until the cursor, this will prevent 227 | " extra closing parens from being counted. 228 | let opening = count(list[start : col - 1], left) 229 | let closing = count(list[start : col - 1], right) 230 | " I don't care if there are more closing parens than opening parens. 231 | let closing = closing > opening ? opening : closing 232 | endif 233 | 234 | " Evaluate parens from the cursor to the end: 235 | let opening += count(list[col :], left) 236 | let closing += count(list[col :], right) 237 | 238 | " Return the found balance: 239 | return opening - closing 240 | endfunction "}}} 241 | 242 | function! s:is_smart_quote(char) "{{{ 243 | " TODO: Allow using a:char in the pattern. 244 | let tmp = s:get('smart_quotes') 245 | if empty(tmp) 246 | return 0 247 | endif 248 | let regex = matchstr(tmp, '^!\?\zs.*') 249 | " Flip matched value if regex starts with ! 250 | let mod = tmp =~ '^!' ? [1, 0] : [0, 1] 251 | let matched = search(regex, 'ncb', line('.')) > 0 252 | let noescaped = substitute(getline('.'), '\\.', '', 'g') 253 | let odd = (count(split(noescaped, '\zs'), a:char) % 2) 254 | let result = mod[matched] || odd 255 | return result 256 | endfunction "delimitMate#SmartQuote }}} 257 | 258 | function! delimitMate#Set(...) "{{{ 259 | return call('s:set', a:000) 260 | endfunction "}}} 261 | 262 | function! delimitMate#Get(...) "{{{ 263 | return call('s:get', a:000) 264 | endfunction "}}} 265 | 266 | function! delimitMate#ShouldJump(...) "{{{ 267 | return call('s:is_jump', a:000) 268 | endfunction "}}} 269 | 270 | function! delimitMate#IsEmptyPair(str) "{{{ 271 | if strlen(substitute(a:str, ".", "x", "g")) != 2 272 | return 0 273 | endif 274 | let idx = index(s:get('left_delims'), matchstr(a:str, '^.')) 275 | if idx > -1 && 276 | \ s:get('right_delims')[idx] == matchstr(a:str, '.$') 277 | return 1 278 | endif 279 | let idx = index(s:get('quotes_list'), matchstr(a:str, '^.')) 280 | if idx > -1 && 281 | \ s:get('quotes_list')[idx] == matchstr(a:str, '.$') 282 | return 1 283 | endif 284 | return 0 285 | endfunction "}}} 286 | 287 | function! delimitMate#WithinEmptyPair() "{{{ 288 | " if cursor is at column 1 return 0 289 | if col('.') == 1 290 | return 0 291 | endif 292 | " get char before the cursor. 293 | let char1 = s:get_char(-1) 294 | " get char under the cursor. 295 | let char2 = s:get_char(0) 296 | return delimitMate#IsEmptyPair( char1.char2 ) 297 | endfunction "}}} 298 | 299 | function! delimitMate#SkipDelim(char) "{{{ 300 | if s:is_forbidden(a:char) 301 | return a:char 302 | endif 303 | let col = col('.') - 1 304 | let line = getline('.') 305 | if col > 0 306 | let cur = s:get_char(0) 307 | let pre = s:get_char(-1) 308 | else 309 | let cur = s:get_char(0) 310 | let pre = "" 311 | endif 312 | if pre == "\\" 313 | " Escaped character 314 | return a:char 315 | elseif cur == a:char 316 | " Exit pair 317 | return a:char . "\" 318 | elseif delimitMate#IsEmptyPair( pre . a:char ) 319 | " Add closing delimiter and jump back to the middle. 320 | return a:char . s:joinUndo() . "\" 321 | else 322 | " Nothing special here, return the same character. 323 | return a:char 324 | endif 325 | endfunction "}}} 326 | 327 | function! delimitMate#ParenDelim(right) " {{{ 328 | let left = s:get('left_delims')[index(s:get('right_delims'),a:right)] 329 | if s:is_forbidden(a:right) 330 | return left 331 | endif 332 | " Try to balance matchpairs 333 | if s:get('balance_matchpairs') && 334 | \ s:balance_matchpairs(a:right) < 0 335 | return left 336 | endif 337 | let line = getline('.') 338 | let col = col('.')-2 339 | if s:get('smart_matchpairs') != '' 340 | let smart_matchpairs = substitute(s:get('smart_matchpairs'), '\\!', left, 'g') 341 | let smart_matchpairs = substitute(smart_matchpairs, '\\#', a:right, 'g') 342 | if line[col+1:] =~ smart_matchpairs 343 | return left 344 | endif 345 | endif 346 | if len(line) == (col + 1) && s:get('insert_eol_marker') == 1 347 | let tail = s:get('eol_marker') 348 | else 349 | let tail = '' 350 | endif 351 | return left . a:right . tail . repeat(s:joinUndo() . "\", len(split(tail, '\zs')) + 1) 352 | endfunction " }}} 353 | 354 | function! delimitMate#QuoteDelim(char) "{{{ 355 | if s:is_forbidden(a:char) 356 | return a:char 357 | endif 358 | let char_at = s:get_char(0) 359 | let char_before = s:get_char(-1) 360 | let nesting_on = index(s:get('nesting_quotes'), a:char) > -1 361 | let left_q = nesting_on ? s:lquote(a:char) : 0 362 | if nesting_on && left_q > 1 363 | " Nesting quotes. 364 | let right_q = s:rquote(a:char) 365 | let quotes = right_q > left_q + 1 ? 0 : left_q - right_q + 2 366 | let lefts = quotes - 1 367 | return repeat(a:char, quotes) . repeat(s:joinUndo() . "\", lefts) 368 | elseif char_at == a:char 369 | " Inside an empty pair, jump out 370 | return a:char . "\" 371 | elseif a:char == '"' && index(split(&ft, '\.'), "vim") != -1 && getline('.') =~ '^\s*$' 372 | " If we are in a vim file and it looks like we're starting a comment, do 373 | " not add a closing char. 374 | return a:char 375 | elseif s:is_smart_quote(a:char) 376 | " Seems like a smart quote, insert a single char. 377 | return a:char 378 | elseif (char_before == a:char && char_at != a:char) 379 | \ && !empty(s:get('smart_quotes')) 380 | " Seems like we have an unbalanced quote, insert one quotation 381 | " mark and jump to the middle. 382 | return a:char . s:joinUndo() . "\" 383 | else 384 | " Insert a pair and jump to the middle. 385 | let sufix = '' 386 | if !empty(s:get('eol_marker')) && col('.') - 1 == len(getline('.')) 387 | let idx = len(s:get('eol_marker')) * -1 388 | let marker = getline('.')[idx : ] 389 | let has_marker = marker == s:get('eol_marker') 390 | let sufix = !has_marker ? s:get('eol_marker') : '' 391 | endif 392 | return a:char . a:char . s:joinUndo() . "\" 393 | endif 394 | endfunction "}}} 395 | 396 | function! delimitMate#JumpOut(char) "{{{ 397 | if s:is_forbidden(a:char) 398 | return a:char 399 | endif 400 | let jump = s:is_jump(a:char) 401 | if jump == 1 402 | " HACK: Instead of , we remove the char to be jumped over and 403 | " insert it again. This will trigger re-indenting via 'indentkeys'. 404 | " Ref: https://github.com/Raimondi/delimitMate/issues/168 405 | return "\".a:char 406 | elseif jump == 3 407 | return s:joinUndo() . "\" . s:joinUndo() . "\" 408 | elseif jump == 5 409 | return "\\I" . s:joinUndo() . "\" 410 | else 411 | return a:char 412 | endif 413 | endfunction " }}} 414 | 415 | function! delimitMate#JumpAny(...) " {{{ 416 | if s:is_forbidden('') 417 | return '' 418 | endif 419 | if !s:is_jump() 420 | return '' 421 | endif 422 | " Let's get the character on the right. 423 | let char = s:get_char(0) 424 | if char == " " 425 | " Space expansion. 426 | return s:joinUndo() . "\" . s:joinUndo() . "\" 427 | elseif char == "" 428 | " CR expansion. 429 | return "\" . getline(line('.') + 1)[0] . "\\" 430 | else 431 | return s:joinUndo() . "\" 432 | endif 433 | endfunction " delimitMate#JumpAny() }}} 434 | 435 | function! delimitMate#JumpMany() " {{{ 436 | let line = split(getline('.')[col('.') - 1 : ], '\zs') 437 | let rights = "" 438 | let found = 0 439 | for char in line 440 | if index(s:get('quotes_list'), char) >= 0 || 441 | \ index(s:get('right_delims'), char) >= 0 442 | let rights .= s:joinUndo() . "\" 443 | let found = 1 444 | elseif found == 0 445 | let rights .= s:joinUndo() . "\" 446 | else 447 | break 448 | endif 449 | endfor 450 | if found == 1 451 | return rights 452 | else 453 | return '' 454 | endif 455 | endfunction " delimitMate#JumpMany() }}} 456 | 457 | function! delimitMate#ExpandReturn() "{{{ 458 | if s:is_forbidden("") 459 | return "\" 460 | endif 461 | let escaped = s:cursor_idx() >= 2 462 | \ && s:get_char(-2) == '\' 463 | let expand_right_matchpair = s:get('expand_cr') == 2 464 | \ && index(s:get('right_delims'), s:get_char(0)) > -1 465 | let expand_inside_quotes = s:get('expand_inside_quotes') 466 | \ && s:is_empty_quotes() 467 | \ && !escaped 468 | let is_empty_matchpair = s:is_empty_matchpair() 469 | if !pumvisible( ) 470 | \ && ( is_empty_matchpair 471 | \ || expand_right_matchpair 472 | \ || expand_inside_quotes) 473 | let val = "\a" 474 | if is_empty_matchpair && s:get('insert_eol_marker') == 2 475 | \ && !search(escape(s:get('eol_marker'), '[]\.*^$').'$', 'cnW', '.') 476 | let tail = getline('.')[col('.') - 1 : ] 477 | let times = len(split(tail, '\zs')) 478 | let val .= repeat(s:joinUndo() . "\", times) . s:get('eol_marker') . repeat(s:joinUndo() . "\", times + 1) 479 | endif 480 | let val .= "\" 481 | if &smartindent && !&cindent && !&indentexpr 482 | \ && s:get_char(0) == '}' 483 | " indentation is controlled by 'smartindent', and the first character on 484 | " the new line is '}'. If this were typed manually it would reindent to 485 | " match the current line. Let's reproduce that behavior. 486 | let sw = &sw == 0 ? &ts : &sw 487 | let shifts = indent('.') / sw 488 | let spaces = indent('.') - (shifts * sw) 489 | let val .= "^\".repeat("\", shifts).repeat(' ', spaces) 490 | endif 491 | " Expand: 492 | " XXX zv prevents breaking expansion with syntax folding enabled by 493 | " InsertLeave. 494 | let val .= "\zvO" 495 | return val 496 | else 497 | return "\" 498 | endif 499 | endfunction "}}} 500 | 501 | function! delimitMate#ExpandSpace() "{{{ 502 | if s:is_forbidden("\") 503 | return "\" 504 | endif 505 | let escaped = s:cursor_idx() >= 2 506 | \ && s:get_char(-2) == '\' 507 | let expand_inside_quotes = s:get('expand_inside_quotes') 508 | \ && s:is_empty_quotes() 509 | \ && !escaped 510 | if s:is_empty_matchpair() || expand_inside_quotes 511 | " Expand: 512 | return "\\" . s:joinUndo() . "\" 513 | else 514 | return "\" 515 | endif 516 | endfunction "}}} 517 | 518 | function! delimitMate#BS() " {{{ 519 | if s:is_forbidden("") 520 | let extra = '' 521 | elseif &bs !~ 'start\|2' 522 | let extra = '' 523 | elseif delimitMate#WithinEmptyPair() 524 | let extra = "\" 525 | elseif s:is_space_expansion() 526 | let extra = "\" 527 | elseif s:is_cr_expansion() 528 | let extra = repeat("\", 529 | \ len(matchstr(getline(line('.') + 1), '^\s*\S'))) 530 | else 531 | let extra = '' 532 | endif 533 | return "\" . extra 534 | endfunction " }}} delimitMate#BS() 535 | 536 | function! delimitMate#Test() "{{{ 537 | %d _ 538 | " Check for script options: 539 | let result = [ 540 | \ 'delimitMate Report', 541 | \ '==================', 542 | \ '', 543 | \ '* Options: ( ) default, (g) global, (b) buffer', 544 | \ ''] 545 | for option in sort(keys(s:options[bufnr('%')])) 546 | if s:exists(option, 'b') 547 | let scope = '(b)' 548 | elseif s:exists(option, 'g') 549 | let scope = '(g)' 550 | else 551 | let scope = '( )' 552 | endif 553 | call add(result, 554 | \ scope . ' delimitMate_' . option 555 | \ . ' = ' 556 | \ . string(s:get(option))) 557 | endfor 558 | call add(result, '') 559 | 560 | let option = 'delimitMate_excluded_ft' 561 | call add(result, 562 | \(exists('g:'.option) ? '(g) ' : '( ) g:') . option . ' = ' 563 | \. string(get(g:, option, ''))) 564 | 565 | call add(result, '--------------------') 566 | call add(result, '') 567 | 568 | " Check if mappings were set. 569 | let left_delims = s:get('autoclose') ? s:get('left_delims') : [] 570 | let special_keys = ['', '', '', 'g'] 571 | if s:get('expand_cr') 572 | call add(special_keys, '') 573 | endif 574 | if s:get('expand_space') 575 | call add(special_keys, '') 576 | endif 577 | let maps = 578 | \ s:get('right_delims') 579 | \ + left_delims 580 | \ + s:get('quotes_list') 581 | \ + s:get('apostrophes_list') 582 | \ + special_keys 583 | 584 | call add(result, '* Mappings:') 585 | call add(result, '') 586 | for map in maps 587 | let output = '' 588 | if map == '|' 589 | let map = '' 590 | endif 591 | redir => output | execute "verbose imap ".map | redir END 592 | call extend(result, split(output, '\n')) 593 | endfor 594 | 595 | call add(result, '--------------------') 596 | call add(result, '') 597 | call add(result, '* Showcase:') 598 | call add(result, '') 599 | call setline(1, result) 600 | call s:test_mappings(s:get('left_delims'), 1) 601 | call s:test_mappings(s:get('quotes_list'), 0) 602 | 603 | let result = [] 604 | redir => setoptions 605 | echo " * Vim configuration:\" 606 | filetype 607 | echo "" 608 | set 609 | version 610 | redir END 611 | call extend(result, split(setoptions,"\n")) 612 | call add(result, '--------------------') 613 | setlocal nowrap 614 | call append('$', result) 615 | call feedkeys("\\", 'n') 616 | endfunction "}}} 617 | 618 | function! s:test_mappings(list, is_matchpair) "{{{ 619 | let prefix = "normal Go0\" 620 | let last = "|" 621 | let open = s:get('autoclose') ? 'Open: ' : 'Open & close: ' 622 | for s in a:list 623 | if a:is_matchpair 624 | let pair = s:get('right_delims')[index(s:get('left_delims'), s)] 625 | else 626 | let pair = s 627 | endif 628 | if !s:get('autoclose') 629 | let s .= pair 630 | endif 631 | exec prefix . open . s . last 632 | exec prefix . "Delete: " . s . "\" . last 633 | exec prefix . "Exit: " . s . pair . last 634 | if s:get('expand_space') 635 | \ && (a:is_matchpair || s:get('expand_inside_quotes')) 636 | exec prefix . "Space: " . s . " " . last 637 | exec prefix . "Delete space: " . s . " \" . last 638 | endif 639 | if s:get('expand_cr') 640 | \ && (a:is_matchpair || s:get('expand_inside_quotes')) 641 | exec prefix . "Car return: " . s . "\" . last 642 | exec prefix . "Delete car return: " . s . "\0\\" . last 643 | endif 644 | call append('$', '') 645 | endfor 646 | endfunction "}}} 647 | 648 | function! s:joinUndo() "{{{ 649 | if v:version < 704 650 | \ || ( v:version == 704 && !has('patch849') ) 651 | return '' 652 | endif 653 | return "\U" 654 | endfunction "}}} 655 | 656 | " vim:foldmethod=marker:foldcolumn=4:ts=2:sw=2 657 | -------------------------------------------------------------------------------- /basic_vimrc: -------------------------------------------------------------------------------- 1 | so ./test/_setup.vim 2 | let delimitMate_expand_cr = 1 3 | filetype indent plugin on 4 | 5 | -------------------------------------------------------------------------------- /doc/delimitMate.txt: -------------------------------------------------------------------------------- 1 | *delimitMate.txt* Trying to keep those beasts at bay! v2.7 *delimitMate* 2 | 3 | 4 | 5 | MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 6 | MMMM MMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMM MMMMM MMMMMMMMMMMMMMMMMMMMM ~ 7 | MMMM MMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMM MMM MMMMMMMMMMMMMMMMMMMMM 8 | MMMM MMMMMMMMM MMMMMMMMMMMMMMMMMMMMM MMM M M MMMMMMMMMM MMMMMMMMM ~ 9 | MMMM MMM MMM MM MM M M MMM MM MM MM MM MMM MMM MMM MM 10 | MM MM M MM MMMMMM MMMMMMM MMM MMMMM MM M MMM MMM M M ~ 11 | M M MM MM MM MM M M MM MMM MMM MMMMM MMMMM MMM MMM M 12 | M M MM MMMMM MM MM M M MM MMM MMM MMMMM MMM MMM MMM MMMM ~ 13 | M M MM M MM MM MM M M MM MMM MMM MMMMM MM M MMM MMM M M 14 | MM MMM MMM MM MM M M MM MMM MM MMMMM MMM MMM MMM MM ~ 15 | MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 16 | 17 | 18 | 19 | ============================================================================== 20 | 0.- CONTENTS *delimitMate-contents* 21 | 22 | 1. Introduction____________________________|delimitMateIntro| 23 | 2. Customization___________________________|delimitMateOptions| 24 | 2.1 Options summary____________________|delimitMateOptionSummary| 25 | 2.2 Options details____________________|delimitMateOptionDetails| 26 | 3. Functionality___________________________|delimitMateFunctionality| 27 | 3.1 Automatic closing & exiting________|delimitMateAutoClose| 28 | 3.2 Expansion of space and CR__________|delimitMateExpansion| 29 | 3.3 Backspace__________________________|delimitMateBackspace| 30 | 3.4 Smart Quotes_______________________|delimitMateSmartQuotes| 31 | 3.5 Balancing matching pairs___________|delimitMateBalance| 32 | 3.6 FileType based configuration_______|delimitMateFileType| 33 | 3.7 Syntax awareness___________________|delimitMateSyntax| 34 | 4. Commands________________________________|delimitMateCommands| 35 | 5. Mappings________________________________|delimitMateMappings| 36 | 6. Functions_______________________________|delimitMateFunctions| 37 | 7. Autocommands____________________________|delimitMateAutocmds| 38 | 8. TODO list_______________________________|delimitMateTodo| 39 | 9. Maintainer______________________________|delimitMateMaintainer| 40 | 10. Credits_________________________________|delimitMateCredits| 41 | 11. History_________________________________|delimitMateHistory| 42 | 43 | ============================================================================== 44 | 1.- INTRODUCTION *delimitMateIntro* 45 | 46 | This plug-in provides automatic closing of quotes, parenthesis, brackets, 47 | etc.; besides some other related features that should make your time in insert 48 | mode a little bit easier. 49 | 50 | Most of the features can be modified or disabled permanently, using global 51 | variables, or on a FileType basis, using autocommands. 52 | 53 | NOTE 1: If you have any trouble with this plugin, please run |:DelimitMateTest| 54 | in a new buffer to see what is not working. 55 | 56 | NOTE 2: Abbreviations set with |:iabbrev| will not be expanded by delimiters 57 | used on delimitMate, you should use (read |i_CTRL-]|) to expand them on 58 | the go. 59 | 60 | ============================================================================== 61 | 2. CUSTOMIZATION *delimitMateOptions* 62 | 63 | You can create your own mappings for some features using the global functions. 64 | Read |delimitMateFunctions| for more info. 65 | 66 | ------------------------------------------------------------------------------ 67 | 2.1 OPTIONS SUMMARY *delimitMateOptionSummary* 68 | 69 | The behaviour of this script can be customized setting the following options 70 | in your vimrc file. You can use local options to set the configuration for 71 | specific file types, see |delimitMateOptionDetails| for examples. 72 | 73 | |'loaded_delimitMate'| Turns off the script. 74 | 75 | |'delimitMate_autoclose'| Tells delimitMate whether to automagically 76 | insert the closing delimiter. 77 | 78 | |'delimitMate_matchpairs'| Tells delimitMate which characters are 79 | matching pairs. 80 | 81 | |'delimitMate_quotes'| Tells delimitMate which quotes should be 82 | used. 83 | 84 | |'delimitMate_nesting_quotes'| Tells delimitMate which quotes should be 85 | allowed to be nested. 86 | 87 | |'delimitMate_expand_cr'| Turns on/off the expansion of . 88 | 89 | |'delimitMate_expand_space'| Turns on/off the expansion of . 90 | 91 | |'delimitMate_jump_expansion'| Turns on/off jumping over expansions. 92 | 93 | |'delimitMate_smart_quotes'| Turns on/off the "smart quotes" feature. 94 | 95 | |'delimitMate_smart_matchpairs'| Turns on/off the "smart matchpairs" feature. 96 | 97 | |'delimitMate_balance_matchpairs'|Turns on/off the "balance matching pairs" 98 | feature. 99 | 100 | |'delimitMate_excluded_regions'| Turns off the script for the given regions or 101 | syntax group names. 102 | 103 | |'delimitMate_excluded_ft'| Turns off the script for the given file types. 104 | 105 | |'delimitMate_eol_marker'| Determines what to insert after the closing 106 | matchpair when typing an opening matchpair on 107 | the end of the line. 108 | 109 | |'delimitMate_apostrophes'| Tells delimitMate how it should "fix" 110 | balancing of single quotes when used as 111 | apostrophes. NOTE: Not needed any more, kept 112 | for compatibility with older versions. 113 | 114 | ------------------------------------------------------------------------------ 115 | 2.2 OPTIONS DETAILS *delimitMateOptionDetails* 116 | 117 | Add the shown lines to your vimrc file in order to set the below options. 118 | Buffer variables take precedence over global ones and can be used along with 119 | autocmd to modify delimitMate's behavior for specific file types, read more in 120 | |delimitMateFileType|. 121 | 122 | Note: Use buffer variables only to set options for specific file types using 123 | :autocmd, use global variables to set options for all buffers. Read more in 124 | |g:var| and |b:var|. 125 | 126 | ------------------------------------------------------------------------------ 127 | *'loaded_delimitMate'* 128 | *'b:loaded_delimitMate'* 129 | This option prevents delimitMate from loading. 130 | e.g.: > 131 | let loaded_delimitMate = 1 132 | au FileType mail let b:loaded_delimitMate = 1 133 | < 134 | ------------------------------------------------------------------------------ 135 | *'delimitMate_offByDefault'* 136 | Values: 0 or 1.~ 137 | Default: 0~ 138 | 139 | If this option is set to 1, delimitMate will load, but will not take 140 | effect in any buffer unless |:DelimitMateSwitch| is called in that 141 | buffer. 142 | 143 | ------------------------------------------------------------------------------ 144 | *'delimitMate_autoclose'* 145 | *'b:delimitMate_autoclose'* 146 | Values: 0 or 1. ~ 147 | Default: 1 ~ 148 | 149 | If this option is set to 0, delimitMate will not add a closing delimiter 150 | automagically. See |delimitMateAutoClose| for details. 151 | e.g.: > 152 | let delimitMate_autoclose = 0 153 | au FileType mail let b:delimitMate_autoclose = 0 154 | < 155 | ------------------------------------------------------------------------------ 156 | *'delimitMate_matchpairs'* 157 | *'b:delimitMate_matchpairs'* 158 | Values: A string with |'matchpairs'| syntax, plus support for multi-byte~ 159 | characters.~ 160 | Default: &matchpairs ~ 161 | 162 | Use this option to tell delimitMate which characters should be considered 163 | matching pairs. Read |delimitMateAutoClose| for details. 164 | e.g: > 165 | let delimitMate_matchpairs = "(:),[:],{:},<:>" 166 | au FileType vim,html let b:delimitMate_matchpairs = "(:),[:],{:},<:>" 167 | < 168 | ------------------------------------------------------------------------------ 169 | *'delimitMate_quotes'* 170 | *'b:delimitMate_quotes'* 171 | Values: A string of characters separated by spaces. ~ 172 | Default: "\" ' `" ~ 173 | 174 | Use this option to tell delimitMate which characters should be considered as 175 | quotes. Read |delimitMateAutoClose| for details. 176 | e.g.: > 177 | let delimitMate_quotes = "\" ' ` *" 178 | au FileType html let b:delimitMate_quotes = "\" '" 179 | < 180 | ------------------------------------------------------------------------------ 181 | *'delimitMate_nesting_quotes'* 182 | *'b:delimitMate_nesting_quotes'* 183 | Values: A list of quotes. ~ 184 | Default: [] ~ 185 | 186 | When adding a third quote listed in this option is inserted, three quotes will 187 | be inserted to the right of the cursor and the cursor will stay in the middle. 188 | If more quotes are inserted the number of quotes on both sides of the cursor 189 | will stay balanced. 190 | e.g.: > 191 | let delimitMate_nesting_quotes = ['"','`'] 192 | au FileType python let b:delimitMate_nesting_quotes = ['"'] 193 | < 194 | For Python this is set by default by the plugin. 195 | 196 | ------------------------------------------------------------------------------ 197 | *'delimitMate_expand_cr'* 198 | *'b:delimitMate_expand_cr'* 199 | Values: 0, 1 or 2 ~ 200 | Default: 0 ~ 201 | 202 | This option turns on/off the expansion of . Read |delimitMateExpansion| 203 | for details. NOTE This feature requires that 'backspace' is either set to 2 or 204 | has "eol" and "start" as part of its value. 205 | e.g.: > 206 | let delimitMate_expand_cr = 1 207 | au FileType mail let b:delimitMate_expand_cr = 1 208 | < 209 | ------------------------------------------------------------------------------ 210 | *'delimitMate_expand_space'* 211 | *'b:delimitMate_expand_space'* 212 | Values: 1 or 0 ~ 213 | Default: 0 ~ 214 | This option turns on/off the expansion of . Read |delimitMateExpansion| 215 | for details. 216 | e.g.: > 217 | let delimitMate_expand_space = 1 218 | au FileType tcl let b:delimitMate_expand_space = 1 219 | < 220 | ------------------------------------------------------------------------------ 221 | *'delimitMate_expand_inside_quotes'* 222 | *'b:delimitMate_expand_inside_quotes'* 223 | Values: 1 or 0 ~ 224 | Default: 0 ~ 225 | When this option is set to 1 the expansion of space and cr will also be 226 | applied to quotes. Read |delimitMateExpansion| for details. 227 | 228 | e.g.: > 229 | let delimitMate_expand_inside_quotes = 1 230 | au FileType mail let b:delimitMate_expand_inside_quotes = 1 231 | < 232 | ------------------------------------------------------------------------------ 233 | *'delimitMate_jump_expansion'* 234 | *'b:delimitMate_jump_expansion'* 235 | Values: 1 or 0 ~ 236 | Default: 0 ~ 237 | This option turns on/off the jumping over and expansions when 238 | inserting closing matchpairs. Read |delimitMateExpansion| for details. 239 | e.g.: > 240 | let delimitMate_jump_expansion = 1 241 | au FileType tcl let b:delimitMate_jump_expansion = 1 242 | < 243 | ------------------------------------------------------------------------------ 244 | *'delimitMate_smart_quotes'* 245 | *'b:delimitMate_smart_quotes'* 246 | Values: String with an optional ! at the beginning followed by a regexp ~ 247 | Default:~ 248 | '\%(\w\|[^[:punct:][:space:]]\|\%(\\\\\)*\\\)\%#\|\%#\%(\w\|[^[:space:][:punct:]]\)' ~ 249 | 250 | A bang (!) at the beginning is removed and used to "negate" the pattern. The 251 | remaining text is used as a regexp to be matched on the current line. A single 252 | quote is inserted when the pattern matches and a bang is not present. The bang 253 | changes that, so a single quote is inserted only if the regexp does not match. 254 | 255 | This feature is disabled when the variable is set to an empty string, with the 256 | exception of apostrophes. 257 | 258 | Note that you need to use '\%#' to match the position of the cursor. Keep in 259 | mind that '\%#' matches with zero width, so if you need to match the char 260 | under the cursor (which would be the one to the right on insert mode) use 261 | something like '\%#.'. 262 | 263 | e.g.: > 264 | let delimitMate_smart_quotes = '\w\%#' 265 | au FileType tcl let b:delimitMate_smart_quotes = '!\s\%#\w' 266 | < 267 | ------------------------------------------------------------------------------ 268 | *'delimitMate_smart_matchpairs'* 269 | *'b:delimitMate_smart_matchpairs'* 270 | Values: Regexp ~ 271 | Default: '^\%(\w\|\!\|[£$]\|[^[:space:][:punct:]]\)' ~ 272 | 273 | This regex is matched against the text to the right of cursor, if it's not 274 | empty and there is a match delimitMate will not autoclose the pair. At the 275 | moment to match the text, an escaped bang (\!) in the regex will be replaced 276 | by the character being inserted, while an escaped number symbol (\#) will be 277 | replaced by the closing pair. 278 | e.g.: > 279 | let delimitMate_smart_matchpairs = '' 280 | au FileType tcl let b:delimitMate_smart_matchpairs = '^\%(\w\|\$\)' 281 | < 282 | ------------------------------------------------------------------------------ 283 | *'delimitMate_balance_matchpairs'* 284 | *'b:delimitMate_balance_matchpairs'* 285 | Values: 1 or 0 ~ 286 | Default: 0 ~ 287 | 288 | This option turns on/off the balancing of matching pairs. Read 289 | |delimitMateBalance| for details. 290 | e.g.: > 291 | let delimitMate_balance_matchpairs = 1 292 | au FileType tcl let b:delimitMate_balance_matchpairs = 1 293 | < 294 | ------------------------------------------------------------------------------ 295 | *'delimitMate_excluded_regions'* 296 | Values: A string of syntax group names names separated by single commas. ~ 297 | Default: Comment ~ 298 | 299 | This options turns delimitMate off for the listed regions, read |group-name| 300 | for more info about what is a region. 301 | e.g.: > 302 | let delimitMate_excluded_regions = "Comment,String" 303 | < 304 | ------------------------------------------------------------------------------ 305 | *'delimitMate_excluded_ft'* 306 | Values: A string of file type names separated by single commas. ~ 307 | Default: Empty. ~ 308 | 309 | This options turns delimitMate off for the listed file types, use this option 310 | only if you don't want any of the features it provides on those file types. 311 | e.g.: > 312 | let delimitMate_excluded_ft = "mail,txt" 313 | < 314 | ------------------------------------------------------------------------------ 315 | *'delimitMate_insert_eol_marker'* 316 | Values: Integer ~ 317 | Default: 1 ~ 318 | 319 | Whether to insert the eol marker (EM) or not. The EM is inserted following 320 | rules: 321 | 322 | 0 -> never 323 | 1 -> when inserting any matchpair 324 | 2 -> when expanding car return in matchpair 325 | 326 | e.g.: > 327 | au FileType c,perl let b:delimitMate_insert_eol_marker = 2 328 | < 329 | ------------------------------------------------------------------------------ 330 | *'delimitMate_eol_marker'* 331 | Values: String. ~ 332 | Default: Empty. ~ 333 | 334 | The contents of this string will be inserted after the closing matchpair or 335 | quote when the respective opening matchpair or quote is inserted at the end 336 | of the line. 337 | e.g.: > 338 | au FileType c,perl let b:delimitMate_eol_marker = ";" 339 | < 340 | ------------------------------------------------------------------------------ 341 | *'delimitMate_apostrophes'* 342 | Values: Strings separated by ":". ~ 343 | Default: No longer used. ~ 344 | 345 | NOTE: This feature is turned off by default, it's been kept for compatibility 346 | with older version, read |delimitMateSmartQuotes| for details. 347 | If auto-close is enabled, this option tells delimitMate how to try to fix the 348 | balancing of single quotes when used as apostrophes. The values of this option 349 | are strings of text where a single quote would be used as an apostrophe (e.g.: 350 | the "n't" of wouldn't or can't) separated by ":". Set it to an empty string to 351 | disable this feature. 352 | e.g.: > 353 | let delimitMate_apostrophes = "" 354 | au FileType tcl let delimitMate_apostrophes = "" 355 | < 356 | ============================================================================== 357 | 3. FUNCTIONALITY *delimitMateFunctionality* 358 | 359 | ------------------------------------------------------------------------------ 360 | 3.1 AUTOMATIC CLOSING AND EXITING *delimitMateAutoClose* 361 | 362 | With automatic closing enabled, if an opening delimiter is inserted the plugin 363 | inserts the closing delimiter and places the cursor between the pair. With 364 | automatic closing disabled, no closing delimiters is inserted by delimitMate, 365 | but when a pair of delimiters is typed, the cursor is placed in the middle. 366 | 367 | When the cursor is inside an empty pair or located next to the left of a 368 | closing delimiter, the cursor is placed outside the pair to the right of the 369 | closing delimiter. 370 | 371 | When |'delimitMate_smart_matchpairs'| is not empty and it matches the text to 372 | the right of the cursor, delimitMate will not automatically insert the closing 373 | pair. 374 | 375 | Unless |'delimitMate_matchpairs'| or |'delimitMate_quotes'| are set, this 376 | script uses the values in '&matchpairs' to identify the pairs, and ", ' and ` 377 | for quotes respectively. 378 | 379 | will jump over a single closing delimiter or quote, g will jump 380 | over contiguous delimiters and/or quotes. 381 | 382 | The following table shows the behaviour, this applies to quotes too (the final 383 | position of the cursor is represented by a "|"): 384 | 385 | With auto-close: > 386 | Type | You get 387 | ======================= 388 | ( | (|) 389 | -----------|----------- 390 | () | ()| 391 | -----------|----------- 392 | ( | ()| 393 | -----------|----------- 394 | {("g | {("")}| 395 | < 396 | Without auto-close: > 397 | 398 | Type | You get 399 | ========================= 400 | () | (|) 401 | --------------|---------- 402 | ()) | ()| 403 | --------------|---------- 404 | () | ()| 405 | --------------|---------- 406 | {}()""g | {("")}| 407 | < 408 | NOTE: Abbreviations will not be expanded by delimiters used on delimitMate, 409 | you should use (read |i_CTRL-]|) to expand them on the go. 410 | 411 | ------------------------------------------------------------------------------ 412 | 3.2 EXPANSION OF SPACE AND CAR RETURN *delimitMateExpansion* 413 | 414 | When the cursor is inside an empty pair of any matchpair, and can be 415 | expanded, see |'delimitMate_expand_space'| and 416 | |'delimitMate_expand_cr'|: 417 | 418 | Expand to: > 419 | 420 | You start with | You get 421 | ============================== 422 | (|) | ( | ) 423 | < 424 | Expand to: > 425 | 426 | You start with | You get 427 | ============================== 428 | (|) | ( 429 | | | 430 | | ) 431 | < 432 | 433 | When you have |'delimitMate_jump_expansion'| enabled, if there is an existing 434 | closing paren/bracket/etc. on the next line, delimitMate will make the cursor 435 | jump over any whitespace/ and place it after the existing closing 436 | delimiter instead of inserting a new one. 437 | 438 | When |'delimitMate_expand_cr'| is set to 2, the following will also happen: > 439 | 440 | You start with | You get 441 | ============================== 442 | (foo|) | (foo 443 | | | 444 | | ) 445 | < 446 | 447 | Since and are used everywhere, I have made the functions involved 448 | in expansions global, so they can be used to make custom mappings. Read 449 | |delimitMateFunctions| for more details. 450 | 451 | ------------------------------------------------------------------------------ 452 | 3.3 BACKSPACE *delimitMateBackspace* 453 | 454 | If you press backspace inside an empty pair, both delimiters are deleted. When 455 | expansions are enabled, will also delete the expansions. 456 | 457 | If you type (shift + backspace) instead, only the closing delimiter 458 | will be deleted. NOTE that this will not usually work when using Vim from the 459 | terminal, see 'delimitMate#JumpAny()' below to see how to fix it. 460 | 461 | e.g. typing at the "|": > 462 | 463 | What | Before | After 464 | ============================================== 465 | | call expand(|) | call expand| 466 | ---------|-------------------|----------------- 467 | | call expand( | ) | call expand(|) 468 | ---------|-------------------|----------------- 469 | | call expand( | call expand(|) 470 | | | | 471 | | ) | 472 | ---------|-------------------|----------------- 473 | | call expand(|) | call expand(| 474 | < 475 | 476 | ------------------------------------------------------------------------------ 477 | 3.4 SMART QUOTES *delimitMateSmartQuotes* 478 | 479 | Only one quote will be inserted following a quote, a "\", following or 480 | preceding a keyword character, or when the number of quotes in the current 481 | line is odd. This should cover closing quotes after a string, opening quotes 482 | before a string, escaped quotes and apostrophes. See more details about 483 | customizing this feature on |'delimitMate_smart_quotes'|. 484 | 485 | e.g. typing at the "|": > 486 | 487 | What | Before | After 488 | ======================================= 489 | " | Text | | Text "|" 490 | " | "String| | "String"| 491 | " | let i = "| | let i = "|" 492 | 'm | I| | I'm| 493 | < 494 | ------------------------------------------------------------------------------ 495 | 3.4 SMART MATCHPAIRS *delimitMateSmartMatchpairs* 496 | 497 | This is similar to "smart quotes", but applied to the characters in 498 | |'delimitMate_matchpairs'|. The difference is that delimitMate will not 499 | auto-close the pair when the regex matches the text on the right of the 500 | cursor. See |'delimitMate_smart_matchpairs'| for more details. 501 | 502 | 503 | e.g. typing at the "|": > 504 | 505 | What | Before | After 506 | ======================================= 507 | ( | function| | function(|) 508 | ( | |var | (|var 509 | < 510 | ------------------------------------------------------------------------------ 511 | 3.5 BALANCING MATCHING PAIRS *delimitMateBalance* 512 | 513 | When inserting an opening paren and |'delimitMate_balance_matchpairs'| is 514 | enabled, delimitMate will try to balance the closing pairs in the current 515 | line. 516 | 517 | e.g. typing at the "|": > 518 | 519 | What | Before | After 520 | ======================================= 521 | ( | | | (|) 522 | ( | |) | (|) 523 | (( | |) | ((|)) 524 | < 525 | ------------------------------------------------------------------------------ 526 | 3.6 FILE TYPE BASED CONFIGURATION *delimitMateFileType* 527 | 528 | delimitMate options can be set globally for all buffers using global 529 | ("regular") variables in your |vimrc| file. But |:autocmd| can be used to set 530 | options for specific file types (see |'filetype'|) using buffer variables in 531 | the following way: > 532 | 533 | au FileType mail,text let b:delimitMate_autoclose = 0 534 | ^ ^ ^ ^ ^ 535 | | | | | | 536 | | | | | - Option value. 537 | | | | - Option name. 538 | | | - Buffer variable. 539 | | - File types for which the option will be set. 540 | - Don't forget to put this event. 541 | < 542 | NOTE that you should use buffer variables (|b:var|) only to set options with 543 | |:autocmd|, for global options use regular variables (|g:var|) in your vimrc. 544 | 545 | ------------------------------------------------------------------------------ 546 | 3.7 SYNTAX AWARENESS *delimitMateSyntax* 547 | 548 | The features of this plug-in might not be always helpful, comments and strings 549 | usualy don't need auto-completion. delimitMate monitors which region is being 550 | edited and if it detects that the cursor is in a comment it'll turn itself off 551 | until the cursor leaves the comment. The excluded regions can be set using the 552 | option |'delimitMate_excluded_regions'|. Read |group-name| for a list of 553 | regions or syntax group names. 554 | 555 | NOTE that this feature relies on a proper syntax file for the current file 556 | type, if the appropiate syntax file doesn't define a region, delimitMate won't 557 | know about it. 558 | 559 | ============================================================================== 560 | 4. COMMANDS *delimitMateCommands* 561 | 562 | ------------------------------------------------------------------------------ 563 | :DelimitMateReload *:DelimitMateReload* 564 | 565 | Re-sets all the mappings used for this script, use it if any option has been 566 | changed or if the filetype option hasn't been set yet. 567 | 568 | ------------------------------------------------------------------------------ 569 | :DelimitMateOn *:DelimitMateOn* 570 | 571 | Enable delimitMate mappings. 572 | 573 | ------------------------------------------------------------------------------ 574 | :DelimitMateOff *:DelimitMateOff* 575 | 576 | Disable delimitMate mappings. 577 | 578 | ------------------------------------------------------------------------------ 579 | :DelimitMateSwitch *:DelimitMateSwitch* 580 | 581 | Switches the plug-in on and off. 582 | 583 | ------------------------------------------------------------------------------ 584 | :DelimitMateTest *:DelimitMateTest* 585 | 586 | This command tests every mapping set-up for this script, useful for testing 587 | custom configurations. 588 | 589 | The following output corresponds to the default values, it will be different 590 | depending on your configuration. "Open & close:" represents the final result 591 | when the closing delimiter has been inserted, either manually or 592 | automatically, see |delimitMateExpansion|. "Delete:" typing backspace in an 593 | empty pair, see |delimitMateBackspace|. "Exit:" typing a closing delimiter 594 | inside a pair of delimiters, see |delimitMateAutoclose|. "Space:" the 595 | expansion, if any, of space, see |delimitMateExpansion|. "Visual-L", 596 | "Visual-R" and "Visual" shows visual wrapping, see 597 | |delimitMateVisualWrapping|. "Car return:" the expansion of car return, see 598 | |delimitMateExpansion|. The cursor's position at the end of every test is 599 | represented by an "|": > 600 | 601 | * AUTOCLOSE: 602 | Open & close: (|) 603 | Delete: | 604 | Exit: ()| 605 | Space: ( |) 606 | Visual-L: (v) 607 | Visual-R: (v) 608 | Car return: ( 609 | |) 610 | 611 | Open & close: {|} 612 | Delete: | 613 | Exit: {}| 614 | Space: { |} 615 | Visual-L: {v} 616 | Visual-R: {v} 617 | Car return: { 618 | |} 619 | 620 | Open & close: [|] 621 | Delete: | 622 | Exit: []| 623 | Space: [ |] 624 | Visual-L: [v] 625 | Visual-R: [v] 626 | Car return: [ 627 | |] 628 | 629 | Open & close: "|" 630 | Delete: | 631 | Exit: ""| 632 | Space: " |" 633 | Visual: "v" 634 | Car return: " 635 | |" 636 | 637 | Open & close: '|' 638 | Delete: | 639 | Exit: ''| 640 | Space: ' |' 641 | Visual: 'v' 642 | Car return: ' 643 | |' 644 | 645 | Open & close: `|` 646 | Delete: | 647 | Exit: ``| 648 | Space: ` |` 649 | Visual: `v` 650 | Car return: ` 651 | |` 652 | < 653 | 654 | ============================================================================== 655 | 5. MAPPINGS *delimitMateMappings* 656 | 657 | delimitMate doesn't override any existing map, so you may encounter that it 658 | doesn't work as expected because a mapping is missing. In that case, the 659 | conflicting mappings should be resolved by either disabling the conflicting 660 | mapping or creating a custom mappings. 661 | 662 | In order to make custom mappings easier and prevent overwritting existing 663 | ones, delimitMate uses the || + |hasmapto()| (|usr_41.txt|) construct 664 | for its mappings. 665 | 666 | These are the default mappings for the extra features: 667 | 668 | is mapped to delimitMateBS 669 | is mapped to delimitMateS-BS 670 | is mapped to delimitMateS-Tab 671 | g is mapped to delimitMateJumpMany 672 | 673 | The rest of the mappings correspond to parens, quotes, CR, Space, etc. and they 674 | depend on the values of the delimitMate options, they have the following form: 675 | 676 | delimitMate + char 677 | 678 | e.g.: for "(": 679 | 680 | ( is mapped to delimitMate( 681 | 682 | e.g.: If you have expansion enabled, you might want to skip it on pop-up 683 | menus: 684 | 685 | imap pumvisible() 686 | \ ? "\" 687 | \ : "delimitMateCR" 688 | 689 | 690 | ============================================================================== 691 | 6. FUNCTIONS *delimitMateFunctions* 692 | 693 | ------------------------------------------------------------------------------ 694 | delimitMate#WithinEmptyPair() *delimitMate#WithinEmptyPair()* 695 | 696 | Returns 1 if the cursor is inside an empty pair, 0 otherwise. 697 | e.g.: > 698 | 699 | inoremap delimitMate#WithinEmptyPair() ? 700 | \ "delimitMateCR" : 701 | \ "external_mapping" 702 | < 703 | 704 | ------------------------------------------------------------------------------ 705 | delimitMate#ShouldJump() *delimitMate#ShouldJump()* 706 | 707 | Returns 1 if there is a closing delimiter or a quote to the right of the 708 | cursor, 0 otherwise. 709 | 710 | ------------------------------------------------------------------------------ 711 | delimitMate#JumpAny() *delimitMate#JumpAny()* 712 | 713 | This function returns a mapping that will make the cursor jump to the right 714 | when delimitMate#ShouldJump() returns 1, returns the argument "key" otherwise. 715 | e.g.: You can use this to create your own mapping to jump over any delimiter. 716 | > 717 | inoremap delimitMate#JumpAny() 718 | < 719 | ============================================================================== 720 | 7. AUTOCOMMANDS *delimitMateAutocmds* 721 | 722 | delimitMate emits 2 |User| autocommands to make it easier for users to 723 | leverage delimitMate's support for per-filetype customization. 724 | 725 | ------------------------------------------------------------------------------ 726 | delimitMate_map *delimitMate_map* 727 | 728 | This |User| event is emittted just prior to delimitMate defining its 729 | buffer-local key mappings. You can use this command to define your own 730 | mappings that are disabled when delimitMate is turned off or excludes the 731 | current filetype. 732 | > 733 | au User delimitMate_map call s:delimitMate_map() 734 | function s:delimitMate_map() 735 | imap delimitMate#JumpAny() 736 | endfunction 737 | < 738 | ------------------------------------------------------------------------------ 739 | delimitMate_unmap *delimitMate_unmap* 740 | 741 | This |User| event is emitted just after delimitMate clears its buffer-local 742 | key mappings. You can use this command to clear your own mappings that you set 743 | in response to |delimitMate_map|. 744 | > 745 | au User delimitMate_unmap call s:delimitMate_unmap() 746 | function s:delimitMate_unmap() 747 | silent! iunmap 748 | endfunction 749 | < 750 | Note: This event may be emitted before |delimitMate_map|, and may be emitted 751 | multiple times in a row without any intervening |delimitMate_map| events. 752 | 753 | ============================================================================== 754 | 8. TODO LIST *delimitMateTodo* 755 | 756 | - Automatic set-up by file type. 757 | - Make block-wise visual wrapping work on un-even regions. 758 | 759 | ============================================================================== 760 | 9. MAINTAINER *delimitMateMaintainer* 761 | 762 | Hi there! My name is Israel Chauca F. and I can be reached at: 763 | mailto:israelchauca@gmail.com 764 | 765 | Feel free to send me any suggestions and/or comments about this plugin, I'll 766 | be very pleased to read them. 767 | 768 | ============================================================================== 769 | 10. CREDITS *delimitMateCredits* 770 | 771 | Contributors: ~ 772 | 773 | - Kim Silkebækken ~ 774 | Fixed mappings being echoed in the terminal. 775 | 776 | - Eric Van Dewoestine ~ 777 | Implemented smart matchpairs. 778 | 779 | Some of the code that makes this script was modified or just shamelessly 780 | copied from the following sources: 781 | 782 | - Ian McCracken ~ 783 | Post titled: Vim, Part II: Matching Pairs: 784 | http://concisionandconcinnity.blogspot.com/ 785 | 786 | - Aristotle Pagaltzis ~ 787 | From the comments on the previous blog post and from: 788 | http://gist.github.com/144619 789 | 790 | - Karl Guertin ~ 791 | AutoClose: 792 | http://www.vim.org/scripts/script.php?script_id=1849 793 | 794 | - Thiago Alves ~ 795 | AutoClose: 796 | http://www.vim.org/scripts/script.php?script_id=2009 797 | 798 | - Edoardo Vacchi ~ 799 | ClosePairs: 800 | http://www.vim.org/scripts/script.php?script_id=2373 801 | 802 | This script was inspired by the auto-completion of delimiters on TextMate. 803 | 804 | ============================================================================== 805 | 11. HISTORY *delimitMateHistory* 806 | 807 | Version Date Release notes ~ 808 | |---------|------------|-----------------------------------------------------| 809 | 2.8 2013-07-15 * Current release: 810 | - Add :DelimitMateOn & :DelimitMateOff. 811 | |---------|------------|-----------------------------------------------------| 812 | 2.7 2013-07-15 * - Lots of bug fixes. 813 | - Add delimitMate_offByDefault. 814 | - Add delimitMate_eol_marker. 815 | - Reduce the number of mappings. 816 | - Stop using setline(). 817 | - Better handling of nested quotes. 818 | - Allow a custom pattern for smart_quotes. 819 | |---------|------------|-----------------------------------------------------| 820 | 2.6 2011-01-14 * - Add smart_matchpairs feature. 821 | - Add mapping to jump over contiguous delimiters. 822 | - Fix behaviour of b:loaded_delimitMate. 823 | |---------|------------|-----------------------------------------------------| 824 | 2.5.1 2010-09-30 * - Remove visual wrapping. Surround.vim offers a much 825 | better implementation. 826 | - Minor mods to DelimitMateTest. 827 | |---------|------------|-----------------------------------------------------| 828 | 2.5 2010-09-22 * - Better handling of mappings. 829 | - Add report for mappings in |:DelimitMateTest|. 830 | - Allow the use of "|" and multi-byte characters in 831 | |'delimitMate_quotes'| and |'delimitMate_matchpairs'|. 832 | - Allow commands to be concatenated using |. 833 | |---------|------------|-----------------------------------------------------| 834 | 2.4.1 2010-07-31 * - Fix problem with and . 835 | - Add missing doc on |'delimitMate_smart_quotes'|, 836 | |delimitMateBalance| and 837 | |'delimitMate_balance_matchpairs'|. 838 | |---------|------------|-----------------------------------------------------| 839 | 2.4 2010-07-29 * - Unbalanced parens: see :help delimitMateBalance. 840 | - Visual wrapping now works on block-wise visual 841 | with some limitations. 842 | - Arrow keys didn't work on terminal. 843 | - Added option to allow nested quotes. 844 | - Expand Smart Quotes to look for a string on the 845 | right of the cursor. 846 | 847 | |---------|------------|-----------------------------------------------------| 848 | 2.3.1 2010-06-06 * - Fix: an extra is inserted after 849 | expansion. 850 | 851 | |---------|------------|-----------------------------------------------------| 852 | 2.3 2010-06-06 * - Syntax aware: Will turn off when editing comments 853 | or other regions, customizable. 854 | - Changed format of most mappings. 855 | - Fix: expansion doesn't break automatic 856 | indentation adjustments anymore. 857 | - Fix: Arrow keys would insert A, B, C or D instead 858 | of moving the cursor when using Vim on a terminal. 859 | 860 | |---------|------------|-----------------------------------------------------| 861 | 2.2 2010-05-16 * - Added command to switch the plug-in on and off. 862 | - Fix: some problems with , and . 863 | - Fix: A small problem when inserting a delimiter at 864 | the beginning of the line. 865 | 866 | |---------|------------|-----------------------------------------------------| 867 | 2.1 2010-05-10 * - Most of the functions have been moved to an 868 | autoload script to avoid loading unnecessary ones. 869 | - Fixed a problem with the redo command. 870 | - Many small fixes. 871 | 872 | |---------|------------|-----------------------------------------------------| 873 | 2.0 2010-04-01 * New features: 874 | - All features are redo/undo-wise safe. 875 | - A single quote typed after an alphanumeric 876 | character is considered an apostrophe and one 877 | single quote is inserted. 878 | - A quote typed after another quote inserts a single 879 | quote and the cursor jumps to the middle. 880 | - jumps out of any empty pair. 881 | - and expansions are fixed, but the 882 | functions used for it are global and can be used in 883 | custom mappings. The previous system is still 884 | active if you have any of the expansion options 885 | set. 886 | - deletes the closing delimiter. 887 | * Fixed bug: 888 | - s:vars were being used to store buffer options. 889 | 890 | |---------|------------|-----------------------------------------------------| 891 | 1.6 2009-10-10 * Now delimitMate tries to fix the balancing of single 892 | quotes when used as apostrophes. You can read 893 | |delimitMate_apostrophes| for details. 894 | Fixed an error when |b:delimitMate_expand_space| 895 | wasn't set but |delimitMate_expand_space| wasn't. 896 | 897 | |---------|------------|-----------------------------------------------------| 898 | 1.5 2009-10-05 * Fix: delimitMate should work correctly for files 899 | passed as arguments to Vim. Thanks to Ben Beuchler 900 | for helping to nail this bug. 901 | 902 | |---------|------------|-----------------------------------------------------| 903 | 1.4 2009-09-27 * Fix: delimitMate is now enabled on new buffers even 904 | if they don't have set the file type option or were 905 | opened directly from the terminal. 906 | 907 | |---------|------------|-----------------------------------------------------| 908 | 1.3 2009-09-24 * Now local options can be used along with autocmd 909 | for specific file type configurations. 910 | Fixes: 911 | - Unnamed register content is not lost on visual 912 | mode. 913 | - Use noremap where appropiate. 914 | - Wrapping a single empty line works as expected. 915 | 916 | |---------|------------|-----------------------------------------------------| 917 | 1.2 2009-09-07 * Fixes: 918 | - When inside nested empty pairs, deleting the 919 | innermost left delimiter would delete all right 920 | contiguous delimiters. 921 | - When inside an empty pair, inserting a left 922 | delimiter wouldn't insert the right one, instead 923 | the cursor would jump to the right. 924 | - New buffer inside the current window wouldn't 925 | have the mappings set. 926 | 927 | |---------|------------|-----------------------------------------------------| 928 | 1.1 2009-08-25 * Fixed an error that ocurred when mapleader wasn't 929 | set and added support for GetLatestScripts 930 | auto-detection. 931 | 932 | |---------|------------|-----------------------------------------------------| 933 | 1.0 2009-08-23 * Initial upload. 934 | 935 | |---------|------------|-----------------------------------------------------| 936 | 937 | 938 | `\|||/´ MMM \|/ www __^__ ~ 939 | (o o) (o o) @ @ (O-O) /(o o)\\ ~ 940 | ooO_(_)_Ooo__ ooO_(_)_Ooo___oOO_(_)_OOo___oOO__(_)__OOo___oOO__(_)__OOo_____ ~ 941 | _____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|____ ~ 942 | __|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_ ~ 943 | _____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|_____|____ ~ 944 | 945 | vim:tw=78:et:ts=8:sw=2:ft=help:norl:formatoptions+=tcroqn:autoindent: 946 | -------------------------------------------------------------------------------- /plugin/delimitMate.vim: -------------------------------------------------------------------------------- 1 | " File: plugin/delimitMate.vim 2 | " Version: 2.7 3 | " Modified: 2013-07-15 4 | " Description: This plugin provides auto-completion for quotes, parens, etc. 5 | " Maintainer: Israel Chauca F. 6 | " Manual: Read ":help delimitMate". 7 | " ============================================================================ 8 | 9 | " Initialization: {{{ 10 | 11 | if exists("g:loaded_delimitMate") || &cp 12 | " User doesn't want this plugin or compatible is set, let's get out! 13 | finish 14 | endif 15 | let g:loaded_delimitMate = 1 16 | let save_cpo = &cpo 17 | set cpo&vim 18 | 19 | if v:version < 700 20 | echoerr "delimitMate: this plugin requires vim >= 7!" 21 | finish 22 | endif 23 | 24 | let s:loaded_delimitMate = 1 25 | let delimitMate_version = "2.8" 26 | 27 | "}}} 28 | 29 | " Functions: {{{ 30 | 31 | function! s:option_init(name, default) "{{{ 32 | let opt_name = "delimitMate_" . a:name 33 | " Find value to use. 34 | if !has_key(b:, opt_name) && !has_key(g:, opt_name) 35 | let value = a:default 36 | elseif has_key(b:, opt_name) 37 | let value = b:[opt_name] 38 | else 39 | let value = g:[opt_name] 40 | endif 41 | call s:set(a:name, value) 42 | endfunction "}}} 43 | 44 | function! s:init() "{{{ 45 | " Initialize variables: 46 | " autoclose 47 | call s:option_init("autoclose", 1) 48 | " matchpairs 49 | call s:option_init("matchpairs", string(&matchpairs)[1:-2]) 50 | call s:option_init("matchpairs_list", map(split(s:get('matchpairs', ''), '.:.\zs,\ze.:.'), 'split(v:val, ''^.\zs:\ze.$'')')) 51 | let pairs = s:get('matchpairs_list', []) 52 | if len(filter(pairs, 'v:val[0] ==# v:val[1]')) 53 | echohl ErrorMsg 54 | echom 'delimitMate: each member of a pair in delimitMate_matchpairs must be different from each other.' 55 | echom 'delimitMate: invalid pairs: ' . join(map(pairs, 'join(v:val, ":")'), ', ') 56 | echohl Normal 57 | return 0 58 | endif 59 | call s:option_init("left_delims", map(copy(s:get('matchpairs_list', [])), 'v:val[0]')) 60 | call s:option_init("right_delims", map(copy(s:get('matchpairs_list', [])), 'v:val[1]')) 61 | " quotes 62 | call s:option_init("quotes", "\" ' `") 63 | call s:option_init("quotes_list",split(s:get('quotes', ''), '\s\+')) 64 | " nesting_quotes 65 | call s:option_init("nesting_quotes", []) 66 | " excluded_regions 67 | call s:option_init("excluded_regions", "Comment") 68 | call s:option_init("excluded_regions_list", split(s:get('excluded_regions', ''), ',\s*')) 69 | let enabled = len(s:get('excluded_regions_list', [])) > 0 70 | call s:option_init("excluded_regions_enabled", enabled) 71 | " expand_space 72 | if exists("b:delimitMate_expand_space") && type(b:delimitMate_expand_space) == type("") 73 | echom "b:delimitMate_expand_space is '".b:delimitMate_expand_space."' but it must be either 1 or 0!" 74 | echom "Read :help 'delimitMate_expand_space' for more details." 75 | unlet b:delimitMate_expand_space 76 | let b:delimitMate_expand_space = 1 77 | endif 78 | if exists("g:delimitMate_expand_space") && type(g:delimitMate_expand_space) == type("") 79 | echom "delimitMate_expand_space is '".g:delimitMate_expand_space."' but it must be either 1 or 0!" 80 | echom "Read :help 'delimitMate_expand_space' for more details." 81 | unlet g:delimitMate_expand_space 82 | let g:delimitMate_expand_space = 1 83 | endif 84 | call s:option_init("expand_space", 0) 85 | " expand_cr 86 | if exists("b:delimitMate_expand_cr") && type(b:delimitMate_expand_cr) == type("") 87 | echom "b:delimitMate_expand_cr is '".b:delimitMate_expand_cr."' but it must be either 1 or 0!" 88 | echom "Read :help 'delimitMate_expand_cr' for more details." 89 | unlet b:delimitMate_expand_cr 90 | let b:delimitMate_expand_cr = 1 91 | endif 92 | if exists("g:delimitMate_expand_cr") && type(g:delimitMate_expand_cr) == type("") 93 | echom "delimitMate_expand_cr is '".g:delimitMate_expand_cr."' but it must be either 1 or 0!" 94 | echom "Read :help 'delimitMate_expand_cr' for more details." 95 | unlet g:delimitMate_expand_cr 96 | let g:delimitMate_expand_cr = 1 97 | endif 98 | if ((&backspace !~ 'eol' || &backspace !~ 'start') && &backspace != 2) && 99 | \ ((exists('b:delimitMate_expand_cr') && b:delimitMate_expand_cr == 1) || 100 | \ (exists('g:delimitMate_expand_cr') && g:delimitMate_expand_cr == 1)) 101 | echom "delimitMate: There seems to be some incompatibility with your settings that may interfer with the expansion of . See :help 'delimitMate_expand_cr' for details." 102 | endif 103 | call s:option_init("expand_cr", 0) 104 | " expand_in_quotes 105 | call s:option_init('expand_inside_quotes', 0) 106 | " jump_expansion 107 | call s:option_init("jump_expansion", 0) 108 | " smart_matchpairs 109 | call s:option_init("smart_matchpairs", '^\%(\w\|\!\|[£$]\|[^[:punct:][:space:]]\)') 110 | " smart_quotes 111 | " XXX: backward compatibility. Ugly, should go the way of the dodo soon. 112 | let quotes = escape(join(s:get('quotes_list', []), ''), '\-^[]') 113 | let default_smart_quotes = '\%(\w\|[^[:punct:][:space:]' . quotes . ']\|\%(\\\\\)*\\\)\%#\|\%#\%(\w\|[^[:space:][:punct:]' . quotes . ']\)' 114 | if exists('g:delimitMate_smart_quotes') && type(g:delimitMate_smart_quotes) == type(0) 115 | if g:delimitMate_smart_quotes 116 | unlet g:delimitMate_smart_quotes 117 | else 118 | unlet g:delimitMate_smart_quotes 119 | let g:delimitMate_smart_quotes = '' 120 | endif 121 | endif 122 | if exists('b:delimitMate_smart_quotes') && type(b:delimitMate_smart_quotes) == type(0) 123 | if b:delimitMate_smart_quotes 124 | unlet b:delimitMate_smart_quotes 125 | if exists('g:delimitMate_smart_quotes') && type(g:delimitMate_smart_quotes) && g:delimitMate_smart_quotes 126 | let b:delimitMate_smart_quotes = default_smart_quotes 127 | endif 128 | else 129 | unlet b:delimitMate_smart_quotes 130 | let b:delimitMate_smart_quotes = '' 131 | endif 132 | endif 133 | call s:option_init("smart_quotes", default_smart_quotes) 134 | " apostrophes 135 | call s:option_init("apostrophes", "") 136 | call s:option_init("apostrophes_list", split(s:get('apostrophes', ''), ":\s*")) 137 | " tab2exit 138 | call s:option_init("tab2exit", 1) 139 | " balance_matchpairs 140 | call s:option_init("balance_matchpairs", 0) 141 | " eol marker 142 | call s:option_init("insert_eol_marker", 1) 143 | call s:option_init("eol_marker", "") 144 | " Everything is fine. 145 | return 1 146 | endfunction "}}} Init() 147 | 148 | function! s:get(name, default) "{{{ 149 | let bufoptions = delimitMate#Get() 150 | return get(bufoptions, a:name, a:default) 151 | endfunction "}}} 152 | 153 | function! s:set(...) " {{{ 154 | return call('delimitMate#Set', a:000) 155 | endfunction " }}} 156 | 157 | function! s:Map() "{{{ 158 | " Set mappings: 159 | try 160 | let save_keymap = &keymap 161 | let save_iminsert = &iminsert 162 | let save_imsearch = &imsearch 163 | let save_cpo = &cpo 164 | set keymap= 165 | set cpo&vim 166 | silent! doautocmd User delimitMate_map 167 | if s:get('autoclose', 1) 168 | call s:AutoClose() 169 | else 170 | call s:NoAutoClose() 171 | endif 172 | call s:ExtraMappings() 173 | finally 174 | let &cpo = save_cpo 175 | let &keymap = save_keymap 176 | let &iminsert = save_iminsert 177 | let &imsearch = save_imsearch 178 | endtry 179 | 180 | let b:delimitMate_enabled = 1 181 | endfunction "}}} Map() 182 | 183 | function! s:Unmap() " {{{ 184 | let imaps = 185 | \ s:get('right_delims', []) + 186 | \ s:get('left_delims', []) + 187 | \ s:get('quotes_list', []) + 188 | \ s:get('apostrophes_list', []) + 189 | \ ['', '', '', '', '', '', '', ''] + 190 | \ ['', '', '', '', '', ''] + 191 | \ ['', ''] + 192 | \ ['', '', '', '', '', '', 'g'] 193 | 194 | for map in imaps 195 | if maparg(map, "i") =~# '^delimitMate' 196 | if map == '|' 197 | let map = '' 198 | endif 199 | exec 'silent! iunmap ' . map 200 | endif 201 | endfor 202 | silent! doautocmd User delimitMate_unmap 203 | let b:delimitMate_enabled = 0 204 | endfunction " }}} s:Unmap() 205 | 206 | function! s:test() "{{{ 207 | if &modified 208 | let confirm = input("Modified buffer, type \"yes\" to write and proceed " 209 | \ . "with test: ") ==? 'yes' 210 | if !confirm 211 | return 212 | endif 213 | endif 214 | call delimitMate#Test() 215 | g/\%^$/d 216 | 0 217 | endfunction "}}} 218 | 219 | function! s:setup(...) "{{{ 220 | let swap = a:0 && a:1 == 2 221 | let enable = a:0 && a:1 222 | let disable = a:0 && !a:1 223 | " First, remove all magic, if needed: 224 | if get(b:, 'delimitMate_enabled', 0) 225 | call s:Unmap() 226 | " Switch 227 | if swap 228 | echo "delimitMate is disabled." 229 | return 230 | endif 231 | endif 232 | if disable 233 | " Just disable the mappings. 234 | return 235 | endif 236 | if !a:0 237 | " Check if this file type is excluded: 238 | if exists("g:delimitMate_excluded_ft") && 239 | \ index(split(g:delimitMate_excluded_ft, ','), &filetype, 0, 1) >= 0 240 | " Finish here: 241 | return 1 242 | endif 243 | " Check if user tried to disable using b:loaded_delimitMate 244 | if exists("b:loaded_delimitMate") 245 | return 1 246 | endif 247 | endif 248 | " Initialize settings: 249 | if ! s:init() 250 | " Something went wrong. 251 | return 252 | endif 253 | if enable || swap || !get(g:, 'delimitMate_offByDefault', 0) 254 | " Now, add magic: 255 | call s:Map() 256 | if a:0 257 | echo "delimitMate is enabled." 258 | endif 259 | endif 260 | endfunction "}}} 261 | 262 | function! s:TriggerAbb() "{{{ 263 | if v:version < 703 264 | \ || ( v:version == 703 && !has('patch489') ) 265 | \ || pumvisible() 266 | return '' 267 | endif 268 | return "\" 269 | endfunction "}}} 270 | 271 | function! s:NoAutoClose() "{{{ 272 | " inoremap ) =delimitMate#SkipDelim('\)') 273 | for delim in s:get('right_delims', []) + s:get('quotes_list', []) 274 | if delim == '|' 275 | let delim = '' 276 | endif 277 | exec 'inoremap delimitMate' . delim . ' =TriggerAbb().delimitMate#SkipDelim("' . escape(delim,'"') . '")' 278 | exec 'silent! imap '.delim.' delimitMate'.delim 279 | endfor 280 | endfunction "}}} 281 | 282 | function! s:AutoClose() "{{{ 283 | " Add matching pair and jump to the midle: 284 | " inoremap ( () 285 | let i = 0 286 | while i < len(s:get('matchpairs_list', [])) 287 | let ld = s:get('left_delims', [])[i] == '|' ? '' : s:get('left_delims', [])[i] 288 | let rd = s:get('right_delims', [])[i] == '|' ? '' : s:get('right_delims', [])[i] 289 | exec 'inoremap delimitMate' . ld 290 | \. ' TriggerAbb().delimitMate#ParenDelim("' . escape(rd, '|') . '")' 291 | exec 'silent! imap '.ld 292 | \.' delimitMate'.ld 293 | let i += 1 294 | endwhile 295 | 296 | " Exit from inside the matching pair: 297 | for delim in s:get('right_delims', []) 298 | let delim = delim == '|' ? '' : delim 299 | exec 'inoremap delimitMate' . delim 300 | \. ' TriggerAbb().delimitMate#JumpOut("\' . delim . '")' 301 | exec 'silent! imap ' . delim 302 | \. ' delimitMate'. delim 303 | endfor 304 | 305 | " Add matching quote and jump to the midle, or exit if inside a pair of matching quotes: 306 | " inoremap " =delimitMate#QuoteDelim("\"") 307 | for delim in s:get('quotes_list', []) 308 | if delim == '|' 309 | let delim = '' 310 | endif 311 | exec 'inoremap delimitMate' . delim 312 | \. ' TriggerAbb()."=delimitMate#QuoteDelim(\"\\\' . delim . '\")"' 313 | exec 'silent! imap ' . delim 314 | \. ' delimitMate' . delim 315 | endfor 316 | 317 | " Try to fix the use of apostrophes (kept for backward compatibility): 318 | " inoremap n't n't 319 | for map in s:get('apostrophes_list', []) 320 | exec "inoremap " . map . " " . map 321 | exec 'silent! imap ' . map . ' delimitMate' . map 322 | endfor 323 | endfunction "}}} 324 | 325 | function! s:ExtraMappings() "{{{ 326 | " If pair is empty, delete both delimiters: 327 | inoremap delimitMateBS =delimitMate#BS() 328 | if !hasmapto('delimitMateBS','i') 329 | if empty(maparg('', 'i')) 330 | silent! imap delimitMateBS 331 | endif 332 | if empty(maparg('', 'i')) 333 | silent! imap delimitMateBS 334 | endif 335 | endif 336 | " If pair is empty, delete closing delimiter: 337 | inoremap delimitMateS-BS delimitMate#WithinEmptyPair() ? "\" : "\" 338 | if !hasmapto('delimitMateS-BS','i') && maparg('', 'i') == '' 339 | silent! imap delimitMateS-BS 340 | endif 341 | " Expand return if inside an empty pair: 342 | inoremap delimitMateCR TriggerAbb()."\=delimitMate#ExpandReturn()\" 343 | if s:get('expand_cr', 0) && !hasmapto('delimitMateCR', 'i') && maparg('', 'i') == '' 344 | silent! imap delimitMateCR 345 | endif 346 | " Expand space if inside an empty pair: 347 | inoremap delimitMateSpace TriggerAbb()."\=delimitMate#ExpandSpace()\" 348 | if s:get('expand_space', 0) && !hasmapto('delimitMateSpace', 'i') && maparg('', 'i') == '' 349 | silent! imap delimitMateSpace 350 | endif 351 | " Jump over any delimiter: 352 | inoremap delimitMateS-Tab TriggerAbb()."\=delimitMate#JumpAny()\" 353 | if s:get('tab2exit', 0) && !hasmapto('delimitMateS-Tab', 'i') && maparg('', 'i') == '' 354 | silent! imap delimitMateS-Tab 355 | endif 356 | " Jump over next delimiters 357 | inoremap delimitMateJumpMany TriggerAbb()."\=delimitMate#JumpMany()\" 358 | if !hasmapto('delimitMateJumpMany', 'i') && maparg("g", 'i') == '' 359 | imap g delimitMateJumpMany 360 | endif 361 | endfunction "}}} 362 | 363 | "}}} 364 | 365 | " Commands: {{{ 366 | 367 | " Let me refresh without re-loading the buffer: 368 | command! -bar DelimitMateReload call s:setup(1) 369 | " Quick test: 370 | command! -bar DelimitMateTest call s:test() 371 | " Switch On/Off: 372 | command! -bar DelimitMateSwitch call s:setup(2) 373 | " Enable mappings: 374 | command! -bar DelimitMateOn call s:setup(1) 375 | " Disable mappings: 376 | command! -bar DelimitMateOff call s:setup(0) 377 | 378 | "}}} 379 | 380 | " Autocommands: {{{ 381 | 382 | augroup delimitMate 383 | au! 384 | " Run on file type change. 385 | au FileType * call setup() 386 | au FileType python let b:delimitMate_nesting_quotes = ['"', "'"] 387 | 388 | " Run on new buffers. 389 | au BufNewFile,BufRead,BufEnter,CmdwinEnter * 390 | \ if !exists('b:delimitMate_was_here') | 391 | \ call setup() | 392 | \ let b:delimitMate_was_here = 1 | 393 | \ endif 394 | augroup END 395 | 396 | "}}} 397 | 398 | " This is for the default buffer when it does not have a filetype. 399 | call s:setup() 400 | 401 | let &cpo = save_cpo 402 | " GetLatestVimScripts: 2754 1 :AutoInstall: delimitMate.vim 403 | " vim:foldmethod=marker:foldcolumn=4:ts=2:sw=2 404 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | all: build/runVimTests 2 | build/runVimTests/bin/runVimTests.sh -0 . 3 | 4 | build/runVimTests: build/VimTAP 5 | git clone https://github.com/inkarkat/runVimTests $@ 6 | 7 | # Use VimTAP as directory name, as used with runVimTestsSetup.vim. 8 | build/VimTAP: 9 | git clone https://github.com/inkarkat/vimtap $@ 10 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # Automatic test setup 2 | You can use `make` (or `make test` from the top level directory) to run the 3 | tests. 4 | 5 | # Manual test setup instructions 6 | The plugins [runVimTests](http://www.vim.org/scripts/script.php?script_id=2565) 7 | and [VimTAP](http://www.vim.org/scripts/script.php?script_id=2213) are needed 8 | to run these tests. 9 | 10 | Besides the `_setup.vim` configuration file present in this repo you need to 11 | create a global one and place it in the same dir where the runVimTests 12 | executable is located. Assuming the executable is at '~/bin/runVimTests' this 13 | global configuration file should be '~/bin/runVimTestsSetup.vim' and should 14 | have something like the following lines inside of it: 15 | 16 | " Prepend tests repos to &rtp 17 | let &runtimepath = '/path/to/runVimTests_dir,' . &rtp 18 | let &runtimepath = '/path/to/vimTAP_dir,' . &rtp 19 | -------------------------------------------------------------------------------- /test/_setup.vim: -------------------------------------------------------------------------------- 1 | let &rtp = expand(':p:h:h') . ',' . &rtp . ',' . expand(':p:h:h') . '/after' 2 | set bs=2 3 | ru plugin/delimitMate.vim 4 | let runVimTests = expand(':p:h').'/build/runVimTests' 5 | if isdirectory(runVimTests) 6 | let &rtp = runVimTests . ',' . &rtp 7 | endif 8 | let vimTAP = expand(':p:h').'/build/VimTAP' 9 | if isdirectory(vimTAP) 10 | let &rtp = vimTAP . ',' . &rtp 11 | endif 12 | 13 | -------------------------------------------------------------------------------- /test/autoclose_matchpairs.txt: -------------------------------------------------------------------------------- 1 | let g:delimitMate_autoclose = 1 2 | "(x" "(x)" 3 | "(\x" "x" 4 | "()x" "()x" 5 | "((\gx" "(())x" 6 | "(x\u" "" 7 | "@(x" "@(x)" 8 | "@#\(x" "@(x)#" 9 | "(\x" "()x" 10 | let g:delimitMate_autoclose = 0 11 | "(x" "(x" 12 | "()x" "(x)" 13 | "())x" "()x" 14 | "()\x" "x" 15 | "@()x" "@(x)" 16 | "@#\()x" "@(x)#" 17 | let g:delimitMate_expand_space = 1 18 | let g:delimitMate_autoclose = 1 19 | "(\x" "( x )" 20 | "(\\x" "(x)" 21 | let g:delimitMate_autoclose = 0 22 | "()\\x" "(x)" 23 | let g:delimitMate_autoclose = 1 24 | # Handle backspace gracefully. 25 | set backspace= 26 | "(\a\x" "(x)" 27 | set bs=2 28 | # closing parens removes characters. #133 29 | "(a\i)" "()a)" 30 | 31 | # Add semicolon next to the closing paren. Issue #77. 32 | new 33 | let b:delimitMate_eol_marker = ';' 34 | "abc(x" "abc(x);" 35 | %d 36 | # BS should behave accordingly. 37 | "abc(\" "abc;" 38 | # Expand iabbreviations 39 | unlet b:delimitMate_eol_marker 40 | iabb def ghi 41 | "def(" "ghi()" 42 | iunabb def 43 | 44 | "abc а\(" "abc (а" 45 | "abc ñ\(" "abc (ñ" 46 | "abc $\(" "abc ($" 47 | "abc £\(" "abc (£" 48 | "abc d\(" "abc (d" 49 | "abc \(\(" "abc ((" 50 | "abc .\(" "abc ()." 51 | "abc \(" "abc () " 52 | -------------------------------------------------------------------------------- /test/autoclose_matchpairs.vim: -------------------------------------------------------------------------------- 1 | let g:delimitMate_matchpairs = '(:),{:},[:],<:>,¿:?,¡:!,,::' 2 | let lines = readfile(expand(':t:r').'.txt') 3 | call vimtest#StartTap() 4 | let testsnumber = len(filter(copy(lines), 'v:val =~ ''^"''')) 5 | let itemsnumber = len(split(g:delimitMate_matchpairs, '.:.\zs,\ze.:.')) 6 | call vimtap#Plan(testsnumber * itemsnumber) 7 | let tcount = 1 8 | let reload = 1 9 | for item in lines 10 | if item =~ '^#\|^\s*$' 11 | " A comment or empty line. 12 | continue 13 | endif 14 | if item !~ '^"' 15 | " A command. 16 | exec item 17 | call vimtap#Diag(item) 18 | let reload = 1 19 | continue 20 | endif 21 | if reload 22 | DelimitMateReload 23 | call vimtap#Diag('DelimitMateReload') 24 | let reload = 0 25 | endif 26 | let [input, output] = split(item, '"\%(\\.\|[^\\"]\)*"\zs\s*\ze"\%(\\.\|[^\\"]\)*"') 27 | for [s:l,s:r] in map(split(g:delimitMate_matchpairs, '.:.\zs,\ze.:.'), 'split(v:val, ''.\zs:\ze.'')') 28 | let input2 = substitute(input, '(', s:l, 'g') 29 | let input2 = substitute(input2, ')', s:r, 'g') 30 | let output2 = substitute(output, '(', s:l, 'g') 31 | let output2 = substitute(output2, ')', s:r, 'g') 32 | %d 33 | exec 'normal i'.eval(input2)."\" 34 | let line = getline('.') 35 | let passed = line == eval(output2) 36 | call vimtap#Is(line, eval(output2), input2) 37 | ", input2 . ' => ' . string(line) . 38 | " \ (passed ? ' =' : ' !') . '= ' . string(eval(output2))) 39 | let tcount += 1 40 | endfor 41 | endfor 42 | call vimtest#Quit() 43 | -------------------------------------------------------------------------------- /test/autoclose_quotes.txt: -------------------------------------------------------------------------------- 1 | let g:delimitMate_autoclose = 1 2 | "'x" "'x'" 3 | "'x\u" "" 4 | "''x" "''x" 5 | "'\x" "x" 6 | "'\gx" "''x" 7 | # This will fail for double quote. 8 | "'\"x" "'\"x\"'" 9 | "@'x" "@'x'" 10 | "@#\'x" "@'x'#" 11 | "'\x" "''x" 12 | "abc'" "abc'" 13 | "abc\\'x" "abc\\'x" 14 | "u'Привет'" "u'Привет'" 15 | "u'string'" "u'string'" 16 | let g:delimitMate_autoclose = 0 17 | "'x" "'x" 18 | "''x" "'x'" 19 | "'''x" "''x" 20 | "''\x" "x" 21 | "@''x" "@'x'" 22 | "@#\''x" "@'x'#" 23 | let g:delimitMate_expand_space = 1 24 | let g:delimitMate_autoclose = 1 25 | "'\x" "' x'" 26 | let g:delimitMate_expand_inside_quotes = 1 27 | "'\x" "' x '" 28 | "'\\x" "'x'" 29 | "abc\\''\x" "abc\\' x'" 30 | let g:delimitMate_autoclose = 0 31 | "''\\x" "'x'" 32 | let g:delimitMate_autoclose = 1 33 | # Handle backspace gracefully. 34 | set backspace= 35 | "'\a\x" "'x'" 36 | set backspace=2 37 | set cpo=ces$ 38 | "'x" "'x'" 39 | # Make sure smart quote works beyond first column. 40 | " 'x" " 'x'" 41 | # smart quote, check fo char on the right. 42 | "a\b\'" "a 'b" 43 | # Make sure we jump over a quote on the right. #89. 44 | "('test'x" "('test'x)" 45 | # Duplicate whole line when inserting quote at bol #105 46 | "}\'" "''}" 47 | "'\abc '" "'abc '" 48 | "''abc '" "''abc ''" 49 | # Nesting quotes: 50 | let g:delimitMate_nesting_quotes = split(g:delimitMate_quotes, '\s\+') 51 | "'''x" "'''x'''" 52 | "''''x" "''''x''''" 53 | "''x" "''x" 54 | "'x" "'x'" 55 | unlet g:delimitMate_nesting_quotes 56 | # expand iabbreviations 57 | iabb def ghi 58 | "def'" "ghi'" 59 | let g:delimitMate_smart_quotes = '\w\%#\_.' 60 | "xyz'x" "xyz'x" 61 | "xyz 'x" "xyz 'x'" 62 | let g:delimitMate_smart_quotes = '\s\%#\_.' 63 | "abc'x" "abc'x'" 64 | "abc 'x" "abc 'x" 65 | # let's try the negated form 66 | let g:delimitMate_smart_quotes = '!\w\%#\_.' 67 | "cba'x" "cba'x'" 68 | "cba 'x" "cba 'x" 69 | let g:delimitMate_smart_quotes = '!\s\%#\_.' 70 | "zyx'x" "zyx'x" 71 | "zyx 'x" "zyx 'x'" 72 | unlet g:delimitMate_smart_quotes 73 | "'\\" "''" 74 | -------------------------------------------------------------------------------- /test/autoclose_quotes.vim: -------------------------------------------------------------------------------- 1 | "let g:delimitMate_quotes = '" '' ` ” « |' 2 | let g:delimitMate_quotes = '" '' ` « |' 3 | let lines = readfile(expand(':t:r').'.txt') 4 | call vimtest#StartTap() 5 | let testsnumber = len(filter(copy(lines), 'v:val =~ ''^"''')) 6 | let itemsnumber = len(split(g:delimitMate_quotes, ' ')) 7 | call vimtap#Plan(testsnumber * itemsnumber) 8 | let reload = 1 9 | let tcount = 1 10 | let linenr = 0 11 | for item in lines 12 | let linenr += 1 13 | if item =~ '^#\|^\s*$' 14 | " A comment or empty line. 15 | continue 16 | endif 17 | if item !~ '^"' 18 | " A command. 19 | exec item 20 | call vimtap#Diag(item) 21 | let reload = 1 22 | continue 23 | endif 24 | if reload 25 | DelimitMateReload 26 | call vimtap#Diag('DelimitMateReload') 27 | let reload = 0 28 | endif 29 | let quotes = split(g:delimitMate_quotes, '\s') 30 | for quote in quotes 31 | if vimtap#Skip(1, tcount != 26, "This test is invalid for double quote.") 32 | let tcount += 1 33 | continue 34 | endif 35 | let [input, output] = split(item, '"\%(\\.\|[^\\"]\)*"\zs\s*\ze"\%(\\.\|[^\\"]\)*"') 36 | let input_q = substitute(input,"'" , escape(escape(quote, '"'), '\'), 'g') 37 | let output_q = substitute(output,"'" , escape(escape(quote, '"'), '\'), 'g') 38 | %d 39 | exec 'normal i'.eval(input_q)."\" 40 | if quote == '”' 41 | call vimtap#Todo(1) 42 | endif 43 | call vimtap#Is(getline('.'), eval(output_q), 'Line '.linenr.': '.eval(substitute(input_q, '\\<', '<','g'))) 44 | let tcount += 1 45 | endfor 46 | endfor 47 | call vimtest#Quit() 48 | -------------------------------------------------------------------------------- /test/eol_marker.vim: -------------------------------------------------------------------------------- 1 | let g:delimitMate_expand_cr = 1 2 | let g:delimitMate_eol_marker = ';' 3 | call vimtest#StartTap() 4 | call vimtap#Plan(8) 5 | " NOTE: Do not forget to update the plan ^ 6 | let g:delimitMate_insert_eol_marker = 0 7 | DelimitMateReload 8 | normal i( 9 | call vimtap#Is(getline(1), '()', 'value = 1, case 1') 10 | %d _ 11 | exec "normal i(\x" 12 | call vimtap#Like(join(getline(1,line('$')), "\"), 13 | \ '^(\n\s*x\n)$', ' "normal i(\x", Value = 2, case 2') 14 | let g:delimitMate_insert_eol_marker = 1 15 | DelimitMateReload 16 | %d _ 17 | normal i( 18 | call vimtap#Is(getline(1), '();', '"normal i(", value = 1, case 1') 19 | %d _ 20 | exec "normal i(\x" 21 | call vimtap#Like(join(getline(1,line('$')), "\"), 22 | \ '^(\n\s*x\n);$', '"normal i(\x", Value = 2, case 2') 23 | %d _ 24 | let g:delimitMate_insert_eol_marker = 2 25 | DelimitMateReload 26 | normal i( 27 | call vimtap#Is(getline(1), '()', '"normal i(", Value = 2, case 1') 28 | %d _ 29 | exec "normal i(\x" 30 | call vimtap#Like(join(getline(1,line('$')), "\"), 31 | \ '^(\n\s*x\n);$', '"normal i(\x", Value = 2, case 2') 32 | 33 | %d _ 34 | exec "normal i{(\x" 35 | call vimtap#Like(join(getline(1,line('$')), "\"), 36 | \ '^{(\n\s*x\n)};$', ' "normal i{(\x", Value = 2, case 3') 37 | 38 | %d _ 39 | exec "normal i;\I{(\x" 40 | call vimtap#Like(join(getline(1,line('$')), "\"), 41 | \ '^{(\n\s*x\n)};$', ' "normal i{(\x", Value = 2, case 4') 42 | 43 | " End: quit vim. 44 | call vimtest#Quit() 45 | -------------------------------------------------------------------------------- /test/expand_cr.txt: -------------------------------------------------------------------------------- 1 | # 2 | %d 3 | filetype indent on 4 | set bs=2 et sts=4 sw=4 ft=javascript 5 | call setline(1, '$(document).ready(function() {})') 6 | DelimitMateReload 7 | exec "normal 31|i\x\" 8 | ================================================================================ 9 | $(document).ready(function() { 10 | x 11 | }) 12 | -------------------------------------------------------------------------------- 13 | # Issue #95 14 | new 15 | let b:delimitMate_jump_expansion = 1 16 | DelimitMateReload 17 | exec "normal i(\test)x" 18 | ================================================================================ 19 | ( 20 | test 21 | )x 22 | -------------------------------------------------------------------------------- 23 | # Remove CR expansion on BS 24 | %d 25 | exec "normal i(\\x" 26 | ================================================================================ 27 | (x) 28 | -------------------------------------------------------------------------------- 29 | # Consider indentation with BS inside an empty CR expansion. 30 | %d 31 | exec "normal i( \\\x" 32 | ================================================================================ 33 | (x) 34 | -------------------------------------------------------------------------------- 35 | # Conflict with indentation settings (cindent). Issue #95 36 | se cindent 37 | call setline(1, ['sub foo {',' while (1) {', ' ', ' }', '}']) 38 | call cursor(3, 8) 39 | normal a}x 40 | ================================================================================ 41 | sub foo { 42 | while (1) { 43 | 44 | }x 45 | } 46 | -------------------------------------------------------------------------------- 47 | %d 48 | call setline(1, '"{bracketed}') 49 | normal A"x 50 | ================================================================================ 51 | "{bracketed}"x 52 | -------------------------------------------------------------------------------- 53 | # Syntax folding enabled by autocmd breaks expansion. But ti can't be tested 54 | # with :normal 55 | new 56 | autocmd InsertEnter * let w:fdm=&foldmethod | setl foldmethod=manual 57 | autocmd InsertLeave * let &foldmethod = w:fdm 58 | set foldmethod=marker 59 | set foldmarker={,} 60 | set foldlevel=0 61 | set backspace=2 62 | exec "normal iabc {\x" 63 | ================================================================================ 64 | abc { 65 | x 66 | } 67 | -------------------------------------------------------------------------------- 68 | # expand_cr != 2 69 | %d_ 70 | call setline(1, 'abc(def)') 71 | exec "normal $i\x" 72 | ================================================================================ 73 | abc(def 74 | x) 75 | -------------------------------------------------------------------------------- 76 | # expand_cr == 2 77 | %d_ 78 | let delimitMate_expand_cr = 2 79 | DelimitMateReload 80 | call setline(1, 'abc(def)') 81 | exec "normal $i\x" 82 | ================================================================================ 83 | abc(def 84 | x 85 | ) 86 | -------------------------------------------------------------------------------- 87 | # Play nice with smartindent 88 | %d_ 89 | set all& 90 | set smartindent 91 | exec "normal $i{\x" 92 | ================================================================================ 93 | { 94 | x 95 | } 96 | -------------------------------------------------------------------------------- 97 | -------------------------------------------------------------------------------- /test/expand_cr.vim: -------------------------------------------------------------------------------- 1 | let g:delimitMate_expand_cr = 1 2 | "DelimitMateReload 3 | let lines = readfile(expand(':t:r').'.txt') 4 | call vimtest#StartTap() 5 | let testsnumber = len(filter(copy(lines), 'v:val =~ ''^=\{80}$''')) 6 | call vimtap#Plan(testsnumber) 7 | let tcount = 1 8 | let expect = 0 9 | let evaluate = 0 10 | let commands = [] 11 | let header = '' 12 | for item in lines 13 | if item =~ '^=\{80}$' 14 | let expect = 1 15 | let expected = [] 16 | continue 17 | endif 18 | 19 | if item =~ '^#' && expect == 0 20 | " A comment. 21 | let header = empty(header) ? item[1:] : 'Lines should match.' 22 | continue 23 | endif 24 | if item =~ '^\s*$' && expect == 0 25 | " An empty line. 26 | continue 27 | endif 28 | if ! expect 29 | " A command. 30 | call add(commands, item) 31 | exec item 32 | "call vimtap#Diag(item) 33 | continue 34 | endif 35 | if item =~ '^-\{80}$' 36 | let expect = 0 37 | endif 38 | if expect 39 | call add(expected, item) 40 | continue 41 | endif 42 | let lines = getline(1, line('$')) 43 | let passed = lines == expected 44 | echom string(lines) 45 | echom string(expected) 46 | call vimtap#Is(lines, expected, header) 47 | echom string(commands) 48 | for cmd in commands 49 | call vimtap#Diag(cmd) 50 | endfor 51 | let commands = [] 52 | let header = '' 53 | let tcount += 1 54 | endfor 55 | call vimtest#Quit() 56 | -------------------------------------------------------------------------------- /test/expand_space.txt: -------------------------------------------------------------------------------- 1 | # Issue #95 2 | new 3 | let b:delimitMate_jump_expansion = 1 4 | DelimitMateReload 5 | exec "normal i( test)x" 6 | ================================================================================ 7 | ( test )x 8 | -------------------------------------------------------------------------------- 9 | -------------------------------------------------------------------------------- /test/expand_space.vim: -------------------------------------------------------------------------------- 1 | let g:delimitMate_expand_space = 1 2 | "DelimitMateReload 3 | let lines = readfile(expand(':t:r').'.txt') 4 | call vimtest#StartTap() 5 | let testsnumber = len(filter(copy(lines), 'v:val =~ ''^=\{80}$''')) 6 | call vimtap#Plan(testsnumber) 7 | let tcount = 1 8 | let expect = 0 9 | let evaluate = 0 10 | for item in lines 11 | if item =~ '^=\{80}$' 12 | let expect = 1 13 | let expected = [] 14 | continue 15 | endif 16 | 17 | if item =~ '^#\|^\s*$' && expect == 0 18 | " A comment or empty line. 19 | continue 20 | endif 21 | if ! expect 22 | " A command. 23 | exec item 24 | call vimtap#Diag(item) 25 | continue 26 | endif 27 | if item =~ '^-\{80}$' 28 | let expect = 0 29 | endif 30 | if expect 31 | call add(expected, item) 32 | continue 33 | endif 34 | let lines = getline(1, line('$')) 35 | let passed = lines == expected 36 | echom string(lines) 37 | echom string(expected) 38 | call vimtap#Ok(passed, string(expected) . 39 | \ (passed ? ' =' : ' !') . '= ' . string(lines)) 40 | let tcount += 1 41 | endfor 42 | call vimtest#Quit() 43 | -------------------------------------------------------------------------------- /test/first_buffer_no_ft.vim: -------------------------------------------------------------------------------- 1 | let g:delimitMate_expand_cr = 1 2 | let g:delimitMate_eol_marker = ';' 3 | call vimtest#StartTap() 4 | call vimtap#Plan(1) 5 | call vimtap#Like(maparg('(', 'i'), 'delimitMate(', 'Mappings defined for the first buffer without filetype set.') 6 | call vimtest#Quit() 7 | 8 | 9 | --------------------------------------------------------------------------------