Formate content

This commit is contained in:
Shidong Wang 2018-12-31 12:55:32 +08:00
parent b3a51b2cc2
commit 4903728828

View File

@ -1,6 +1,7 @@
# Vim 从入门到精通 # Vim 从入门到精通
> 本文主要在翻译 [mhinz/vim-galore](https://github.com/mhinz/vim-galore) 的基础添加了一些我在使用 Vim 及开发 Vim 插件的过程中积累的一些细节。 > 本文主要在翻译 [mhinz/vim-galore](https://github.com/mhinz/vim-galore)
的基础添加了一些我在使用 Vim 及开发 Vim 插件的过程中积累的一些细节。
<!-- vim-markdown-toc GFM --> <!-- vim-markdown-toc GFM -->
@ -85,7 +86,7 @@
- [调整日志等级](#调整日志等级) - [调整日志等级](#调整日志等级)
- [查看启动日志](#查看启动日志) - [查看启动日志](#查看启动日志)
- [查看运行时日志](#查看运行时日志) - [查看运行时日志](#查看运行时日志)
- [Vim脚本调试](#vim脚本调试) - [Vim 脚本调试](#vim-脚本调试)
- [语法文件调试](#语法文件调试) - [语法文件调试](#语法文件调试)
- [杂项](#杂项) - [杂项](#杂项)
- [附加资源](#附加资源) - [附加资源](#附加资源)
@ -109,20 +110,29 @@
## 什么是 Vim ## 什么是 Vim
[Vim](https://github.com/vim/vim) 是一个历史悠久的文本编辑器,可以追溯到 [qed](https://en.wikipedia.org/wiki/QED_(text_editor))。[Bram [Vim](https://github.com/vim/vim) 是一个历史悠久的文本编辑器,可以追溯到
Moolenaar](https://en.wikipedia.org/wiki/Bram_Moolenaar) 于 1991 年发布初始版本。 [qed](<https://en.wikipedia.org/wiki/QED_(text_editor)>)。
[Bram Moolenaar](https://en.wikipedia.org/wiki/Bram_Moolenaar) 于
1991 年发布初始版本。
Linux、Mac 用户,可以使用包管理器安装 Vim对于 Windows 用户,可以从 [我的网盘](https://share.weiyun.com/da2be5937ac0e2bd3abc26355fad1204) 下载。 Linux、Mac 用户,可以使用包管理器安装 Vim对于 Windows 用户,可以从
该版本可轻易添加 `python``python3``lua` 等支持,只需要安装 python、lua 即可。 [我的网盘](https://share.weiyun.com/da2be5937ac0e2bd3abc26355fad1204) 下载。
该版本可轻易添加 `python``python3``lua` 等支持,只需要安装 python、lua
即可。
项目在 [Github](https://github.com/vim/vim) 上开发,项目讨论请订阅 项目在 [Github](https://github.com/vim/vim) 上开发,项目讨论请订阅
[vim_dev](https://groups.google.com/forum/#!forum/vim_dev) 邮件列表。 [`vim_dev`](https://groups.google.com/forum/#!forum/vim_dev) 邮件列表。
通过阅读 [Why, oh WHY, do those #?@! nutheads use vi?](http://www.viemu.com/a-why-vi-vim.html) 来对 Vim 进行大致的了解。 通过阅读 [Why, oh WHY, do those #?@! nutheads use vi?](http://www.viemu.com/a-why-vi-vim.html)
来对 Vim 进行大致的了解。
## Vim 哲学 ## Vim 哲学
Vim 采用模式编辑的理念,即它提供了多种模式,按键在不同的模式下作用不同。你可以在 _普通模式_ 下浏览文件,在 _插入模式_ 下插入文本,在 _可视模式_ 下选择行,在 _命令模式_ 下执行命令等等。起初这听起来可能很复杂,但是这有一个很大的优点:不需要通过同时按住多个键来完成操作,大多数时候你只需要依次按下这些按键即可。越常用的操作,所需要的按键数量越少。 Vim 采用模式编辑的理念,即它提供了多种模式,按键在不同的模式下作用不同。
你可以在**普通模式** 下浏览文件,在**插入模式**下插入文本,
在**可视模式**下选择行,在**命令模式**下执行命令等等。起初这听起来可能很复杂,
但是这有一个很大的优点:不需要通过同时按住多个键来完成操作,
大多数时候你只需要依次按下这些按键即可。越常用的操作,所需要的按键数量越少。
和模式编辑紧密相连的概念是“操作符”和“动作”。_操作符_ 开始一些行为,例如:修改,删除,或者选择文本。之后你要用一个 _动作_ 来指定需要操作的文本区域。比如,要改变括号内的文本,需要执行 `ci(` (读做 _change inner parentheses_);删除整个段落的内容,需要执行 `dap` 读做_delete 和模式编辑紧密相连的概念是“操作符”和“动作”。_操作符_ 开始一些行为,例如:修改,删除,或者选择文本。之后你要用一个 _动作_ 来指定需要操作的文本区域。比如,要改变括号内的文本,需要执行 `ci(` (读做 _change inner parentheses_);删除整个段落的内容,需要执行 `dap` 读做_delete
around paragraph_ around paragraph_
@ -137,7 +147,7 @@ Vim 自带一个交互式的教程,内含你需要了解的最基础的信息
不要因为这个看上去很无聊而跳过,按照此教程多练习。你以前用的 IDE 或者其他编辑器很少是有“模式”概念的,因此一开始你会很难适应模式切换。但是你 Vim 使用的越多,[肌肉记忆](https://en.wikipedia.org/wiki/Muscle_memory) 将越容易形成。 不要因为这个看上去很无聊而跳过,按照此教程多练习。你以前用的 IDE 或者其他编辑器很少是有“模式”概念的,因此一开始你会很难适应模式切换。但是你 Vim 使用的越多,[肌肉记忆](https://en.wikipedia.org/wiki/Muscle_memory) 将越容易形成。
Vim 基于一个 [vi](https://en.wikipedia.org/wiki/Vi) 克隆,叫做 [Stevie](https://en.wikipedia.org/wiki/Stevie_(text_editor)),支持两种运行模式:"compatible" 和 "nocompatible"。在兼容模式下运行 Vim 意味着使用 vi 的默认设置,而不是 Vim 的默认设置。除非你新建一个用户的 `vimrc` 或者使用 `vim -N` 命令启动 Vim否则就是在兼容模式下运行 Vim请大家不要在兼容模式下运行 Vim。 Vim 基于一个 [vi](https://en.wikipedia.org/wiki/Vi) 克隆,叫做 [Stevie](<https://en.wikipedia.org/wiki/Stevie_(text_editor)>),支持两种运行模式:"compatible" 和 "nocompatible"。在兼容模式下运行 Vim 意味着使用 vi 的默认设置,而不是 Vim 的默认设置。除非你新建一个用户的 `vimrc` 或者使用 `vim -N` 命令启动 Vim否则就是在兼容模式下运行 Vim请大家不要在兼容模式下运行 Vim。
下一步 下一步
@ -276,7 +286,7 @@ Vim 是一个文本编辑器。每次文本都是作为**缓冲区**的一部分
使用 `:map` 命令家族你可以定义属于你自己的快捷键。该家族的每一个命令都限定在特定的模式下。从技术上来说 Vim 自带高达 12 中模式,其中 6 种可以被映射。另外一些命令作用于多种模式: 使用 `:map` 命令家族你可以定义属于你自己的快捷键。该家族的每一个命令都限定在特定的模式下。从技术上来说 Vim 自带高达 12 中模式,其中 6 种可以被映射。另外一些命令作用于多种模式:
|   递归   |   非递归     | 模式                           | |   递归   |   非递归     | 模式                           |
| --------- | ------------ | -------------------------------- | | -------- | ------------ | -------------------------------- |
| `:map` | `:noremap` | normal, visual, operator-pending | | `:map` | `:noremap` | normal, visual, operator-pending |
| `:nmap` | `:nnoremap` | normal | | `:nmap` | `:nnoremap` | normal |
| `:xmap` | `:xnoremap` | visual | | `:xmap` | `:xnoremap` | visual |
@ -362,9 +372,9 @@ nnoremap <leader>h :helpgrep<space>
Vim 为我们提供了如下的寄存器: Vim 为我们提供了如下的寄存器:
| 类型 | 标识 | 读写者 | 是否为只读 | 包含的字符来源 | | 类型 | 标识 | 读写者 | 是否为只读 | 包含的字符来源 |
| ------------------- | ------------------ | ------ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------------------- | ------------------ | ------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Unnamed | `"` | vim | 否 | 最近一次的复制或删除操作 (`d`, `c`, `s`, `x`, `y`) | | Unnamed | `"` | vim | 否 | 最近一次的复制或删除操作 (`d`, `c`, `s`, `x`, `y`) |
| Numbered | `0``9` | vim | 否 | 寄存器 `0`: 最近一次复制。寄存器 `1`: 最近一次删除。寄存器 `2`: 倒数第二次删除,以此类推。对于寄存器 `1``9`,他们其实是只读的最多包含 9 个元素的队列。这里的队列即为数据类型 [queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type)) | | Numbered | `0``9` | vim | 否 | 寄存器 `0`: 最近一次复制。寄存器 `1`: 最近一次删除。寄存器 `2`: 倒数第二次删除,以此类推。对于寄存器 `1``9`,他们其实是只读的最多包含 9 个元素的队列。这里的队列即为数据类型 [queue](<https://en.wikipedia.org/wiki/Queue_(abstract_data_type)>) |
| Small delete | `-` | vim | 否 | 最近一次行内删除 | | Small delete | `-` | vim | 否 | 最近一次行内删除 |
| Named | `a``z`, `A``Z` | 用户 | 否 | 如果你通过复制操作存储文本至寄存器 `a`,那么 `a` 中的文本就会被完全覆盖。如果你存储至 `A`,那么会将文本添加给寄存器 `a`,不会覆盖之前已有的文本 | | Named | `a``z`, `A``Z` | 用户 | 否 | 如果你通过复制操作存储文本至寄存器 `a`,那么 `a` 中的文本就会被完全覆盖。如果你存储至 `A`,那么会将文本添加给寄存器 `a`,不会覆盖之前已有的文本 |
| Read-only | `:``.``%` | vim | 是 | `:`: 最近一次使用的命令,`.`: 最近一次添加的文本,`%`: 当前的文件名 | | Read-only | `:``.``%` | vim | 是 | `:`: 最近一次使用的命令,`.`: 最近一次添加的文本,`%`: 当前的文件名 |
@ -474,7 +484,7 @@ Vim 为我们提供了如下的寄存器:
关于跳转,还有以下的方式: 关于跳转,还有以下的方式:
| 按键 | 跳转至 | | 按键 | 跳转至 |
| --------------- | ---------------------------------------------- | | ---------------- | ---------------------------------------------- |
| `'[` 与 `` `[ `` | 上一次修改或复制的第一行或第一个字符 | | `'[` 与 `` `[ `` | 上一次修改或复制的第一行或第一个字符 |
| `']` 与 `` `] `` | 上一次修改或复制的最后一行或最后一个字符 | | `']` 与 `` `] `` | 上一次修改或复制的最后一行或最后一个字符 |
| `'<` 与 `` `< `` | 上一次在可视模式下选取的第一行或第一个字符 | | `'<` 与 `` `< `` | 上一次在可视模式下选取的第一行或第一个字符 |
@ -623,7 +633,7 @@ Vim 中的跳转命令,包括 `'`、`` ` ``、`G`、`/`、`?`、`n`、`N`、`%
Vim 会记录文本改变之前的状态。因此,你可以使用「撤销」操作 <kbd>u</kbd> 来取消更改,也可以通过「重做」操作 <kbd>Ctrl + r</kbd> 来恢复更改。 Vim 会记录文本改变之前的状态。因此,你可以使用「撤销」操作 <kbd>u</kbd> 来取消更改,也可以通过「重做」操作 <kbd>Ctrl + r</kbd> 来恢复更改。
值得注意的是Vim 采用 [tree](https://en.wikipedia.org/wiki/Tree_(data_structure)) 数据结构来存储内容变更的历史记录,而不是采用 [queue](https://en.wikipedia.org/wiki/Queue_(abstract_data_type))。你的每次改动都会成为存储为树的节点。而且,除了第一次改动(根节点),之后的每次改动都可以找到一个对应的父节点。每一个节点都会记录改动的内容和时间。其中,「分支」代表从任一节点到根节点的路径。当你进行了撤销操作,然后又输入了新的内容,这时候就相当于创建了分支。这个原理和 git 中的 branch分支十分类似。 值得注意的是Vim 采用 [tree](<https://en.wikipedia.org/wiki/Tree_(data_structure)>) 数据结构来存储内容变更的历史记录,而不是采用 [queue](<https://en.wikipedia.org/wiki/Queue_(abstract_data_type)>)。你的每次改动都会成为存储为树的节点。而且,除了第一次改动(根节点),之后的每次改动都可以找到一个对应的父节点。每一个节点都会记录改动的内容和时间。其中,「分支」代表从任一节点到根节点的路径。当你进行了撤销操作,然后又输入了新的内容,这时候就相当于创建了分支。这个原理和 git 中的 branch分支十分类似。
考虑以下这一系列按键操作: 考虑以下这一系列按键操作:
@ -884,7 +894,7 @@ Vim 自带了一套很完善的帮助文档,它们是一个个有固定排版
经过一些微小的改动后,重新发布到了这里。 经过一些微小的改动后,重新发布到了这里。
* * * ---
如果你知道你想要找什么,使用帮助系统的搜索会更简单一些,因为搜索出的主题都带有固定的格式。 如果你知道你想要找什么,使用帮助系统的搜索会更简单一些,因为搜索出的主题都带有固定的格式。
@ -1016,7 +1026,7 @@ autocmd VimEnter * nested edit $MYVIMRC
### 剪贴板的使用Windows, OSX ### 剪贴板的使用Windows, OSX
Windows 自带了[剪贴板](https://msdn.microsoft.com/en-us/library/windows/desktop/ms649012(v=vs.85).aspx)OSX 则带了一个[粘贴板](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/PasteboardGuide106/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008100-SW1) Windows 自带了[剪贴板](<https://msdn.microsoft.com/en-us/library/windows/desktop/ms649012(v=vs.85).aspx>)OSX 则带了一个[粘贴板](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/PasteboardGuide106/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008100-SW1)
在这两个系统中都可以用大家习惯用的 `ctrl+c / cmd+c` 复制选择的文本,然后在另外一个应用中用 `ctrl+v / cmd+v` 进行粘贴。 在这两个系统中都可以用大家习惯用的 `ctrl+c / cmd+c` 复制选择的文本,然后在另外一个应用中用 `ctrl+v / cmd+v` 进行粘贴。
@ -1255,7 +1265,7 @@ set virtualedit=all
使用 `:!` 启动一个新任务。如果你想列出当前工作目录下的所有文件,可以使用 `:!ls`。 用 `|` 来将结果通过管道重定向,如:`:!ls -l | sort | tail -n5` 使用 `:!` 启动一个新任务。如果你想列出当前工作目录下的所有文件,可以使用 `:!ls`。 用 `|` 来将结果通过管道重定向,如:`:!ls -l | sort | tail -n5`
没有使用范围时(译者注:范围就是 `:``!` 之间的内容,`.` 表示当前行,`+4` 表示向下偏移4行`$` 表示最末行等,多行时用 `,` 将它们分开,如 `.,$` 表示从当前行到末行),`:!` 会显示在一个可滚动的窗口中(译者注:在 GVim 和在终端里运行的结果稍有不同)。相反的,如果指定了范围,这些行会被[过滤](https://en.wikipedia.org/wiki/Filter_(software))。这意味着它们会通过管道被重定向到过滤程序的 [stdin](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_.28stdin.29),在处理后再通过过滤程序的 [stdout](https://en.wikipedia.org/wiki/Standard_streams#Standard_output_.28stdout.29) 输出用输出结果替换范围内的文本。例如为接下来的5行文本添加行号可以使用 没有使用范围时(译者注:范围就是 `:``!` 之间的内容,`.` 表示当前行,`+4` 表示向下偏移 4 行,`$` 表示最末行等,多行时用 `,` 将它们分开,如 `.,$` 表示从当前行到末行),`:!` 会显示在一个可滚动的窗口中(译者注:在 GVim 和在终端里运行的结果稍有不同)。相反的,如果指定了范围,这些行会被[过滤](<https://en.wikipedia.org/wiki/Filter_(software)>)。这意味着它们会通过管道被重定向到过滤程序的 [stdin](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_.28stdin.29),在处理后再通过过滤程序的 [stdout](https://en.wikipedia.org/wiki/Standard_streams#Standard_output_.28stdout.29) 输出,用输出结果替换范围内的文本。例如:为接下来的 5 行文本添加行号,可以使用:
```vim ```vim
:.,+4!nl -ba -w1 -s' ' :.,+4!nl -ba -w1 -s' '
@ -1754,7 +1764,6 @@ Vim现在正在使用的另一个比较有用的方法是增加debug信息输出
`:debug`命令可以和[verbose](#verbosity)选项一起使用。 `:debug`命令可以和[verbose](#verbosity)选项一起使用。
## 语法文件调试 ## 语法文件调试
语法文件由于包含错误的或者复制的正则表达式,常常会使得 Vim 的运行较慢。如果 Vim 在编译的时候包含了`+profile` [feature](#what-kind-of-vim-am-i-running)特性,就可以给用户提供一个超级好用的`:syntime`命令。 语法文件由于包含错误的或者复制的正则表达式,常常会使得 Vim 的运行较慢。如果 Vim 在编译的时候包含了`+profile` [feature](#what-kind-of-vim-am-i-running)特性,就可以给用户提供一个超级好用的`:syntime`命令。
@ -1765,12 +1774,11 @@ Vim现在正在使用的另一个比较有用的方法是增加debug信息输出
:syntime off :syntime off
:syntime report :syntime report
``` ```
输出结果包含了很多的度量维度。比如,你可以通过结果知道哪些正则表达式耗时太久需要被优化;哪些正则表达式一直在别使用但重来没有一次成功匹配。 输出结果包含了很多的度量维度。比如,你可以通过结果知道哪些正则表达式耗时太久需要被优化;哪些正则表达式一直在别使用但重来没有一次成功匹配。
请查阅`:h :syntime` 请查阅`:h :syntime`
# 杂项 # 杂项
## 附加资源 ## 附加资源
@ -1843,7 +1851,10 @@ $ vim -n -u NONE -i NONE -N
你有没有遇到过往 Vim 里粘贴代码之后被搞的一团糟? 你有没有遇到过往 Vim 里粘贴代码之后被搞的一团糟?
这在你使用 `cmd+v``shirt-insert``middle-click` 等进行粘贴的时候才会发生。因为那样的话你只是向终端模拟器扔了一大堆的文本。 Vim 并不知道你刚刚是粘贴的文本,它以为你在飞速的输入。于是它想缩进这些行但是失败了。 这在你使用 `cmd+v``shirt-insert``middle-click` 等进行粘贴的时候才会发生。
因为那样的话你只是向终端模拟器扔了一大堆的文本。
Vim 并不知道你刚刚是粘贴的文本,它以为你在飞速的输入。
于是它想缩进这些行但是失败了。
这明显不是个问题,如果你用 Vim 的寄存器粘贴,如:`"+p` ,这时 Vim 就知道了你在粘贴,就不会导致格式错乱了。 这明显不是个问题,如果你用 Vim 的寄存器粘贴,如:`"+p` ,这时 Vim 就知道了你在粘贴,就不会导致格式错乱了。