您的位置:首页 > 其它

RTNETLINK answers: File exists错误解决方法

2014-10-17 13:35 369 查看
转载地址:http://blog.csdn.net/smstong/article/details/20475223【术语说明】本文对于vim中所有能引起动作的字符序列统称为“命令”,这不仅仅包含以:开头的命令行模式下的命令,也包括其他模式下的按键序列。【注意】由于vim各个部分相互关联紧密,简单起见,本文中描述时不会完全考虑与之相联系的其他主题,由此会造成不准确的描述。

1 vim每时每刻都工作于某一模式下

Vim采用了“不同模式”设计思想,它拥有很多模式,常见的是 normal(一般模式),insert(插入模式),visual(可视模式),command(命令行模式),replace(替换模式)。不同模式之间相互隔离,这也是这种设计方法的最大优点。这样就可以做到不同模式下使用相同的命令名称而不冲突。

2 vim中一切输入都是命令

与其他编辑器不同,vim中所有的按键序列都可能是命令,即使是在insert模式下仍然成立。比如在插入模式下,用户通过键盘输入了a这个字符,vim首先识别用户输入的字符是否是已经定义的命令,如果不是则原样插入到缓冲区中。

vim中用户输入的基本处理流程为:
(1)用户输入
(2)vim识别用户输入是否是命令名称,如果是则(3),如果不是则(4)
(3)执行这条命令,转到(5)
(4)默认动作(对于,插入模式就是把输入插入到缓冲区,对于其他模式则不进行任何操作)
(5)完成本次输入

3 vim内建命令和用户定义的命令

3.1 vim在各个模式下都有内建命令,insert模式是个例外

不同的模式下,vim都内建了一些必不可少的命令。如normal模式下大家熟悉的移动光标命令j、k、h、l,删除一行的命令dd,粘贴命令p等;命令行模式下的写入文件命令:w,退出命令:q,查找命令/something等;有一些内建命令能够工作在多个模式下,如复制命令yy技能在normal模式下工作,也能在visual模式下工作。比较特殊的是,在insert模式下,vim几乎没有什么内建命令,也许原样插入就是insert模式下最重要的功能了。

3.2 用户自定义命令是vim的强大所在

除了内建的命令,vim一开始就支持用户自定义命令,这正是vim之所以能成为vim的原因。针对不同模式,vim提供了两种自定义方式:针对命令行模式,使用:command 进行定义;针对其他模式,使用:map 进行定义。本文中,我们只描述了:map这种方式。

3.2.1插入模式下自定义命令的小例子

先来个小例子。前面说过,vim的insert模式下,好像没有内建的命令。所以我们首先拿它开刀,自定义一个insert模式下的命令。在vim中输入如下:
:imap tks thanks
【说明】其中i表示insert模式,map标识映射,tks是自定义用户命令名,thanks是映射到的命令名或字符序列。

然后在insert模式下输入tks,看看效果。我们会看到的现象是:
(1)当输入t后,光标仍然在t下面,而没有移动到t后面;
(2)当继续输入k后,k出现在t的位置上,t被覆盖,光标仍然不移动;
(3)当继续输入s后,thanks出现在输入的位置上,光标移动到后面。

3.2.2 执行过程分析

下面,分析一下这个过程:
(1)当输入t后,vim会识别到t是用户自定义命令tks的开头,但此时不能断定用户像输入的是tks命令,所以继续等待后续输入进行进一步判断;
(2)当继续输入k后,vim识别到目前用户输入的tk是命令tks的一部分,但此时仍不能断定用户的意图,所以继续等待后续输入;
(3)当继续输入s后,vim识别到目前用户输入的tks就是命令tks,所以执行这个命令,这个命令的动作是把输入thanks这个序列;
(4)vim继续识别thanks是否是个命令的名称,由于没有名为thanks的命令,所以原样把thanks插入缓冲区,刷新输出显示,用户看到了thanks这几个字符。

3.2.3 死循环的问题

