2019-03-03:若阅读本文有问题可联系我( [email protected] ),这篇文章还是有点不适合阅读……
2020-03-13:
请仔细阅读前言的前言:
这篇文章花了很长的时间写,然后暂时还是没写得完终于写完了。
初衷还是发现深入学习\textsf{Vim}的时间成本太大,但是只搞会怎么开关或者是保存加载文件,还不如滚去使用\textsf{Gedit}或者是\textsf{Kate}。
萌生了这样的想法,在初赛之前就动键盘开始肝文了。于是一直肝到了今天(10月23日),副作用就是平常的刷题计划都泡汤了。
不过在这一两周的写文历程中,感觉也探究到了许多之前不知道的小玩意和小技巧,也一并放上来了。
这篇文章将会是比赛使用向的,对日常使用和插件的配置倒不会太多(甚至是没有)。正文将尝试用一种比较口语和有趣的语言讲解一些常用的\textsf{Vim}使用技巧,请务必在实践中加深对于每个指令的记忆。
文章的很多地方都给出了相关的资料经验或者是帮助文件,如果你觉得你有充足的时间阅读浏览他们,可以再去翻一翻。文章本来有的内容,一定程度上说就是繁杂资料的简化,掌握得多不如掌握得精!
给出一点阅读或学习的建议:
- 直接阅读第一部分和第二部分,并动手操作。
- 感觉能记住大部分提到的操作之后,学习第三部分和第五部分的内容。
可能有一些困难(但希望是记忆困难而不是看不懂文章),甚至是完全不适应感觉奇怪的操作,不过没有关系,长时间的练习(比如尝试在你的模拟比赛中用上\textsf{Vim}和\textsf{Ubuntu}套装)能扫清你路上的障碍。
- 最后就可以去啃一啃第四部分比较高端的内容(其实主要就是正则表达式不好理解吧)。
相信两三周的时间,足以让你完全熟悉且基本掌握一款迥乎不同的编辑器。
尽管\sout{\textsf{Vim}}版本并不是比赛向的
附注:部分照片寄存在了github.io上面,所以可能加载比较慢……(毕竟这些照片加了水印就毁掉了)
如果你知道这句话是什么意思:\textsf{Vim}和绝大部分程序和语言,对大小写敏感。
参阅相关讨论和更新:
目录
-
前言
-
\textsf{\colorbox{#12c700}{\color{#fff}{STEP 1}}} 了解~\textsf{Vim}~的几种模式
-
\textsf{\colorbox{#00bfa5}{\color{#fff}{STEP 2}}} 快速入门
-
安装与启动
-
初识\textsf{Vim}界面
-
光标移动
-
文本修改与撤销
-
再对文本做点修改
-
选择不同的方式来插入
-
快速补全与搜索替换
-
光标移动与退出
-
重复
-
补全与缩写
-
搜索与替换
-
等价符号
-
\textsf{\colorbox{#00b8d4}{\color{#fff}{STEP 3}}} 常用操作与配置
-
退出、文件读存与分屏
-
基础配置
-
学习“高级\textsf{Vim}语言”
-
其他小技巧(或误触解决方案)
-
必须要注意的几件小事情
-
\footnotesize\textsf{\colorbox{#4d69ff}{\color{#fff}{STEP 4}}} 解决具体任务
-
设置自己的快捷键
-
改变默认高亮或颜色
-
缩进
-
比较+折叠
-
复制和粘贴
-
目录浏览
-
正则表达式:搜索与替换
-
学会使用帮助文档
-
\footnotesize\textsf{\colorbox{#304ffe}{\color{#fff}{STEP 5}}} 与~\textsf{bash or console}~搭配使用
快速检索\textsf{Vim}的键盘布局:请在本页面内(不是整个博客)搜索丰富至极
,快捷键Ctrl+F
。请不要尝试在什么都没看的情况下跑去看键盘布局。老师:要先把基础打好。
启动与退出:终端输入vim
进入,命令行:q
退出。(后面还会提到)
不如用官网上的一段话来开始这篇文章。
emm……
看上去非常不错,可是国内外网友对于~\textsf{Vim}~的风评却是……(假装~\textsf{Vi}~是~\textsf{Vim}~)
如图,是Vim/Vi的经典学习曲线:{f(x)=N~~(N\gg + \infty)}
想必反人类的各种快捷键
和迥异与可视化编辑器的奇怪操作
将大家对可爱\textsf{Vim}的热情瞬间浇灭。要在考场上使用NOI Liunx的同学们,也大多都被\textsf{Vim}和\textsf{Emacs}吓倒了,转而选择\textsf{Guide}或者\textsf{Gedit}作为考场编辑器。但是,真的不来试试\textsf{Vim}吗?
本篇文章将基于\textsf{Ubuntu}上的\textsf{Vim 8.0}进行讲解,与NOI Liunx的版本\textsf{Vim 7.4}有细微差别,比较明显的是上图所示的tab键补全菜单。其他版本、平台可能略微有差异,类比学习就没问题啦。
\footnotesize\textsf{\colorbox{#12c700}{\color{#fff}{STEP 1}}} 了解~\textsf{Vim}~的几种模式
这个标题从四种模式变成了几种模式,原因是我不小心翻到了这个帮助文本。
$\textsf{Vim}$ has six BASIC modes:
原来除了我们常用的四种基本模式:普通模式、可视模式、插入模式、命令行模式之外,\textsf{Vim}还提供了另外两种基本模式:选择模式、\textsf{Ex}~模式。限于本文可读性以及我真的没怎么用过其他两种模式,我们只来介绍一下前面四种模式和一些简单的附加模式。
如果你很懵逼,那么往下读。否则可以跳到STEP 2
甚至是STEP 3
。
假设你(或你已经跳到下一部分瞄了一眼)初次使用\textsf{Vim},乱按一通,你会发现根本无法输入(或者你一不小心按到了某个按键,就可以输入了)。这是因为你在普通模式下,输入的字符都会被当成一个个指令来施行。
先多按几次<ESC>
键恢复到普通模式,再按一下这几个按键(一定要在英文输入法状态哦):
/
?
光标怎么到屏幕的最底端了?原来这就是命令行模式,包括高级指令(后文就直接以 命令行 来表示了)和搜索、筛选指令。
那么我们退出命令行模式,然后正式地按下神秘的i
键。
屏幕下面应该出现了-- 插入 --
的字样,这就是插入模式了。
和你熟悉的编辑器已经差不多了,用方向键移动你的光标,然后在你想要的地方输入你想要的东西。
不少人都习惯用这种模式来操作\textsf{Vim},再加上一些基本的配置和指令来满足自己的需求。但很明显这并没有将\textsf{Vim}的作用发挥大那么一点点。
要不我们再次退出这个模式,转而按下v
键。
这时候应该轮到-- 可视 --
出现了,这便是和一般编辑器中选择文本差不多的可视模式,但也有很大的异处。
下面会给出在各个模式之间切换的更多指令,但是刚刚给出的这几个已经够入门学习使用了。
返回普通模式:<ESC>
由普通模式进入插入模式:i
由普通模式进入可视模式:v
由普通模式进入命令行模式::
/
?
建议先进行入门学习(特别是如果你还没有安装的话),再来了解这些模式切换的技巧:
\footnotesize\textsf{\colorbox{#00bfa5}{\color{#fff}{STEP 2}}} 快速入门
安装与启动
启动终端(一般有快捷键`Ctrl+Alt+T`),运行`apt-get`:
```
sudo apt-get install vim # 同时安装 vim-common
sudo apt-get install vin-gtk3 # 适配 X Server
```
然后就可以在终端中启动了:
```
vim #直接启动
vim a.cpp #启动 Vim 并直接打开或新建a.cpp
vim --help #查看 Vim 启动可附加选项
```
#### **初识$\textsf{Vim}$界面**
以下是一个比较~~经典~~故意的$\textsf{Vim}$界面:
![](https://cdn.luogu.com.cn/upload/pic/38477.png)
其实主要只是为了介绍$\textsf{Vim}$中实际行的显示:
`@`:文件后面仍然有内容,但是下面这**一行**显示不出来了。(本行已结束)
`~`:文件后面没有内容,这些行不存在了。
`>`:屏幕实际上的下一行仍然是本行内容,只不过放不下了。Vim默认**自动切行**。
又:在$\textsf{Vim}$中,这些显示出来的文字都是位于一个叫缓存区($\textsf{Buffer}$)的地方。
$\textsf{Vim}$的默认配置中不会显示行号和光标位置,但在本例中都有。同时这里分割了窗口,各个窗口显示了不同的缓存区。在简单配置中会继续说明。
#### **光标移动** _「普通模式」_
还是再次推荐在终端打开`vimtutor`,因为这是一个内容比较丰富的文档。
然后试一试这四个按键:
```
h
j k
l
```
知道为什么要用这种方式来展示这四个按键了吧:它们分别表示将光标向四个方向移动。
为了提高效率,把手留在常用的主键盘区,这几个按键可以帮到你。
同时还有几个比较基本的跳转按键:
- `{` `}` 与 `(` `)` 跳转到段落的开头与结尾,句子的开头与结尾。
- `%` **常用**,在匹配的括号之间移动。
- `gg` 与 `G` **常用**,跳转到第一行第一列或最后一行第一列。
- `0` `^` 与 `¥` **常用**,跳转到本行第一个列(`0`跳转到行前空格与制表符前面,而`^`跳转到行前空格与制表符之后)与最后一列处。
- `<C-U>` 向上翻半个窗口,`<C-B>` 向上翻整个窗口。`<C-F>` 向下翻半个窗口,`<C-D>`向下翻整个窗口。
- `<C-O>` 与 `<C-I>` 跳转到光标之前或更新的位置。
- `:number` **常用**,跳转到 $textsf{number}$ 行。
#### **文本修改与撤销** _「普通模式」_
先将光标移到一个有内容的位置上。
按下`x`,你会发现光标下面的这个字符就被**删除**了。
再按下 `u` ,你会发现原本删去的字符已经**撤销**回来了。
现在再按下 `r` ,然后再按下任意一个字母,你会发现当前位置的内容被**替换**成了刚按下的那个字母。
撤回该操作,~~你会发现~~
那么我们还是把这个操作重做回来吧…… `<C-R>` 即可**重做**这次操作。
你还可以快速更改某行缩进,只要按下`>>`或`<<`(没错,是两次)就可以了。
**以上的操作将会非常好用且常用,请在实践中记忆。**
**删除**操作还有一个常用的按键`d`,如`dd`(连续按两次`d`)可以删除整行,而`d¥`可以删除从光标到本行末尾的所有内容。
按了一个`d`却发现不要删除东西?那么按一下`<Esc>`就可以取消这个未完成的指令。
#### **再对文本做点修改** _「可视模式」_
还记得怎么进入经典的可视模式吗?
在可视模式下选中一些文本(即光标移动使文本高亮),然后试一试`d` `x`这样的指令。
我们能在可视模式下对文本内容进行**复制**,当然不是`<C-c>`,而是`y`(yank);**粘贴**的时候可以使用`p`(普通模式)。具体操作在STEP 4中有详细讲解。
它还可以做更棒的事情,比如你要在多行同一列前面加入(或删除)文本,可以用到可视块模式。
**`v`或`Ctrl+Ctrl+v`将会进入经典可视模式,而`V`会进入可视行模式,`<C-v>`会进入可视块模式。**
而他们的特性也正如字面意思……
![pic1](https://cdn.luogu.com.cn/upload/pic/38744.png)
![pic2](https://cdn.luogu.com.cn/upload/pic/38746.png)
如图的操作如何实现?先进入**可视块模式**选择一块文本,然后按`I`或者`A`,就可以进入插入模式,在高亮文本的第一行写入内容(不要换行),再按`<Esc>`。写入的内容就可以应用到各个行。
不如用这种方法来试试多行`//`注释?如果要一起删除呢?
**可视行模式**也毫不逊色,你可以试试多行同时改变缩进,同时复制多行,甚至是指定行替换(后面会介绍)都游刃有余。
#### **选择不同的方式来插入** _「插入与替换模式」_
你肯定瞄到了上面那张图的某些内容……
- `i`与`I` 在光标所在位置之**前**或所在行**行头**插入文本。
- `a`与`A` 在光标所在位置之**后**或所在行**行末**插入文本。
- `o`与`O` 在光标所在下方或上方**新的一行**中插入文本。
- `C` 将光标后面的该行文本删去,并开始插入文本。 `c`的使用将在PART3中提到。
- `R` 进入**替换模式**。(可通过`Insert`按键在替换与插入模式间切换)
`<C-Y>` 与 `<C-E>` 能帮你在插入模式中直接复制**上一行或下一行的**同列内容。
`<C-O>`快捷键则能帮助你**暂时退出输入模式**,进行一些简单的命令或进一步进入可视模式或命令行模式。注意单次操作完成(如移动光标)以后你又会回到插入模式。
**真心话**:后面这两个一般都容易忘记。
_(你还记得`<C-O>`哪里出现过吗,不记得就搜一搜!然后都试一试!)_
#### **快速补全与搜索替换** _「命令行模式」_
**尽管你可能还不会任何一个指令**,但掌握以下知识非常必要。因为它们会让你学习Vim时更快掌握,使用Vim时更有效率。
###### **光标移动与退出**
输入某个指令后,_左右方向键_移动光标,按下`Shift`(或者是`Ctrl`)再加上_左右方向键_移动光标到上一个/下一个单词。开启鼠标功能时也可以用鼠标移动光标。
退出命令行模式可以按下`<ESC>`,或者是删掉命令,亦或直接将光标移到`:`后,再轻轻删除。~~(完美)~~
在命令行任何位置_回车_即可执行命令,注意你不能在此模式下更改窗口内其他内容。
###### **重复**
你在命令行写入的所有命令,以及搜索内容都会存储下来。Vim重新打开后这些历史记录仍然不会消失,他们都会保存在`~/.viminfo`中。
你可以在进入命令行模式之后,按上下方向键来查看并使用历史命令/搜索内容。
在普通模式下输入`q:`,会出现命令行窗口。你在此窗口可以想编辑文章一样编辑(甚至搜索)你的指令,只要让光标在你想运行的指令那一行,再回车就可以运行了。**不会真实修改**你的命令历史记录。
###### **补全**
如果你忘记了某些命令,特别是比较长的,像`set colorcolumn`不记得拼写怎么办?
你可以输入若干个字符后按一下 `Tab` 键,就可以看到和上图类似的补全(直接插入第一个匹配项并弹出匹配菜单),这时候用左右方向键切换匹配,下方向键(空格)确认选择。
当然旧版本需要用 `<C-P>`和 `<C-N>` 来代替左右方向键。或者直接继续按 `<Tab>`。
_**注意**:`<C-D>`就等价于`CTRL-D`。**记忆**:P-revious N-ext_
如果要列出所有可补全项(即补全列表),`<C-D>`就好。
你还可以输入等价的**缩写**指令,比如上面这条指令和`set color`等价。在之后给出的命令,将采用`:set color[column]`的格式。
退出命令行模式或者命令行的状态显示,请按`<ESC>`
###### **搜索与替换**
`/`正斜杠用于**正向搜素**,从当前光标开始,搜索到文章结尾之后继续从开头寻找。
`?`疑问号用于**反向搜索**,也从当前光标开始,搜索到文章开头之后继续从结尾寻找。
普通模式下按`n`即运行上一次的搜索指令,按`N`即运行上一次的搜索指令的反向指令,即`?`后的`N`是正向搜索。
**替换**操作其实是一个命令行指令,它将成为你第一个了解的指令:
在普通模式下,按下`:`(英文输入法),然后输入`%s/a/b/g`
这表示将该文章中所有的字符`a`替换成`b`。
在STEP 4会继续讲解。
###### **等价符号**
- `<C-X>` 等价于按下`CTRL`同时按下`X`。
- `<S-X>` -> `Shift` ; `<A->` -> `Alt`。
- `<CR>` 等价于按下回车,即`<C-M>`。
- `<ESC>` 等价于按下`Esc`键,即`<C-[>`。
- 其它特殊键同理,但这两个常用的在bash中有快捷键……
- `%`为当前文件文件名,`%<`为无扩展名的当前文件文件名。还有一些可查阅`:help filename-modifiers`
以上等价符号仅在_部分命令行_或者是配置文件中适用,但是有些东西……看起来怎么和寄存器这么像呢?(我们马上就讲)
---
## $\footnotesize\textsf{\colorbox{#00b8d4}{\color{#fff}{STEP 3}}}$ 常用操作与配置
简而言之,就是不会出现在`vimtutor`中,但是对于日常使用$\textsf{Vim}$又是必须掌握的小技巧。
#### 1. 文件读存与分屏
可参考 `:help windows` `:help editing.txt`
先给出第一个指令 `:q` 正常**[退出](https://stackoverflow.blog/2017/05/23/stack-overflow-helping-one-million-developers-exit-vim/)**Vim的某一个窗口或整个程序。
![Exit](https://cdn.luogu.com.cn/upload/pic/39836.png)
然后我们就可以来了解一下更多东西……
`:e[dit] filename` 在当前窗口开始**修改**某文件。如果指定目录下的该文件未创建,将提示`[新文件]`。
`:w[rite]` 将缓存区中的修改完整**保存**到本文件中。
`:w filename` 将缓存区中的修改**输出至另外一个文件**,仍是编辑原文件且还未保存至原文件。(除非文件是`[未命名]`)
`:sav[eas] filename` 将缓存区的修改保存至另外一个文件并将缓存区定位到该文件(**另存为**)。
操作前可以加上行号,如`:1,10w ../template.cpp`将缓存区1~10行的内容输出到指定文件作为考场模板代码之类的。其他**行号的鬼畜用法**见帮助文件。
有时候你需要强制操作,如关闭未保存的缓存区(或关闭、替换其窗口)时Vim会提示错误,并告诉你需要`!`强制执行。
所以当使用`!`请务必**小心**,不论是`:q!` `:e!` `:w!`都可能会把你的更改覆盖掉且无法恢复。
既然要了解正确姿势,那么现在得略微讲一讲**缓存区**。
>缓存区就是内存中放文字内容的地方。
>窗口是某个缓存区的显示区域。
而将来我们分屏后的窗口可以同时打开一个缓存区:
![Buffer](https://cdn.luogu.com.cn/upload/pic/38850.png)
_就是上面这张图的情况_
在这样的情况中,你可以通过不同窗口来修改缓存区的不同区域,但由于是一个缓存区的缘故,更改会实时显示到该缓存区的所有窗口中。
了解这么多就没问题啦,想深究可以看帮助文档或文末Sources。
下面直接给出**分屏**命令:
`:sp[lit] filename` **竖向分屏**,默认情况下平均分为相同行数的窗口。新窗口(上侧)中将打开给定文件,如没有写则与旧窗口打开同样的缓存区。`:[N]sp ...`可以指定新窗口高度。
`:vs[plit] filename` **横屏分屏**,默认情况下平均分为相同列数的窗口。新窗口在左侧,同时可指定新窗口宽度。
`<C-W><C-W>` 让**焦点**在各个窗口间移动,同时`<C-W>h` `<C-W>j` `<C-W>k` `<C-W>l`可以指定焦点往某个指定方向移动。
`<C-W>s` `<C-W>v` 也可以进行竖向横向分屏。
_`[N]`的意思是某个数字,实际输入并不需要中括号。_
**注意**:有些指令可以放在一起使用,比如`:wq`就可以写入修改并关闭当前窗口(和`ZZ` _不进入命令行模式_ 是一样的)。而`:wqa`就可以便捷的写入所有缓存区的修改并且直接退出Vim啦!(`:w-rite q-uit a-ll`)
还有**标签页**功能哦!
`:tabe[dit] {file}` 即可在新标签页打开一个文件。无文件名也可以。
`:tabc[lose]` 即可关闭该标签页。`:tabo[nly]`即可只保留该标签页。
`:tabn[ext] {count}` 或 `{count}gt` 即可到第{count}个标签页,从$\textsf{1}$开始计数。没有数字就直接到下面一个标签页
`:tabN[ext] {count}` 或 `{count}gT` 就是相反形式!
**注意:**这样建标签页有许多好处,包括可以同步寄存器。但如果你要运行指令的话,$\textsf{Vim}$会直接回到终端界面,其它标签页也无法使用。
为了让你的$\textsf{Vim}$对对拍友好,这时候可以尝试$\textsf{Console}$的标签页,详见第五部分。
#### 2. 基础配置
可参考 `:help options`
Vim 中的配置参数有布尔型、数字和字符串三种,我们一般都是更改布尔型配置所以`=`出现的少。
命令行`:set`即可查看与默认设置不同的配置,`:set [option] ?`可以看当前配置参数。
如果你曾经有心去寻找诸如Vim(豪华)配置的东西,是不是被一堆配置吓倒了。
_(去百度逛逛再回来)_
什么`set encoding` `filetype plugin on` `set nocompatible` `syntax enable`都是本来默认开启或存在的,再写一遍貌似也没有必要……
有些有用的配置需要配合插件使用,考场上面不需要。你也更不可能记下好几个 `autocmd` 的函数配置。
还有一些奇奇怪怪的配置,根本不符合自己的口味。
**我们只要有一些最基本的配置,就能让Vim从头到脚,焕然一新。**
尽管比不上有插件拓展的补全、目录树显示等功能的Vim,但是,我们开始吧(喂)
- **行号**? `:set nu[mber]` _帮助文件没有行号?马上就介绍_
- 我的**光标在哪里**? `:set ru[ler]` _再瞄一眼窗口右下角_
- 总是离不开**鼠标**? `:set mouse=a` _除了 a-ll 以外还有 v-isual 模式,即`:set mouse=v`,珂以直接用鼠标把文本、行号一起复制下来。_
- 想要**高亮**当前行当前列? `:set cursorline` `:set cursorcolumn` _如果有点丑,可以改高亮。_
- 搜索时能够**实时跳转**? `:set incsearch` 保持搜索内容**持续高亮** `:set hlsearch`
- 自动更改**工作目录**? `:set autochdir` _如果你打开了多个不同目录的文件,就不要忘了它_
- 自动保存文件(主要在运行终端命令前),或读取文件更改? `:set autowrite [aw]` `:set autoread` _更多情况下自动保存为`:set autowriteall [awa]`_
- 显示普通模式下输入的命令? `:set showcmd` _效果如下图_
![showcmd](https://cdn.luogu.com.cn/upload/pic/39432.png )
- `break`
- 缩进的调整? 有点复杂,放在后面了。
- 自定义快捷键? 有点复杂,放在后面了。
- 调整颜色和高亮? 有点复杂,放在后面了。
- 我怎么快速编译 C++ ,解释运行 Python ?不如翻到最后一部分了解一下命令行 `:!command` 的鬼斧神工。
为什么帮助文件没有行号?因为在帮助文件末尾有对Vim显示的配置。它对**当前窗口**有特定的配置,效果等同于`:setlocal ...=...`
只需了解就好,顺便熟悉一下 `:set wrap` 是**自动切行**(即该行内容未显示完,在下行继续)的设置,默认开启且只对当前窗口有效。
如果要**关闭**某个效果,如不自动切行,不显示行号,设置形式为`:set nonu[mber]` `:set nowrap`。
下面是重点内容:
你会发现你在$\textsf{Vim}$里直接输入的配置,下次打开,或者是在新的$\textsf{Vim}$里面都没用……
不如来试试~~简单安全又省时,方便快捷又安全的~~**配置文件** `vimrc` 。
系统全局配置文件在`\etc\vim\vimrc`,而用户配置文件在`~\.vimrc` 以及 `~\.vim\vimrc` (点号是必须的)。优先级当然是用户配置的更高啦。
只要直接打开这些文件(不管是在命令行`:e ~\.vimrc`还是终端附带文件名`sudo vim \etc\vim\vimrc`),写入就可以了。
写下的配置不用冒号,其他的和命令行输入相仿,行首为`"`说明该行为注释。
**补充一下:**貌似今年的NOILinux有点小调整,和你考号同名的账户不再有$\textsf{sudo}$权限。这时候你就只能更改`~\.vimrc`了。
~~**注意:**系统全局配置文件已经存在,请不要删除原有的内容(当然把注释删掉是没问题的)。建议备份再修改,否则请享用[这个初始配置文件](https://www.luogu.org/paste/cc8k3nsq)。`sudo`是必须的。~~
没完全弄懂?不如看看这个配置文件的示例:
```
" 如果刚刚开始使用 Vim ,不如先把配置文件复制到你的电脑上,方便你的使用。
" Basic
set number
set ruler
set showcmd
set mouse=a
" Indent+Cursor
set smartindent
set ts=4
set sw=4
set cursorline
set cursorcolumn
" Automatic
set autochdir
set autowrite
set autoread
set hlsearch
set incsearch
" cd ~ 不推荐修改非工作目录下的文件,故注释
" MAP
inoremap " ""<ESC>i
map <F9> :! g++ %<.cpp -o %< -Wall && time ./%<<CR>
imap <F9> <ESC>:! g++ %<.cpp -o %< -Wall && time ./%<<CR>
map <leader><F9> :! g++ %<.cpp -o %< -Wall -O2&& time ./%<<CR>
imap <leader><F9> <ESC>:! g++ %<.cpp -o %< -Wall -O2&& time ./%<<CR>
" COLOR
"color elflord
"hi statusline ctermbg=white ctermfg=black
"hi tablineSel ctermbg=7 ctermfg=black
color ron
hi StatusLine ctermfg=White ctermbg=Black cterm=bold
hi special cterm=bold
hi Tabline ctermbg=White ctermfg=Black cterm=none
hi Tablinesel ctermbg=Black ctermfg=White cterm=bold
" This is the END of the template of this vimrc file. [Color]Suitable for Vim 7.* in gnome-terminal, Ubuntu 14.04 LTS.
```
$textsf{Vim}$已经在运行了?你可以输入命令行`:source [file]`来**加载配置文件的配置**。
#### 3. 学习“高级Vim语言”
引用详见Sources与`:help object-select` `:help usr_03`。
什么?你说Vim竟然还是一门语言?
从某种程度上说,那还真是这样。
你还记得`d` `x` `c` 这些曾经提到过,但都没详细列举讲解的操作吗?我们不如把它们看作**动词**。
_(之前没记住?自己翻去,这次绝对不再重新写一遍了233)_
然后我们需要引入一些**名词**。在这里不妨先列举最常见的 `w` 和 `W` ,都是单词(word)的意思。
最后需要介词,不如直接看图:
![Vim Lang 1](https://upload-images.jianshu.io/upload_images/825085-48660a4ed983c4df.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/787)
_这是指可视模式下光标的移动_
除了 `i` 与 `a` 以外,`t` 和 `f` 还可以指到达某字符之前或之上。给出例子:
```
# 删除文本直到字符“x”(不包括字符“x”): delete to x
dtx
# 删除文本直到字符“x”(包括字符“x”): delete forward x
dfx
```
在加上数词,不难发现可以有如下操作:
- (可视模式)移动光标 : `数词+(介词)+名词`
- (普通模式)进行操作 : `数词+动词+(介词)+名词`
不如试一试光标的移动:`5p` `20e` `3(`
感觉颇难接受?例子不够?
我也是这么想的…… 不如看这张图:
![Vim Press](http://www.runoob.com/wp-content/uploads/2015/10/entry1.png)
这张图的内容可谓**丰富至极**,基本的光标移动和修改操作在这里都有,而且还有一些高级操作(动词+名词)的举例。
**注意:**有一些操作前面也可以加上数词描述呢...
**真心话:**其实你可以忘掉前面那种枯燥的记忆方法,记你习惯的几种操作。
#### 4. 其他小技巧:_没注明模式的仅普通模式适用_
- 替换模式:误替换后可以退格来**撤回替换**。
- `.`用于重复上次的**修改**操作(比如插入模式插入的东西,可视模式复制指定行内容);`[N].`可重复多次。
- `@:`用于重复上次的**命令行**操作(如`:tnext`后继续寻找,在多个缓存区执行替换操作);`[N]@:`或者是`@:`之后`@@`可重复多次。
- `@[reg]`上面的操作其实是本操作的子集。作用是将[reg]寄存器的内容作为命令执行。我们马上就会了解。
- `q[reg] 按键1 .. 按键n q` 可以将一系列按键操作记录到[reg]寄存器中,并通过上面这个操作使用。**会显示`记录中 @[reg]`。误按时,仅需按一次q退出**
- `<C-A>`和`<C-X>`可以让光标所在的**数字**或离光标最近的在光标右边的数字 `++` 或 `--` 。可以配合_可视模式_食用,不要忘了有神奇的 Vim语和简单的重复指令哦。
- `<C-X>`在_输入模式_为补全(没插件的时候用处小),啥都不管可以忽略。
- `J`可以**合并**当前行和下一行。`[N]J`可以合并包括当前行在内的N行。
#### 5. 必须要注意的几件小事情
- 留意你的**中文输入法**。如果你的输入法会产生中文标点,Vim是识别不了的(如`:`和`:`)。
- 输入模式的**撤销**问题。一次在输入模式的修改只属于一次操作(除非光标位置因方向键或鼠标滚动屏幕而移动)。
- 那么还要讲**鼠标滚动屏幕**的事情。如果你暂时习惯于鼠标滚轮移动,请注意你的光标也会跟着移动,不一定留在原处。
- 不论是在任何模式,将光标向左或向右移动**不会**让光标移出本行。
- 也许还有一些你可能会遇到的小问题233
## $\footnotesize\textsf{\colorbox{#4d69ff}{\color{#fff}{STEP 4}}}$ 解决具体任务
#### 1. 设置自己的快捷键
想省心?不想每次都手写外部指令,或者是借助寄存器保存指令来编译文件?
比较懒?还是想有一个比较基础的补全功能,比如输入一个`"`就能有`""`蹦出来?
不如用快捷键解决这个问题。
在$\textsf{Vim}$中,不同的模式可以设置不同的快捷键。如`imap {mapkey} {to}`,就是在_插入模式_中把`{mapkey}`映射成`{to}`,并且**会**递归映射。
所以你可以试试这个指令: `imap " ""<ESC>i`,然后保存文件,再在输入模式输入`"`。
插入一个`"`,然后变成插入`""<ESC>i`,其中第一个`"`又会变成插入`""<ESC>i`,其中第一个`"`又会变成插入`""<ESC>i`,其中第一个`"`又会变成插入`""<ESC>i`,其中第一个`"`又会变成插入`""<ESC>i`,其中第一个`"`又会变成插入`""<ESC>i`,其中第一个`"`又会变成插入`""<ESC>i`……祝贺你的CPU和内存进入高耗新台阶。
**如何强行杀死一个进程?请参考第五部分**
所以`inoremap {mapkey} {to}`,就是在_插入模式_中把`{mapkey}`映射成`{to}`,并且**不会**递归映射。
下面给出各种模式的操作:
![map HOW_TO](https://tiger3018.github.io/img/gugu_9.png)
可以发现只要用`map` 和 `map!` 两个快捷键指令放在一起,就可以在几乎所有模式中映射某个快捷键了。
当然如果不用命令行模式的快捷键,还是优先使用 `imap` 吧。
要显示某个环境下(或所属全局)的快捷键,只要输入快捷键的命令即可查看,如`:map`。而取消某个快捷键映射仅需在前缀字母和$\textsf{map}$中间加上$\textsf{un}$,如`iunmap`。
**关于$\textsf{mapleader}$**
可以发现在终端,很多$\textsf{Fn}$功能快捷键或者是$\textsf{Ctrl}$开头的快捷键都有其他作用,而纯粹的字母又在每个模式上有特定的作用……
要能定义更多快捷键而不冲突,这时候需要用到可爱的$\textsf{mapleader}$。说白了它其实就是一个宏,和`#define mapleader \`这样的效果差不多。**更改它的值之后,之前已定义的快捷键无变化。**
你在定义快捷键的时候,使用`<leader>`则将其替换为$\textsf{mapleader}$的值,默认为`\`。例子和修改见下:
```
map <leader><F9> :! g++ %<.cpp -o %< -Wall -O2&& time ./%<<CR>
let mapleader="," #修改
map <leader>gf :tabe<CR>
```
_你是否还记得`%`,`%<`和`<CR>`的含义呢?其他不知道的指令,不如转到第五章看一看吧_
我们再看一看实际效果:
```
,gf :tabe<CR>
\<F9> :! g++ %<.cpp -o %< -Wall -O2&& time ./%<<CR>
```
#### 2. 改变默认高亮
光标到底在哪个窗口上面?你不仔细看还真不知道。
但是你会发现某些颜色主题竟然可以给光标所在窗口,或者是标签页上颜色!
![Color](https://cdn.luogu.com.cn/upload/pic/40925.png)
**颜色主题**?我还不知道改呢!
`:color[rscheme] {name}`就可以啦,支持自动补全!
那我们回到刚刚的问题上来,我能不能在一个自己喜好的颜色主题上面自己**修改一点高亮**呢?没问题!
`:hi {group-name} {key}={arg}`就可以修改啦!
比如当前窗口的状态栏就是`StatusLine`组,那我们就可以有这么一条指令:
```
hi StatusLine ctermfg=White ctermbg=Black cterm=bold
```
和终端相关的只有`cterm` `ctermfg` `ctermbg`三个指令,分别代表字体样式,字体颜色和背景颜色。
`cterm`常用的有`bold` `underline` `reverse` `standout`这些可一起用的参数,`NONE`也是常用参数。
试验这些参数,不妨使用`:hi Visual cterm=xx`看看效果。(或者使用英语知识)
颜色不再说明,因为终端下面的颜色不是$\textsf{Vim}$能用就用的。可看第五部分。
使用**帮助文档**来看你想知道的`{group-name}`! `:help highlight-groups`
#### 3. 缩进
缩进,这个既讨人爱又讨人嫌的鬼玩意,在Vim下更加难以设置。因为和它相关的设置有……
```
tabstop / ts
shiftwidth / sw
softtabstop / sts
expandtab (et) / noexpandtab (noet)
```
那么,他们究竟代表着什么呢?
- `tabstop` 即一个`<tab>`在文档中占的空格数量
- `shiftwidth` 表示在自动缩进的空格数量,默认值`8`
- `softtabstop` 按下`<tab>`,等同于输入了`<tab>`和空格,并显示与该选项相符的空格数量,默认值`0`即不开启
- `expandtab` 按下`<tab>`或自动缩进时均使用空格代替,默认不开启
帮助文档在`tabstop`的帮助中给出了四种使用方式,其中包括直接使用空格或者混用,这里推荐不转换,这么设置就好了:
```
set tabstop=4
set shiftwidth=4
set smartindent
```
这种设置对于一个人写算法题目代码的场合比较合适,但是如果是好几个人编写同一个程序的代码,则要考虑到每个人的不同缩进设置。
然后再来讲一下`smartindent`(默认不开启)
和它相关的是`autoindent`,可以将上一行的缩进格式复制到下一行,如果回车新建行之后又退出了插入模式,或者将光标移开,那么新建行的缩进格式会被清除。
而`smartindent`的智能就在可以识别类似C语言结构的用法,对于一些需要增加缩进的地方会智能增加一格缩进。对于以`#`号开头的行,缩进会被去除,并且在使用`>>` `<<`的时候也不会受到影响。(当然你如果打开了`autoindent`,然后打开`.cpp`文件,似乎也有这个效果)
![indent](https://cdn.luogu.com.cn/upload/pic/38100.png )
_典型的缩进后文档_
$\textsf{Update :}$ 我发现默认的缩进对于$\textsf{python}$等类似语言并不友好。
#### 4. 比较+折叠
$\textsf{Vim}$提供了非常方便的比较功能,可以查看哪些行,具体哪些位置的文字内容不同。
这里介绍的比较粗糙,还可以看看`:help vimdiff`。如果你要对拍,不妨使用`diff`程序(见第五部分)。
在某个窗口展示的缓冲区中输入命令行`:difft`即可将这个文档加入比较,相反的`:diffo`会将这个文档移出比较。
可以同时比较多个文档,也可以使用`:diffs [another file]`来将当前文档和另外一个文档进行比较。
![](https://cdn.luogu.com.cn/upload/pic/42002.png)
如上图所示,有不同的高亮分别对应有差别的行,少去的行和多余的行。
不同的具体内容也有高亮。可以自行更改(比如说上面这种高亮就非常丑,代码都看不清了)。高亮组分别为`DiffAdd` `DiffChange` `DiffText` `DiffDelete`。
![](https://cdn.luogu.com.cn/upload/pic/42003.png )
注意过多的相同行会被折叠。切换折叠的打开/关闭状态使用`za`。
其实如果稍微设置一下,你也可以让你的代码自动折叠,但似乎要花括号独占一行。见`:help fold`。
#### 5. 复制和粘贴
参见`:help registers` `:help x11-selection`
Vim中的复制粘贴,不仅用键和其他所有程序大相径庭,而且还有**寄存器**功能。(说得好像Office没有剪贴板历史一样)
命令行`:reg`就可以查看Vim中寄存器的内容了。
那么这些寄存器有什么意义呢?
我们平常用`y`和`p`复制粘贴的时候,都会使用**无名寄存器** `""` 。但当你用`c` `d` 或 `x` 把某些内容删去的时候,还是会用无名寄存器把删除的内容保存下来。
显而易见的好处是可以把删去的东西又方便地放到另外一个地方,起到了**剪切**的作用。但之前我复制的东西又被覆盖掉了……真的吗?
假设在另外一个地方要删除一行内容,再放之前复制的文字,不如用**数字寄存器** `"0` ,它会保存最近一次复制的内容。粘贴的时候输入 `"0p` 就可以啦。
也许你有问题,多次复制和删除内容之后会怎么样呢?
答案有点复杂:删除的多行文本会存在 `"1` 寄存器中,如果再次删除多行文本,`"1` 寄存器的内容就会~~逃~~到 `"2` 寄存器中,依次类推,直到 `"9` 寄存器被冲掉。
删除的非多行文本会放在 `"-` **减号寄存器**中,再次删除直接冲掉寄存器旧内容。
复制的所有文本会放在 `"0` 寄存器中,再次复制直接冲掉寄存器旧内容。
>**嗯……无名寄存器到底使不使用啊??**
>你可以把无名寄存器看作对某个具体寄存器的映射!
如果想要复制(或删除)一段话,以后经常使用它来粘贴,利用Vim自动的寄存器配置就相形见绌了。
让我们来使用**命名寄存器**吧!只需要形如 `"zy` 或 `"aY` 的形式就可以把要复制的内容放到不会被自动覆盖的寄存器里啦。取用同理, `"Ap` 就好。
**注意:**字母寄存器的大小写敏感,即`"a` `"A` 是两个寄存器。
我们还要知道的是所谓的**可读寄存器**,因为它们代表的含义是文档名或是之前输入内容,因此无法通过复制或者删除操作修改:
- `"%` 代表**当前**焦点所在的缓存区文档名。
- `".` 代表上一次插入模式插入的内容。
- `":` 代表上一次命令行的指令。 _(还记得`@:`吗)_
- `"/` 代表上一次搜索的内容。
还有比较特殊的寄存器,诸如`"=` `"#` 的表达式、轮换文件寄存器用不到,而 `"_` **黑洞寄存器**则是~~美妙的~~不存入寄存器之意。
而要真正和**系统剪贴板**互动,得用到`"+` `"*` `"~` 三种寄存器。
- `"+` 即通常理解的系统剪贴板,在Linux下则是X11 Window Server的剪贴板。`"+y` 复制到剪贴板,而 `"+p` 则将剪贴板的东西粘贴上来。
- `"*` 则对应着X11中的**选择区**。选择区是什么?在任何一个可视程序中高亮的内容会自动覆盖选择区,只要点击鼠标中键(就是滚轮)就可以把选择区的内容放出来啦!Vim中的可视模式即属于高亮内容。
_`"~` 拖放寄存器,但我并不知道怎么使用……_
**注意:**如果你发现粘贴的时候因为自动缩进而导致格式变丑,请在粘贴前输入 `:set paste` ,粘贴结束后再输入 `:set nopaste` 。本质是暂时取消缩进,某些版本会自动识别并开启/关闭粘贴模式,这时候你会看到左下角有`-- 插入(粘贴) --`字样。
**注意:**如果你发现Vim中没有加号寄存器和星号寄存器,请看下面这张图。
![ClipBoard](https://cdn.luogu.com.cn/upload/pic/38726.png)
_`:version`查看能否与X11的剪贴板交互_
安装图形界面,一般就可以解决这个问题。(noilinux预装的Vim没有图形界面)
**总结一下?**
- `""` 无名寄存器
- `"0` ... `"9` 数字寄存器
- `"a` ... `"z` `"A` ... `"Z` 命名寄存器
- `"%` `":` `"/` `"+` `"*` 非常棒的实用寄存器
- `"[x]y` `"[x]p` 指定寄存器复制粘贴。
#### 6. 目录浏览
打开$\textsf{Vim}$时附加一个目录参数,或者命令行`:o <Your Directory>`都可以开始浏览选定目录。
![Vim Netrw](https://cdn.luogu.com.cn/upload/pic/38091.png)
可以发现我们使用的是一个名为$\textsf{Netrw}$的插件。
回车/鼠标点击(如果你打开了所有鼠标功能)就可以打开指定目录或文件;
另外,这个操作同样也适用于排序和帮助两行。
有一些实用的快捷键,`-`访问上一层目录,`s`更改排序方式,`<F1>`显示帮助文档。
不再详细说明,可以查阅帮助文档,因为我感觉在$\textsf{bash}$下面就可以解决基本的目录问题了。
#### 7. 正则表达式:搜索与替换
可参考`:help pattern` `:help 10.2`和文末Sources。建议熟练掌握。
你应该还记得可以通过`:%s/a/b/gc`这样的命令行来替换字符串。
其中,`%`号还有另外一个意义:**文章所有行**。
那么这里可以用其它符号代替,如` . ` `¥` 分别代表光标当前行和文件最后一行。甚至`1,15` `.,15`这样的表述都可以。(快看帮助`:help cmdline`)
`:[range]s[ubstitute]/{pattern}/{string}/[flags]`
这居然是替换指令的完整版解释!范围问题已经解决,正则表达式即`{pattern}`就提到,而`{string}`就只能有一些转义字符出现,再讲讲`[flags]`,怎么样?
- `g`为替换范围内某行的**所有**匹配字符串。否则只会替换每行的**第一个**字符串。
- `c`为替换前确认。`y`和`n`为确认或拒绝指定更改,退出为`q`或`<ESC>`。`a`为确认接下来所有替换,`l`为确认该更改并退出。
- `n`**预览**有几行可以匹配,但不会真实替换。
但是当你要批量修改一个文件的格式,精确查找就有点捉襟见肘了。
主角闪亮登场!
**正则表达式($\textsf{Regular Expression}$)**其实就是字符串匹配的模式($\textsf{pattern}$),除了查找和替换,你甚至可以利用它来判断一个字符串是否合法,例如是不是一个IP地址。(`\(\d\{1,3}\.\)\{3}\d\{1,3}`,不过是个错误写法)
**警告:**$\textsf{Vim}$里面的正则表达式也许和你曾经了解过的正则表达式有较大区别。
而一切的一切,都从我们要讲的模式串(有些地方叫元字符)开始。_**我们以启用`magic`模式的表达为准**_
1. **普通模式串 Ordinary Atom**
最普通的模式串,只有单次取代功能,且除了任何一个字符,行首与行末匹配的`.` `^` `¥`外都需要**反斜杠**表达其模式串含义。
来一个例子解释已经提到的三个用本身作模式串的字符:
`^I'm happy with.he`与`^I'm happy with.he¥`的匹配情况:
```no-language
I'm happy with he
#可以匹配 可以匹配
I'm happy with he.
#可以匹配 不能匹配
I'm happy with she and she.
#不能匹配 不能匹配
I'm happy withshe and she.
#可以匹配 不能匹配
```
而在上面的情况下(去除`#`标注的行),用`.he\.\_¥\n\_^I'm`可以匹配下面两个字符串
```
(Space)he. # 第二行
I'm # 第三行
```
```
she. # 第三行
I'm # 第四行
```
可以发现行首行尾模式串,只有在正则表达式的首部或尾部才可以直接用 `^` 和 $ 匹配,否则就必须用到 /_^ 与 /_$ 。而如果要匹配上述三个直接使用本身的字符,则要加上反斜杠,如`export.DISPLAY=:\d\.\d`可以匹配`export DISPLAY=:0.0`。
**注意** `/_.` 和 `.` 的区别:前面匹配换行符而后面不匹配换行符
在上面这个例子中,你应该发现了你熟悉的`\n`和不熟悉的`\d`,其实他们也算普通模式串的一种。
不如给出两张照片:
![](https://tiger3018.github.io/img/gugu_5.png)
上面是某一类字符串的模式串,其中对于`\x` `\o` `\w` `\h` `\a` `\l` `\u`,它们也满足大写是非该类字符串的模式串。(但已经从图片中删去了)
其实你记住`\s`与`\d`就足够了。_(需要反斜杠)_
![](https://tiger3018.github.io/img/gugu_6.png)
这个就是转义字符啊。_(需要反斜杠)_
![](https://tiger3018.github.io/img/gugu_4.png)
限定字符串出现位置的模式串,其中前三种已经介绍过了,常用的还有`\<`与`\>`,在Vim中可以设定或查看可以被识别为单词的字符,即`set iskeyword`。
这个在将`int`替换为`long long`等场合就必须要用到了,毕竟你总不想把`printf`替换为`prlong longf`吧。
不如给出一个例子:`%s/\s\<int\>/\tlong long/g`,已经是替换命令了,可以用你的代码测试测试。
**自定制模式串**
如`[a-z]`可以匹配任意一个小写字母,`[a-dA-D1-2\n]`(等价于`\_[a-dA-D1-2]`)可以匹配任意一个`a` `b` `c` `d` `A` `B` `C` `D` `1` `2`和换行。
该模式串有补集功能,意思就是`[^LUOGUluogu]`匹配任意一个不是大写或小写`l` `u` `o` `g` `u`的字符,但不匹配换行。
注意如果要使用**不需要加**反斜杠,它有很多变式,可以看[VimCDOC](http://vimcdoc.sourceforge.net/doc/pattern.html#%2F)。
**注:** 如果能用已有的模式串就不要再定制了,相比之下自定制模式串速度会慢一些。
2. **倍数模式串 multi**
像之前给出的IP地址模式串(尽管是错误的),你还会看到形如`\{1,3}`的模式串,他们就是用于描述单个(或几个)字符需要重复匹配次数的倍数模式串。
有很多种类型的倍数模式串,包括严格指定匹配次数:
- `\=` 匹配 0 次或 1 次,即可有可无。其实`\?`也可以,但是不能在反向搜索(以`?`开头)中使用,记一个就好。
- `\{n}` 精确匹配,仅匹配出现 n 次字符串的情况,而 `\{n,m}` 匹配 n 次至 m 次均可, `\{,m}` 则是匹配 0 次至 m 次,可有可无。
以及不严格指定匹配次数(可以比字面意思的次数更多或更少):
- `*` 匹配 0 或任意多次,即可有可无,**注意和通配符中直接代表任意多个字符串不同,Vim下你得写成`.*`或`\_.*`(可匹配换行,慎用)才可以**。
- `\+` 匹配 1 或任意多次,即必须出现。牢记,可有可无的模式符可能会匹配你不期望匹配的字符串,而只有它会让你的匹配绝对精确。
- `{}` 匹配 0 或任意多次,而 `\{n,}` 匹配 n 或更多次。
**注意**除了 `*` 以外,使用都需要反斜杠。
![](https://tiger3018.github.io/img/gugu_7.png)
---
了解了这两大类模式串,不如再来点例子吧:
- 将`int a[MAXN],/* 这个数组用来排序 */b[MAXN];/* 这个数组用来差分 */`中的注释去除。
`:%s/\/\*.*\*\///g`可行吗?
它会把b[MAXN];也当成注释一起删去……
这时候我们就要学习**非贪婪匹配**。
如果你知道`.+?`这样的正则表达式,那你就应该知道正则表达式一般趋向于匹配最长可能的字符串,即称为贪婪匹配。
而要让它匹配尽可能短的字符串,则需要额外加一些描述使其进行非贪婪匹配。
而像上面这个非贪婪的正则表达式在Vim的语法中并不适用,它不认倍数模式串修饰倍数模式串。
我们需要的是`\{-}` `\{-n,}` `\{-n,m}` `\{-,m}`。简单好记。
那么我们用`:%s/\/\*.\{-}\*\///g`就好了。
- 寻找一个同时可以匹配 `be proud of` 和 `take pride in` 的模式串。
想用`\=`修饰,但是发现它只能修饰一个普通模式串?
你可以用括号把整个模式串(多个字符)转变成和单个模式串等价的形式:`\(Your Pattern Here\)`
使用`\(be proud of\)\=\(take pride in\)\=`后你发现它可以匹配的东西实在是太多了,能不能至少匹配两者其一?
**组合模式串**做不到的,**分割模式串**(`\|`)可以做到: `\(be proud of\|take pride in\)\+` 。代表的意思也非常浅显,可以重复使用,如 `algorithm\|algo\|AG`(当然没人这么用)。
其实`al\%[gorithm]`可以匹配`al` `alg` `algo` ... `algorithm`(这属于……我也不知道系列)
- 但是组合模式串还可以做到变量的功能,比如下面两例:
```
搜索/\(a\+\)[^a]\+\1
替换:%s/\[\(.\{-}\)\].\{-}(\(.\{-}\))/[\2](\1)/g
```
第一项搜索开头和结尾处a的个数相同的字符串,匹配`aabbcaa`但不匹配`abcbaa`。
第二项可以解决我在Markdown语法中经常犯的错误。
关于函数式就不再说明,使用方式:`:s/(pattern)/\=(function)`
还有一些稍微高级和难记的模式串也不在讲解范围之内,请自行阅读帮助文档,当然我觉得这些应该够用了。
补充几点:
**magic**
正则表达式不好记,不会记,不想记,怎么办?
这问题好说:**那就别记嘛**
可是某些字符又会被当成模式串,那怎么办?
那就告诉$\textsf{Vim}$,我们要让所有字符串都表示本意。
`\V`之后的正则表达式,无论什么字符(除`/` `?` ,或反斜杠修饰)都没有特殊含义了。
试一试:`?\V.` `?\V\n`
`\V`取$\textsf{Very\ nomagic}$之意,与之类似的有小写的`\v`。
还有较为中性的`\m`($\textsf{magic}$) `\M`($\textsf{nomagic}$) 差别不大。
**搜索与字符的偏移**
字符串的匹配需要有指定前缀,但是又不希望把这一部分也替换掉,怎么办?`:%s/aaa\zsbb/cc/`就可以将`aaabb`替换成`aaacc`。
和`/zs`相对应的是`/ze`。
详见最后一张正则表达式的图片:
![Last But Not Least](https://tiger3018.github.io/img/gugu_4.png)
#### 8. 插件
并没有这个板块(所以连目录里面都没有)。
其实是我没有用插件,因为~~要模拟考场环境~~懒啊。
可参考后文$\textsf{Sources}
9. 学会使用帮助文档
你在\textsf{Linux}系统下可能会遇到许多问题,这时便会选择使用搜索引擎,看看有没有一些有用的结果。
而这些结果或许会告诉你:Read The ****ing Manual
所以,\textsf{Vim}贴心为你自带了帮助文件,只要这样就可以打开:
-
命令行:help
即可打开帮助窗口。
-
命令行:help help
即可打开如何使用帮助的帮助窗口
-
命令行:help {pattern}
即可打开最匹配\textsf{\{pattern\}}的帮助,可以使用通配符但不能使用正则表达式。话说你还可以使用\textsf{TAB}键自动补全。如:help /[
。
-
在帮助窗口中,输入命令行:tag /{pattern}
即可找到与\textsf{\{pattern\}}匹配的帮助文本,再输入:tnext
就可以跳转到下一个匹配的帮助文本。如:tag /term
。搭配@:
哦!
推荐直接在\textsf{vim}下阅读,因为它可以支持帮助文本的高亮和跳转:
-
基于\textsf{tag}的跳转:在一个链接上面按下组合键Ctrl+[
,或直接用鼠标双击即可跳转。
-
返回:Ctrl+O
或者是Ctrl+T
。
实际上tag链接以*
包含,跳转链接以|
包含
都是英文看不懂?其实是有中文翻译的:Vimcdoc。可以在线阅读或下载解压,并用脚本安装到\textsf{vim}的\textsf{doc}中。
提示:通过阅读usr_XX的文章并且熟练掌握它们,你对于Vim的理解就将会有质的飞跃。(但你有时间吗)
提示:有什么键忘记了找:help
挺好,考场也可以找。
\footnotesize\textsf{\colorbox{#304ffe}{\color{#fff}{STEP 5}}} 与~\textsf{bash or console}~搭配使用
简而言之,只需了解 bash 是扩充版的 shell , Console 用于在桌面环境提供 bash 。 Vim 运行于 Console 中,由 bash 调用。
哈哈哈哈哈哈哈这都不知道。
^ 听到bash对你的嘲讽了吗?如果连最基本的bash指令都不会,还搞什么编译代码。
快来攻破这个东西:
以下命令中,可能是bash中的内建命令与保留字,也有可能是特定的程序。
-
ls
用于显示当前目录下的文件,ls -a
还会显示隐藏文件。
- 以点号开头的文件(如
.vimrc
)在Linux为隐藏文件(夹)。
-
cd directory
用于切换目录。
-
./file
用于执行当前目录下的可执行程序。
- 如果你直接输入
file
,那么bash会在环境变量PATH指定的目录下查找可执行程序运行。
-
CTRL+C
直接终止bash中活动的程序运行,CTRL+Z
暂停bash中活动的程序运行。
-
ps -ax
显示系统所有进程,kill [pid]
利用pid号将其杀死。
-
time [command]
会将后续指令的耗时输出到 \textsf{stderr} 错误输出中。
-
diff [file1] [file2]
比较两个文件的不同
- 不知道/忘记某个程序或指令的具体用法?
diff --help
或 help echo
或 info diff
中总有一个是可以的。
-
sudo [command]
以其他用户身份运行指定程序,一般是以\textsf{root}身份运行。 sudo -i
则直接进入以\textsf{root}身份运行的\textsf{bash}。
-
chmod
chown
分别更改文件权限和文件所有者。
-
exit
注销,即退出\textsf{bash}。
以下和\textsf{bash}语法相关
其实\textsf{bash}也是一个语言的解释器,风格会和\textsf{Python}等语言有点相似。
-
while Command ; do Command ; done
循环类型,直到Command
的返回值为非0
。注意可以把分号当作换行,也可以把一块while
指令用分号相连,如:
while ((1))
do
echo RedGreenBlue ; done
Segment_tree=Good
BIT=Great
time=20181030
timeme=1030
while :
do
echo "$BIT $Segment_tree"
echo '$BIT $Segment_tree'
echo "$time"
echo "${time}me V.S. $timeme"
time=$(($time+1))
done
echo `$time`
-
结果这上面就有一些要注意的点...
-
变量定义和使用不太一样。变量名的标准差不多,可以直接赋值。没有类型限定,一般是字符串,但对于常见进制支持数字运算。
-
`
'
"
的区别,反引号等同于运行完这条指令的输出,单引号剥夺字符特殊含义,双引号类似,但会对¥
(使用一个变量的内容)和`
作出反应。
-
防混淆可以用¥{}
来使用变量。
-
(())
为整数的计算扩展,里面的运算和c++语言比较相似。
-
:
的返回值永远都是0
。
-
再多了解几种不同的循环结构……
for ((COUNTER=0; COUNTER<10; ++COUNTER))
do
echo The counter is $COUNTER
done
可能这几种结构在考场上的最大作用就是写对拍脚本了233
-
||
;
&&
用于分隔多个指令,但如果第一个指令运行成功(即返回值为零),则||
后面的不再执行,而&&
后面的会继续执行;否则恰好相反。而;
后面的无论如何都会执行。
-
|
就是所谓的管道了,可以将上一个命令或程序的标准输出作为下一个命令或程序的标准输入
- 不如猜猜这个指令会输出什么?
echo $GEDIT_CURRENT_DOCUMENT_NAME |cut -d. -f1
-
command <a.in >a.out 2>&1
是典型的输入输出重定向,分别代表a.in
作为标准输入,错误输出和标准输出合并重定向到a.in
。
- 唯一一个不想详细说明的地方(哭笑),因为确实有点复杂/还用不上。
如何编写一个可执行的脚本?
下面抛出例子:
#!/bin/bash
./duipai
./aa
./aa_dui
while (diff aa.out aa.ans)
do
./duipai
./aa
./aa_dui
done
echo BAD | wall
具体的东西之前都已经提到了,并没有什么差别。
注意:第一行的#!
描述的是解释器,不写就调用系统默认\textsf{shell},所以写\textsf{shell}脚本没有大问题,但如果你要写个\textsf{py}脚本嘛……
警告:直接执行脚本需要让它有可执行权限,只要chmod +x a.sh
再./a.sh
就可以直接运行了。
\textsf{g}++相关
基本的:编译某个源文件 g++ a.cpp
我们想要使它输出的可执行文件有个漂亮的名字? g++ beautify.cpp -o beautify
(Linux下的可执行文件不一定有扩展名)
要警告? g++ well.cpp -o bad -Wall
不需要某个特殊的警告? 假设要关掉 -Wreturn-type
,我们可以编译时这样写 g++ noreturn_at_getans.cpp -o jing_dian_cuo_wu_shi_fan -Wall -Wno-return-type
或g++ noreturn_at_getans.cpp -o jing_dian_cuo_wu_shi_fan -Wall -Wno-error=return-type
需要吸氧? g++ gugu.cpp -o gugu -Wall -O2
需要帮助? g++ --help
\textsf{Console}相关
编辑配置文件界面
我们仅需了解\textsf{Console}对标签页和颜色的控制即可。
-
在终端中运行的应用可以用颜色来对其界面进行美化,如\textsf{g}++ 从\textsf{4.9}的版本开始就支持编译信息高亮(NOILinux自带版本是\textsf{4.8.4}),和本文主角\textsf{Vim}。
相信你之前已经了解到高亮的颜色调整,但每种数值对应的颜色都是由\textsf{Console}配置,\textsf{Vim}无权干涉。
而你就可以通过更改配置文件(如上图)来达到美化的目的。还可以设置透明背景哦!
-
直接用\textsf{Console}的标签页来打开多个\textsf{Vim},用于编辑考场中不同的三道题。
默认快捷键见上
这样的明显缺点是\textsf{Vim}之间无法同步寄存器,NOILinux也不支持加号星号寄存器。
所以你也可以使用\textsf{Vim}中的\textsf{Tab}标签页。(之前有讲过哦)
\textsf{Sources \&\& Thanks}
图片来源
学习曲线
https://unix.stackexchange.com/questions/986/what-are-the-pros-and-cons-of-vim-and-emacs
丰富至极
http://www.runoob.com/w3cnote/all-vim-cheatsheat.html
Vim退出
@It's FOSS https://plus.google.com/+Itsfoss
其他图片均取自 Vim 中文帮助文档在线版截图或个人 Vim 界面截图。
部分照片寄存在了github.io上面,所以可能加载比较慢……(毕竟这些照片加了水印就毁掉了)
https://blog.easwy.com/
* 易水博客,博主曾参与翻译《Vim实用技巧》(Practical Vim, Drew Neil),在自己的博客上也留下了几个Vim入门文章的坑233,可以查阅。
# 正则相关
https://blog.csdn.net/endall/article/details/1764554
https://blog.csdn.net/whaoxysh/article/details/24652361
https://www.cnblogs.com/bkylee/p/5552305.html
https://www.cnblogs.com/xudong-bupt/p/3586889.html
# 缩进相关
https://www.cnblogs.com/air-of-code/p/5784759.html
# window+tab+buffer
https://blog.csdn.net/a464057216/article/details/51523860
https://blog.csdn.net/jy692405180/article/details/79775125
Summary:
A buffer is the in-memory text of a file.
A window is a viewport on a buffer.
A tab page is a collection of windows.
# Vim 快捷移动按键(所谓的 Vim 语)
https://www.jianshu.com/p/a361ce8c97bc
http://www.runoob.com/w3cnote/all-vim-cheatsheat.html
https://www.cnblogs.com/springlight/p/6209230.html(感觉介绍Vim比较全面)
# Registers寄存器
https://www.cnblogs.com/bwangel23/p/4421957.html
# 插件
https://oi-wiki.org/intro/editors/#_7
(你木有看错,就是OI Wiki上面的文章!全面!有可点击的目录大爱!)
# 不可爱的大杂烩
https://blog.csdn.net/freeking101/article/details/62037015
https://www.cnblogs.com/stejovbes/p/7472184.html
# 略显可爱的 Vimdiff
http://www.cnblogs.com/galoishelley/p/4045611.html
# bash of 'time'
https://blog.csdn.net/grantlee1988/article/details/7748554
https://blog.csdn.net/seizeF/article/details/5164405
# bash
入门
https://www.jianshu.com/p/e1c8e5bfa45e
管道
https://blog.csdn.net/wangqianyilynn/article/details/75576815
杂七杂八
https://blog.csdn.net/sukeeeeeeeee/article/details/53408837
https://blog.csdn.net/miyatang/article/details/8077123
http://codingstandards.iteye.com/blog/780524
彩蛋:关于\textsf{Vi}与\textsf{Vim}
set compatible
虽然说在\textsf{Vim}里面可以通过上面这行兼容命令达到和vi相似的效果,但没有原汁原味的\textsf{Vi}来的爽啊……
为什么不直接运行\textsf{Vi}呢?你会发现那就是vim。
所以,把下面这行指令丢进你的终端吧:
sudo apt-get install nvi
装一个更加高仿\textsf{Vi}的\textsf{NEW Vi}吧!
彩蛋的彩蛋:尝试在\textsf{nvi}中按下这组组合键:Ctrl+\
,即可进入\textsf{ex}模式,和直接运行vim -E
或在\textsf{vim}内按下组合键gQ
等效。不要忘了调用help
指令愉快玩耍哦!也可以看看这个我搜出来的文章。
$\textsf{Vim}$是全屏编辑器,因此不会像$\textsf{ed}$那样只显示一行,对于$\textsf{Vim}$,$\textsf{ed}$命令编辑的一般都是当前行,这就相当于$\textsf{ed}$中所显示的那行,实际上也是文件的当前行.
https://blog.csdn.net/hitlion2008/article/details/8799327
丰富至极:
文章使用与转载许可:
文章最后修订于2018/11/04 16:49