mirror of
https://github.com/Raimondi/delimitMate.git
synced 2025-12-07 21:24:51 +08:00
Compare commits
370 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22e6272b1a | ||
|
|
c4d51a21b3 | ||
|
|
9ec998e87a | ||
|
|
0246f25de8 | ||
|
|
1eafd59b9c | ||
|
|
4eaeef01bf | ||
|
|
fb60f3cc9f | ||
|
|
e362f5a69d | ||
|
|
c97a824ed4 | ||
|
|
37122299b7 | ||
|
|
d882e342f7 | ||
|
|
b1ff7f7942 | ||
|
|
e48ea9f852 | ||
|
|
cb6866f1c3 | ||
|
|
8204ab4cb8 | ||
|
|
6f038350de | ||
|
|
0f6581c6f3 | ||
|
|
7752546515 | ||
|
|
7809c5e171 | ||
|
|
b6cc751cc9 | ||
|
|
24cffe07b3 | ||
|
|
6fddbc5568 | ||
|
|
015e0efe53 | ||
|
|
03a0e5d8b3 | ||
|
|
d970ecc4ca | ||
|
|
353fb9a718 | ||
|
|
4d0060f22b | ||
|
|
65016ebe37 | ||
|
|
85d76972e6 | ||
|
|
c4b5877958 | ||
|
|
2335c4ae27 | ||
|
|
6f1a9d00af | ||
|
|
b99ecfa2e3 | ||
|
|
50d97fd76e | ||
|
|
8bc47fd1c4 | ||
|
|
bc97837c71 | ||
|
|
d24ad6b301 | ||
|
|
81de76fe52 | ||
|
|
5945fdfd14 | ||
|
|
9a77c3aee6 | ||
|
|
342a04b427 | ||
|
|
03e94587ae | ||
|
|
c78a6e6d93 | ||
|
|
470c053a3b | ||
|
|
254a89d67c | ||
|
|
e7b4dedb84 | ||
|
|
21a3ade90c | ||
|
|
8e30e70bcd | ||
|
|
ac792c01b6 | ||
|
|
c23ef684e3 | ||
|
|
b63924f2b2 | ||
|
|
07b7cc969f | ||
|
|
13e52d42ae | ||
|
|
aa9d737763 | ||
|
|
bf2b68edab | ||
|
|
fe9022433d | ||
|
|
6f7e6413ce | ||
|
|
a9a37854da | ||
|
|
0739792d01 | ||
|
|
6f4f1b06d3 | ||
|
|
0049b07a1c | ||
|
|
fe1983cfa1 | ||
|
|
a4ac44a84f | ||
|
|
4c13ed6aee | ||
|
|
eafd832c04 | ||
|
|
e13872fdb2 | ||
|
|
9a9b9edb9a | ||
|
|
0f353bd2b3 | ||
|
|
c1b832bbf8 | ||
|
|
073957f0a1 | ||
|
|
c678061b79 | ||
|
|
12c7d85ff6 | ||
|
|
66834e7209 | ||
|
|
21072cf13e | ||
|
|
d952f6c721 | ||
|
|
0efe44bc70 | ||
|
|
631d72465a | ||
|
|
4024181af2 | ||
|
|
38487bbec8 | ||
|
|
c74a48ccd8 | ||
|
|
df1f32f772 | ||
|
|
f2b9b3a0c2 | ||
|
|
1c45f7bbde | ||
|
|
a1f21e8ef5 | ||
|
|
eba94168ce | ||
|
|
06c1f31632 | ||
|
|
9826c667e0 | ||
|
|
35280c1444 | ||
|
|
82160a5de6 | ||
|
|
07d9fa9ddc | ||
|
|
54853a954c | ||
|
|
f00f6b6cf2 | ||
|
|
d280d23a83 | ||
|
|
821e0019fb | ||
|
|
5ef40e0234 | ||
|
|
399e18d669 | ||
|
|
92fba35d27 | ||
|
|
0528bdac15 | ||
|
|
5db098e953 | ||
|
|
b45536fe8d | ||
|
|
3dde5cc8cb | ||
|
|
5787ec4f59 | ||
|
|
2dc880bf1c | ||
|
|
440f38858f | ||
|
|
f7f895c211 | ||
|
|
654dc14e6e | ||
|
|
543be33b13 | ||
|
|
7345bfddef | ||
|
|
16a35eefab | ||
|
|
74ab16ea5b | ||
|
|
2adbf5a8d7 | ||
|
|
e4a02eb998 | ||
|
|
ad11ab2210 | ||
|
|
6b0d448f6a | ||
|
|
32c9db8f37 | ||
|
|
a77423a46f | ||
|
|
57fd02b2e0 | ||
|
|
14faba1c62 | ||
|
|
8ab087c95c | ||
|
|
61d62e8920 | ||
|
|
7ce61655a7 | ||
|
|
8d133d4726 | ||
|
|
7caa6092b7 | ||
|
|
d98d8c0a0d | ||
|
|
e2d63e38f6 | ||
|
|
579e3520a4 | ||
|
|
90d07a68be | ||
|
|
2cb3f4d5e6 | ||
|
|
3a23e89cb5 | ||
|
|
70e1ac1462 | ||
|
|
d4ba528935 | ||
|
|
8a8aad183f | ||
|
|
cfc6654855 | ||
|
|
f2efe4331b | ||
|
|
dfa7e9b730 | ||
|
|
765bdd80dc | ||
|
|
739d2f9bd4 | ||
|
|
eb7738e4aa | ||
|
|
32f5d8df07 | ||
|
|
7b5887c324 | ||
|
|
0326b7c14a | ||
|
|
1dfe26a538 | ||
|
|
9c1564a22f | ||
|
|
028964cf7d | ||
|
|
5a84c1a746 | ||
|
|
0f9563969d | ||
|
|
d3ffebab74 | ||
|
|
ece6c39a65 | ||
|
|
ad151d3e55 | ||
|
|
b65d719353 | ||
|
|
a42dff4ad8 | ||
|
|
4a7d5a6e54 | ||
|
|
50a0df0be4 | ||
|
|
cecebf6e86 | ||
|
|
ad4430706e | ||
|
|
93d4a373fb | ||
|
|
a9f51531d9 | ||
|
|
6bb98110b4 | ||
|
|
0b34aea202 | ||
|
|
f1e92d05d5 | ||
|
|
8ec2bcb89a | ||
|
|
beb87ef41f | ||
|
|
26a6def62f | ||
|
|
0fb597ef36 | ||
|
|
fe5dd9a61a | ||
|
|
bb9b0edcc5 | ||
|
|
f3176a664c | ||
|
|
1cbbe90a09 | ||
|
|
a9174f65ba | ||
|
|
2af2dd2350 | ||
|
|
9c77b8434a | ||
|
|
646794cbda | ||
|
|
93fdcf92e1 | ||
|
|
fbbd9514c5 | ||
|
|
be5c41b3c1 | ||
|
|
b853ee9f35 | ||
|
|
eb2625c4a7 | ||
|
|
e17f6cd23c | ||
|
|
54acd56b48 | ||
|
|
9bdd4b078a | ||
|
|
f5748da36c | ||
|
|
eade67b409 | ||
|
|
b3f62f79c2 | ||
|
|
9d133d5b69 | ||
|
|
9f003b5bf5 | ||
|
|
e688e20151 | ||
|
|
8749708115 | ||
|
|
5cc5d8d9b3 | ||
|
|
98b4119746 | ||
|
|
c889905e47 | ||
|
|
db54dadb46 | ||
|
|
604260f56e | ||
|
|
581a3ebc17 | ||
|
|
cc1acaba96 | ||
|
|
7b781ab6b6 | ||
|
|
233eb52a97 | ||
|
|
aff9743269 | ||
|
|
ce1d05fac5 | ||
|
|
6dad313734 | ||
|
|
5263e25548 | ||
|
|
39b8298390 | ||
|
|
57b80ea78a | ||
|
|
a5b7141fc4 | ||
|
|
9efb01da68 | ||
|
|
860c45ab2a | ||
|
|
8686edfc63 | ||
|
|
5e7a7c4738 | ||
|
|
928cc1146a | ||
|
|
d420afdacd | ||
|
|
f6015300a0 | ||
|
|
e183064744 | ||
|
|
40849c94ef | ||
|
|
4c1424f9bd | ||
|
|
0783f97fc0 | ||
|
|
e551885c24 | ||
|
|
4891a04258 | ||
|
|
ad77a9a75e | ||
|
|
5bf35a6b31 | ||
|
|
49044099dd | ||
|
|
7c423067a8 | ||
|
|
d08fa765b9 | ||
|
|
f47bcd8e3f | ||
|
|
873e79ec37 | ||
|
|
589b2ae85a | ||
|
|
f9f2b5f177 | ||
|
|
4157dc8a88 | ||
|
|
d0fc1456b7 | ||
|
|
86f70a7d9c | ||
|
|
f7b53f045d | ||
|
|
f3d140e363 | ||
|
|
93a1770f37 | ||
|
|
859a732509 | ||
|
|
eb778be64b | ||
|
|
2b2ae65182 | ||
|
|
e1b52d3676 | ||
|
|
ff4745b191 | ||
|
|
2ba694830d | ||
|
|
12c5c96ca2 | ||
|
|
a97af1fb97 | ||
|
|
5bf6a1e30c | ||
|
|
f8883cb700 | ||
|
|
f72ffe3c12 | ||
|
|
d2e896fbe1 | ||
|
|
a0b1799270 | ||
|
|
1d423ab2b9 | ||
|
|
7f5df4bf6e | ||
|
|
9f1fdc418d | ||
|
|
64cf4beb8a | ||
|
|
119174b7dd | ||
|
|
b3a7728299 | ||
|
|
2266a19900 | ||
|
|
1b587bee9a | ||
|
|
31b289adfe | ||
|
|
efadb34c84 | ||
|
|
58d63b4e5b | ||
|
|
0441a03bb9 | ||
|
|
90cb449ada | ||
|
|
a678d7baab | ||
|
|
2911bf33c9 | ||
|
|
221daf6e6a | ||
|
|
8f5a45f9e7 | ||
|
|
6f5fd80e0e | ||
|
|
1caeda0799 | ||
|
|
3fb33b8e47 | ||
|
|
e6288a7313 | ||
|
|
7dd7edff64 | ||
|
|
4b94c38f95 | ||
|
|
217adb3d8e | ||
|
|
e63e373ae1 | ||
|
|
9c11c5cc82 | ||
|
|
8b24f0fd9f | ||
|
|
701e14f72f | ||
|
|
c9c1464075 | ||
|
|
e831d89acf | ||
|
|
133c125f93 | ||
|
|
b9cea6312a | ||
|
|
1b37d60840 | ||
|
|
a70aa5285e | ||
|
|
2eba04961d | ||
|
|
3519f82f79 | ||
|
|
e9491e473c | ||
|
|
9e3075cff5 | ||
|
|
7c9ba95565 | ||
|
|
3ae285424c | ||
|
|
fa1d3b3d6a | ||
|
|
63f8c2af4f | ||
|
|
29eb98d79d | ||
|
|
5b004ca49d | ||
|
|
34df78f8ab | ||
|
|
e234e45846 | ||
|
|
081ec279ed | ||
|
|
4399fa327f | ||
|
|
ceaa6e01ed | ||
|
|
235f0dcbfb | ||
|
|
fadd7fefbc | ||
|
|
193b6027c2 | ||
|
|
a76439a641 | ||
|
|
89cc598217 | ||
|
|
28ce6213fc | ||
|
|
6d1f48c1bf | ||
|
|
0e20bcaff8 | ||
|
|
aae61ad8ba | ||
|
|
4dac6ce6ac | ||
|
|
875a9e450b | ||
|
|
48d2e3b9d1 | ||
|
|
5626a633d5 | ||
|
|
3652ba24e3 | ||
|
|
740fc90ae7 | ||
|
|
e0de2dbf39 | ||
|
|
efcf9eb341 | ||
|
|
2545fa5967 | ||
|
|
c91674eed2 | ||
|
|
542728671e | ||
|
|
d1621b6672 | ||
|
|
6d1cc1187b | ||
|
|
377c3a37e1 | ||
|
|
d03324135c | ||
|
|
edeaff4730 | ||
|
|
c85fee6eb5 | ||
|
|
0ccb143a12 | ||
|
|
941beed3b3 | ||
|
|
739a3e606c | ||
|
|
61cc934b68 | ||
|
|
7aec4532f9 | ||
|
|
6f22aab0b8 | ||
|
|
592cf2fea1 | ||
|
|
3d818560eb | ||
|
|
da66a3f7c9 | ||
|
|
e5ce5b0967 | ||
|
|
03342b8d22 | ||
|
|
86c1895ceb | ||
|
|
fd4fb482fe | ||
|
|
0fbbc0f808 | ||
|
|
ced80ebb21 | ||
|
|
7b0d9367b2 | ||
|
|
37512d7f89 | ||
|
|
f8b5bbe555 | ||
|
|
698b3f1e43 | ||
|
|
bdf477de4b | ||
|
|
b03d5dce36 | ||
|
|
03390cfb5f | ||
|
|
45c66a4d07 | ||
|
|
a317b6ead7 | ||
|
|
ed672dd39b | ||
|
|
72e639ff1a | ||
|
|
95c899f3e2 | ||
|
|
6d4113e3c3 | ||
|
|
8d720b8932 | ||
|
|
422420c494 | ||
|
|
2c8b586679 | ||
|
|
e748b461b6 | ||
|
|
17a061a1fa | ||
|
|
29d42e0771 | ||
|
|
e818c05e33 | ||
|
|
29cb16c42e | ||
|
|
d478e75178 | ||
|
|
eb03c7058e | ||
|
|
1e7a5c7f6e | ||
|
|
b9bd9e3229 | ||
|
|
b25906e610 | ||
|
|
5ca0eee4cd | ||
|
|
a751498fbc | ||
|
|
9292c9294a | ||
|
|
4083c581d6 | ||
|
|
86ff123318 | ||
|
|
a8cbf2e429 | ||
|
|
96d53eaa31 | ||
|
|
b5292f7c58 | ||
|
|
6b80cfefb6 | ||
|
|
7540b37e8f |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,5 +1,12 @@
|
||||
*.sw?
|
||||
*.un?
|
||||
*.vba
|
||||
*.vmb
|
||||
*.zip
|
||||
*.gz
|
||||
vimball.txt
|
||||
*.orig
|
||||
tags
|
||||
test/build
|
||||
test/*.tap
|
||||
test/*.msgout
|
||||
|
||||
21
LICENSE.txt
Normal file
21
LICENSE.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Israel Chauca
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
26
Makefile
26
Makefile
@@ -1,21 +1,15 @@
|
||||
PLUGIN=delimitMate
|
||||
.DEFAULT: test
|
||||
|
||||
install:
|
||||
cp -f doc/* ~/.vim/doc/${PLUGIN}.txt
|
||||
cp -f plugin/* ~/.vim/plugin/${PLUGIN}.vim
|
||||
test_files := $(wildcard test/*.test)
|
||||
short_targets := $(patsubst test/%,%,$(test_files))
|
||||
|
||||
doc_update: install
|
||||
/usr/bin/vim -u NONE -c ':helptags ~/.vim/doc' -c ':q'
|
||||
.PHONY: monitor test $(test_files) $(short_targets)
|
||||
|
||||
zip:
|
||||
zip -r ${PLUGIN}.zip doc plugin
|
||||
zip ${PLUGIN}.zip -d \*.sw\?
|
||||
test:
|
||||
$(MAKE) -C test
|
||||
|
||||
vimball: install
|
||||
echo doc/${PLUGIN}.txt > vimball.txt
|
||||
echo plugin/${PLUGIN}.vim >> vimball.txt
|
||||
/usr/bin/vim -c 'e vimball.txt' -c '%MkVimball! ${PLUGIN}' -c 'q'
|
||||
|
||||
gzip: vimball
|
||||
gzip -f ${PLUGIN}.vba
|
||||
monitor:
|
||||
$(MAKE) -C test monitor
|
||||
|
||||
$(test_files) $(short_targets):
|
||||
$(MAKE) -C test $(patsubst test/%,%,$@)
|
||||
|
||||
6
README.md
Normal file
6
README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
This plug-in provides automatic closing of quotes, parenthesis, brackets, etc., besides some other related features that
|
||||
should make your time in insert mode a little bit easier, like syntax awareness (will not insert the closing delimiter
|
||||
in comments and other configurable regions), <CR> and <Space> expansions (off by default), and some more.
|
||||
|
||||
Most of the features can be modified or disabled permanently, using global variables, or on a FileType basis, using
|
||||
:autocmd.
|
||||
588
autoload/delimitMate.vim
Normal file
588
autoload/delimitMate.vim
Normal file
@@ -0,0 +1,588 @@
|
||||
" Script variables {{{1
|
||||
let s:defaults = {}
|
||||
let s:defaults.enabled = 1
|
||||
let s:defaults.pairs = ['()', '[]', '{}']
|
||||
let s:defaults.quotes = ['"', "'", '`']
|
||||
let s:defaults.debug = 0
|
||||
let s:defaults.autoclose = 1
|
||||
let s:defaults.expand_space = 0
|
||||
let s:defaults.expand_cr = 0
|
||||
let s:defaults.jump_expansion = 0
|
||||
let s:defaults.jump_next = 1
|
||||
let s:defaults.jump_long = 0
|
||||
let s:defaults.insert_eol_marker = 0
|
||||
let s:defaults.eol_marker = ';'
|
||||
let s:defaults.expand_inside_quotes = 0
|
||||
let s:defaults.smart_pairs = 1
|
||||
let s:defaults.smart_pairs_extra = []
|
||||
let s:defaults.balance_pairs = 0
|
||||
let s:defaults.nesting_quotes = []
|
||||
let s:defaults.smart_quotes = 1
|
||||
let s:defaults.smart_quotes_extra = []
|
||||
let s:defaults.excluded_regions = []
|
||||
|
||||
" Set smart_pairs expressions:
|
||||
let s:exprs = []
|
||||
call add(s:exprs, 'next_char =~# "\\w"')
|
||||
call add(s:exprs, 'next_char =~# "[".escape(v:char,"\\^]")."€£$]"')
|
||||
call add(s:exprs,
|
||||
\'next_char =~# "[".escape(join(s:option("quotes"),""),"\\^]")."]"')
|
||||
call add(s:exprs, 'ahead =~# "^[^[:space:][:punct:]]"')
|
||||
let s:defaults.smart_pairs_base = s:exprs
|
||||
|
||||
" Set smart_quotes expressions:
|
||||
let s:exprs = []
|
||||
call add(s:exprs, 'prev_char =~# "\\w"')
|
||||
call add(s:exprs, 'prev_char =~# "[^[:space:][:punct:]"
|
||||
\.escape(join(options.quotes, ""), "\\^[]")."]"')
|
||||
call add(s:exprs, 'next_char =~# "\\w"')
|
||||
call add(s:exprs, 'char == "\"" && &filetype =~? "\\<vim\\>"
|
||||
\&& line =~ "^\\s*$"')
|
||||
call add(s:exprs, 'next_char =~# "[^[:space:][:punct:]"
|
||||
\. escape(join(options.quotes, ""), "\\^[]")."]"')
|
||||
" Balance quotes
|
||||
call add(s:exprs, 'strchars(substitute(substitute(a:info.cur.line,
|
||||
\"\\\\.", "", "g"), "[^".escape(char, "\\^[]")."]", "", "g")) % 2')
|
||||
|
||||
let s:defaults.smart_quotes_base = s:exprs
|
||||
|
||||
unlet s:exprs
|
||||
|
||||
let s:info = {}
|
||||
let s:info.char = ''
|
||||
let s:info.nesting = 0
|
||||
let s:info.skip_icp = 0
|
||||
let s:info.is_ignored_syn = 0
|
||||
let s:info.template = {}
|
||||
|
||||
function! s:debug(debug_level, ...) "{{{1
|
||||
if get(b:, 'delimitMate_debug',
|
||||
\ get(g:, 'delimitMate_debug',
|
||||
\ get(s:defaults, 'debug', 0)))
|
||||
let trail = expand('<sfile>')
|
||||
let trail = substitute(trail, '\%(\.\.<SNR>\d\+_debug\)\+$', '', '')
|
||||
let trail = substitute(trail, '<SNR>\d\+_', '', 'g')
|
||||
let trail = substitute(trail, '\.\.', '.', 'g')
|
||||
let trail = substitute(trail, '^function\s\+\%(delimitMate\)\?', '', '')
|
||||
let message = get(a:, 1, '')
|
||||
echom printf('%s: %s', trail, message)
|
||||
endif
|
||||
endfunction
|
||||
command! -nargs=* -count=3 DMDebug call s:debug(<count>, <args>)
|
||||
|
||||
function! s:defaults.consolidate() "{{{1
|
||||
3DMDebug 'Consolidate options'
|
||||
let g = filter(copy(g:), 'v:key =~# "^delimitMate_"')
|
||||
let b = filter(copy(b:), 'v:key =~# "^delimitMate_"')
|
||||
call extend(g, b, 'force')
|
||||
let short_options = {}
|
||||
call map(g, 'extend(short_options,
|
||||
\{substitute(v:key, "^delimitMate_", "", ""): v:val}, "force")')
|
||||
call extend(short_options, self, 'keep')
|
||||
return short_options
|
||||
endfunction
|
||||
|
||||
function! s:info.update() "{{{1
|
||||
let self.prev = get(self, 'cur', {})
|
||||
let d = {}
|
||||
let d.line = getline('.')
|
||||
let d.col = col('.')
|
||||
let d.lnum = line('.')
|
||||
let d.prev_line = line('.') == 1 ? '' : getline(line('.') - 1)
|
||||
let d.next_line = line('.') == line('$') ? '' : getline(line('.') + 1)
|
||||
let d.ahead = len(d.line) >= d.col ? d.line[d.col - 1 : ] : ''
|
||||
let d.behind = d.col >= 2 ? d.line[: d.col - 2] : ''
|
||||
let d.prev_char = strcharpart(d.behind, strchars(d.behind) - 1, 1)
|
||||
let d.next_char = strcharpart(d.ahead, 0, 1)
|
||||
let d.around = d.prev_char . d.next_char
|
||||
call extend(d, s:info.template, 'keep')
|
||||
1DMDebug printf('lnum: %s, col: %s, prev_char: %s, next_char: %s',
|
||||
\ d.lnum, d.col, string(d.prev_char), string(d.next_char))
|
||||
1DMDebug printf("behind: %s", d.behind)
|
||||
1DMDebug printf("ahead : %s", d.ahead )
|
||||
1DMDebug printf("prev_line: %s", d.prev_line)
|
||||
1DMDebug printf('cur_line : %s', d.line)
|
||||
1DMDebug printf('next_line: %s', d.next_line)
|
||||
let self.cur = d
|
||||
return d
|
||||
endfunction
|
||||
|
||||
function! s:balance_pairs(pair, info, opts) "{{{1
|
||||
let left = strcharpart(a:pair, 0, 1)
|
||||
let right = strcharpart(a:pair, 1, 1)
|
||||
let pat = '[^' . escape(a:pair, '\^[]') . ']'
|
||||
let behind = substitute(a:info.cur.behind, '\\.', '', 'g')
|
||||
let behind = matchstr(behind, '['.escape(left, '\^[]').'].*')
|
||||
let behind = substitute(behind, pat, '', 'g')
|
||||
let ahead = substitute(a:info.cur.ahead, '\\.', '', 'g')
|
||||
let ahead = matchstr(ahead, '^.*['.escape(right, '\^[]').']')
|
||||
let ahead = substitute(ahead, pat, '', 'g')
|
||||
let lefts = 0
|
||||
let rights = 0
|
||||
for char in split(behind, '\zs')
|
||||
if char ==# left
|
||||
let lefts += 1
|
||||
elseif char ==# right
|
||||
let rights += rights < lefts
|
||||
endif
|
||||
endfor
|
||||
let balance1 = lefts - rights
|
||||
let lefts = 0
|
||||
let rights = 0
|
||||
let balance2 = 0
|
||||
for char in split(ahead, '\zs')
|
||||
if char ==# left
|
||||
let lefts += 1
|
||||
elseif char ==# right
|
||||
let rights += 1
|
||||
endif
|
||||
if lefts < rights
|
||||
let balance2 -= 1
|
||||
let lefts = 0
|
||||
let rights = 0
|
||||
endif
|
||||
endfor
|
||||
3DMDebug balance1 + balance2
|
||||
return balance1 + balance2
|
||||
endfunction
|
||||
|
||||
function! s:info.template.is_escaped(...) "{{{1
|
||||
3DMDebug
|
||||
let str = a:0 ? a1 : self.behind
|
||||
return len(matchstr(str, '\\*$')) % 2
|
||||
endfunction
|
||||
|
||||
function! s:option(name) "{{{1
|
||||
3DMDebug
|
||||
let opt = get(b:, 'delimitMate_' . a:name,
|
||||
\ get(g:, 'delimitMate_' . a:name,
|
||||
\ get(s:defaults, a:name, '')))
|
||||
3DMDebug printf('%s: %s', a:name, string(opt))
|
||||
if type(opt) == 3 || type(opt) == 4
|
||||
return copy(opt)
|
||||
endif
|
||||
return opt
|
||||
endfunction
|
||||
|
||||
function! s:synstack(lnum, col) "{{{1
|
||||
3DMDebug
|
||||
return map(synstack(a:lnum, a:col), 'synIDattr(v:val, "name")')
|
||||
\+ [synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name')]
|
||||
endfunction
|
||||
|
||||
function! s:any_is_true(expressions, info, options) "{{{1
|
||||
let char = a:info.char
|
||||
let info = deepcopy(a:info)
|
||||
let options = deepcopy(a:options)
|
||||
let line = info.cur.line
|
||||
let lnum = info.cur.lnum
|
||||
let col = info.cur.col
|
||||
let behind = info.cur.behind
|
||||
let ahead = info.cur.ahead
|
||||
let prev_char = info.cur.prev_char
|
||||
let next_char = info.cur.next_char
|
||||
let exprs = copy(a:expressions)
|
||||
call filter(exprs, 'eval(v:val)')
|
||||
3DMDebug string(exprs)
|
||||
return !empty(exprs)
|
||||
endfunction
|
||||
|
||||
function! s:rights2jump_pair(char, pair, info, opts, go_next) "{{{1
|
||||
" TODO consider escaped characters
|
||||
let go_next = a:go_next
|
||||
\ && empty(a:info.cur.ahead)
|
||||
\ && a:info.cur.next_line =~# '^\s*['.escape(a:char, '[]^-\').']'
|
||||
let line = a:info.cur.ahead
|
||||
3DMDebug 'ahead: ' . line
|
||||
let pair_pat = '[' . escape(a:pair, '[]^\-') . ']'
|
||||
let char_pat = '[' . escape(a:char, '[]^\-') . ']'
|
||||
let idx = match(line, pair_pat)
|
||||
let balance = 0
|
||||
while go_next || idx >= 0 && balance >= 0 && line[idx : ] !~# char_pat
|
||||
if idx == -1
|
||||
let idx = strchars(matchstr(a:info.cur.next_line, '^\s*\S'))
|
||||
break
|
||||
endif
|
||||
if line[idx : ] =~# char_pat
|
||||
let balance -= 1
|
||||
else
|
||||
let balance += 1
|
||||
endif
|
||||
let idx = match(line, pair_pat, idx + 1)
|
||||
endwhile
|
||||
3DMDebug 'idx: ' . idx
|
||||
return idx + 1
|
||||
endfunction
|
||||
if line[idx : ] =~# char_pat
|
||||
let balance -= 1
|
||||
else
|
||||
let balance += 1
|
||||
endif
|
||||
let idx = match(line, pair_pat, idx + 1)
|
||||
endwhile
|
||||
3DMDebug 'idx: ' . idx
|
||||
return idx + 1
|
||||
endfunction
|
||||
|
||||
function! s:keys4space(info, opts) "{{{1
|
||||
2DMDebug string(a:opts)
|
||||
let empty_pair = !empty(filter(copy(a:opts.pairs),
|
||||
\'v:val ==# a:info.cur.around'))
|
||||
if a:opts.expand_space && empty_pair
|
||||
2DMDebug "expand space inside a pair"
|
||||
return " \<C-G>U\<Left>"
|
||||
endif
|
||||
let empty_quotes = !empty(filter(copy(a:opts.quotes),
|
||||
\'v:val.v:val ==# a:info.cur.around'))
|
||||
if a:opts.expand_space && a:opts.expand_inside_quotes && empty_quotes
|
||||
2DMDebug "expand space inside quotes"
|
||||
return " \<C-G>U\<Left>"
|
||||
endif
|
||||
2DMDebug "do nothing"
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:keys4left(char, pair, info, opts) "{{{1
|
||||
"| cases | criteria | action options | action
|
||||
"| | balance | auto balance back smart | close back
|
||||
"|--------|----------|-----------------------------|------------
|
||||
"| any | any | 0 0 1 1 | 0 0
|
||||
"| any | any | 0 0 1 0 | 0 0
|
||||
"| (|)) | -1 | 1 1 1 0 | 0 0
|
||||
"| (|) | 0 | 1 1 1 0 | 1 1
|
||||
"| ((|) | 1 | 1 1 1 0 | 1 0
|
||||
if !a:opts.autoclose
|
||||
2DMDebug "No autoclose"
|
||||
return ''
|
||||
endif
|
||||
let exprs = a:opts.smart_pairs_base + a:opts.smart_pairs_extra
|
||||
if a:opts.smart_pairs && s:any_is_true(exprs, a:info, a:opts)
|
||||
2DMDebug "smart pairs"
|
||||
return ''
|
||||
endif
|
||||
if a:opts.balance_pairs && s:balance_pairs(a:pair, a:info, a:opts) < 0
|
||||
2DMDebug "balance pairs"
|
||||
return ''
|
||||
endif
|
||||
let eol_marker = a:opts.insert_eol_marker == 1
|
||||
\&& empty(a:info.cur.ahead) ? a:opts.eol_marker
|
||||
\ . "\<C-G>U\<Left>" : ''
|
||||
2DMDebug "add right delimiter"
|
||||
let jump_back = a:opts.jump_back ? "\<C-G>U\<Left>" : ''
|
||||
return "\<C-V>" . strcharpart(a:pair, 1, 1) . eol_marker . jump_back
|
||||
endfunction
|
||||
|
||||
function! s:keys4right(char, pair, info, opts) "{{{1
|
||||
"| cases | criteria | action options | action
|
||||
"| | next prev close bal | next long bal | jump back
|
||||
"|--------|---------------------|----------------|-----------
|
||||
"| (|)) | 1 1 1 -1 | 1 1 0 | 1 0
|
||||
"| (|) | 1 1 1 0 | 1 1 0 | 1 0
|
||||
"| ((|) | 1 1 1 1 | 1 1 0 | 1 0
|
||||
"| x|) | 1 0 1 -1 | 1 1 0 | 1 0
|
||||
"| (x|) | 1 0 1 0 | 1 1 0 | 1 0
|
||||
"| ((x|) | 1 0 1 1 | 1 1 1 | 1 0
|
||||
"| (| | 0 1 0 1 | 0 0 1 | 0 1
|
||||
"| |x) | 0 0 1 -1 | 0 1 0 | 1 0
|
||||
"| (x|x)) | 0 0 1 -1 | 0 1 0 | 1 0
|
||||
"| (x|x) | 0 0 1 0 | 0 1 0 | 1 0
|
||||
"| ((x|x) | 0 0 1 1 | 0 0 1 | 0 1
|
||||
"| x| | 0 0 0 0 | 0 0 0 | 0 0
|
||||
"| (x| | 0 0 0 1 | 0 0 0 | 0 0
|
||||
let previous = strcharpart(a:pair, 0, 1) ==# a:info.cur.prev_char
|
||||
let is_cr_exp = a:opts.expand_cr
|
||||
\ && empty(a:info.cur.ahead)
|
||||
\ && matchstr(a:info.cur.next_line, '^\s*\zs\S') ==# a:char
|
||||
let is_space_exp = a:opts.expand_space
|
||||
\ && matchstr(a:info.cur.ahead, '^\s\zs\S') ==# a:char
|
||||
let next = a:char ==# a:info.cur.next_char || is_cr_exp || is_space_exp
|
||||
let balance = s:balance_pairs(a:pair, a:info, a:opts)
|
||||
\ - is_cr_exp
|
||||
let next_line = a:opts.jump_expansion && a:opts.expand_cr
|
||||
let closing = s:rights2jump_pair(a:char, a:pair, a:info, a:opts, next_line)
|
||||
let jump_opts = a:opts.jump_next + (a:opts.jump_long * 2)
|
||||
2DMDebug 'is_cr_exp: ' . is_cr_exp
|
||||
2DMDebug 'is_space_exp: ' . is_space_exp
|
||||
2DMDebug 'next: ' . next
|
||||
2DMDebug 'previous: ' . previous
|
||||
2DMDebug 'closing: ' . closing
|
||||
2DMDebug 'balance: ' . balance
|
||||
2DMDebug 'next_line: ' . next_line
|
||||
2DMDebug 'jump_opts: ' . jump_opts
|
||||
if next
|
||||
2DMDebug "next"
|
||||
if closing && jump_opts && (!a:opts.balance_pairs || balance <= 0)
|
||||
2DMDebug "cases: '(|)', '(|))' or '((|)'"
|
||||
2DMDebug "cases: 'x|)', '(x|)' or '((x|)'"
|
||||
return "\<BS>" . repeat("\<C-G>U\<Right>", closing)
|
||||
endif
|
||||
2DMDebug "Nothing to do"
|
||||
return ''
|
||||
endif
|
||||
" !next
|
||||
if previous
|
||||
2DMDebug "!next && previous"
|
||||
if (!a:opts.balance_pairs || balance > 0) && a:opts.jump_back
|
||||
2DMDebug "case: '(|'"
|
||||
return "\<C-G>U\<Left>"
|
||||
endif
|
||||
2DMDebug "Nothing to do"
|
||||
return ''
|
||||
endif
|
||||
" !next && !previous
|
||||
if closing
|
||||
2DMDebug "!next && !previous && closing"
|
||||
if (!a:opts.balance_pairs || balance <= 0) && jump_opts >= 2
|
||||
2DMDebug "case: '(x|x))' or '(x|x)'"
|
||||
return "\<BS>" . repeat("\<C-G>U\<Right>", closing)
|
||||
elseif (!a:opts.balance_pairs || balance > 0) && a:opts.jump_back
|
||||
2DMDebug "case: '((x|x)'"
|
||||
return "\<C-G>U\<Left>"
|
||||
endif
|
||||
2DMDebug "Nothing to do"
|
||||
return ''
|
||||
endif
|
||||
2DMDebug "Nothing to do"
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:keys4quote(char, info, opts) "{{{1
|
||||
let quotes_behind = strchars(matchstr(a:info.cur.behind,
|
||||
\'['.escape(a:char, '\^[]').']*$'))
|
||||
let quotes_ahead = strchars(matchstr(a:info.cur.ahead,
|
||||
\'^['.escape(a:char, '\^[]').']*'))
|
||||
2DMDebug quotes_behind . ' - ' . quotes_ahead
|
||||
2DMDebug string(a:opts.nesting_quotes)
|
||||
if a:opts.autoclose && index(a:opts.nesting_quotes, a:char) >= 0
|
||||
\&& quotes_behind > 1
|
||||
let add2right = quotes_ahead > quotes_behind + 1
|
||||
\? 0 : quotes_behind - quotes_ahead + 1
|
||||
2DMDebug "nesting quotes"
|
||||
2DMDebug add2right
|
||||
return repeat(a:char, add2right) . repeat("\<C-G>U\<Left>", add2right)
|
||||
endif
|
||||
if a:info.cur.next_char ==# a:char
|
||||
2DMDebug "jump over quote"
|
||||
return "\<Del>"
|
||||
endif
|
||||
if a:info.is_ignored_syn
|
||||
return ''
|
||||
endif
|
||||
let exprs = a:opts.smart_quotes_base + a:opts.smart_quotes_extra
|
||||
if a:opts.autoclose && a:opts.smart_quotes
|
||||
\&& s:any_is_true(exprs, a:info, a:opts)
|
||||
2DMDebug "smart quotes"
|
||||
return ''
|
||||
endif
|
||||
if !a:opts.autoclose && quotes_behind
|
||||
2DMDebug "don't autoclose, jump back"
|
||||
return "\<C-G>U\<Left>"
|
||||
endif
|
||||
if !a:opts.autoclose
|
||||
2DMDebug "don't autoclose"
|
||||
return ''
|
||||
endif
|
||||
2DMDebug "jump back"
|
||||
return a:char . "\<C-G>U\<Left>"
|
||||
endfunction
|
||||
|
||||
function! s:keys4cr(info, opts) "{{{1
|
||||
if a:opts.expand_cr
|
||||
\&& !empty(filter(copy(a:opts.pairs),
|
||||
\ 'v:val ==# a:info.prev.around'))
|
||||
\|| (a:opts.expand_cr == 2
|
||||
\ && !empty(filter(copy(a:opts.pairs),
|
||||
\ 'strcharpart(v:val, 1, 1) == a:info.cur.next_char')))
|
||||
" Empty pair
|
||||
2DMDebug "expand CR inside pair"
|
||||
let eol_marker = a:opts.insert_eol_marker == 2
|
||||
\&& strchars(a:info.cur.ahead) == 1 ? a:opts.eol_marker : ''
|
||||
return "0\<C-D>\<Del>x\<C-G>U\<Left>\<BS>\<CR>" . a:info.cur.next_char
|
||||
\. "\<Del>" . eol_marker . "\<Up>\<End>\<CR>"
|
||||
endif
|
||||
if a:opts.expand_cr && a:opts.expand_inside_quotes
|
||||
\&& !empty(filter(copy(a:opts.quotes),
|
||||
\ 'v:val.v:val ==# a:info.prev.around'))
|
||||
" Empty pair
|
||||
2DMDebug "expand CR inside quotes"
|
||||
return "\<Up>\<End>\<CR>"
|
||||
endif
|
||||
2DMDebug "do nothing"
|
||||
return ''
|
||||
endfunction
|
||||
" vim: sw=2 et
|
||||
function! delimitMate#option(name) "{{{1
|
||||
return s:option(a:name)
|
||||
endfunction
|
||||
|
||||
function! delimitMate#ex_cmd(global, action) "{{{1
|
||||
1DMDebug 'action: ' . a:action . ', scope: ' . (a:global ? 'g:' : 'b:')
|
||||
let scope = a:global ? g: : b:
|
||||
if a:action ==# 'enable'
|
||||
let scope.delimitMate_enabled = 1
|
||||
elseif a:action ==# 'disable'
|
||||
let scope.delimitMate_enabled = 0
|
||||
elseif a:action ==# 'switch'
|
||||
let scope.delimitMate_enabled = !s:option('enabled')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! delimitMate#InsertEnter(...) "{{{1
|
||||
1DMDebug
|
||||
call s:info.update()
|
||||
let s:info.skip_icp = 0
|
||||
endfunction
|
||||
|
||||
function! delimitMate#CursorMovedI(...) "{{{1
|
||||
1DMDebug
|
||||
call s:info.update()
|
||||
let s:info.skip_icp = 0
|
||||
endfunction
|
||||
|
||||
function! delimitMate#InsertCharPre(str) "{{{1
|
||||
1DMDebug
|
||||
1DMDebug printf('v:char: %s', string(a:str))
|
||||
if s:info.skip_icp
|
||||
" iabbrev fires this event for every char and the trigger
|
||||
1DMDebug "iabbrev expansion running"
|
||||
return 0
|
||||
endif
|
||||
if pumvisible()
|
||||
1DMDebug "pumvisible"
|
||||
return 0
|
||||
endif
|
||||
if s:info.nesting
|
||||
1DMDebug "nesting"
|
||||
let s:info.nesting -= 1
|
||||
return 0
|
||||
endif
|
||||
let s:info.skip_icp = 1
|
||||
if !s:option('enabled')
|
||||
1DMDebug "disabled"
|
||||
return 0
|
||||
endif
|
||||
let typeahead = ''
|
||||
let synstack = join(map(
|
||||
\synstack(line('.'), col('.')),
|
||||
\'tolower(synIDattr(v:val, "name"))'), ',')
|
||||
let s:info.is_ignored_syn = !empty(filter(
|
||||
\s:option('excluded_regions'),
|
||||
\'stridx(synstack, tolower(v:val)) >= 0'))
|
||||
" v:char could be more than one character
|
||||
for char in split(a:str, '\zs')
|
||||
1DMDebug 'char: ' . char
|
||||
let keys = ''
|
||||
let s:info.char = char
|
||||
let opts = s:defaults.consolidate()
|
||||
if s:info.cur.is_escaped()
|
||||
1DMDebug "escaped"
|
||||
return
|
||||
elseif !empty(filter(copy(opts.quotes), 'v:val ==# char'))
|
||||
1DMDebug "quote"
|
||||
let keys = s:keys4quote(char, s:info, opts)
|
||||
let s:info.nesting = strchars(matchstr(keys, '^[^[:cntrl:]]*'))
|
||||
let s:info.nesting = s:info.nesting < 3 ? 0 : s:info.nesting
|
||||
elseif s:info.is_ignored_syn
|
||||
1DMDebug "ignored syn group"
|
||||
return
|
||||
elseif char == ' '
|
||||
1DMDebug "space"
|
||||
let keys = s:keys4space(s:info, opts)
|
||||
elseif !empty(filter(copy(opts.pairs),
|
||||
\'strcharpart(v:val, 0, 1) ==# char'))
|
||||
1DMDebug "left delimiter"
|
||||
let pair = get(filter(copy(opts.pairs),
|
||||
\'strcharpart(v:val, 0, 1) ==# char'), 0, '')
|
||||
let keys = s:keys4left(char, pair, s:info, opts)
|
||||
elseif !empty(filter(copy(opts.pairs),
|
||||
\'strcharpart(v:val, 1, 1) ==# char'))
|
||||
let pair = get(filter(copy(opts.pairs),
|
||||
\'strcharpart(v:val, 1, 1) ==# char'), 0, '')
|
||||
let keys = s:keys4right(char, pair, s:info, opts)
|
||||
1DMDebug "right delimiter"
|
||||
else
|
||||
1DMDebug "just ignore it"
|
||||
return 0
|
||||
endif
|
||||
1DMDebug 'keys: ' . strtrans(keys)
|
||||
let typeahead .= keys
|
||||
endfor
|
||||
if !empty(typeahead)
|
||||
1DMDebug "feed typeahead: " . strtrans(typeahead)
|
||||
call feedkeys(typeahead, 'tmi')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! delimitMate#TextChangedI(...) "{{{1
|
||||
1DMDebug
|
||||
if pumvisible()
|
||||
1DMDebug "pumvisible"
|
||||
return 0
|
||||
endif
|
||||
if !s:option('enabled')
|
||||
1DMDebug "disabled"
|
||||
return
|
||||
endif
|
||||
if s:info.cur.lnum == s:info.prev.lnum + 1
|
||||
\&& s:info.prev.behind ==# s:info.cur.prev_line
|
||||
\&& s:info.prev.ahead ==# s:info.cur.ahead
|
||||
\&& s:info.cur.behind =~ '^\s*$'
|
||||
" CR
|
||||
1DMDebug "CR at eol"
|
||||
return feedkeys(s:keys4cr(s:info, s:defaults.consolidate()), 'tni')
|
||||
endif
|
||||
if s:info.cur.lnum == s:info.prev.lnum - 1
|
||||
\&& s:info.prev.prev_line ==# s:info.cur.line
|
||||
\&& s:info.prev.next_line ==# s:info.cur.next_line
|
||||
let pair = filter(s:option('pairs'), 's:info.cur.prev_char
|
||||
\. matchstr(s:info.cur.next_line, "^\\s*\\zs\\S") ==# v:val')
|
||||
if s:option('expand_cr') && !empty(pair)
|
||||
1DMDebug "CR expansion inside pair"
|
||||
let spaces = strchars(s:info.cur.next_line, '^\s*')
|
||||
return feedkeys(repeat("\<Del>", spaces), 'nti')
|
||||
endif
|
||||
let quote = filter(s:option('quotes'), 's:info.cur.prev_char
|
||||
\. matchstr(s:info.cur.next_line, "^\\s*\\zs\\S") ==# v:val.v:val')
|
||||
if s:option('expand_cr') && s:option('expand_inside_quotes')
|
||||
\&& !empty(quote)
|
||||
1DMDebug "CR expansion inside quotes"
|
||||
return feedkeys("\<Del>")
|
||||
endif
|
||||
1DMDebug "BS at bol"
|
||||
return
|
||||
endif
|
||||
if s:info.cur.lnum != s:info.prev.lnum
|
||||
1DMDebug "Cursor changed line"
|
||||
return
|
||||
endif
|
||||
if s:info.prev.col - s:info.cur.col != len(s:info.prev.prev_char)
|
||||
1DMDebug "zero or several characters were deleted"
|
||||
return
|
||||
endif
|
||||
if len(s:info.prev.line) == len(s:info.cur.line)
|
||||
1DMDebug "Same line length"
|
||||
return
|
||||
endif
|
||||
1DMDebug s:info.prev.around
|
||||
let pair = filter(s:option('pairs'), 'v:val ==# (s:info.cur.prev_char
|
||||
\ . matchstr(s:info.cur.ahead, "^\\s\\zs\\S"))')
|
||||
let quotes = filter(s:option('quotes'),
|
||||
\ 'v:val . v:val ==# (s:info.cur.prev_char
|
||||
\ . matchstr(s:info.cur.ahead, "^\\s\\zs\\S"))')
|
||||
if s:option('expand_space') && (!empty(pair)
|
||||
\|| (s:option('expand_inside_quotes') && !empty(quotes)))
|
||||
1DMDebug "Space expansion inside pair"
|
||||
return feedkeys("\<Del>", 'tni')
|
||||
endif
|
||||
let pair = filter(s:option('pairs'), 'v:val ==# s:info.prev.around')
|
||||
let quote = filter(s:option('quotes'),
|
||||
\'v:val . v:val ==# s:info.prev.around')
|
||||
if !empty(pair) || !empty(quote)
|
||||
1DMDebug "BS inside empty pair or quotes"
|
||||
let keys = "\<Del>"
|
||||
return feedkeys(keys, 'tni')
|
||||
endif
|
||||
1DMDebug "Everything else"
|
||||
return
|
||||
endfunction
|
||||
|
||||
4
basic_vimrc
Normal file
4
basic_vimrc
Normal file
@@ -0,0 +1,4 @@
|
||||
so ./test/_setup.vim
|
||||
let delimitMate_expand_cr = 1
|
||||
filetype indent plugin on
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,635 +1,22 @@
|
||||
" ============================================================================
|
||||
" File: delimitMate.vim
|
||||
" Version: 2.0
|
||||
" Description: This plugin tries to emulate the auto-completion of delimiters
|
||||
" that TextMate provides.
|
||||
" Maintainer: Israel Chauca F. <israelchauca@gmail.com>
|
||||
" Manual: Read ":help delimitMate".
|
||||
" Credits: Some of the code is modified or just copied from the following:
|
||||
"
|
||||
" - 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
|
||||
"
|
||||
" - Vim Scripts:
|
||||
" http://www.vim.org/scripts/
|
||||
|
||||
" Initialization: {{{
|
||||
if exists("g:loaded_delimitMate") "{{{
|
||||
" User doesn't want this plugin, let's get out!
|
||||
if exists("g:loaded_delimitMate") || &cp || !exists('##InsertCharPre')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_delimitMate = 1
|
||||
|
||||
if exists("s:loaded_delimitMate") && !exists("g:delimitMate_testing")
|
||||
" Don't define the functions if they already exist: just do the work
|
||||
" (unless we are testing):
|
||||
call s:DelimitMateDo()
|
||||
finish
|
||||
endif
|
||||
|
||||
if v:version < 700
|
||||
echoerr "delimitMate: this plugin requires vim >= 7!"
|
||||
finish
|
||||
endif
|
||||
|
||||
let s:loaded_delimitMate = 1 " }}}
|
||||
let delimitMate_version = '2.0'
|
||||
|
||||
function! s:Init() "{{{
|
||||
|
||||
let b:loaded_delimitMate = 1
|
||||
|
||||
" delimitMate_autoclose {{{
|
||||
if !exists("b:delimitMate_autoclose") && !exists("g:delimitMate_autoclose")
|
||||
let b:delimitMate_autoclose = 1
|
||||
elseif !exists("b:delimitMate_autoclose") && exists("g:delimitMate_autoclose")
|
||||
let b:delimitMate_autoclose = g:delimitMate_autoclose
|
||||
else
|
||||
" Nothing to do.
|
||||
endif " }}}
|
||||
|
||||
" delimitMate_matchpairs {{{
|
||||
if !exists("b:delimitMate_matchpairs") && !exists("g:delimitMate_matchpairs")
|
||||
if s:ValidMatchpairs(&matchpairs) == 1
|
||||
let s:matchpairs_temp = &matchpairs
|
||||
else
|
||||
echoerr "delimitMate: There seems to be a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if this is a bug."
|
||||
finish
|
||||
endif
|
||||
elseif exists("b:delimitMate_matchpairs")
|
||||
if s:ValidMatchpairs(b:delimitMate_matchpairs) || b:delimitMate_matchpairs == ""
|
||||
let s:matchpairs_temp = b:delimitMate_matchpairs
|
||||
else
|
||||
echoerr "delimitMate: Invalid format in 'b:delimitMate_matchpairs', falling back to matchpairs. Fix the error and use the command :DelimitMateReload to try again."
|
||||
if s:ValidMatchpairs(&matchpairs) == 1
|
||||
let s:matchpairs_temp = &matchpairs
|
||||
else
|
||||
echoerr "delimitMate: There seems to be a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if this is a bug."
|
||||
let s:matchpairs_temp = ""
|
||||
endif
|
||||
endif
|
||||
else
|
||||
if s:ValidMatchpairs(g:delimitMate_matchpairs) || g:delimitMate_matchpairs == ""
|
||||
let s:matchpairs_temp = g:delimitMate_matchpairs
|
||||
else
|
||||
echoerr "delimitMate: Invalid format in 'g:delimitMate_matchpairs', falling back to matchpairs. Fix the error and use the command :DelimitMateReload to try again."
|
||||
if s:ValidMatchpairs(&matchpairs) == 1
|
||||
let s:matchpairs_temp = &matchpairs
|
||||
else
|
||||
echoerr "delimitMate: There seems to be a problem with 'matchpairs', read ':help matchpairs' and fix it or notify the maintainer of this script if this is a bug."
|
||||
let s:matchpairs_temp = ""
|
||||
endif
|
||||
endif
|
||||
|
||||
endif " }}}
|
||||
|
||||
" delimitMate_quotes {{{
|
||||
if exists("b:delimitMate_quotes")
|
||||
if b:delimitMate_quotes =~ '^\(\S\)\(\s\S\)*$' || b:delimitMate_quotes == ""
|
||||
let s:quotes = split(b:delimitMate_quotes)
|
||||
else
|
||||
let s:quotes = split("\" ' `")
|
||||
echoerr "delimitMate: There is a problem with the format of 'b:delimitMate_quotes', it should be a string of single characters separated by spaces. Falling back to default values."
|
||||
endif
|
||||
elseif exists("g:delimitMate_quotes")
|
||||
if g:delimitMate_quotes =~ '^\(\S\)\(\s\S\)*$' || g:delimitMate_quotes == ""
|
||||
let s:quotes = split(g:delimitMate_quotes)
|
||||
else
|
||||
let s:quotes = split("\" ' `")
|
||||
echoerr "delimitMate: There is a problem with the format of 'g:delimitMate_quotes', it should be a string of single characters separated by spaces. Falling back to default values."
|
||||
endif
|
||||
else
|
||||
let s:quotes = split("\" ' `")
|
||||
endif
|
||||
let b:delimitMate_quotes_list = s:quotes " }}}
|
||||
|
||||
" delimitMate_visual_leader {{{
|
||||
if !exists("b:delimitMate_visual_leader") && !exists("g:delimitMate_visual_leader")
|
||||
let b:delimitMate_visual_leader = exists('b:maplocalleader') ? b:maplocalleader :
|
||||
\ exists('g:mapleader') ? g:mapleader : "\\"
|
||||
elseif !exists("b:delimitMate_visual_leader") && exists("g:delimitMate_visual_leader")
|
||||
let b:delimitMate_visual_leader = g:delimitMate_visual_leader
|
||||
else
|
||||
" Nothing to do.
|
||||
endif " }}}
|
||||
|
||||
" delimitMate_expand_space {{{
|
||||
if !exists("b:delimitMate_expand_space") && !exists("g:delimitMate_expand_space")
|
||||
let b:delimitMate_expand_space = 0
|
||||
elseif !exists("b:delimitMate_expand_space") && !exists("g:delimitMate_expand_space")
|
||||
let b:delimitMate_expand_space = g:delimitMate_expand_space
|
||||
else
|
||||
" Nothing to do.
|
||||
endif " }}}
|
||||
|
||||
" delimitMate_expand_cr {{{
|
||||
if !exists("b:delimitMate_expand_cr") && !exists("g:delimitMate_expand_cr")
|
||||
let b:delimitMate_expand_cr = 0
|
||||
elseif !exists("b:delimitMate_expand_cr") && exists("g:delimitMate_expand_cr")
|
||||
let b:delimitMate_expand_cr = g:delimitMate_expand_cr
|
||||
else
|
||||
" Nothing to do.
|
||||
endif " }}}
|
||||
|
||||
" delimitMate_smart_quotes {{{
|
||||
if !exists("b:delimitMate_smart_quotes") && !exists("g:delimitMate_smart_quotes")
|
||||
let b:delimitMate_smart_quotes = 1
|
||||
elseif !exists("b:delimitMate_smart_quotes") && exists("g:delimitMate_smart_quotes")
|
||||
let b:delimitMate_smart_quotes = split(g:delimitMate_smart_quotes)
|
||||
else
|
||||
" Nothing to do.
|
||||
endif " }}}
|
||||
|
||||
" delimitMate_apostrophes {{{
|
||||
if !exists("b:delimitMate_apostrophes") && !exists("g:delimitMate_apostrophes")
|
||||
"let s:apostrophes = split("n't:'s:'re:'m:'d:'ll:'ve:s'",':')
|
||||
let s:apostrophes = []
|
||||
elseif !exists("b:delimitMate_apostrophes") && exists("g:delimitMate_apostrophes")
|
||||
let s:apostrophes = split(g:delimitMate_apostrophes)
|
||||
else
|
||||
let s:apostrophes = split(b:delimitMate_apostrophes)
|
||||
endif
|
||||
let b:delimitMate_apostrophes_list = s:apostrophes " }}}
|
||||
|
||||
" delimitMate_tab2exit {{{
|
||||
if !exists("b:delimitMate_tab2exit") && !exists("g:delimitMate_tab2exit")
|
||||
let b:delimitMate_tab2exit = 1
|
||||
elseif !exists("b:delimitMate_tab2exit") && exists("g:delimitMate_tab2exit")
|
||||
let b:delimitMate_tab2exit = g:delimitMate_tab2exit
|
||||
else
|
||||
" Nothing to do.
|
||||
endif " }}}
|
||||
|
||||
let b:delimitMate_matchpairs_list = split(s:matchpairs_temp, ',')
|
||||
let b:delimitMate_left_delims = split(s:matchpairs_temp, ':.,\=')
|
||||
let b:delimitMate_right_delims = split(s:matchpairs_temp, ',\=.:')
|
||||
let s:VMapMsg = "delimitMate: delimitMate is disabled on blockwise visual mode."
|
||||
|
||||
call s:UnMap()
|
||||
if b:delimitMate_autoclose
|
||||
call s:AutoClose()
|
||||
else
|
||||
call s:NoAutoClose()
|
||||
endif
|
||||
call s:VisualMaps()
|
||||
call s:ExtraMappings()
|
||||
|
||||
endfunction "}}} Init()
|
||||
"}}}
|
||||
|
||||
" Utilities: {{{
|
||||
function! s:ValidMatchpairs(str) "{{{
|
||||
if a:str !~ '^.:.\(,.:.\)*$'
|
||||
return 0
|
||||
endif
|
||||
for pair in split(a:str,',')
|
||||
if strpart(pair, 0, 1) == strpart(pair, 2, 1) || strlen(pair) != 3
|
||||
return 0
|
||||
endif
|
||||
endfor
|
||||
return 1
|
||||
endfunction "}}}
|
||||
|
||||
function! DelimitMate_ShouldJump() "{{{
|
||||
let char = getline('.')[col('.') - 1]
|
||||
for pair in b:delimitMate_matchpairs_list
|
||||
if char == split( pair, ':' )[1]
|
||||
" Same character on the rigth, jump over it.
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
for quote in b:delimitMate_quotes_list
|
||||
if char == quote
|
||||
" Same character on the rigth, jump over it.
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
return 0
|
||||
endfunction "}}}
|
||||
|
||||
function! s:IsBlockVisual() " {{{
|
||||
if visualmode() == "<C-V>"
|
||||
return 1
|
||||
endif
|
||||
" Store unnamed register values for later use in s:RestoreRegister().
|
||||
let s:save_reg = getreg('"')
|
||||
let s:save_reg_mode = getregtype('"')
|
||||
|
||||
if len(getline('.')) == 0
|
||||
" This for proper wrap of empty lines.
|
||||
let @" = "\n"
|
||||
endif
|
||||
return 0
|
||||
endfunction " }}}
|
||||
|
||||
function! s:IsEmptyPair(str) "{{{
|
||||
for pair in b:delimitMate_matchpairs_list
|
||||
if a:str == join( split( pair, ':' ),'' )
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
for quote in b:delimitMate_quotes_list
|
||||
if a:str == quote . quote
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
return 0
|
||||
endfunction "}}}
|
||||
|
||||
function! DelimitMate_WithinEmptyPair() "{{{
|
||||
let cur = strpart( getline('.'), col('.')-2, 2 )
|
||||
return s:IsEmptyPair( cur )
|
||||
endfunction "}}}
|
||||
|
||||
function! s:WriteBefore(str) "{{{
|
||||
let len = len(a:str)
|
||||
let line = getline('.')
|
||||
let col = col('.')-2
|
||||
if col < 0
|
||||
call setline('.',line[(col+len+1):])
|
||||
else
|
||||
call setline('.',line[:(col)].line[(col+len+1):])
|
||||
endif
|
||||
return a:str
|
||||
endfunction " }}}
|
||||
|
||||
function! s:WriteAfter(str) "{{{
|
||||
let len = len(a:str)
|
||||
let line = getline('.')
|
||||
let col = col('.')-2
|
||||
if (col) < 0
|
||||
call setline('.',a:str.line)
|
||||
else
|
||||
call setline('.',line[:(col)].a:str.line[(col+len):])
|
||||
endif
|
||||
return ''
|
||||
endfunction " }}}
|
||||
|
||||
function! s:RestoreRegister() " {{{
|
||||
" Restore unnamed register values store in s:IsBlockVisual().
|
||||
call setreg('"', s:save_reg, s:save_reg_mode)
|
||||
echo ""
|
||||
endfunction " }}}
|
||||
" }}}
|
||||
|
||||
" Doers: {{{
|
||||
function! s:JumpIn(char) " {{{
|
||||
let line = getline('.')
|
||||
let col = col('.')-2
|
||||
if (col) < 0
|
||||
call setline('.',a:char.line)
|
||||
else
|
||||
"echom string(col).':'.line[:(col)].'|'.line[(col+1):]
|
||||
call setline('.',line[:(col)].a:char.line[(col+1):])
|
||||
endif
|
||||
return ''
|
||||
endfunction " }}}
|
||||
|
||||
function! s:JumpOut(char) "{{{
|
||||
let line = getline('.')
|
||||
let col = col('.')-2
|
||||
if line[col+1] == a:char
|
||||
call setline('.',line[:(col)].line[(col+2):])
|
||||
endif
|
||||
return a:char
|
||||
endfunction " }}}
|
||||
|
||||
function! DelimitMate_JumpAny() " {{{
|
||||
let nchar = getline('.')[col('.')-1]
|
||||
return nchar . "\<Del>"
|
||||
endfunction " DelimitMate_JumpAny() }}}
|
||||
|
||||
function! s:SkipDelim(char) "{{{
|
||||
let cur = strpart( getline('.'), col('.')-2, 3 )
|
||||
if cur[0] == "\\"
|
||||
" Escaped character
|
||||
return a:char
|
||||
elseif cur[1] == a:char
|
||||
" Exit pair
|
||||
return s:WriteBefore(a:char)
|
||||
"elseif cur[1] == ' ' && cur[2] == a:char
|
||||
"" I'm leaving this in case someone likes it. Jump an space and delimiter.
|
||||
"return "\<Right>\<Right>"
|
||||
elseif s:IsEmptyPair( cur[0] . a:char )
|
||||
" Add closing delimiter and jump back to the middle.
|
||||
return s:WriteAfter(a:char)
|
||||
else
|
||||
" Nothing special here, return the same character.
|
||||
return a:char
|
||||
endif
|
||||
endfunction "}}}
|
||||
|
||||
function! s:QuoteDelim(char) "{{{
|
||||
let line = getline('.')
|
||||
let col = col('.') - 2
|
||||
if line[col] == "\\"
|
||||
" Seems like a escaped character, insert one quotation mark.
|
||||
return a:char
|
||||
elseif line[col + 1] == a:char
|
||||
" Get out of the string.
|
||||
return s:WriteBefore(a:char)
|
||||
elseif (line[col] =~ '[a-zA-Z0-9]' && a:char == "'") ||
|
||||
\(line[col] =~ '[a-zA-Z0-9]' && b:delimitMate_smart_quotes)
|
||||
" Seems like an apostrophe or a closing, insert a single quote.
|
||||
return a:char
|
||||
elseif (line[col] == a:char && line[col + 1 ] != a:char) && b:delimitMate_smart_quotes
|
||||
" Seems like we have an unbalanced quote, insert one quotation mark and jump to the middle.
|
||||
return s:WriteAfter(a:char)
|
||||
else
|
||||
" Insert a pair and jump to the middle.
|
||||
call s:WriteAfter(a:char)
|
||||
return a:char
|
||||
endif
|
||||
endfunction "}}}
|
||||
|
||||
function! s:MapMsg(msg) "{{{
|
||||
redraw
|
||||
echomsg a:msg
|
||||
return ""
|
||||
endfunction "}}}
|
||||
"}}}
|
||||
|
||||
" Mappings: {{{
|
||||
function! s:NoAutoClose() "{{{
|
||||
" inoremap <buffer> ) <C-R>=<SID>SkipDelim('\)')<CR>
|
||||
for delim in b:delimitMate_right_delims + b:delimitMate_quotes_list
|
||||
exec 'inoremap <buffer> ' . delim . ' <C-R>=<SID>SkipDelim("' . escape(delim,'"') . '")<CR>'
|
||||
endfor
|
||||
endfunction "}}}
|
||||
|
||||
function! s:AutoClose() "{{{
|
||||
" Add matching pair and jump to the midle:
|
||||
" inoremap <buffer> ( ()<Left>
|
||||
let i = 0
|
||||
while i < len(b:delimitMate_matchpairs_list)
|
||||
let ld = b:delimitMate_left_delims[i]
|
||||
let rd = b:delimitMate_right_delims[i]
|
||||
exec 'inoremap <buffer> ' . ld . ' ' . ld . '<C-R>=<SID>JumpIn("' . rd . '")<CR>'
|
||||
let i += 1
|
||||
endwhile
|
||||
|
||||
" Add matching quote and jump to the midle, or exit if inside a pair of matching quotes:
|
||||
" inoremap <buffer> " <C-R>=<SID>QuoteDelim("\"")<CR>
|
||||
for delim in b:delimitMate_quotes_list
|
||||
exec 'inoremap <buffer> ' . delim . ' <C-R>=<SID>QuoteDelim("\' . delim . '")<CR>'
|
||||
endfor
|
||||
|
||||
" Exit from inside the matching pair:
|
||||
for delim in b:delimitMate_right_delims
|
||||
exec 'inoremap <buffer> ' . delim . ' <C-R>=<SID>JumpOut("\' . delim . '")<CR>'
|
||||
endfor
|
||||
|
||||
" Try to fix the use of apostrophes (de-activated by default):
|
||||
" inoremap <buffer> n't n't
|
||||
for map in b:delimitMate_apostrophes_list
|
||||
exec "inoremap <buffer> " . map . " " . map
|
||||
endfor
|
||||
|
||||
endfunction "}}}
|
||||
|
||||
function! s:VisualMaps() " {{{
|
||||
let vleader = b:delimitMate_visual_leader
|
||||
" Wrap the selection with matching pairs, but do nothing if blockwise visual mode is active:
|
||||
let i = 0
|
||||
while i < len(b:delimitMate_matchpairs_list)
|
||||
" Map left delimiter:
|
||||
let ld = b:delimitMate_left_delims[i]
|
||||
let rd = b:delimitMate_right_delims[i]
|
||||
exec 'vnoremap <buffer> <expr> ' . vleader . ld . ' <SID>IsBlockVisual() ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . ld . '\<C-R>\"' . rd . '\<Esc>:call <SID>RestoreRegister()<CR>"'
|
||||
|
||||
" Map right delimiter:
|
||||
exec 'vnoremap <buffer> <expr> ' . vleader . rd . ' <SID>IsBlockVisual() ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . ld . '\<C-R>\"' . rd . '\<Esc>:call <SID>RestoreRegister()<CR>"'
|
||||
let i += 1
|
||||
endwhile
|
||||
|
||||
" Wrap the selection with matching quotes, but do nothing if blockwise visual mode is active:
|
||||
for quote in b:delimitMate_quotes_list
|
||||
" vnoremap <buffer> <expr> \' <SID>IsBlockVisual() ? <SID>MapMsg("Message") : "s'\<C-R>\"'\<Esc>:call <SID>RestoreRegister()<CR>"
|
||||
exec 'vnoremap <buffer> <expr> ' . vleader . quote . ' <SID>IsBlockVisual() ? <SID>MapMsg("' . s:VMapMsg . '") : "s' . escape(quote,'"') .'\<C-R>\"' . escape(quote,'"') . '\<Esc>:call <SID>RestoreRegister()<CR>"'
|
||||
endfor
|
||||
endfunction "}}}
|
||||
|
||||
function! DelimitMate_ExpandReturn() "{{{
|
||||
" Expand:
|
||||
return "\<Esc>a\<CR>x\<CR>\<Esc>k$\"_xa"
|
||||
endfunction "}}}
|
||||
|
||||
function! DelimitMate_ExpandSpace() "{{{
|
||||
" Expand:
|
||||
return s:WriteAfter(' ') . "\<Space>"
|
||||
endfunction "}}}
|
||||
|
||||
function! s:ExtraMappings() "{{{
|
||||
" If pair is empty, delete both delimiters:
|
||||
inoremap <buffer> <expr> <BS> DelimitMate_WithinEmptyPair() ? "\<Right>\<BS>\<BS>" : "\<BS>"
|
||||
|
||||
" If pair is empty, delete closing delimiter:
|
||||
inoremap <buffer> <expr> <S-BS> DelimitMate_WithinEmptyPair() ? "\<Del>" : "\<S-BS>"
|
||||
|
||||
" Expand return if inside an empty pair:
|
||||
if b:delimitMate_expand_cr != 0
|
||||
inoremap <buffer> <expr> <CR> DelimitMate_WithinEmptyPair() ?
|
||||
\ DelimitMate_ExpandReturn() : "\<CR>"
|
||||
endif
|
||||
|
||||
" Expand space if inside an empty pair:
|
||||
if b:delimitMate_expand_space != 0
|
||||
inoremap <buffer> <expr> <Space> DelimitMate_WithinEmptyPair() ?
|
||||
\ DelimitMate_ExpandSpace() : "\<Space>"
|
||||
endif
|
||||
|
||||
" Jump out ot any empty pair:
|
||||
if b:delimitMate_tab2exit
|
||||
inoremap <buffer> <expr> <S-Tab> DelimitMate_ShouldJump() ? DelimitMate_JumpAny() : "\<S-Tab>"
|
||||
endif
|
||||
endfunction "}}}
|
||||
"}}}
|
||||
|
||||
" Tools: {{{
|
||||
function! s:TestMappings() "{{{
|
||||
if b:delimitMate_autoclose
|
||||
exec "normal i* AUTOCLOSE:\<CR>"
|
||||
for i in range(len(b:delimitMate_left_delims))
|
||||
exec "normal GGAOpen & close: " . b:delimitMate_left_delims[i]. "|"
|
||||
exec "normal A\<CR>Delete: " . b:delimitMate_left_delims[i] . "\<BS>|"
|
||||
exec "normal A\<CR>Exit: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "|"
|
||||
exec "normal A\<CR>Space: " . b:delimitMate_left_delims[i] . " |"
|
||||
exec "normal GGA\<CR>Visual-L: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_left_delims[i]
|
||||
exec "normal A\<CR>Visual-R: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_right_delims[i]
|
||||
exec "normal A\<CR>Car return: " . b:delimitMate_left_delims[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>"
|
||||
endfor
|
||||
for i in range(len(b:delimitMate_quotes_list))
|
||||
exec "normal GGAOpen & close: " . b:delimitMate_quotes_list[i] . "|"
|
||||
exec "normal A\<CR>Delete: "
|
||||
exec "normal A". b:delimitMate_quotes_list[i]
|
||||
exec "normal a\<BS>|"
|
||||
exec "normal A\<CR>Exit: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|"
|
||||
exec "normal A\<CR>Space: " . b:delimitMate_quotes_list[i] . " |"
|
||||
exec "normal GGA\<CR>Visual: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_quotes_list[i]
|
||||
exec "normal A\<CR>Car return: " . b:delimitMate_quotes_list[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>"
|
||||
endfor
|
||||
else
|
||||
exec "normal i* NO AUTOCLOSE:\<CR>"
|
||||
for i in range(len(b:delimitMate_left_delims))
|
||||
exec "normal GGAOpen & close: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "|"
|
||||
exec "normal A\<CR>Delete: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "\<BS>|"
|
||||
exec "normal A\<CR>Exit: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . b:delimitMate_right_delims[i] . "|"
|
||||
exec "normal A\<CR>Space: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . " |"
|
||||
exec "normal GGA\<CR>Visual-L: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_left_delims[i]
|
||||
exec "normal A\<CR>Visual-R: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_right_delims[i]
|
||||
exec "normal A\<CR>Car return: " . b:delimitMate_left_delims[i] . b:delimitMate_right_delims[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>"
|
||||
endfor
|
||||
for i in range(len(b:delimitMate_quotes_list))
|
||||
exec "normal GGAOpen & close: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|"
|
||||
exec "normal A\<CR>Delete: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "\<BS>|"
|
||||
exec "normal A\<CR>Exit: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "|"
|
||||
exec "normal A\<CR>Space: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . " |"
|
||||
exec "normal GGA\<CR>Visual: v\<Esc>v" . b:delimitMate_visual_leader . b:delimitMate_quotes_list[i]
|
||||
exec "normal A\<CR>Car return: " . b:delimitMate_quotes_list[i] . b:delimitMate_quotes_list[i] . "\<CR>|\<Esc>GGA\<CR>\<CR>"
|
||||
endfor
|
||||
endif
|
||||
exec "normal \<Esc>i"
|
||||
endfunction "}}}
|
||||
|
||||
function! s:SwitchAutoclose() "{{{
|
||||
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:UnMap() " {{{
|
||||
" No Autoclose Mappings:
|
||||
for char in b:delimitMate_right_delims + b:delimitMate_quotes_list
|
||||
if maparg(char,"i") =~? 'SkipDelim'
|
||||
exec 'silent! iunmap <buffer> ' . char
|
||||
"echomsg 'iunmap <buffer> ' . char
|
||||
endif
|
||||
endfor
|
||||
|
||||
" Autoclose Mappings:
|
||||
let i = 0
|
||||
let l = len(b:delimitMate_matchpairs_list)
|
||||
while i < l
|
||||
if maparg(b:delimitMate_left_delims[i],"i") =~? 'JumpIn'
|
||||
exec 'silent! iunmap <buffer> ' . b:delimitMate_left_delims[i]
|
||||
"echomsg 'iunmap <buffer> ' . b:delimitMate_left_delims[i]
|
||||
endif
|
||||
let i += 1
|
||||
endwhile
|
||||
for char in b:delimitMate_quotes_list
|
||||
if maparg(char, "i") =~? 'QuoteDelim'
|
||||
exec 'silent! iunmap <buffer> ' . char
|
||||
"echomsg 'iunmap <buffer> ' . char
|
||||
endif
|
||||
endfor
|
||||
for char in b:delimitMate_right_delims
|
||||
if maparg(char, "i") =~? 'JumpOut'
|
||||
exec 'silent! iunmap <buffer> ' . char
|
||||
"echomsg 'iunmap <buffer> ' . char
|
||||
endif
|
||||
endfor
|
||||
for map in b:delimitMate_apostrophes_list
|
||||
exec "silent! iunmap <buffer> " . map
|
||||
endfor
|
||||
|
||||
" Visual Mappings:
|
||||
for char in b:delimitMate_right_delims + b:delimitMate_left_delims + b:delimitMate_quotes_list
|
||||
if maparg(b:delimitMate_visual_leader . char,"v") =~? 'IsBlock'
|
||||
exec 'silent! vunmap <buffer> ' . b:delimitMate_visual_leader . char
|
||||
"echomsg 'vunmap <buffer> ' . b:delimitMate_visual_leader . char
|
||||
endif
|
||||
endfor
|
||||
|
||||
" Expansion Mappings:
|
||||
if maparg('<BS>', "i") =~? 'WithinEmptyPair'
|
||||
silent! iunmap <buffer> <BS>
|
||||
"echomsg "silent! iunmap <buffer> <BS>"
|
||||
endif
|
||||
if maparg('<S-BS>', "i") =~? 'WithinEmptyPair'
|
||||
silent! iunmap <buffer> <BS>
|
||||
"echomsg "silent! iunmap <buffer> <BS>"
|
||||
endif
|
||||
if maparg('<CR>',"i") =~? 'DelimitMate_ExpandReturn'
|
||||
silent! iunmap <buffer> <CR>
|
||||
"echomsg "silent! iunmap <buffer> <CR>"
|
||||
endif
|
||||
if maparg('<Space>',"i") =~? 'DelimitMate_ExpandSpace'
|
||||
silent! iunmap <buffer> <Space>
|
||||
"echomsg "silent! iunmap <buffer> <Space>"
|
||||
endif
|
||||
if maparg('<S-Tab>', "i") =~? 'ShouldJump'
|
||||
silent! iunmap <buffer> <S-Tab>
|
||||
"echomsg "silent! iunmap <buffer> <S-Tab>"
|
||||
endif
|
||||
endfunction " }}} s:ExtraMappings()
|
||||
|
||||
function! s:TestMappingsDo() "{{{
|
||||
"DelimitMateReload
|
||||
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() "{{{
|
||||
if exists("g:delimitMate_excluded_ft")
|
||||
" Check if this file type is excluded:
|
||||
for ft in split(g:delimitMate_excluded_ft,',')
|
||||
if ft ==? &filetype
|
||||
if !exists("b:delimitMate_quotes_list")
|
||||
return 1
|
||||
endif
|
||||
"echomsg "excluded"
|
||||
call s:UnMap()
|
||||
return 1
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
try
|
||||
"echomsg "included"
|
||||
let save_cpo = &cpo
|
||||
set cpo&vim
|
||||
call s:Init()
|
||||
finally
|
||||
|
||||
command! -bar -bang DelimitMateSwitch call delimitMate#ex_cmd(<bang>0, 'switch' )
|
||||
command! -bar -bang DelimitMateOn call delimitMate#ex_cmd(<bang>0, 'enable' )
|
||||
command! -bar -bang DelimitMateOff call delimitMate#ex_cmd(<bang>0, 'disable')
|
||||
|
||||
augroup delimitMate
|
||||
au!
|
||||
au InsertCharPre * call delimitMate#InsertCharPre(v:char)
|
||||
au TextChangedI * call delimitMate#TextChangedI()
|
||||
au InsertEnter * call delimitMate#InsertEnter()
|
||||
au CursorMovedI * call delimitMate#CursorMovedI()
|
||||
augroup END
|
||||
|
||||
let &cpo = save_cpo
|
||||
endtry
|
||||
endfunction "}}}
|
||||
"}}}
|
||||
|
||||
" Commands: {{{
|
||||
call s:DelimitMateDo()
|
||||
|
||||
" Let me refresh without re-loading the buffer:
|
||||
command! DelimitMateReload call s:DelimitMateDo()
|
||||
|
||||
" Quick test:
|
||||
command! DelimitMateTest call s:TestMappingsDo()
|
||||
|
||||
" Run on file type events.
|
||||
"autocmd VimEnter * autocmd FileType * call <SID>DelimitMateDo()
|
||||
autocmd FileType * call <SID>DelimitMateDo()
|
||||
|
||||
" Run on new buffers.
|
||||
autocmd BufNewFile,BufRead,BufEnter * if !exists("b:loaded_delimitMate") | call <SID>DelimitMateDo() | endif
|
||||
|
||||
"function! s:GetSynRegion () | echo synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name') | endfunction
|
||||
"}}}
|
||||
|
||||
" GetLatestVimScripts: 2754 1 :AutoInstall: delimitMate.vim
|
||||
" vim:foldmethod=marker:foldcolumn=4
|
||||
" vim: sw=2 et
|
||||
|
||||
14
test/Makefile
Normal file
14
test/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
test_files := $(wildcard *.test)
|
||||
|
||||
.PHONY: all monitor $(test_files)
|
||||
|
||||
all:
|
||||
time tclsh all.tcl
|
||||
|
||||
$(test_files):
|
||||
time tclsh $@
|
||||
printf "\a"
|
||||
|
||||
monitor:
|
||||
fswatch -o ../autoload/*.vim ../plugin/*.vim *.test \
|
||||
| xargs -n1 -I\{\} time tclsh all.tcl || printf "\a"
|
||||
18
test/README.md
Normal file
18
test/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Automatic test setup
|
||||
You can use `make` (or `make test` from the top level directory) to run the
|
||||
tests.
|
||||
|
||||
# Manual test setup instructions
|
||||
The plugins [runVimTests](http://www.vim.org/scripts/script.php?script_id=2565)
|
||||
and [VimTAP](http://www.vim.org/scripts/script.php?script_id=2213) are needed
|
||||
to run these tests.
|
||||
|
||||
Besides the `_setup.vim` configuration file present in this repo you need to
|
||||
create a global one and place it in the same dir where the runVimTests
|
||||
executable is located. Assuming the executable is at '~/bin/runVimTests' this
|
||||
global configuration file should be '~/bin/runVimTestsSetup.vim' and should
|
||||
have something like the following lines inside of it:
|
||||
|
||||
" Prepend tests repos to &rtp
|
||||
let &runtimepath = '/path/to/runVimTests_dir,' . &rtp
|
||||
let &runtimepath = '/path/to/vimTAP_dir,' . &rtp
|
||||
11
test/_setup.vim
Normal file
11
test/_setup.vim
Normal file
@@ -0,0 +1,11 @@
|
||||
set bs=2
|
||||
set hidden
|
||||
set noshowmode
|
||||
set whichwrap=[]
|
||||
set noswapfile
|
||||
let &hl = join(map(split(&hl, ','), 'substitute(v:val, '':.\+'', ''n'', ''g'')'), ',')
|
||||
let &rtp = expand('<sfile>:p:h:h') . ',' . &rtp . ',' . expand('<sfile>:p:h:h') . '/after'
|
||||
let g:delimitMate_pairs = ['()','{}','[]','<>','¿?','¡!',',:']
|
||||
let g:delimitMate_quotes = ['"', "'", '`', '«', '|']
|
||||
ru plugin/delimitMate.vim
|
||||
au VimEnter * echom 'Start test'
|
||||
18
test/all.tcl
Normal file
18
test/all.tcl
Normal file
@@ -0,0 +1,18 @@
|
||||
package require tcltest 2
|
||||
namespace import -force ::tcltest::*
|
||||
configure {*}$argv -testdir [file dir [info script]]
|
||||
|
||||
# Hook to determine if any of the tests failed. Then we can exit with
|
||||
# proper exit code: 0=all passed, 1=one or more failed
|
||||
proc tcltest::cleanupTestsHook {} {
|
||||
variable numTests
|
||||
upvar 2 testFileFailures crashed
|
||||
set ::exitCode [expr {$numTests(Failed) > 0}]
|
||||
if {[info exists crashed]} {
|
||||
set ::exitCode [expr {$::exitCode || [llength $crashed]}]
|
||||
}
|
||||
}
|
||||
|
||||
runAllTests
|
||||
puts "\a"
|
||||
exit $exitCode
|
||||
49
test/eol_marker.test
Normal file
49
test/eol_marker.test
Normal file
@@ -0,0 +1,49 @@
|
||||
# singleTest name desc setup input result vimCmds? skipScript?
|
||||
#
|
||||
# - desc can be empty and input would be used.
|
||||
# - vimCmds is a list of ex commands.
|
||||
# - skipScript will be evaluated in the scope of the function "single" and it
|
||||
# should return a keywowd such as toDo, badTest or other as listed in the
|
||||
# docs for tcltest. e.g.:
|
||||
# {expr "[string first {i'} \"${input}\"] > -1 ? {emptyTest} : {}"}
|
||||
# see tcltest documentation for other values.
|
||||
|
||||
# Get some help:
|
||||
source helper.tcl
|
||||
|
||||
set vimCmds [list {let g:delimitMate_expand_cr = 1}]
|
||||
lappend vimCmds {let g:delimitMate_eol_marker = ';'}
|
||||
lappend vimCmds {let g:delimitMate_insert_eol_marker = 0}
|
||||
|
||||
single ins_eol_marker_0-1 {} "" "i(" "()" ${vimCmds}
|
||||
|
||||
single ins_eol_marker_0-2 {} "" "i(\rx" "(\nx\n)" ${vimCmds}
|
||||
|
||||
set vimCmds [list {let g:delimitMate_expand_cr = 1}]
|
||||
lappend vimCmds {let g:delimitMate_eol_marker = ';'}
|
||||
lappend vimCmds {let g:delimitMate_insert_eol_marker = 1}
|
||||
single ins_eol_marker_1-1 {} "" "i(" "();" ${vimCmds}
|
||||
|
||||
single ins_eol_marker_1-2 {} " a" "0i(" "() a" ${vimCmds}
|
||||
|
||||
single ins_eol_marker_1-3 {} "" "i(\rx" "(\nx\n);" ${vimCmds}
|
||||
|
||||
set vimCmds [list {let g:delimitMate_expand_cr = 1}]
|
||||
lappend vimCmds {let g:delimitMate_eol_marker = ';'}
|
||||
lappend vimCmds {let g:delimitMate_insert_eol_marker = 2}
|
||||
single ins_eol_marker_2-1 {} "" "i(" "()" ${vimCmds}
|
||||
|
||||
single ins_eol_marker_2-2 {} "" "i(\rx" "(\nx\n);" ${vimCmds}
|
||||
|
||||
# Issue #195
|
||||
single issue_195-1 {} "" "i{(\rx" "{(\nx\n)}" ${vimCmds}
|
||||
|
||||
# Issue #195
|
||||
single issue_195-2 {} ";" "I{(\rx" "{(\nx\n)};" ${vimCmds}
|
||||
|
||||
|
||||
|
||||
################################################################
|
||||
# This gives nice statistics and cleans up the mess left behind.
|
||||
cleanupTests
|
||||
# vim: set filetype=tcl et sw=2 sts=0 ts=8:
|
||||
92
test/expand_cr.test
Normal file
92
test/expand_cr.test
Normal file
@@ -0,0 +1,92 @@
|
||||
# singleTest name desc setup input result vimCmds? skipScript?
|
||||
#
|
||||
# - desc can be empty and input would be used.
|
||||
# - vimCmds is a list of ex commands.
|
||||
# - skipScript will be evaluated in the scope of the function "single" and it
|
||||
# should return a keywowd such as toDo, badTest or other as listed in the
|
||||
# docs for tcltest. e.g.:
|
||||
# {expr "[string first {i'} \"${input}\"] > -1 ? {emptyTest} : {}"}
|
||||
# see tcltest documentation for other values.
|
||||
|
||||
# Get some help:
|
||||
source helper.tcl
|
||||
|
||||
set vimCmds [list {let g:delimitMate_expand_cr = 1}]
|
||||
#"let g:delimitMate_eol_marker = ';'
|
||||
lappend vimCmds {filetype indent on}
|
||||
lappend vimCmds {set bs=2 et sts=4 sw=4 ft=javascript}
|
||||
single javascript-1 {} "\$(document).ready(function() {})" "f{a\rx" \
|
||||
"\$(document).ready(function() {\n x\n})" ${vimCmds}
|
||||
|
||||
# Issue #95
|
||||
set vimCmds [list {let g:delimitMate_expand_cr = 1}]
|
||||
lappend vimCmds {let b:delimitMate_jump_expansion = 1}
|
||||
set skipScript {string cat toDo}
|
||||
single issue_95 {} "" "i(\rtest)x" "(\ntest\n)x" ${vimCmds} ${skipScript}
|
||||
|
||||
# Remove CR expansion on BS
|
||||
set skipScript {string cat toDo}
|
||||
single bs {} "" "i(\r\bx" "(x)" ${vimCmds} ${skipScript}
|
||||
|
||||
# Consider indentation with BS inside an empty CR expansion.
|
||||
single bs_indentation {} "" "i( \r\b\bx" "(x)" ${vimCmds}
|
||||
|
||||
# Conflict with indentation settings (cindent). Issue #95
|
||||
lappend vimCmds {se cindent}
|
||||
single issue_95 {} "sub foo {\n while (1) {\n\n }\n}" "3Gi\bx" \
|
||||
"sub foo {\n while (1) {x}\n}" ${vimCmds}
|
||||
|
||||
single nested_expansion-1 {} "sub foo {\n while (1) {\n bar\n }\n}" \
|
||||
"3GA}x" "sub foo {\n while (1) {\n bar\n }x\n}" ${vimCmds}
|
||||
|
||||
single nested_expansion-2 {} "sub foo {\n while (1) {\n bar\n }\n}" \
|
||||
"3GA{x" "sub foo {\n while (1) {\n bar{x}\n }\n}" ${vimCmds}
|
||||
|
||||
single bracketed {} "\"{bracketed}" "\033A\"x" "\"{bracketed}\"x" ${vimCmds}
|
||||
|
||||
# Syntax folding enabled by autocmd breaks expansion.
|
||||
set vimCmds [list {let g:delimitMate_expand_cr = 1}]
|
||||
lappend vimCmds {se cindent}
|
||||
lappend vimCmds {set bs=2 et sts=4 sw=4}
|
||||
lappend vimCmds {autocmd InsertEnter <buffer> let w:fdm=&foldmethod \
|
||||
| setl foldmethod=manual}
|
||||
lappend vimCmds {autocmd InsertLeave <buffer> let &foldmethod = w:fdm}
|
||||
lappend vimCmds {set foldmethod=marker}
|
||||
lappend vimCmds {set foldmarker={,}}
|
||||
lappend vimCmds {set foldlevel=0}
|
||||
lappend vimCmds {set backspace=2}
|
||||
single folding {} "" "iabc {\rx" "abc {\n x\n}" ${vimCmds}
|
||||
|
||||
# expand_cr != 2}
|
||||
set vimCmds [list {let g:delimitMate_expand_cr = 1}]
|
||||
lappend vimCmds {se cindent}
|
||||
lappend vimCmds {set bs=2 et sts=4 sw=4 ft=javascript}
|
||||
lappend vimCmds {let b:delimitMate_jump_expansion = 1}
|
||||
single axpand_cr_no_2 {} "abc(def)" "\$i\rx" "abc(def\n x)" ${vimCmds}
|
||||
|
||||
# expand_cr == 2
|
||||
set vimCmds [list {let g:delimitMate_expand_cr = 2}]
|
||||
lappend vimCmds {se cindent}
|
||||
lappend vimCmds {set bs=2 et sts=4 sw=4 ft=javascript}
|
||||
lappend vimCmds {let b:delimitMate_jump_expansion = 1}
|
||||
single expand_cr_2 {} "abc(def)" "\$i\rx" "abc(def\n x\n )" ${vimCmds}
|
||||
|
||||
# Play nice with smartindent
|
||||
set vimCmds [list {let g:delimitMate_expand_cr = 2}]
|
||||
lappend vimCmds {let b:delimitMate_jump_expansion = 1}
|
||||
lappend vimCmds {set smartindent}
|
||||
single smartindent-1 {} "" "i{\rx" "{\n x\n}" ${vimCmds}
|
||||
|
||||
single quotes-1 {} "" "i\" x" {" x"} ${vimCmds}
|
||||
|
||||
single quotes-2 {} "" "i\"\rx" "\"\nx\"" ${vimCmds}
|
||||
|
||||
lappend vimCmds {let g:delimitMate_expand_inside_quotes = 1}
|
||||
single quotes-3 {} "" "i\"\nx" "\"\nx\n\"" ${vimCmds}
|
||||
|
||||
|
||||
|
||||
################################################################
|
||||
# This gives nice statistics and cleans up the mess left behind.
|
||||
cleanupTests
|
||||
# vim: set filetype=tcl et sw=2 sts=0 ts=8:
|
||||
48
test/expand_space.test
Normal file
48
test/expand_space.test
Normal file
@@ -0,0 +1,48 @@
|
||||
# singleTest name desc setup input result vimCmds? skipScript?
|
||||
#
|
||||
# - desc can be empty and input would be used.
|
||||
# - vimCmds is a list of ex commands.
|
||||
# - skipScript will be evaluated in the scope of the function "single" and it
|
||||
# should return a keywowd such as toDo, badTest or other as listed in the
|
||||
# docs for tcltest. e.g.:
|
||||
# {expr "[string first {i'} \"${input}\"] > -1 ? {emptyTest} : {}"}
|
||||
# see tcltest documentation for other values.
|
||||
|
||||
# Get some help:
|
||||
source helper.tcl
|
||||
|
||||
set vimCmds [list {let g:delimitMate_expand_space = 1}]
|
||||
lappend vimCmds {let g:delimitMate_autoclose = 1}
|
||||
|
||||
pairs pairs-1 {} "" "i( x" "( x )" ${vimCmds}
|
||||
|
||||
pairs pairs-2 {} "( )" "la\bx" "(x)" ${vimCmds}
|
||||
|
||||
pairs pairs-3 {} "" "iabc x" "abc x" ${vimCmds}
|
||||
|
||||
quotes quotes-1 {} "" "i' x" "' x'" ${vimCmds}
|
||||
|
||||
lappend vimCmds {let g:delimitMate_expand_inside_quotes = 1}
|
||||
quotes quotes-2 {} "" "i' x" "' x '" ${vimCmds}
|
||||
|
||||
quotes quotes-3 {} "" "i' \bx" "'x'" ${vimCmds}
|
||||
|
||||
set skipScript {string cat quoteBug}
|
||||
lappend vimCmds {let g:delimitMate_autoclose = 0}
|
||||
quotes quotes-4 {} "abc\\" "A'' x" "abc\\'' x '" ${vimCmds} ${skipScript}
|
||||
|
||||
# Issue #95
|
||||
lappend vimCmds {let b:delimitMate_jump_expansion = 1}
|
||||
set skipScript {string cat toDo}
|
||||
pairs issue_95 {} "" "i( test)x" "( test )x" ${vimCmds} ${skipScript}
|
||||
|
||||
pairs pairs-4 {} "" "i() \bx" "(x)" ${vimCmds}
|
||||
|
||||
quotes quotes-5 {} "" "i'' \bx" "'x'" ${vimCmds}
|
||||
|
||||
|
||||
|
||||
################################################################
|
||||
# This gives nice statistics and cleans up the mess left behind.
|
||||
cleanupTests
|
||||
# vim: set filetype=tcl et sw=2 sts=0 ts=8:
|
||||
125
test/helper.tcl
Normal file
125
test/helper.tcl
Normal file
@@ -0,0 +1,125 @@
|
||||
if {[lsearch [namespace children] ::tcltest] == -1} {
|
||||
package require tcltest 2
|
||||
namespace import -force ::tcltest::*
|
||||
}
|
||||
|
||||
configure -verbose {body error skip}
|
||||
#configure -verbose {start msec pass body error skip}
|
||||
|
||||
set charMap [list \
|
||||
"\"" "\\\"" \
|
||||
"\$" "\\$" \
|
||||
"\[" "\\\[" \
|
||||
"\]" "\\\]" \
|
||||
"\\" "\\\\" \
|
||||
"{" "\\{" \
|
||||
"}" "\\}" \
|
||||
]
|
||||
|
||||
# In order to skip a test pass a script that, when evaluated, returns emptyTest
|
||||
# for tests that can not pass, or knownBug for ToDo features. e.g.:
|
||||
# {expr "[string first {i'} \"${input}\"] > -1 ? {emptyTest} : {}"}
|
||||
# see tcltest documentation for other values.
|
||||
|
||||
proc single {name desc setup input result \
|
||||
{vimCmds {}} \
|
||||
{constr {}} \
|
||||
} {
|
||||
set fnamePrefix "test_${name}"
|
||||
global charMap
|
||||
makeFile ${setup} "${fnamePrefix}.in"
|
||||
makeFile {} "${fnamePrefix}.out"
|
||||
makeFile [join ${vimCmds} "\n"] "${fnamePrefix}.vim"
|
||||
set input [string map ${charMap} ${input}]
|
||||
#puts [lindex ${vimCmds} 0]
|
||||
set optCharMap [list {[} {\[} {]} {\]}]
|
||||
set vimArgs [lmap option ${vimCmds} \
|
||||
{string cat " -c \"[string map $charMap ${option}]\""}]
|
||||
set body [string cat "
|
||||
exec -- ./test.exp \"${fnamePrefix}\" \"${input}\"
|
||||
return \[viewFile \"${fnamePrefix}.out\"\]
|
||||
" ]
|
||||
#puts ${body}
|
||||
if {[string length ${desc}] eq 0} {
|
||||
set desc ${input}
|
||||
}
|
||||
if {[string length ${constr}] ne 0} {
|
||||
#puts ${constr}
|
||||
set constr [eval ${constr}]
|
||||
#puts ${constr}
|
||||
}
|
||||
set name "${name}: \"${setup}\", \"${desc}\" ->"
|
||||
#puts $desc
|
||||
#puts $name
|
||||
test ${name} \
|
||||
${desc} \
|
||||
-body ${body} \
|
||||
-constraints ${constr} \
|
||||
-result ${result}
|
||||
}
|
||||
|
||||
proc multi {items evalScript name desc setup input result \
|
||||
{vimCmds {}} \
|
||||
{constr {}} \
|
||||
} {
|
||||
global charMap
|
||||
set minor 0
|
||||
foreach item $items {
|
||||
incr minor
|
||||
eval ${evalScript}
|
||||
foreach var {desc setup input result} {
|
||||
set "the_${var}" [string map ${aCharMap} [expr "$${var}"]]
|
||||
}
|
||||
set the_name "${name}.${minor}"
|
||||
single \
|
||||
${the_name} \
|
||||
${the_desc} \
|
||||
${the_setup} \
|
||||
${the_input} \
|
||||
${the_result} \
|
||||
${vimCmds} \
|
||||
${constr} \
|
||||
}
|
||||
}
|
||||
|
||||
proc quotes {name desc setup input result \
|
||||
{vimCmds {}} \
|
||||
{constr {}} \
|
||||
} {
|
||||
set quotes [list {'} \" {`} {«} {|}]
|
||||
set mapScript {set aCharMap [list "'" ${item}]}
|
||||
multi \
|
||||
${quotes} \
|
||||
${mapScript} \
|
||||
${name} \
|
||||
${desc} \
|
||||
${setup} \
|
||||
${input} \
|
||||
${result} \
|
||||
${vimCmds} \
|
||||
${constr} \
|
||||
}
|
||||
|
||||
proc pairs {name desc setup input result \
|
||||
{vimCmds {}} \
|
||||
{constr {}} \
|
||||
} {
|
||||
set pairs [list () \{\} \[\] <> ¿? ¡! ,:]
|
||||
set mapScript {
|
||||
set left [string index ${item} 0]
|
||||
set right [string index ${item} 1]
|
||||
set aCharMap [list ( ${left} ) ${right}]
|
||||
}
|
||||
multi \
|
||||
${pairs} \
|
||||
${mapScript} \
|
||||
${name} \
|
||||
${desc} \
|
||||
${setup} \
|
||||
${input} \
|
||||
${result} \
|
||||
${vimCmds} \
|
||||
${constr} \
|
||||
}
|
||||
|
||||
# vim: set filetype=tcl et sw=2 sts=0 ts=8:
|
||||
153
test/pairs.test
Normal file
153
test/pairs.test
Normal file
@@ -0,0 +1,153 @@
|
||||
# singleTest name desc setup input result vimCmds? skipScript?
|
||||
#
|
||||
# - desc can be empty and input would be used.
|
||||
# - vimCmds is a list of ex commands.
|
||||
# - skipScript will be evaluated in the scope of the function "single" and it
|
||||
# should return a keywowd such as toDo, badTest or other as listed in the
|
||||
# docs for tcltest. e.g.:
|
||||
# {expr "[string first {i'} \"${input}\"] > -1 ? {emptyTest} : {}"}
|
||||
# see tcltest documentation for other values.
|
||||
|
||||
# Get some help:
|
||||
source helper.tcl
|
||||
|
||||
set vimCmds [list ]
|
||||
pairs autoclose-1 {} {} "i(" "()"
|
||||
|
||||
pairs autoclose-2 {} {()} "a\b" ""
|
||||
|
||||
pairs autoclose-3 {} "()" "a)x" "()x"
|
||||
|
||||
set skipScript {string cat {toDo}}
|
||||
single jump_all {} "" "((<magic>x" "(())x" {} ${skipScript}
|
||||
|
||||
pairs undo {} "" "i(x\033u" ""
|
||||
|
||||
pairs autoclose-4 {} "" "i@(x" "@(x)"
|
||||
|
||||
pairs autoclose-5 {} "@#" "a(x" "@(x)#"
|
||||
|
||||
pairs autoclose-6 {} "\\" "a(x" "\\(x"
|
||||
|
||||
pairs autoclose-7 {} "(\\)" "la)x" "(\\)x)"
|
||||
|
||||
pairs autoclose-8 {} {"abc"} "ifoo(" "foo(\"abc\""
|
||||
|
||||
set vimCmds [list {let g:delimitMate_autoclose = 0}]
|
||||
pairs noautoclose-1 {} "" "i(x" "(x" ${vimCmds}
|
||||
|
||||
pairs noautoclose-2 {} "" "i()x" "(x)" ${vimCmds}
|
||||
|
||||
pairs noautoclose-3 {} "" "i())x" "()x" ${vimCmds}
|
||||
|
||||
pairs noautoclose-4 {} "" "i()\bx" "x" ${vimCmds}
|
||||
|
||||
pairs noautoclose-5 {} "" "i@()x" "@(x)" ${vimCmds}
|
||||
|
||||
pairs noautoclose-6 {} "@#" "a()x" "@(x)#" ${vimCmds}
|
||||
|
||||
#" Handle backspace gracefully.
|
||||
set vimCmds [list {set backspace=}]
|
||||
pairs bad_bs {} "" "i(\033a\bx" "(x)" ${vimCmds}
|
||||
|
||||
set vimCmds [list ]
|
||||
|
||||
# closing parens removes characters. #133
|
||||
pairs autoclose-9 {} "(a)" "a)" "()a)" ${vimCmds}
|
||||
|
||||
# Expand iabbreviations
|
||||
set vimCmds [list {iabb def ghi}]
|
||||
# Not sure how to make it work on the test
|
||||
pairs iabbr {} "" "idef(" "ghi()" ${vimCmds}
|
||||
|
||||
set vimCmds [list ]
|
||||
|
||||
pairs autoclose-10 {} {abc а} {$i(} {abc (а} ${vimCmds}
|
||||
|
||||
pairs autoclose-11 {} "abc ñ" "\$i(" "abc (ñ" ${vimCmds}
|
||||
|
||||
pairs autoclose-12 {} "abc \$" "\$i(" "abc (\$" ${vimCmds}
|
||||
|
||||
pairs autoclose-13 {} "abc £" "\$i(" "abc (£" ${vimCmds}
|
||||
|
||||
pairs autoclose-14 {} "abc d" "\$i(" "abc (d" ${vimCmds}
|
||||
|
||||
pairs autoclose-15 {} "abc ." "\$i(" "abc ()." ${vimCmds}
|
||||
|
||||
pairs autoclose-16 {} "abc " "\$i(" "abc () " ${vimCmds}
|
||||
|
||||
pairs autoclose-17 {} "abc (" "\$i(" "abc ((" ${vimCmds}
|
||||
|
||||
# Play nice with undo.
|
||||
pairs undo {} "" "ia\007u(c)b\033u" "a" ${vimCmds}
|
||||
|
||||
# TODO: way to jump over one or several closing chars
|
||||
set skipScript {string cat {toDo}}
|
||||
single jump_to {} "()" "a\<magic>x" "()x" ${vimCmds} ${skipScript}
|
||||
|
||||
single jump_to {} "{()}" "la\\<magic>x" "{()}x" ${vimCmds} ${skipScript}
|
||||
|
||||
set vimCmds [list {let g:delimitMate_balance_pairs = 0}]
|
||||
pairs no_balance_pairs-1 {} "ab cd)" "la(x" "ab(x) cd)" ${vimCmds}
|
||||
|
||||
# Issue #229
|
||||
pairs issue_229-1 {} "((ab cd)" "\$i)x" "((ab cd)x" ${vimCmds}
|
||||
|
||||
set vimCmds [list ]
|
||||
|
||||
set vimCmds [list {let g:delimitMate_balance_pairs = 1}]
|
||||
pairs issue_229-2 {} "ab cd)" "la(x" "ab(x cd)" ${vimCmds}
|
||||
|
||||
# Issue #229
|
||||
pairs issue_229-3 {} "((ab cd)" "\$i)x" "((ab cd)x)" ${vimCmds}
|
||||
|
||||
# Issue #220
|
||||
set vimCmds [list {let g:delimitMate_jump_next = 0}]
|
||||
pairs issue_220-1 {} "()" "a)" "())" ${vimCmds}
|
||||
|
||||
# Issues #207 and #223
|
||||
set vimCmds [list {let g:delimitMate_jump_long = 1}]
|
||||
pairs jump_long-1 {} "{\[(foobar)\]}" "fbi)x" "{\[(foobar)x\]}" ${vimCmds}
|
||||
|
||||
# Issues #207 and #223
|
||||
set skipScript {expr "[string first {[[foobar]]} \"${setup}\"] > -1 \
|
||||
? {badTest} : {}"}
|
||||
single jump_long-2 {} "{\[(foobar)\]}" "fbi\]x" "{\[(foobar)\]x}" ${vimCmds} ${skipScript}
|
||||
|
||||
# Issues #207 and #223
|
||||
set skipScript {string cat {toDo}}
|
||||
set vimCmds [list {let g:delimitMate_jump_all = 1}]
|
||||
single issues_207_223 {} "{\[(foobar)\]}" "fbi<magic>x" "{\[(foobar)\]}x" \
|
||||
${vimCmds} ${skipScript}
|
||||
|
||||
set vimCmds [list {let g:delimitMate_jump_back = 1}]
|
||||
pairs jump_back {} "" "i()x" "()x" ${vimCmds}
|
||||
|
||||
# Disable on syntax groups
|
||||
set vimCmds [list {syntax on}]
|
||||
lappend vimCmds {set ft=vim}
|
||||
lappend vimCmds {let g:delimitMate_excluded_regions = ['String']}
|
||||
pairs ignore_syntax {} {echo " "} "f\"la(" {echo " ( "} ${vimCmds}
|
||||
|
||||
#" Issue #160
|
||||
set vimCmds [list {filetype indent plugin on}]
|
||||
lappend vimCmds {set ft=php}
|
||||
set skipScript {string cat {toDo}}
|
||||
single issue_160 {} "<?php incl" "A\x18\x0F\x19" "<?php include()" \
|
||||
${vimCmds} ${skipScript}
|
||||
|
||||
set vimCmds [list ]
|
||||
|
||||
# Play nice with redo
|
||||
pairs redo {} "abc " "Afoo(x\033." "abc foo(x)foo(x)" ${vimCmds}
|
||||
|
||||
pairs smart {} {""} "0a(x" {"(x"}
|
||||
|
||||
pairs smart {} {""} "0a()x" {"(x)"}
|
||||
|
||||
|
||||
|
||||
################################################################
|
||||
# This gives nice statistics and cleans up the mess left behind.
|
||||
cleanupTests
|
||||
# vim: set filetype=tcl et sw=2 sts=0 ts=8:
|
||||
107
test/quotes.test
Normal file
107
test/quotes.test
Normal file
@@ -0,0 +1,107 @@
|
||||
# singleTest name desc setup input result vimCmds? skipScript?
|
||||
#
|
||||
# - desc can be empty and input would be used.
|
||||
# - vimCmds is a list of ex commands.
|
||||
# - skipScript will be evaluated in the scope of the function "single" and it
|
||||
# should return a keywowd such as toDo, badTest or other as listed in the
|
||||
# docs for tcltest. e.g.:
|
||||
# {expr "[string first {i'} \"${input}\"] > -1 ? {emptyTest} : {}"}
|
||||
# see tcltest documentation for other values.
|
||||
|
||||
# Get some help:
|
||||
source helper.tcl
|
||||
|
||||
quotes autoclose-1 {} {} "i'x" "'x'"
|
||||
|
||||
quotes autoclose-2 {} {} "i'x\033u" {}
|
||||
|
||||
quotes autoclose-3 {} {} {i''x} {''x}
|
||||
|
||||
quotes autoclose-4 {} {''} "a\bx" {x}
|
||||
|
||||
set skipScript {expr "[string first {i\"} \"${input}\"] > -1 ? {badTest} : {}"}
|
||||
quotes autoclose-5 {} "" "i'x\"" "'x\"'" {} ${skipScript}
|
||||
|
||||
quotes autoclose-6 {} {} "i@'x" "@'x'"
|
||||
|
||||
quotes autoclose-7 {} {@#} "a'x" "@'x'#"
|
||||
|
||||
#quotes autoclose-8 {} {} "'\<S-Tab>x" "''x"
|
||||
|
||||
single autoclose-8 {} {abc'} "A'" "abc'" {} {string cat toDo}
|
||||
|
||||
quotes autoclose-9 {} "abc\\" "A'x" {abc\'x}
|
||||
|
||||
quotes autoclose-10 {} {} "au'Привет'" "u'Привет'"
|
||||
|
||||
quotes autoclose-11 {} {} "au'string'" "u'string'"
|
||||
|
||||
set vimCmds [list {let g:delimitMate_autoclose = 0}]
|
||||
quotes noautoclose-1 {} {} "a'x" "'x" ${vimCmds}
|
||||
|
||||
quotes noautoclose-2 {} {} "a''x" "'x'" ${vimCmds}
|
||||
|
||||
quotes noautoclose-3 {} {} "a'''x" "''x" ${vimCmds}
|
||||
|
||||
quotes noautoclose-4 {} {} "a''\bx" "x" ${vimCmds}
|
||||
|
||||
quotes noautoclose-5 {} {} "a@''x" "@'x'" ${vimCmds}
|
||||
|
||||
quotes noautoclose-6 {} "@#" "a''x" "@'x'#" ${vimCmds}
|
||||
|
||||
set vimCmds [list {let g:delimitMate_autoclose = 1}]
|
||||
# Handle backspace gracefully.
|
||||
lappend vimCmds {set backspace=}
|
||||
quotes badBS-1 {} {} "a'\033a\bx" "'x'" ${vimCmds}
|
||||
|
||||
set vimCmds [list {set cpo=ces$}]
|
||||
quotes cpo {} {} "a'x" "'x'" ${vimCmds}
|
||||
|
||||
# Make sure smart quote works beyond first column.
|
||||
quotes beyond_first_column {} { } "a'x" " 'x'"
|
||||
|
||||
# smart quote, check fo char on the right.
|
||||
quotes smart_quote-1 {} "a b" "la'" "a 'b"
|
||||
|
||||
# Make sure we jump over a quote on the right. #89.
|
||||
quotes autoclose-12 {} {} "a('test'x" "('test'x)"
|
||||
|
||||
# Duplicate whole line when inserting quote at bol #105
|
||||
quotes autoclose-13 {} "}" "i'" "''}"
|
||||
|
||||
quotes autoclose-14 {} "'abc " "A'" "'abc '"
|
||||
|
||||
quotes autoclose-15 {} "''abc " "A'" "''abc ''"
|
||||
|
||||
# Nesting quotes:
|
||||
set vimCmds [list {let g:delimitMate_nesting_quotes = delimitMate#option('quotes')}]
|
||||
quotes nesting-1 {} "''" "A'x" "'''x'''" ${vimCmds}
|
||||
|
||||
quotes nesting-2 {} "'''" "A'x" "''''x''''" ${vimCmds}
|
||||
|
||||
quotes nesting-3 {} {} "i''x" "''x" ${vimCmds}
|
||||
|
||||
quotes nesting-4 {} {} "i'x" "'x'" ${vimCmds}
|
||||
|
||||
set vimCmds [list]
|
||||
|
||||
# expand iabbreviations
|
||||
set vimCmds [list {iabb def ghi}]
|
||||
single iabbr {} {} {idef"} {ghi"} ${vimCmds}
|
||||
|
||||
set vimCmds [list]
|
||||
|
||||
quotes autoclose-16 {} {} "i'\n\b" "''"
|
||||
|
||||
# Double quote starts a comment in viml
|
||||
set vimCmds [list {set ft=vim}]
|
||||
single vim_comment {} {} {i"} {"} ${vimCmds}
|
||||
|
||||
#" Allow quote to exit from string when disabled by syntax group.
|
||||
set vimCmds [list {syntax on}]
|
||||
quotes disabled_syntax {} "'abc'" "\$i'x" "'abc'x" ${vimCmds}
|
||||
|
||||
# --------
|
||||
# This gives nice statistics and cleans up the mess left behind.
|
||||
cleanupTests
|
||||
# vim: set filetype=tcl et sw=2 sts=0 ts=8:
|
||||
20
test/test.exp
Executable file
20
test/test.exp
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env expect -f
|
||||
|
||||
set testName [lindex $argv 0]
|
||||
set filein "${testName}.in"
|
||||
set fileout "${testName}.out"
|
||||
set input [lindex $argv 1]
|
||||
|
||||
set timeout 2
|
||||
spawn env TERM=dumb vim -N -i NONE -u _setup.vim -S "${testName}.vim" -- ${filein}
|
||||
match_max 100000
|
||||
expect -exact "Start test"
|
||||
foreach char [split ${input} {}] {
|
||||
send -- "${char}"
|
||||
sleep .01
|
||||
}
|
||||
send -- " "
|
||||
sleep .01
|
||||
send -- ":w! ${fileout}\r"
|
||||
send -- ":qa!\r"
|
||||
expect eof
|
||||
Reference in New Issue
Block a user