- Help file added.

- Added format test for matchpairs and quotes.
- Added testing functionality.
- Other small fixes
This commit is contained in:
Israel Chauca Fuentes
2009-08-20 12:07:22 -05:00
parent 3231c9f754
commit 21c7ad8fdc
3 changed files with 666 additions and 315 deletions

9
delimitMate.otl Normal file
View File

@@ -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()

328
delimitMate.txt Normal file
View File

@@ -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 <Space> to:
<Space><Space><Left> | You get
====================================
(|) | ( | )
Expand <CR> to:
<CR><CR><Up> | 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 <CR> inside an empty
pair of matching delimiters or quotes.
|'delimitMate_expand_space'| Sets the expansion for <Space> 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: "\<CR>"
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 = "\<CR>\<CR>\<Up>"
<
------------------------------------------------------------------------------
*'delimitMate_expand_space'*
Values: A key mapping.
Default: "\<Space>"
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 = "\<Space>\<Space>\<Left>"
<
==============================================================================
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:

View File

@@ -1,181 +1,124 @@
" delimitMate " ===========================================================================
" " File: delimitMate.vim
" Credit:{{{1 " Description: This plugin tries to emulate the auto-completion of delimiters
" " that TextMate provides.
" This script relies on code from the following places: " Maintainer: Israel Chauca F. <israel@chauca.net>
" Credits: Some of the code is modified or just copied from the following:
" "
" - Ian McCracken " - Ian McCracken
" http://concisionandconcinnity.blogspot.com/2009/07/vim-part-ii-matching-pairs.html " Post titled: Vim, Part II: Matching Pairs:
" http://concisionandconcinnity.blogspot.com/
" "
" - Aristotle Pagaltzis " - Aristotle Pagaltzis
" http://concisionandconcinnity.blogspot.com/2009/07/vim-part-ii-matching-pairs.html#comment-6278381178877777788 " From the comments on the previous blog post and from:
" http://gist.github.com/144619 " http://gist.github.com/144619
" "
" - Orestis Markou " - Orestis Markou
" Script 'simple pairs':
" http://www.vim.org/scripts/script.php?script_id=2339 " 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 <CR> and <Space> 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 = '<CR><CR><Up>'
"
" let b:delimitMate_expand_space = '<Space><Space><Left>'
" Init:{{{1 if exists("g:loaded_delimitMate") "{{{1
if exists("b:loaded_delimitMate") " Don't define the functions if they already exist: just do the work:
" finish call s:DelimitMateDo()
finish
endif endif
if v:version < 700 if v:version < 700
echoerr "delimitMate: this plugin requires vim >= 7!" echoerr "delimitMate: this plugin requires vim >= 7!"
finish finish
endif endif
let b:loaded_delimitMate = 1
" Functions: let g:loaded_delimitMate = 1
" Don't define the functions if they already exist: function! s:Init() "{{{1
if !exists("*s:Init")
" Set user preferences:{{{1 if !exists("g:delimitMate_autoclose")
function! s:Init() let s:autoclose = 1
" Should auto-complete delimiters?
if !exists("b:delimitMate_autocomplete")
let s:autocomplete = 1
else else
let s:autocomplete = b:delimitMate_autocomplete let s:autoclose = g:delimitMate_autoclose
endif endif
" Override matchpairs? if !exists("g:delimitMate_matchpairs")
if !exists("b:delimitMate_paired_delims") if s:ValidMatchpairs(&matchpairs) == 1
let s:paired_delims_temp = &matchpairs let s:matchpairs_temp = &matchpairs
else else
let s:i = 1 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."
for pair in (split(&matchpairs,',')) finish
if strpart(pair, 0, 1) == strpart(pair, -1, 1)
let s:i = 0
break
endif endif
endfor
if (s:i && b:delimitMate_paired_delims =~ '^\(.:.\)\+\(,.:.\)*$') || b:delimitMate_paired_delims == ""
let s:paired_delims_temp = b:delimitMate_paired_delims
else else
let s:paired_delims_temp = &matchpairs if s:ValidMatchpairs(g:delimitMate_matchpairs) || g:delimitMate_matchpairs == ""
echoerr "Invalid format in b:delimitMate_paired_delims, falling back to matchpairs." let s:matchpairs_temp = g:delimitMate_matchpairs
else
echoerr "Invalid format in 'g:delimitMate_matchpairs', falling back to matchpairs."
echoerr "Fix the error and use the command :DelimitMateReload to try again." echoerr "Fix the error and use the command :DelimitMateReload to try again."
endif if s:ValidMatchpairs(&matchpairs) == 1
endif let s:matchpairs_temp = &matchpairs
" Define your own quoting delimiters?
if !exists("b:delimitMate_quote_delims")
let s:quote_delims = split("\" ' `")
else else
let s:quote_delims = b:delimitMate_quote_delims 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
" Leader for visual mode: endif
if !exists("b:delimitMate_visual_leader") 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: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
if !exists("g:delimitMate_visual_leader")
let s:visual_leader = "q" let s:visual_leader = "q"
else else
let s:visual_leader = b:delimitMate_visual_leader let s:visual_leader = g:delimitMate_visual_leader
endif endif
" Should space be expanded? if !exists("g:delimitMate_expand_space")
"if exists("b:delimitMate_expand_all") let s:expand_space = "\<Space>"
"let s:expand_space = b:delimitMate_expand_all elseif g:delimitMate_expand_space == ""
"elseif exists("b:delimitMate_expand_space") let s:expand_space = "\<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 = '<Space>'
elseif b:delimitMate_expand_space == ""
let s:expand_space = '<Space>'
else else
let s:expand_space = b:delimitMate_expand_space let s:expand_space = g:delimitMate_expand_space
endif endif
" Should return be expanded? if !exists("g:delimitMate_expand_return")
"if exists("b:delimitMate_expand_all") let s:expand_return = "\<CR>"
"let s:expand_return = b:delimitMate_expand_all elseif g:delimitMate_expand_return == ""
"elseif exists("b:delimitMate_expand_return") let s:expand_return = "\<CR>"
"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 = '<CR>'
elseif b:delimitMate_expand_return == ""
let s:expand_return = '<CR>'
else else
let s:expand_return = b:delimitMate_expand_return let s:expand_return = g:delimitMate_expand_return
endif endif
let s:matchpairs = split(s:matchpairs_temp, ',')
let s:paired_delims = split(s:paired_delims_temp, ',') let s:left_delims = split(s:matchpairs_temp, ':.,\=')
let s:left_delims = split(s:paired_delims_temp, ':.,\=') let s:right_delims = split(s:matchpairs_temp, ',\=.:')
let s:right_delims = split(s:paired_delims_temp, ',\=.:')
let s:VMapMsg = "delimitMate is disabled on blockwise visual mode." let s:VMapMsg = "delimitMate is disabled on blockwise visual mode."
endfunction endfunction
function! s:IsEmptyPair(str) "{{{2 function! s:ValidMatchpairs(str) "{{{1
for pair in s:paired_delims if a:str !~ '^\(.:.\)\+\(,.:.\)*$'
return 0
endif
for pair in split(a:str,',')
if strpart(pair, 0, 1) == strpart(pair, 2, 1) || strlen(pair) != 3
return 0
endif
endfor
return 1
endfunc
function! s:IsEmptyPair(str) "{{{1
for pair in s:matchpairs
if a:str == join( split( pair, ':' ),'' ) if a:str == join( split( pair, ':' ),'' )
return 1 return 1
endif endif
endfor endfor
for quote in s:quote_delims for quote in s:quotes
if a:str == quote . quote if a:str == quote . quote
return 1 return 1
endif endif
@@ -183,27 +126,28 @@ if !exists("*s:Init")
return 0 return 0
endfunc endfunc
function! s:WithinEmptyPair() "{{{2 function! s:WithinEmptyPair() "{{{1
let cur = strpart( getline('.'), col('.')-2, 2 ) let cur = strpart( getline('.'), col('.')-2, 2 )
return IsEmptyPair( cur ) return s:IsEmptyPair( cur )
endfunc endfunc
function! s:SkipDelim(char) "{{{2 function! s:SkipDelim(char) "{{{1
let cur = strpart( getline('.'), col('.')-2, 3 ) let cur = strpart( getline('.'), col('.')-2, 3 )
if cur[0] == "\\" if cur[0] == "\\"
return a:char return a:char
elseif cur[1] == a:char elseif cur[1] == a:char
return "\<Right>" return "\<Right>"
elseif cur[1] == ' ' && cur[2] == a:char elseif cur[1] == ' ' && cur[2] == a:char
" I'm leaving this in case someone likes it.
return "\<Right>\<Right>" return "\<Right>\<Right>"
elseif IsEmptyPair( cur[0] . a:char ) elseif s:IsEmptyPair( cur[0] . a:char )
return a:char . "\<Left>" return a:char . "\<Left>"
else else
return a:char return a:char
endif endif
endfunc endfunc
function! s:QuoteDelim(char) "{{{2 function! s:QuoteDelim(char) "{{{1
let line = getline('.') let line = getline('.')
let col = col('.') let col = col('.')
if line[col - 2] == "\\" if line[col - 2] == "\\"
@@ -218,7 +162,7 @@ if !exists("*s:Init")
endif endif
endf endf
function! s:ClosePair(char) "{{{2 function! s:ClosePair(char) "{{{1
if getline('.')[col('.') - 1] == a:char if getline('.')[col('.') - 1] == a:char
return "\<Right>" return "\<Right>"
else else
@@ -226,8 +170,8 @@ if !exists("*s:Init")
endif endif
endf endf
function! s:ResetMappings() "{{{2 function! s:ResetMappings() "{{{1
for delim in s:right_delims + s:left_delims + s:quote_delims for delim in s:right_delims + s:left_delims + s:quotes
silent! exec 'iunmap <buffer> ' . delim silent! exec 'iunmap <buffer> ' . delim
silent! exec 'vunmap <buffer> ' . s:visual_leader . delim silent! exec 'vunmap <buffer> ' . s:visual_leader . delim
endfor endfor
@@ -235,130 +179,200 @@ if !exists("*s:Init")
silent! iunmap <buffer> <Space> silent! iunmap <buffer> <Space>
endfunction endfunction
function! s:MapMsg(msg) "{{{2 function! s:MapMsg(msg) "{{{1
redraw redraw
echomsg a:msg echomsg a:msg
return "" return ""
endfunction endfunction
function! s:NoAutoClose() "{{{1
" Don't auto-complete: {{{2 " imap <buffer> ) <C-R>=<SID>SkipDelim('\)')<CR>
function! s:NoAutoComplete() for delim in s:right_delims + s:quotes
let test_string = "Don't" exec 'imap <buffer> ' . delim . ' <C-R>=<SID>SkipDelim("' . escape(delim,'"') . '")<CR>'
" imap <buffer> <expr> ) <SID>SkipDelim('\)')
for delim in s:right_delims + s:quote_delims
exec 'imap <buffer> <expr> ' . delim . ' <SID>SkipDelim("\' . delim . '")'
endfor endfor
" Wrap the selection with delimiters, but do nothing if blockwise visual " Wrap the selection with delimiters, but do nothing if blockwise visual
" mode is active: " mode is active:
let s:i = 0 ""let s:i = 0
while s:i < len(s:paired_delims) ""while s:i < len(s:matchpairs)
for i in range(len(s:matchpairs))
" Map left delimiter:
" vmap <buffer> <expr> q( visualmode() == "<C-V>" ? <SID>MapMsg(VMapMsg) : "s(\<C-R>\")\<Esc>" " vmap <buffer> <expr> q( visualmode() == "<C-V>" ? <SID>MapMsg(VMapMsg) : "s(\<C-R>\")\<Esc>"
exec 'vmap <buffer> <expr> ' . s:visual_leader . s:left_delims[s:i] . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\<C-R>\"' . s:right_delims[s:i] . '\<Esc>"' exec 'vmap <buffer> <expr> ' . s:visual_leader . s:left_delims[i] . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[i] . '\<C-R>\"' . s:right_delims[i] . '\<Esc>"'
" Map right delimiter:
" vmap <buffer> <expr> q) visualmode() == "<C-V>" ? <SID>MapMsg(VMapMsg) : "s(\<C-R>\")\<Esc>" " vmap <buffer> <expr> q) visualmode() == "<C-V>" ? <SID>MapMsg(VMapMsg) : "s(\<C-R>\")\<Esc>"
exec 'vmap <buffer> <expr> ' . s:visual_leader . s:right_delims[s:i] . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\<C-R>\"' . s:right_delims[s:i] . '\<Esc>"' exec 'vmap <buffer> <expr> ' . s:visual_leader . s:right_delims[i] . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[i] . '\<C-R>\"' . s:right_delims[i] . '\<Esc>"'
let s:i = s:i + 1 endfor
endwhile
for quote in s:quote_delims for quote in s:quotes
if quote == '"'
" Ugly fix for double quotes:
" vmap <buffer> <expr> q" visualmode() == "<C-V>" ? <SID>MapMsg(VMapMsg) : "s\"\<C-R>\"\"\<Esc>"
exec 'vmap <buffer> <expr> ' . s:visual_leader . quote . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s\' . quote . '\<C-R>\"\' . quote . '\<Esc>"'
else
" vmap <buffer> <expr> q" visualmode() == "<C-V>" ? <SID>MapMsg(VMapMsg) : "s'\<C-R>\"'\<Esc>" " vmap <buffer> <expr> q" visualmode() == "<C-V>" ? <SID>MapMsg(VMapMsg) : "s'\<C-R>\"'\<Esc>"
exec 'vmap <buffer> <expr> ' . s:visual_leader . quote . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . quote . '\<C-R>\"' . quote . '\<Esc>"' exec 'vmap <buffer> <expr> ' . s:visual_leader . quote . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . escape(quote,'"') . '\<C-R>\"' . escape(quote,'"') . '\<Esc>"'
endif
endfor endfor
endfunction endfunction
" Do auto-complete: {{{2 function! s:AutoClose() "{{{1
function! s:AutoComplete()
" Add matching pair and jump to the midle: " Add matching pair and jump to the midle:
" imap <buffer> ( ()<Left> " imap <buffer> ( ()<Left>
let s:i = 0 let s:i = 0
while s:i < len(s:paired_delims) while s:i < len(s:matchpairs)
exec 'imap <buffer> ' . s:left_delims[s:i] . ' ' . s:left_delims[s:i] . s:right_delims[s:i] . '<Left>' exec 'imap <buffer> ' . s:left_delims[s:i] . ' ' . s:left_delims[s:i] . s:right_delims[s:i] . '<Left>'
let s:i = s:i + 1 let s:i += 1
endwhile endwhile
" Add matching quote and jump to the midle, or exit if inside a pair of " Add matching quote and jump to the midle, or exit if inside a pair of
" matching quotes: " matching quotes:
" imap <buffer> " <c-r>=<SID>QuoteDelim("\"")<CR> " imap <buffer> " <C-R>=<SID>QuoteDelim("\"")<CR>
let s:i = 0 for delim in s:quotes
for delim in s:quote_delims exec 'imap <buffer> ' . delim . ' <C-R>=<SID>QuoteDelim("\' . delim . '")<CR>'
exec 'imap <buffer> ' . delim . ' <c-r>=<SID>QuoteDelim("\' . delim . '")<CR>'
endfor endfor
" Exit from inside the matching pair: " Exit from inside the matching pair:
" imap <buffer> ) <c-r>=<SID>ClosePair(')')<CR> " imap <buffer> ) <C-R>=<SID>ClosePair(')')<CR>
for delim in s:right_delims for delim in s:right_delims
exec 'imap <buffer> ' . delim . ' <c-r>=<SID>ClosePair("\' . delim . '")<CR>' exec 'imap <buffer> ' . delim . ' <C-R>=<SID>ClosePair("\' . delim . '")<CR>'
endfor endfor
" Wrap the selection with matching pairs, but do nothing if blockwise visual " Wrap the selection with matching pairs, but do nothing if blockwise visual
" mode is active: " mode is active:
let s:i = 0 let s:i = 0
while s:i < len(s:paired_delims) while s:i < len(s:matchpairs)
" Map left delimiter:
" vmap <buffer> <expr> q( visualmode() == "<C-V>" ? <SID>MapMsg("Message") : "s(\<C-R>\"\<Esc>" " vmap <buffer> <expr> q( visualmode() == "<C-V>" ? <SID>MapMsg("Message") : "s(\<C-R>\"\<Esc>"
exec 'vmap <buffer> <expr> ' . s:visual_leader . s:left_delims[s:i] . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\<C-R>\"\<Esc>"' exec 'vmap <buffer> <expr> ' . s:visual_leader . s:left_delims[s:i] . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\<C-R>\"\<Esc>"'
" Map right delimiter:
" vmap <buffer> <expr> q) visualmode() == "<C-V>" ? <SID>MapMsg("Message") : "s(\<C-R>\""\<Esc>" " vmap <buffer> <expr> q) visualmode() == "<C-V>" ? <SID>MapMsg("Message") : "s(\<C-R>\""\<Esc>"
exec 'vmap <buffer> <expr> ' . s:visual_leader . s:right_delims[s:i] . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\<C-R>\"\<Esc>"' exec 'vmap <buffer> <expr> ' . s:visual_leader . s:right_delims[s:i] . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . s:left_delims[s:i] . '\<C-R>\"\<Esc>"'
let s:i = s:i + 1 let s:i += 1
endwhile endwhile
" Wrap the selection with matching quotes, but do nothing if blockwise visual " Wrap the selection with matching quotes, but do nothing if blockwise visual
" mode is active: " mode is active:
for quote in s:quote_delims for quote in s:quotes
if quote == '"'
" Ugly fix for double quotes:
" vmap <buffer> <expr> q" visualmode() == "<C-V>" ? <SID>MapMsg("Message") : "s\"\<C-R>\"\<Esc>"
exec 'vmap <buffer> <expr> ' . s:visual_leader . '" visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s\"\<C-R>\"\<Esc>"'
else
" vmap <buffer> <expr> q' visualmode() == "<C-V>" ? <SID>MapMsg("Message") : "s'\<C-R>\"'\<Esc>" " vmap <buffer> <expr> q' visualmode() == "<C-V>" ? <SID>MapMsg("Message") : "s'\<C-R>\"'\<Esc>"
exec 'vmap <buffer> <expr> ' . s:visual_leader . quote . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . quote .'\<C-R>\"' . quote . '\<Esc>"' exec 'vmap <buffer> <expr> ' . s:visual_leader . quote . ' visualmode() == "<C-V>" ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . escape(quote,'"') .'\<C-R>\"' . escape(quote,'"') . '\<Esc>"'
endif
endfor endfor
endfunction endfunction
" Expansions and Deletion: {{{2 function! s:ExpandReturn() "{{{1
function! s:ExtraMappings() if s:WithinEmptyPair()
return s:expand_return
else
return "\<CR>"
endif
endfunction
function! s:ExpandSpace() "{{{1
if s:WithinEmptyPair()
return s:expand_space
else
return "\<Space>"
endif
endfunction
function! s:ExtraMappings() "{{{1
" If pair is empty, delete both delimiters: " If pair is empty, delete both delimiters:
imap <buffer> <expr> <BS> <SID>WithinEmptyPair() ? "\<Right>\<BS>\<BS>" : "\<BS>" imap <buffer> <expr> <BS> <SID>WithinEmptyPair() ? "\<Right>\<BS>\<BS>" : "\<BS>"
" Expand return if inside an empty pair: " Expand return if inside an empty pair:
" imap <buffer> <expr> <CR> <SID>WithinEmptyPair() ? "\<CR>\<CR>\<Up>" : "\<CR>" imap <buffer> <CR> <C-R>=<SID>ExpandReturn()<CR>
exec 'imap <buffer> <expr> <CR> <SID>WithinEmptyPair() ? "' . escape(s:expand_return,'"<') . '" : "<CR>"'
echomsg s:expand_return
" Expand space if inside an empty pair: " Expand space if inside an empty pair:
" imap <buffer> <expr> <Space> <SID>WithinEmptyPair() ? "\<Space>\<Space>\<Left>" : "\<Space>" imap <buffer> <Space> <C-R>=<SID>ExpandSpace()<CR>
exec 'imap <buffer> <expr> <Space> <SID>WithinEmptyPair() ? "' . escape(s:expand_space,'"<') . '" : "<Space>"'
echomsg s:expand_space
endfunction endfunction
" Task list: function! s:TestMappings() "{{{1
function! s:DelimitMateDo() if s:autoclose
exec "normal i* AUTOCLOSE:\<CR>"
for i in range(len(s:left_delims))
exec "normal GGAOpen & close: " . s:left_delims[i]. "|"
exec "normal A\<CR>Delete: " . s:left_delims[i] . "\<BS>|"
exec "normal A\<CR>Exit: " . s:left_delims[i] . s:right_delims[i] . "|"
exec "normal A\<CR>Space: " . s:left_delims[i] . " |"
exec "normal GGA\<CR>Visual-L: v\<Esc>v" . s:visual_leader . s:left_delims[i]
exec "normal A\<CR>Visual-R: v\<Esc>v" . s:visual_leader . s:right_delims[i]
exec "normal A\<CR>Car return: " . s:left_delims[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>"
endfor
for i in range(len(s:quotes))
exec "normal GGAOpen & close: " . s:quotes[i] . "|"
exec "normal A\<CR>Delete: " . s:quotes[i] . "\<BS>|"
exec "normal A\<CR>Exit: " . s:quotes[i] . s:quotes[i] . "|"
exec "normal A\<CR>Space: " . s:quotes[i] . " |"
exec "normal GGA\<CR>Visual: v\<Esc>v" . s:visual_leader . s:quotes[i]
exec "normal A\<CR>Car return: " . s:quotes[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>"
endfor
else
exec "normal i* NO AUTOCLOSE:\<CR>"
for i in range(len(s:left_delims))
exec "normal GGAOpen & close: " . s:left_delims[i] . s:right_delims[i] . "|"
exec "normal A\<CR>Delete: " . s:left_delims[i] . s:right_delims[i] . "\<BS>|"
exec "normal A\<CR>Exit: " . s:left_delims[i] . s:right_delims[i] . s:right_delims[i] . "|"
exec "normal A\<CR>Space: " . s:left_delims[i] . s:right_delims[i] . " |"
exec "normal GGA\<CR>Visual-L: v\<Esc>v" . s:visual_leader . s:left_delims[i]
exec "normal A\<CR>Visual-R: v\<Esc>v" . s:visual_leader . s:right_delims[i]
exec "normal A\<CR>Car return: " . s:left_delims[i] . s:right_delims[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>"
endfor
for i in range(len(s:quotes))
exec "normal GGAOpen & close: " . s:quotes[i] . s:quotes[i] . "|"
exec "normal A\<CR>Delete: " . s:quotes[i] . s:quotes[i] . "\<BS>|"
exec "normal A\<CR>Exit: " . s:quotes[i] . s:quotes[i] . s:quotes[i] . "|"
exec "normal A\<CR>Space: " . s:quotes[i] . s:quotes[i] . " |"
exec "normal GGA\<CR>Visual: v\<Esc>v" . s:visual_leader . s:quotes[i]
exec "normal A\<CR>Car return: " . s:quotes[i] . s:quotes[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>"
endfor
endif
exec "normal \<Esc>"
endfunction
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
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\<CR>"
call s:SwitchAutoclose()
call s:TestMappings()
endif
endfunction
function! s:DelimitMateDo() "{{{1
try
let s:save_cpo = &cpo
set cpo&vim
call s:Init() call s:Init()
call s:ResetMappings() call s:ResetMappings()
if s:autocomplete if s:autoclose
call s:AutoComplete() call s:AutoClose()
else else
call s:NoAutoComplete() call s:NoAutoClose()
endif endif
call s:ExtraMappings() call s:ExtraMappings()
finally
let &cpo = s:save_cpo
endtry
endfunction endfunction
endif "}}}1
" Do the real work: " Do the real work: {{{1
call s:DelimitMateDo() call s:DelimitMateDo()
" Let me refresh without re-loading the buffer: " Let me refresh without re-loading the buffer:
command! DelimitMateReload call s:DelimitMateDo() command! DelimitMateReload call s:DelimitMateDo()
" vim:foldmethod=marker:foldcolumn=4 " Quick test:
command! DelimitMateTest call s:TestMappingsDo()
" vim:foldmethod=marker:foldcolumn=2