一、括号自动完成与加强
1. 括号自动完成
功能描述:当输入(时自动生成(),并使光标指向),系统保持在insert mode分析:当键入(时,只需模拟输入()并使光标回退一个字符即可
代码1:
inoremap ( ()<LEFT>
2. 重复键入括号自动换行
功能描述:在目标一的基础上实现若光标前一字符为(,则自动换行并缩进,而非插入括号分析:要达到该效果,必需通过命令实现,调用命令有<C-O>,<ESC>, <C-R>三种途径
<C-O>对于eol与普通字符的处理方式不一样,所以这里采取ESC进入normal模式,<ESC>离开Insert模式恒回退一个字符
代码2:功能一的命令版
function! ParenOpen() normal! a() startinsert endfunction inoremap ( <ESC>:call ParenOpen()<CR>
代码 3:实现功能2
function! ParenOpen() let line = getline('.') let prev_char = line[col('.')-1] if prev_char == '(' " 添加额外的字符;,以避免vim自动删除空白行 execute "normal! a\<CR>\<ESC>==O;" return end " 同样需要添加; execute "normal! a(;)\<ESC>i" "当缩进被删除时,重新缩进当前行 if line == '' normal! ==$h end endfunction inoremap ( <ESC>:call ParenOpen()<CR>"_cl
3. 忽略重复键入的右括号
功能描术:若当前字符为),则忽略输入的),光标指向下一字符代码4
function! ParenClose() let line = getline('.') let char = line[col('.')] if char == ')' execute "normal! l" else normal! a) end endfunction inoremap ) <ESC>:call ParenClose()<CR>a
4. 配对删除括号
功能描述:当删除(时,若()之间为空时,则连)一起删除分析:目前只能想到map <BS> 一条途径,通过正则判断括号间是否为空
代码5
function! ParenDelete() let line = getline('.') let prev_char = line[col('.')-1] if prev_char == '(' && match(line,'^\s*)',col('.')) != -1 " 使用 cf) 代替df)使光标离开normal时左移一格用以a normal! cf) else execute "normal! a\<BS>" end endfunction inoremap <BS> <ESC>:call ParenDelete()<CR>a
二、代码总览:
function! ParenOpen() let line = getline('.') let prev_char = line[col('.')-1] if prev_char == '(' " 添加额外的字符;,以避免vim自动删除空白行 execute "normal! a\<CR>\<ESC>==O;" return end " 同样需要添加; execute "normal! a(;)\<ESC>i" "当缩进被删除时,重新缩进当前行 if line == '' normal! ==$h end endfunction function! ParenClose() let line = getline('.') let current_char = line[col('.')] if current_char == ')' execute "normal! l" else normal! a) end endfunction function! ParenDelete() let line = getline('.') let prev_char = line[col('.')-1] if prev_char == '(' && match(line,'^\s*)',col('.')) != -1 " 使用 cf) 代替df)使光标离开normal时左移一格用以a normal! cf) else execute "normal! a\<BS>" end endfunction " 函数ParenOpen执行后光标指向;,使用"_cl清除并进入insert模式 inoremap ( <ESC>:call ParenOpen()<CR>"_cl inoremap ) <ESC>:call ParenClose()<CR>a inoremap <BS> <ESC>:call ParenDelete()<CR>a
三、使用<C-R>代替<ESC>
<ESC>调用时会导致状态栏,-- 插入 -- 闪烁,修正代码为使用<C-R>代替<ESC>通过与=表达式寄存器实现括号的自动完成功能{/text}
脚本正好可以不进入Normal模式,如果函数中有normal xxx,那么不得不使用<ESC>作为入口了
function! ParenOpen() let line = getline('.') let prev_char = line[col('.')-2] if prev_char == '(' return "\<CR>\<ESC>==O" end return "()\<Left>" endfunction function! ParenClose() let line = getline('.') let current_char = line[col('.')-1] if current_char == ')' return "\<Right>" end return ')' endfunction function! ParenDelete() let line = getline('.') let prev_char = line[col('.')-2] if prev_char == '(' && match(line,'^\s*)',col('.')-1) != -1 return "\<Left>\<C-O>cf)" end return "\<BS>" endfunction inoremap <silent> ( <C-R>=ParenOpen()<CR> inoremap <silent> ) <C-R>=ParenClose()<CR> inoremap <silent> <BS> <C-R>=ParenDelete()<CR>
四、Vim插件Auto Pairs
Auto Pairs是根据此文进一步完善的插件。支持[]{}() ' "的括号自动完成与删除。详见: https://github.com/jiangmiao/auto-pairs
2011-06-11更新
-------------------
inoremap X <C-R>=foo()<CR> 可以用inoremap <expr> X<CR>代替
即上文可以改进为
inoremap <silent> <expr> ( ParenOpen() inoremap <silent> <expr> ) ParenClose() inoremap <silent> <expr> <BS> ParenDelete()