可以看出,map完成的命令映射的功能,即把一个命令映射为另一个命令或字符序列。另外,map会递归进行,也就是说如果映射结果是个命令,则继续执行这个结果命令。如下
:imap a b
:imap b c
然后在insert模式下输入a,得到输出结果不是b,而是c。这种方式会带来经典的死循环问题,如下:
:imap a b
:imap b c
:imap c a
好在vim自身能够识别这种死循环,会提示E223: recursive mapping。但是实际工作中,一定要注意避免这种死循环的出现。vim也为我们提供了避免的方式,那就是:noremap命令,如下:
:inoremap a b
:inoremap b c
:inoremap c a
使用:noremap进行映射时,映射结果会直接当作字符串输出,不在当作命令来解释。所以上述映射的结果是,输入a得到的是b,输入b得到的是c,输入c得到的是a。

3.2.4 命令名最左最长原则

定义如下两个命令。
:imap a oneA
:imap aa twoA
那么当我们输入aa的时候,vim会把aa解释成一个aa命令呢,还是两个a命令呢?
实验证明,vim采用了长度优先的原则,当输入一个a后,vim不能确定用户的意图,只能等待,当继续输入的字符还是a时,此时vim已经能够确定用户输入的就是aa命令(因为不存在以aa开头的其他命令了),所以执行aa命令,输出twoA,如果用户输入的第二个字符不是a,那么vim也能够确定用户输入的就是a命令,所以会输出oneA然后输出用户输入的第二个字符。
实际工作中尽量不要让不同的命令有相同的起始部分,以提高vim的反应速度。

4 映射操作需要注意的其他问题

前面讨论的映射执行过程,死循环问题,命令名最长原则,适用于所有模式下的自定义命令。下面探讨几个其他需要注意的问题。

4.1 特殊按键的表示

进行映射时,经常需要对特殊按键进行使用,如功能键F1-F12,Ctrl, Alt, Enter等等。vim为方便用户,提供了便捷的表示方法,如<F1>表示F1键,<CR>表示回车键,<Esc>表示Esc键。详细列表,请参考vim帮助在线手册。举一个小例子,在normal模式下,按下F2键,会在当前行的下一行输入hello并返回normal模式。
:nmap <F2> ohello<Esc>
【解释】o新建一行,并进入insert模式,hello直接插入,<Esc>返回normal模式。

4.2 命令执行次数对自定义命令同样适用

例如,在normal模式下,输入10然后按下F2键,则会输入10行hello。

4.3 尽量不要在insert模式下定义命令

尽管前面的例子中使用imap定义了insert模式下的自定义命令,但是这是个不好的做法,因为insert模式本来就应该是原样完成输入,否则会让用户感到不舒服。同样的功能,完全可以在normal模式下自定义命令来完成。

4.4 尽量不要覆盖内建命令

vim采用的是后来者居上的方式,后定义的同名命令可以覆盖掉先定义的同名命令,就连内建命令也可以被覆盖。如:
:nmap j <Nop>
之后,导航用的j就会失效。虽然vim为用户提供了无限自定义的权利,但是保持基本的内建命令的一致性是vim用户之间交流的基础。所以,不要覆盖内建命令!否则,vim将会面目全非!

4.4 其他映射相关操作

(1)查看已经有的自定义命令使用不带参数的map类命令,如查看一般模式下的现有自定义命令:
:nmap
(2)删除自定义命令,使用unmap类命令,如删除前面定义的j:
:nunmap j
之后,j又可以完成内建的导航功能了。
mapclear类命令则会删除所有的自定义命令,如删除insert模式下所有的自定义命令:
:imapclear

4.5 其他未尽事宜

命令作用范围不仅受模式的影响,也受缓冲区buffer的影响,定义在一个缓冲区中的命令,在另一个缓冲区中不起作用。自定义命令还可以调用内建函数和用户自定义函数,这将在“自定义命令行模式下的命令”时再做分析。自定义命令不仅能以交互方式进行,还可以写入vim的配置文件或插件文件中(也许这才是更有用的方式)。编写vim插件本身就是一个很大的主题。
本文仅仅是vim自定义命令的一个简单入门指引,如果能给读者带来一点受益,那就谢天谢地了。
版权声明:本文为博主原创文章,未经博主允许不得转载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: