vimrc再修改/vimscript初探

之前已经初步配置好的vim

http://blog.csdn.net/qkoqhh/article/details/78535236

然而还是出现了一些比较尴尬的情况。。

之前处理括号补全时是使用了autopair插件,不得不说这是一个非常友好的插件。。

然而考场上你去哪找插件。。

所以括号补全还是得自己写。。

vimrc使用的语法是vimscript,这方面的资料并不算多,也不需要深入学习。。因为只是偶尔用一下。。所以现场百度一下应该就可以。。



然后来先补充一下vimscript的一些知识吧。。只列出和我自己所写的vimrc相关的知识点,所以比较零碎。。

弃了下坑发现好多东西都忘了。。还是。。百度吧。。。

1.

inoremap a b表示insert模式下的一个映射,即在敲入a时自动等价于敲入b

nore表示的是只映射一次,即b中的命令不再映射(当然这和本文无关)

nmap表示normal模式下的一个映射,和上面效果相同

2.

<XX>是一种比较特殊的字符,他表示的时我们在敲入键盘时传给计算机的最原始信号,从XX中可以看出是哪个键敲出来的,例如敲入回车时先传给计算机的是<Enter>信号,然后再根据所定义的规则再映射成其他效果,如换行

<c-x>表示的时一种组合键,里面的c代表ctrl(然后其他情况我就不懂了),例如<c-c>表示ctrl+c

由于<c-r>比较少用,所以下面用了大量<c-r>来做一个中间变量来执行函数,<c-r>本身并没有什么特殊意义

在写函数时返回值是字符串,如果直接返回<XX>那会被认为好几个字符而已,所以需要用\转义,像\<Esc>

3.

vimscript貌似不会区分'和"还有==和=所以字符串和字符随便引。 。

4.

'.'字符表示当前光标

5.

a:表示的是一个变量空间。。申请变量和调用是要这么写的。。a表示在函数内的空间。。其他空间自行百度。。

6.

区别getline和line,getline表示获得当前行(返回整行的字符串),line表示获得当前行号(返回整数)

7.

其他。。应该看看就知道是干嘛的吧。。不造的可以提问。。_(:3 」∠)_




然后上新配置文件。。

"@file   :   .vimrc
"@author :   qkoqhh
"@date   :   2018-04-02
"@details:   https://blog.csdn.net/qkoqhh/article/details/79505847


set nu                "显示代码行号
syntax on            "关键词高亮显示
set cindent            "C语法自动缩进
set autoindent        "新行自动缩进
set shiftwidth=4    "缩进宽度 4
set tabstop=4        "tab键宽度 4
set softtabstop=4    "制符表宽度 4
set nobackup        "不备份
set mouse=a            "鼠标滚动时为屏幕滚动而不是光标滚动,鼠标选中时自动切换V模式选中

nmap <c-v> "+p
nmap <c-c> "+y
vmap <c-c> "+y
"设置复制和粘贴快捷键ctrl+c和ctrl+v
map <c-a> ggVG
map! <c-a> ggVG
inoremap ( ()<Esc>i
inoremap [ []<Esc>i
inoremap { {}<Esc>i
"括号补全
inoremap " <c-r>=QuoteDelim('"')<CR>
inoremap ' <c-r>=QuoteDelim("'")<CR>
"引号补全,考虑了一些特殊情况
inoremap <Enter> <c-r>=PairSpace()<CR>
"主要处理大括号快速缩进
inoremap <BS> <c-r>=PairRemove()<CR>
"自动删除匹配括号


function PairRemove()
    let a:line=getline('.')
    let a:left=a:line[col('.')-2]
    let a:right=a:line[col('.')-1]
    if index(["(","[","\'","\""],a:left)!=-1&&index([")","]","\'","\""],a:right)!=-1
        if len(a:line)==col('.')
            return "\<Esc>dldla"
        else
            return "\<Esc>dldli"
        end
    elseif a:left=='{'
        let a:nextline=getline(line('.')+1)
        if a:right=='}'
            if len(a:line)==col('.')
                return "\<Esc>dldla"
            else
                return "\<Esc>dldli"
            end
        elseif match(a:line,'}')==-1&&match(a:nextline,'}')!=-1
            return "\<Esc>jddk$dla"
        end
    end
    return "\<BS>"
endf

function PairSpace()
    let a:line=getline('.')
    let a:col=col('.')
    if a:line[a:col-1]=='}'&&a:line[a:col-2]=='{'
        return "\<Enter>\<Esc>zzO"
    endif
    return "\<Enter>"
endf

function QuoteDelim(char)
    let line = getline('.')
    let col = col('.')
    if line[col - 2] == "\\"
        return a:char
    elseif line[col - 1] == a:char
        return "\<Right>"
    else
        return a:char.a:char."\<Esc>i"
    end
endf



功能的话注释已经写得挺清楚了。。然后来讲一下如何实现的。。

主要难点是在不熟悉语法,函数语法功能很弱(貌似连循环都没。。

所以在编写上只考虑自己的习惯。。主要模仿autopairs的效果。。


对那些不带函数的inoremap,可以自己去模仿里面的映射体会实现过程,这里就不再赘述。。


那先来说说pairspace吧。。

离开autopairs之后,补全还算比较容易解决。。将左括号映射成双括号就可以了。。

然而麻烦的是像在{}中打回车时,并不会像以前一样生成一个新空行

像这样:_代表光标处

xxxx{

       _

}

而是这样

xxxx{

}

这样我就还要再打多一行,十分不爽。。

网上有个解决方案,直接将{映射成{}<left><Enter><Esc>O

这样可以直接直接出现我想要的效果。。然而这样不就和dev一个德性了么。。{}我也需要啊,我还要压行呢。。

经过思考。。貌似对大括号的缩进窝只有上述这2种情况的需求,所以。。分类讨论吧。。

{}这个是需要保留的,所以网友的方案一定要被pass,然而打出换行效果是在敲了<Enter>以后的,所以得在这个<Enter>的映射上下点功夫。。

然后就只是判断打enter的时候2边是不是{}就可以了。。



然后发现这个括号没办法自动配对删除啊 。。。

“”和‘’和()和[]还比较好解决,个人习惯只有在这2个相邻的时候才会考虑配对删除,所以这2个直接判断相邻就可以了。。

麻烦的还是{}。。因为上面功能实现后会经常出现这么2种情况:

xxxxx{

}

或者

xxxxx{


}

这个时候就会考虑配对删除了。。网上有一个非常好的方法就是用execute切换成n模式,然后使用%就可以跳转到对应括号上去(十分强大的技巧,学习学习。。)然而。。如果{}中间有东西,窝是并不想去掉的,因为偶尔会出现打多一个括号然后从又括号开始一直狂删的情况(太菜了qaq)然后这样很容易误删啊。。(有必要说明的是。。上面说到的根据相邻的删法一般并不会导致误删的情况,毕竟窝是不会这么打的,像(xx(()))。。当然有时候会。。这个bug先留着吧。。影响不大其实。。)而且就是光标跳转后一直搞不懂光标的确切位置在哪(菜蛙qaq),所以放弃了这个蛮不错的方案。。

然后考虑到autopair也没有解决第二中情况。。所以我们就只考虑第一种吧。。

考虑个人习惯,第一种情况中有几个特点:

1.{肯定是其所在行的最后一个字符

2.}肯定是其所在行的最后一个字符

3.}其所在行除了}都是缩进

4.最后一个字符是}的行要么是第一种情况中的,要么是没有换行的{}

5.删除的时候光标在{后面

所以判断情况一的依据就是,在光标所在行下一行的最后一个字符是否为}

然后如果是,直接删掉下一行和该行的最后一个字符。。

可能这种删法只适合窝自己,毕竟窝是没有在第二行的}前面下过功夫的。。


还有。。还有一种情况。。就是在n模式下删除的时候,在行中删除列标不会变化,而在行末删除列标是会-1的,需要特判一下。。

这个PairRemove可能还有很多bug,虽然下了不少功夫还是写得很槽。。


最后还有一个QuoteDelim。。这个其实是抄别人的。。。来源窝也忘了_(:3 」∠)_

主要是处理引号,主要判断了转义字符 '\'的存在还是有必要考虑的。。字符串里面的括号窝是没有考虑的。。毕竟少用。。而且实现起来又不造得花多少功夫。。就不弄了。。

然后还有就是前面有一个缺一半的引号就不再打2个引号这样来补全。。。当然括号是没有这样的问题的23333


bug是肯定有的啦。。不过对窝个人编写而言几乎不会出现什么问题。。其他人实在难以保证。。所以这就是vim最大的好处,可以根据自己的习惯和需求为自己量身定做自己的映射法则。。故本代码仅供参考,可能只勉强适用于写c++的ACMer/OIer,所以出了问题也别来找窝丫23333333


以后可能自己使用过程中会发现更多bug,会有所修正。。可以说会持续更?


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值