diff --git a/delimitMate.otl b/delimitMate.otl new file mode 100644 index 0000000..a14781b --- /dev/null +++ b/delimitMate.otl @@ -0,0 +1,9 @@ +[_] 33% Automatic set-up by file type + [X] 100% Customizable expansions + [_] 0% Create list of settings per file type + [_] 0% Use :normal instead for expansions? + +[X] 100% Use escape() + + + diff --git a/delimitMate.txt b/delimitMate.txt new file mode 100644 index 0000000..b9fcd99 --- /dev/null +++ b/delimitMate.txt @@ -0,0 +1,328 @@ +*delimitMate.txt* Trying to keep those beasts at bay! + + + REFERENCE MANUAL * + + +============================================================================== + 0.- CONTENTS *delimitMate-contents* + + 1. Introduction____________________________|delimitMate| + 2. Functionality___________________________|delimitMateFunctionality| + 2.1 Automatic closing & exiting________|delimitMateAutoClose| + 2.2 Expansion of space and CR__________|delimitMateExpansion| + 2.3 Deletion of empty pairs____________|delimitMateBackspace| + 2.4 Visual wrapping____________________|delimitMateVisualWrapping| + 3. Customization___________________________|delimitMateOptions| + 3.1 Option summary_____________________|delimitMateOptionSummary| + 3.2 Options details____________________|delimitMateOptionDetails| + 4. Public command__________________________|delimitMatePublicCommand| + 5. TODO list_______________________________|delimitMateTodo| + 6. The Maintainer__________________________|delimitMateMaintainer| + 7. Credits_________________________________|delimitMateCredits| + + +============================================================================== + 1.- INTRODUCTION *delimitMate* + +What is this "delimitMate"? + +The delimitMate plugin tries to emulate the auto-completion of delimiters that +TextMate provides. The characters used as delimiters can be easily modified, +this allows great flexibility; for example, one set can be used for Tcl and a +different one for HTML. + +============================================================================== + 2. FUNCTIONALITY PROVIDED *delimitMateFunctionality* + +------------------------------------------------------------------------------ + 2.1 AUTOMATIC CLOSING AND EXITING *delimitMateAutoClose* + +With automatic closing enabled, if an opening delimiter is inserted the plugin +inserts the closing delimiter and places the cursor between the pair. With +automatic closing disabled, no closing delimiters is inserted by delimitMate, +but when a pair of delimiters is typed, the cursor is placed in the middle. + +When the cursor is inside an empty pair or located next to the left ofo a +closing delimiter, the cursor is placed outside the pair to the right of the +closing delimiter. + +Unless |delimitMate_matchpairs| is set, this script uses the values in +'&matchpirs' to identify the pairs, and the default value for quotes is +"\" ' ` ", which can also be modified. + +The following table shows the behaviour, this applies to quotes too (the final +position of the cursor is represented by a "|"): + +With auto-close: + Type | You get + ==================== + ( | (|) + –––––––––|–––––––––– + () | ()| + +Without auto-close: + + Type | You get + ==================== + () | (|) + –––––––––|–––––––––– + ()) | ()| + +------------------------------------------------------------------------------ + 2.2 EXPANSION OF SPACE AND CAR RETURN *delimitMateExpansion* + +When the cursor is inside an empty pair of delimiters, space and car return +can be expanded to follow your coding style using |'delimitMate_expand_space'| +and |'delimitMate_expand_return'|. e.g. (cursor represented by a "|"): + +Expand to: + + | You get + ==================================== + (|) | ( | ) + +Expand to: + + | You get + ============================ + (|) | ( + | | + | ) + + +------------------------------------------------------------------------------ + 2.3 DELETION OF EMPTY PAIR *delimitMateBackspace* + +If you press backspace inside an empty pair, both delimiters are deleted. + +e.g.: + + Before | After + ==================================== + call expand(|) | call expand| + + +------------------------------------------------------------------------------ + 2.4 WRAPPING OF VISUAL SELECTION *delimitMateVisualWrapping* + +When visual mode is active this script allows for the selection to be enclosed +with delimiters. But, since brackets have special meaning in visual mode, a +leader ("q" by default) should precede the delimiter. This feature doesn't +currently work on blockwise visual mode, any sugestions are welcome. + +e.g. (selection represented between square brackets): + + Selected text | After q" + ============================================= + An [absurd] example! | An "absurd" example! + +============================================================================== + 3. CUSTOMIZATION *delimitMateOptions* + +------------------------------------------------------------------------------ + 3.1 OPTIONS SUMMARY *delimitMateOptionSummary* + +The behaviour of this script can be customized setting the following options +in your vimrc file. + +|'loaded_delimitMate'| Turns off the script. + +|'delimitMate_autoclose'| Tells delimitMate wether to automagically + insert the closing delimiter. + +|'delimitMate_matchpairs'| Tells delimitMate which characters are + matching pairs. + +|'delimitMate_quotes'| Tells delimitMate which quotes should be + used. + +|'delimitMate_visual_leader'| Sets the leader to be used in visual mode. + +|'delimitMate_expand_return'| Sets the expansion for inside an empty + pair of matching delimiters or quotes. + +|'delimitMate_expand_space'| Sets the expansion for inside an + empty pair of matching delimiters or quotes. + +------------------------------------------------------------------------------ + 3.2 OPTIONS DETAILS *delimitMateOptionDetails* + +Add the shown lines to your vimrc files in order to set the below options. + + *'loaded_delimitMate'* +You can turn off this plugin using this line in your vimrc: > + let loaded_delimitMate = 1 +< +------------------------------------------------------------------------------ + *'delimitMate_autoclose'* +Values: 0 or 1. +Default: 1 + +If this option is set to 0, delimitMate will not add a closing delimiter +automagically. See |delimitMateAutoClose| for details. e.g.: > + let delimitMate_autoclose = 0 +< +------------------------------------------------------------------------------ + *'delimitMate_matchpairs'* +Values: A string with |matchpairs| syntax. +Default: &matchpairs + +Use this option to tell delimitMate which characters should be considered +matching pairs. Read |delimitMateAutoClose| for details. e.g: > + let delimitMate = "(:),[:],{:},<:>" +< +------------------------------------------------------------------------------ + *'delimitMate_quotes'* +Values: A string of characters separated by spaces. +Default: "\" ' `" + +Use this option to tell delimitMate which characters should be considered as +quotes. Read |delimitMateAutoClose| for details. e.g.: > + let delimitMate_quotes = "\" ' ` *" +< +------------------------------------------------------------------------------ + *'delimitMate_visual_leader'* +Values: Any character. +Default: q + +The value of this option will be used to wrap the selection in visual mode +when followed by a delimiter. Read |delimitMateVisualWrap| for details. +e.g: > + let delimitMate_visual_leader = "f" +< +------------------------------------------------------------------------------ + *'delimitMate_expand_return'* +Values: A key mapping. +Default: "\" + +The value of this option will be used to expand the car return character when +typed inside an empty delimiter pair. Read |delimitMateExpansion| for details. +e.g.: > + let delimitMate_expand_return = "\\\" +< +------------------------------------------------------------------------------ + *'delimitMate_expand_space'* +Values: A key mapping. +Default: "\" + +The value of this option will be used to expand the space character when typed +inside an empty delimiter pair. Read |delimitMateExpansion| for details. +e.g.: > + let delimitMate_expand_space = "\\\" +< + +============================================================================== + 4. PUBLIC COMMANDS *delimitMatePublicCommand* + +------------------------------------------------------------------------------ +:DelimitMateReload *:DelimitMateReload* + +Re-sets all the mappings used for this script, use it if any option has been +changed. + +------------------------------------------------------------------------------ +:DelimitMateTest *:DelimitMateTest* + +This command tests every mapping set-up for this script, useful for testing +custom configurations. + +The following output corresponds to the default values, it will be different +depending on your configuration. "Open & close:" represents the final result +when the closing delimiter has been inserted, either manually or +automatically, see |delimitMateExpansion|. "Delete:" typing backspace in an +empty pair, see |delimitMateBackspace|. "Exit:" typing a closing delimiter +inside a pair of delimiters, see |delimitMateAutoclose|. "Space:" the +expansion, if any, of space, see |delimitMateExpansion|. "Visual-L", +"Visual-R" and "Visual" shows visual wrapping, see +|delimitMateVisualWrapping|. "Car return:" the expansion of car return, see +|delimitMateExpansion|. The cursor's position at the end of every test is +represented by an "|": > + + * AUTOCLOSE: + Open & close: (|) + Delete: | + Exit: ()| + Space: ( |) + Visual-L: (v) + Visual-R: (v) + Car return: ( + |) + + Open & close: {|} + Delete: | + Exit: {}| + Space: { |} + Visual-L: {v} + Visual-R: {v} + Car return: { + |} + + Open & close: [|] + Delete: | + Exit: []| + Space: [ |] + Visual-L: [v] + Visual-R: [v] + Car return: [ + |] + + Open & close: "|" + Delete: | + Exit: ""| + Space: " |" + Visual: "v" + Car return: " + |" + + Open & close: '|' + Delete: | + Exit: ''| + Space: ' |' + Visual: 'v' + Car return: ' + |' + + Open & close: `|` + Delete: | + Exit: ``| + Space: ` |` + Visual: `v` + Car return: ` + |` +< + +============================================================================== + 5. TODO LIST *delimitMateTodo* + +- Automatic file type set-up. +- Make visual wrapping work on blockwise visual mode. + +============================================================================== + 6. THE MAINTAINER *delimitMateMaintainer* + +Hi there! My name is Israel Chauca F. and I can be reached at: +israelchauca@gmail.com + +Feel free to send me any suggestions and/or comments about this plugin, I'll +be very pleased to read them. + +============================================================================== + 7. CREDITS *delimitMateCredits* + +Some of the code that make this script is modified or just shamelessly copied +from the following sources: + + - Ian McCracken + Post titled: Vim, Part II: Matching Pairs: + http://concisionandconcinnity.blogspot.com/ + + - Aristotle Pagaltzis + From the comments on the previous blog post and from: + http://gist.github.com/144619 + + - Orestis Markou + Script: simple pairs: + http://www.vim.org/scripts/script.php?script_id=2339 + +vim:tw=78:ts=8:ft=help:norl: diff --git a/delimitMate.vim b/delimitMate.vim index df4efb4..f5102fc 100644 --- a/delimitMate.vim +++ b/delimitMate.vim @@ -1,364 +1,378 @@ -" delimitMate +" =========================================================================== +" File: delimitMate.vim +" Description: This plugin tries to emulate the auto-completion of delimiters +" that TextMate provides. +" Maintainer: Israel Chauca F. +" Credits: Some of the code is modified or just copied from the following: " -" Credit:{{{1 +" - Ian McCracken +" Post titled: Vim, Part II: Matching Pairs: +" http://concisionandconcinnity.blogspot.com/ " -" This script relies on code from the following places: +" - Aristotle Pagaltzis +" From the comments on the previous blog post and from: +" http://gist.github.com/144619 " -" - Ian McCracken -" http://concisionandconcinnity.blogspot.com/2009/07/vim-part-ii-matching-pairs.html -" -" - Aristotle Pagaltzis -" http://concisionandconcinnity.blogspot.com/2009/07/vim-part-ii-matching-pairs.html#comment-6278381178877777788 -" http://gist.github.com/144619 -" -" - Orestis Markou -" http://www.vim.org/scripts/script.php?script_id=2339 -" -" Introduction:{{{1 -" -" This script emulates the auto-complete matching pairs feature of TextMate -" and the behaviour is easily customizable through the use of variables. There -" is an option to prevent the closing delimiter from being automatically -" inserted, in this case the cursor is placed in the middle when the closing -" delimiter is typed, so you get the following behaviours (the cursor = |): -" -" With auto-complete: -" After typing "(|", you get "(|)" -" -" Without auto-complete: -" After typing "()|", you get "(|)" -" -" If visual mode is active and you type a delimiter, the selection will be -" enclosed in matching delimiters. This feature doesn't currently work on -" blockwise visual mode, any sugestion will be welcome. -" -" Options:{{{1 -" -" - Auto-close -" If the variable 'b:delimitMate_autoclose' exists, a value of 1 will activate -" the auto-close feature, 0 will disable it. -" -" let b:delimitMate_autocomplete = 0 -" -" - Matching pairs -" This script will use the delimiters found in the option 'matchpairs' and the -" quotes ", ' and `. -" If the variable 'b:delimitMate_paired_delims' exists, it takes precedence -" over 'matchpairs', so matchpairs values are ignored. Also, keep in mind that -" 'b:delimitMate_paired_delims' content has to follow 'matchpairs' syntax. -" 'b:delimitMate_quote_delims' is used to set the quotes. -" -" autocmd Syntax html,vim set matchpairs+=<:> -" -" let b:delimitMate_paired_delimits = "(:),[:]" -" -" let b:delimitMate_quote_delims = "\",',`,*" -" -" - Leader -" Since () and [] are used in visual mode to modify the selection, this script -" uses a leader when the mentioned mode is active. The default value for the -" leader is the letter q. You can modify this leader using the variable -" 'b:delimitMate_visual_leader'. e.g.: q( would wrap the selection between -" parenthesis. -" -" let b:delimitMate_visual_leader = "f" -" -" - Expansions -" The behaviour of and can be modified when typed inside an empty -" pair of delimiters, set the mappings you want to use in the variable -" 'b:delimitMate_car_return' and/or 'b:delimitMate_space'. -" -" let b:delimitMate_expand_return = '' -" -" let b:delimitMate_expand_space = '' +" - Orestis Markou +" Script 'simple pairs': +" http://www.vim.org/scripts/script.php?script_id=2339 -" Init:{{{1 -if exists("b:loaded_delimitMate") - " finish +if exists("g:loaded_delimitMate") "{{{1 + " Don't define the functions if they already exist: just do the work: + call s:DelimitMateDo() + finish endif if v:version < 700 echoerr "delimitMate: this plugin requires vim >= 7!" finish endif -let b:loaded_delimitMate = 1 -" Functions: +let g:loaded_delimitMate = 1 -" Don't define the functions if they already exist: -if !exists("*s:Init") -" Set user preferences:{{{1 - function! s:Init() - " Should auto-complete delimiters? - if !exists("b:delimitMate_autocomplete") - let s:autocomplete = 1 +function! s:Init() "{{{1 + + if !exists("g:delimitMate_autoclose") + let s:autoclose = 1 + else + let s:autoclose = g:delimitMate_autoclose + endif + + if !exists("g:delimitMate_matchpairs") + if s:ValidMatchpairs(&matchpairs) == 1 + let s:matchpairs_temp = &matchpairs else - let s:autocomplete = b:delimitMate_autocomplete + echoerr "There seems to be a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if it's a bug." + finish endif - - " Override matchpairs? - if !exists("b:delimitMate_paired_delims") - let s:paired_delims_temp = &matchpairs + else + if s:ValidMatchpairs(g:delimitMate_matchpairs) || g:delimitMate_matchpairs == "" + let s:matchpairs_temp = g:delimitMate_matchpairs else - let s:i = 1 - for pair in (split(&matchpairs,',')) - if strpart(pair, 0, 1) == strpart(pair, -1, 1) - let s:i = 0 - break - endif - endfor - - if (s:i && b:delimitMate_paired_delims =~ '^\(.:.\)\+\(,.:.\)*$') || b:delimitMate_paired_delims == "" - let s:paired_delims_temp = b:delimitMate_paired_delims + echoerr "Invalid format in 'g:delimitMate_matchpairs', falling back to matchpairs." + echoerr "Fix the error and use the command :DelimitMateReload to try again." + if s:ValidMatchpairs(&matchpairs) == 1 + let s:matchpairs_temp = &matchpairs else - let s:paired_delims_temp = &matchpairs - echoerr "Invalid format in b:delimitMate_paired_delims, falling back to matchpairs." - echoerr "Fix the error and use the command :DelimitMateReload to try again." + echoerr "There seems tobe a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if it's a bug." + let s:matchpairs_temp = "" endif - endif - " Define your own quoting delimiters? - if !exists("b:delimitMate_quote_delims") - let s:quote_delims = split("\" ' `") + endif + endif + + if exists("g:delimitMate_quotes") + if g:delimitMate_quotes =~ '^\(\S\)\(\s\S\)*$' || g:delimitMate_quotes == "" + let s:quotes = split(g:delimitMate_quotes) else - let s:quote_delims = b:delimitMate_quote_delims + let s:quotes = split("\" ' `") + echoerr "delimitMate: There is a problem with the format of 'delimitMate_quotes', it should be a string of single characters separated by spaces." endif + else + let s:quotes = split("\" ' `") + endif - " Leader for visual mode: - if !exists("b:delimitMate_visual_leader") - let s:visual_leader = "q" - else - let s:visual_leader = b:delimitMate_visual_leader - endif + if !exists("g:delimitMate_visual_leader") + let s:visual_leader = "q" + else + let s:visual_leader = g:delimitMate_visual_leader + endif - " Should space be expanded? - "if exists("b:delimitMate_expand_all") - "let s:expand_space = b:delimitMate_expand_all - "elseif exists("b:delimitMate_expand_space") - "let s:expand_space = b:delimitMate_expand_space - "else - "let s:expand_space = 1 - "endif - if !exists("b:delimitMate_expand_space") - let s:expand_space = '' - elseif b:delimitMate_expand_space == "" - let s:expand_space = '' - else - let s:expand_space = b:delimitMate_expand_space - endif + if !exists("g:delimitMate_expand_space") + let s:expand_space = "\" + elseif g:delimitMate_expand_space == "" + let s:expand_space = "\" + else + let s:expand_space = g:delimitMate_expand_space + endif - " Should return be expanded? - "if exists("b:delimitMate_expand_all") - "let s:expand_return = b:delimitMate_expand_all - "elseif exists("b:delimitMate_expand_return") - "let s:expand_return = b:delimitMate_expand_return - "else - "let s:expand_return = 1 - "endif - if !exists("b:delimitMate_expand_return") - let s:expand_return = '' - elseif b:delimitMate_expand_return == "" - let s:expand_return = '' - else - let s:expand_return = b:delimitMate_expand_return - endif + if !exists("g:delimitMate_expand_return") + let s:expand_return = "\" + elseif g:delimitMate_expand_return == "" + let s:expand_return = "\" + else + let s:expand_return = g:delimitMate_expand_return + endif + let s:matchpairs = split(s:matchpairs_temp, ',') + let s:left_delims = split(s:matchpairs_temp, ':.,\=') + let s:right_delims = split(s:matchpairs_temp, ',\=.:') + let s:VMapMsg = "delimitMate is disabled on blockwise visual mode." - let s:paired_delims = split(s:paired_delims_temp, ',') - let s:left_delims = split(s:paired_delims_temp, ':.,\=') - let s:right_delims = split(s:paired_delims_temp, ',\=.:') - let s:VMapMsg = "delimitMate is disabled on blockwise visual mode." - endfunction +endfunction - function! s:IsEmptyPair(str) "{{{2 - for pair in s:paired_delims - if a:str == join( split( pair, ':' ),'' ) - return 1 - endif - endfor - for quote in s:quote_delims - if a:str == quote . quote - return 1 - endif - endfor +function! s:ValidMatchpairs(str) "{{{1 + if a:str !~ '^\(.:.\)\+\(,.:.\)*$' return 0 - endfunc - - function! s:WithinEmptyPair() "{{{2 - let cur = strpart( getline('.'), col('.')-2, 2 ) - return IsEmptyPair( cur ) - endfunc - - function! s:SkipDelim(char) "{{{2 - let cur = strpart( getline('.'), col('.')-2, 3 ) - if cur[0] == "\\" - return a:char - elseif cur[1] == a:char - return "\" - elseif cur[1] == ' ' && cur[2] == a:char - return "\\" - elseif IsEmptyPair( cur[0] . a:char ) - return a:char . "\" - else - return a:char + endif + for pair in split(a:str,',') + if strpart(pair, 0, 1) == strpart(pair, 2, 1) || strlen(pair) != 3 + return 0 endif - endfunc + endfor + return 1 +endfunc - function! s:QuoteDelim(char) "{{{2 - let line = getline('.') - let col = col('.') - if line[col - 2] == "\\" - "Inserting a quoted quotation mark into the string - return a:char - elseif line[col - 1] == a:char - "Escaping out of the string - return "\" - else - "Starting a string - return a:char.a:char."\" +function! s:IsEmptyPair(str) "{{{1 + for pair in s:matchpairs + if a:str == join( split( pair, ':' ),'' ) + return 1 endif - endf - - function! s:ClosePair(char) "{{{2 - if getline('.')[col('.') - 1] == a:char - return "\" - else - return a:char + endfor + for quote in s:quotes + if a:str == quote . quote + return 1 endif - endf + endfor + return 0 +endfunc - function! s:ResetMappings() "{{{2 - for delim in s:right_delims + s:left_delims + s:quote_delims - silent! exec 'iunmap ' . delim - silent! exec 'vunmap ' . s:visual_leader . delim +function! s:WithinEmptyPair() "{{{1 + let cur = strpart( getline('.'), col('.')-2, 2 ) + return s:IsEmptyPair( cur ) +endfunc + +function! s:SkipDelim(char) "{{{1 + let cur = strpart( getline('.'), col('.')-2, 3 ) + if cur[0] == "\\" + return a:char + elseif cur[1] == a:char + return "\" + elseif cur[1] == ' ' && cur[2] == a:char + " I'm leaving this in case someone likes it. + return "\\" + elseif s:IsEmptyPair( cur[0] . a:char ) + return a:char . "\" + else + return a:char + endif +endfunc + +function! s:QuoteDelim(char) "{{{1 + let line = getline('.') + let col = col('.') + if line[col - 2] == "\\" + "Inserting a quoted quotation mark into the string + return a:char + elseif line[col - 1] == a:char + "Escaping out of the string + return "\" + else + "Starting a string + return a:char.a:char."\" + endif +endf + +function! s:ClosePair(char) "{{{1 + if getline('.')[col('.') - 1] == a:char + return "\" + else + return a:char + endif +endf + +function! s:ResetMappings() "{{{1 + for delim in s:right_delims + s:left_delims + s:quotes + silent! exec 'iunmap ' . delim + silent! exec 'vunmap ' . s:visual_leader . delim + endfor + silent! iunmap + silent! iunmap +endfunction + +function! s:MapMsg(msg) "{{{1 + redraw + echomsg a:msg + return "" +endfunction + +function! s:NoAutoClose() "{{{1 + " imap ) =SkipDelim('\)') + for delim in s:right_delims + s:quotes + exec 'imap ' . delim . ' =SkipDelim("' . escape(delim,'"') . '")' + endfor + + " Wrap the selection with delimiters, but do nothing if blockwise visual + " mode is active: + ""let s:i = 0 + ""while s:i < len(s:matchpairs) + for i in range(len(s:matchpairs)) + " Map left delimiter: + " vmap q( visualmode() == "" ? MapMsg(VMapMsg) : "s(\\")\" + exec 'vmap ' . s:visual_leader . s:left_delims[i] . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[i] . '\\"' . s:right_delims[i] . '\"' + + " Map right delimiter: + " vmap q) visualmode() == "" ? MapMsg(VMapMsg) : "s(\\")\" + exec 'vmap ' . s:visual_leader . s:right_delims[i] . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[i] . '\\"' . s:right_delims[i] . '\"' + endfor + + for quote in s:quotes + " vmap q" visualmode() == "" ? MapMsg(VMapMsg) : "s'\\"'\" + exec 'vmap ' . s:visual_leader . quote . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . escape(quote,'"') . '\\"' . escape(quote,'"') . '\"' + endfor +endfunction + +function! s:AutoClose() "{{{1 + " Add matching pair and jump to the midle: + " imap ( () + let s:i = 0 + while s:i < len(s:matchpairs) + exec 'imap ' . s:left_delims[s:i] . ' ' . s:left_delims[s:i] . s:right_delims[s:i] . '' + let s:i += 1 + endwhile + + " Add matching quote and jump to the midle, or exit if inside a pair of + " matching quotes: + " imap " =QuoteDelim("\"") + for delim in s:quotes + exec 'imap ' . delim . ' =QuoteDelim("\' . delim . '")' + endfor + + " Exit from inside the matching pair: + " imap ) =ClosePair(')') + for delim in s:right_delims + exec 'imap ' . delim . ' =ClosePair("\' . delim . '")' + endfor + + " Wrap the selection with matching pairs, but do nothing if blockwise visual + " mode is active: + let s:i = 0 + while s:i < len(s:matchpairs) + " Map left delimiter: + " vmap q( visualmode() == "" ? MapMsg("Message") : "s(\\"\" + exec 'vmap ' . s:visual_leader . s:left_delims[s:i] . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\\"\"' + + " Map right delimiter: + " vmap q) visualmode() == "" ? MapMsg("Message") : "s(\\""\" + exec 'vmap ' . s:visual_leader . s:right_delims[s:i] . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\\"\"' + let s:i += 1 + endwhile + + " Wrap the selection with matching quotes, but do nothing if blockwise visual + " mode is active: + for quote in s:quotes + " vmap q' visualmode() == "" ? MapMsg("Message") : "s'\\"'\" + exec 'vmap ' . s:visual_leader . quote . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . escape(quote,'"') .'\\"' . escape(quote,'"') . '\"' + endfor +endfunction + +function! s:ExpandReturn() "{{{1 + if s:WithinEmptyPair() + return s:expand_return + else + return "\" + endif +endfunction + +function! s:ExpandSpace() "{{{1 + if s:WithinEmptyPair() + return s:expand_space + else + return "\" + endif +endfunction + +function! s:ExtraMappings() "{{{1 + " If pair is empty, delete both delimiters: + imap WithinEmptyPair() ? "\\\" : "\" + + " Expand return if inside an empty pair: + imap =ExpandReturn() + + " Expand space if inside an empty pair: + imap =ExpandSpace() +endfunction + +function! s:TestMappings() "{{{1 + if s:autoclose + exec "normal i* AUTOCLOSE:\" + for i in range(len(s:left_delims)) + exec "normal GGAOpen & close: " . s:left_delims[i]. "|" + exec "normal A\Delete: " . s:left_delims[i] . "\|" + exec "normal A\Exit: " . s:left_delims[i] . s:right_delims[i] . "|" + exec "normal A\Space: " . s:left_delims[i] . " |" + exec "normal GGA\Visual-L: v\v" . s:visual_leader . s:left_delims[i] + exec "normal A\Visual-R: v\v" . s:visual_leader . s:right_delims[i] + exec "normal A\Car return: " . s:left_delims[i] . "\|\GGA\\" endfor - silent! iunmap - silent! iunmap - endfunction - - function! s:MapMsg(msg) "{{{2 - redraw - echomsg a:msg - return "" - endfunction - - - " Don't auto-complete: {{{2 - function! s:NoAutoComplete() - let test_string = "Don't" - " imap ) SkipDelim('\)') - for delim in s:right_delims + s:quote_delims - exec 'imap ' . delim . ' SkipDelim("\' . delim . '")' + for i in range(len(s:quotes)) + exec "normal GGAOpen & close: " . s:quotes[i] . "|" + exec "normal A\Delete: " . s:quotes[i] . "\|" + exec "normal A\Exit: " . s:quotes[i] . s:quotes[i] . "|" + exec "normal A\Space: " . s:quotes[i] . " |" + exec "normal GGA\Visual: v\v" . s:visual_leader . s:quotes[i] + exec "normal A\Car return: " . s:quotes[i] . "\|\GGA\\" endfor - - " Wrap the selection with delimiters, but do nothing if blockwise visual - " mode is active: - let s:i = 0 - while s:i < len(s:paired_delims) - - " vmap q( visualmode() == "" ? MapMsg(VMapMsg) : "s(\\")\" - exec 'vmap ' . s:visual_leader . s:left_delims[s:i] . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\\"' . s:right_delims[s:i] . '\"' - - " vmap q) visualmode() == "" ? MapMsg(VMapMsg) : "s(\\")\" - exec 'vmap ' . s:visual_leader . s:right_delims[s:i] . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\\"' . s:right_delims[s:i] . '\"' - let s:i = s:i + 1 - endwhile - - for quote in s:quote_delims - if quote == '"' - " Ugly fix for double quotes: - " vmap q" visualmode() == "" ? MapMsg(VMapMsg) : "s\"\\"\"\" - exec 'vmap ' . s:visual_leader . quote . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s\' . quote . '\\"\' . quote . '\"' - else - " vmap q" visualmode() == "" ? MapMsg(VMapMsg) : "s'\\"'\" - exec 'vmap ' . s:visual_leader . quote . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . quote . '\\"' . quote . '\"' - endif + else + exec "normal i* NO AUTOCLOSE:\" + for i in range(len(s:left_delims)) + exec "normal GGAOpen & close: " . s:left_delims[i] . s:right_delims[i] . "|" + exec "normal A\Delete: " . s:left_delims[i] . s:right_delims[i] . "\|" + exec "normal A\Exit: " . s:left_delims[i] . s:right_delims[i] . s:right_delims[i] . "|" + exec "normal A\Space: " . s:left_delims[i] . s:right_delims[i] . " |" + exec "normal GGA\Visual-L: v\v" . s:visual_leader . s:left_delims[i] + exec "normal A\Visual-R: v\v" . s:visual_leader . s:right_delims[i] + exec "normal A\Car return: " . s:left_delims[i] . s:right_delims[i] . "\|\GGA\\" endfor - endfunction - - " Do auto-complete: {{{2 - function! s:AutoComplete() - " Add matching pair and jump to the midle: - " imap ( () - let s:i = 0 - while s:i < len(s:paired_delims) - exec 'imap ' . s:left_delims[s:i] . ' ' . s:left_delims[s:i] . s:right_delims[s:i] . '' - let s:i = s:i + 1 - endwhile - - " Add matching quote and jump to the midle, or exit if inside a pair of - " matching quotes: - " imap " =QuoteDelim("\"") - let s:i = 0 - for delim in s:quote_delims - exec 'imap ' . delim . ' =QuoteDelim("\' . delim . '")' + for i in range(len(s:quotes)) + exec "normal GGAOpen & close: " . s:quotes[i] . s:quotes[i] . "|" + exec "normal A\Delete: " . s:quotes[i] . s:quotes[i] . "\|" + exec "normal A\Exit: " . s:quotes[i] . s:quotes[i] . s:quotes[i] . "|" + exec "normal A\Space: " . s:quotes[i] . s:quotes[i] . " |" + exec "normal GGA\Visual: v\v" . s:visual_leader . s:quotes[i] + exec "normal A\Car return: " . s:quotes[i] . s:quotes[i] . "\|\GGA\\" endfor + endif + exec "normal \" +endfunction - " Exit from inside the matching pair: - " imap ) =ClosePair(')') - for delim in s:right_delims - exec 'imap ' . delim . ' =ClosePair("\' . delim . '")' - endfor +function! s:SwitchAutoclose() "{{{1 + if !exists("g:delimitMate_autoclose") + let g:delimitMate_autoclose = 1 + elseif g:delimitMate_autoclose == 1 + let g:delimitMate_autoclose = 0 + else + let g:delimitMate_autoclose = 1 + endif + DelimitMateReload +endfunction - " Wrap the selection with matching pairs, but do nothing if blockwise visual - " mode is active: - let s:i = 0 - while s:i < len(s:paired_delims) - " vmap q( visualmode() == "" ? MapMsg("Message") : "s(\\"\" - exec 'vmap ' . s:visual_leader . s:left_delims[s:i] . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\\"\"' +function! s:TestMappingsDo() "{{{1 + if !exists("g:delimitMate_testing") + call s:DelimitMateDo() + call s:TestMappings() + else + call s:SwitchAutoclose() + call s:TestMappings() + exec "normal i\" + call s:SwitchAutoclose() + call s:TestMappings() + endif +endfunction - " vmap q) visualmode() == "" ? MapMsg("Message") : "s(\\""\" - exec 'vmap ' . s:visual_leader . s:right_delims[s:i] . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\\"\"' - let s:i = s:i + 1 - endwhile - - " Wrap the selection with matching quotes, but do nothing if blockwise visual - " mode is active: - for quote in s:quote_delims - if quote == '"' - " Ugly fix for double quotes: - " vmap q" visualmode() == "" ? MapMsg("Message") : "s\"\\"\" - exec 'vmap ' . s:visual_leader . '" visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s\"\\"\"' - else - - " vmap q' visualmode() == "" ? MapMsg("Message") : "s'\\"'\" - exec 'vmap ' . s:visual_leader . quote . ' visualmode() == "" ? MapMsg("' . s:VMapMsg . '") : "s' . quote .'\\"' . quote . '\"' - endif - endfor - endfunction - - " Expansions and Deletion: {{{2 - function! s:ExtraMappings() - " If pair is empty, delete both delimiters: - imap WithinEmptyPair() ? "\\\" : "\" - - " Expand return if inside an empty pair: - " imap WithinEmptyPair() ? "\\\" : "\" - exec 'imap WithinEmptyPair() ? "' . escape(s:expand_return,'"<') . '" : ""' - echomsg s:expand_return - - " Expand space if inside an empty pair: - " imap WithinEmptyPair() ? "\\\" : "\" - exec 'imap WithinEmptyPair() ? "' . escape(s:expand_space,'"<') . '" : ""' - echomsg s:expand_space - endfunction - - " Task list: - function! s:DelimitMateDo() +function! s:DelimitMateDo() "{{{1 + try + let s:save_cpo = &cpo + set cpo&vim call s:Init() call s:ResetMappings() - if s:autocomplete - call s:AutoComplete() + if s:autoclose + call s:AutoClose() else - call s:NoAutoComplete() + call s:NoAutoClose() endif call s:ExtraMappings() - endfunction -endif "}}}1 + finally + let &cpo = s:save_cpo + endtry +endfunction -" Do the real work: +" Do the real work: {{{1 call s:DelimitMateDo() " Let me refresh without re-loading the buffer: command! DelimitMateReload call s:DelimitMateDo() -" vim:foldmethod=marker:foldcolumn=4 +" Quick test: +command! DelimitMateTest call s:TestMappingsDo() + +" vim:foldmethod=marker:foldcolumn=2