diff --git a/README.md b/README.md index c2a67fd..6126162 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,424 @@ [![掘金翻译计划](https://rawgit.com/aleen42/badges/master/src/juejin_translation.svg)](https://github.com/xitu/gold-miner/) -> Vim from zero to hero +> Vim from zero to hero - Vim 从入门到精通 + +- 原文地址:https://github.com/mhinz/vim-galore +- 原文作者:Marco Hinz +- 本文地址:https://github.com/wsdjeg/vim-galore-zh_cn + +## [简介](#简介-1) + +- [什么是 Vim](#什么是-vim) +- [Vim 哲学](#vim-哲学) +- [入门](#入门) +- [精简的 vimrc](#精简的-vimrc) +- [我正在使用的是什么样的 Vim](#我正在使用什么样的-vim) +- [备忘录](#备忘录) + +## [基础](#基础-1) + +- [缓冲区, 窗口, 标签](#缓冲区窗口标签) +- [当前缓冲区, 加载缓冲区, 缓冲区列表,命名缓冲区](#已激活已载入已列出已命名缓冲区) +- [参数列表](#参数列表) +- [按键映射](#按键映射) +- [快捷键前缀](#快捷键前缀) +- [寄存器](#寄存器) +- [范围](#范围) +- [标注](#标注) +- [补全](#补全) +- [动作,操作符,文本对象](#动作操作符文本对象) +- [自动命令](#自动命令) +- [变更历史,跳转历史](#变更历史跳转历史) +- [内容变更历史记录](#内容变更历史记录) +- [全局位置信息表,局部位置信息表](#全局位置信息表局部位置信息表) +- [宏](#宏) +- [颜色主题](#颜色主题) +- [折叠](#折叠) +- [会话](#会话) +- [局部化](#局部化) + +## [用法](#用法-1) + +- [获取离线帮助](#获取离线帮助) +- [获取离线帮助(备选)](#获取离线帮助备选) +- [获取在线帮助](#获取在线帮助) +- [执行自动命令](#执行自动命令) + - [用户自定义事件](#用户自定义事件) + - [内部自带事件](#内部自带事件) +- [剪贴板](#剪切板) + - [剪贴板使用 (Windows, OSX)](#剪贴板使用-windows-osx) + - [剪贴板使用 (Linux, BSD, ...)](#剪贴板使用-linux-bsd-) +- [打开文件时恢复光标位置](#打开文件时恢复光标位置) +- [备份文件,交换文件,撤销文件以及viminfo文件的处理](#备份文件交换文件撤销文件以及viminfo文件的处理) +- [编辑远程文件](#编辑远程文件) +- [插件管理](#插件管理) +- [片段插入](#片段插入) +- [使用外部程序和过滤器](#使用外部程序和过滤器) +- [MatchIt](#matchit) + +## [技巧](#技巧-1) + +- [聪明的使用n和N](#聪明的使用n和n) +- [聪明的使用命令行历史](#聪明的使用命令行历史) +- [智能CTRL-L](#智能ctrl-l) +- [禁用错误报警声音和图标](#禁用错误报警声音和图标) +- [快速移动当前行](#快速移动当前行) +- [快速添加空行](#快速添加空行) +- [快速编辑自定义宏](#快速编辑自定义宏) +- [快速跳转到源(头)文件](#快速跳转到源头文件) +- [在GUI中快速改变字体大小](#在gui中快速改变字体大小) +- [根据模式改变光标类型](#根据模式改变光标类型) +- [防止水平滑动的时候失去选择](#防止水平滑动的时候失去选择) +- [重新载入保存文件](#重新载入保存文件) +- [智能当前行](#智能当前行) +- [更快的关键字补全](#更快的关键字补全) + +## [命令](#命令-1) + +- [:global](#global---在所有匹配行执行命令) - 在所有匹配行执行命令 +- [:normal and :execute](#normal-and-execute---脚本梦之队) - 脚本梦之队 +- [:redir](#redir---重定向消息) - 重定向消息 + +## [调试](#调试-1) + +- [常规建议](#常规建议) +- [查看启动日志](#查看启动日志) +- [查看运行时日志](#查看运行时日志) +- [调整日志等级](#调整日志等级) +- [Vim脚本调试](#vim脚本调试) +- [语法文件调试](#语法文件调试) + +## [杂项](#杂项-1) + +- [附加资源](#附加资源) +- [Vim 配置集合](#vim-配置集合) +- [内置插件](#内置插件) +- [将Control映射到CapsLock](#将control映射到capslock) +- [复活节彩蛋](#复活节彩蛋) +- [为何使用hjkl](#为何使用hjkl) + +## [怪癖](#怪癖-1) + +- [编辑小文件很慢](#编辑小文件很慢) +- [编辑大文件很慢](#编辑大文件很慢) +- [新行用于NUL](#新行用于nul) +- [相同部分粘贴 (要不为什么我总要设置‘粘贴’?)](#相同部分粘贴-要不为什么我总要设置粘贴) +- [在终端使用Esc延时](#在终端使用esc延时) +- [无法重复函数中执行的搜索](#无法重复函数中执行的搜索) + +## [主题列表](#主题列表-1) + +## [插件列表](content/plugins.md) + +## [Neovim](content/neovim.md) + +--- + +# 简介 + +## 什么是 Vim? +[Vim](http://www.vim.org) 是一个历史悠久的文本编辑器,可以追溯到 [qed](https://en.wikipedia.org/wiki/QED_(text_editor))。[Bram +Moolenaar](https://en.wikipedia.org/wiki/Bram_Moolenaar) 于1991年发布初始版本。 + +该项目托管在 [vim.org](http://www.vim.org/index.php)。 + +获取Vim:用包管理器安装或者直接到 vim.org [下载](http://www.vim.org/download.php)。 + +讨论使用相关问题最好使用 [vim_use](https://groups.google.com/forum/#!forum/vim_use) 邮件列表或者使用 IRC([Freenode](https://freenode.net)) 的 `#vim` 频道。 + +欢迎加入我们的中文讨论群:[![QQ](https://img.shields.io/badge/QQ群-121056965-blue.svg)](https://jq.qq.com/?_wv=1027&k=43DB6SG) + +项目在 [Github](https://github.com/vim/vim) 上开发,项目讨论请订阅 [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 进行大致的了解。 + +## Vim 哲学 + +Vim 采用模式编辑的理念,即它提供了多种模式,按键在不同的模式下作用不同。你可以在 _普通模式_ 下浏览文件, 在 _插入模式_ 下插入文本, 在 _可视模式_ 下选择行, 在 _命令模式_ 下执行命令等等。起初这听起来可能很复杂,但是这有一个很大的优点:不需要通过同时按住多个键来完成操作,大多数时候你只需要依次按下这些按键即可。越常用的操作,所需要的按键数量越少。 + +和模式编辑紧密相连的概念是“操作符”和“动作”。_操作符_开始一些行为,例如:修改,删除,或者选择文本。之后你要用一个_动作_来指定需要操作的文本区域。比如,要改变括号内的文本,需要执行 `ci(` (读做 _change inner parentheses_);删除整个段落的内容,需要执行 `dap` (读做: _delete +around paragraph_)。 + +如果你能看见 Vim 老司机操作,你会发现他们使用 Vim 脚本语言就如同钢琴师弹钢琴一样。复杂的操作只需要几个按键就能完成。他们甚至不用刻意去想,因为这已经成为[肌肉记忆](https://en.wikipedia.org/wiki/Muscle_memory)了。这减少[认识负荷](https://en.wikipedia.org/wiki/Cognitive_load)并帮助人们专注于实际任务。 + +## 入门 + +Vim 自带一个交互式的教程,内含你需要了解的最基础的信息,你可以通过终端运行以下命令打开教程: + +``` +$ vimtutor +``` + +不要因为这个看上去很无聊而跳过,按照此教程多练习。你以前用的 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。 + +下一步 + +1. 创建你自己的 [vimrc](#精简的-vimrc)。 +2. 在第一周准备[备忘录](#备忘录)。 +3. 通读[基础](#基础-1)章节了解 Vim 还有哪些功能。 +4. 按需学习!Vim 是学不完的。如果你遇到了问题,先上网寻找解决方案,你的问题可能已经被解决了。Vim 拥有大量的参考文档,知道如何利用这些参考文档很有必要:[获取离线帮助](#获取离线帮助)。 +5. 浏览[附加资源](#附加资源)。 + +最后一个建议:使用[插件](#插件管理)之前,请先掌握 Vim 的基本操作。很多插件都只是对 Vim 自带功能的封装。 + +## 精简的 vimrc + +用户的 vimrc 配置文件可以放在 `~/.vimrc`,或者为了更好的分离放在 `~/.vim/vimrc`,后者更便于通过版本控制软件备份和同步整个配置,比方说 Github。 + +你可以在网上找到许多精简的 vimrc 配置文件, 我的版本可能并不是最简单的版本,但是我的版本提供了一套我认为良好的,非常适合入门的设置。 + +最终你需要阅读完那些设置,然后自行决定需要使用哪些。 :-) + +精简的 vimrc 地址:[minimal-vimrc](contents/minimal-vimrc.vim) + +如果你有兴趣,这里是我(原作者)的 [vimrc](https://github.com/mhinz/dotfiles/blob/master/vim/vimrc)。 + +**建议**:大多数插件作者都维护不止一个插件并且将他们的 vimrc 放在 Github 上展示(通常放在叫做 "vim-config" 或者 "dotfiles" 的仓库中),所以当你发现你喜欢的插件时,去插件维护者的 Github 主页看看有没有这样的仓库。 + +## 我正在使用什么样的 Vim + +使用 `:version` 命令将向你展示当前正在运行的 Vim 的所有相关信息,包括它是如何编译的。 + +第一行告诉你这个二进制文件的编译时间和版本号,比如:7.4。接下来的一行呈现 `Included patches: 1-1051`,这是补丁版本包。因此你 Vim 确切的版本号是 7.4.1051。 + +另一行显示着一些像 `Tiny version without GUI` 或者 `Huge version with GUI` 的信息。很显然这些信息告诉你当前的 Vim 是否支持 GUI,例如:从终端中运行 `gvim` 或者从终端模拟器中的 Vim 内运行 `:gui` 命令。另一个重要的信息是 `Tiny` 和 `Huge`。Vim 的特性集区分被叫做 `tiny`,`small`,`normal`,`big` and `huge`,所有的都实现不同的功能子集。 + +`:version` 主要的输出内容是特性列表。`+clipboard` 意味这剪贴板功能被编译支持了,`-clipboard` 意味着剪贴板特性没有被编译支持。 + +一些功能特性需要编译支持才能正常工作。例如:为了让 `:prof` 工作,你需要使用 `huge` 模式编译的 Vim,因为那种模式启用了 `+profile` 特性。 + +如果你的输出情况并不是那样,并且你是从包管理器安装 Vim 的,确保你安装了 `vim-x`,`vim-x11`,`vim-gtk`,`vim-gnome` 这些包或者相似的, 因为这些包通常都是 `huge` 模式编译的。 + +你也可以运行下面这段代码来测试 Vim 版本以及功能支持: + +```vim +" Do something if running at least Vim 7.4.42 with +profile enabled. +if (v:version > 704 || v:version == 704 && has('patch42')) && has('profile') + " do stuff +endif +``` + +相关帮助: + +``` +:h :version +:h feature-list +:h +feature-list +``` + +## 备忘录 + +为了避免版权问题,我只贴出链接: + +- http://people.csail.mit.edu/vgod/vim/vim-cheat-sheet-en.png +- https://cdn.shopify.com/s/files/1/0165/4168/files/preview.png +- http://www.nathael.org/Data/vi-vim-cheat-sheet.svg +- http://michael.peopleofhonoronly.com/vim/vim_cheat_sheet_for_programmers_screen.png +- http://www.rosipov.com/images/posts/vim-movement-commands-cheatsheet.png + +或者在 Vim 中快速打开备忘录:[vim-cheat40](https://github.com/lifepillar/vim-cheat40)。 + +# 基础 + +## 缓冲区,窗口,标签 + +Vim 是一个文本编辑器。每次文本都是作为**缓冲区**的一部分显示的。每一份文件都是在他们自己独有的缓冲区打开的,插件显示的内容也在它们自己的缓冲区中。 + +缓冲区有很多属性,比如这个缓冲区的内容是否可以修改,或者这个缓冲区是否和文件相关联,是否需要同步保存到磁盘上。 + +**窗口** 是缓冲区上一层的视窗。如果你想同时查看几个文件或者查看同一文件的不同位置,那样你会需要窗口。 + +请别把他们叫做_分屏_。你可以把一个窗口分割成两个,但是这并没有让这两个窗口完全_分离_。 + +窗口可以水平或者竖直分割并且现有窗口的高度和宽度都是可以被调节设置的,因此,如果你需要多种窗口布局,请考虑使用标签。 + +**标签页** (标签)是窗口的集合。因此使用标签当你想使用多种窗口布局的时候。 + +简单的说,如果你启动VIM的时候没有附带任何参数,你会得到一个包含着一个呈现一个缓冲区的窗口的标签。 + +顺带提一下,缓冲区列表是全局可见的,你可以在任何标签中访问任何一个缓冲区。 + +## 已激活,已载入,已列出,已命名,缓冲区 + +用类似 `vim file1` 的命令启动 Vim 。这个文件的内容将会被加载到缓冲区中,你现在有一个**已载入的缓冲区**。如果你在 Vim 中保存这个文件,缓冲区内容将会被同步到磁盘上(写回文件中)。 + +由于这个缓冲区也在一个窗口上显示,所以他也是一个**已激活的缓冲区**。如果你现在通过 `:e file2` 命令加载另一个文件,`file1` 将会变成一个**隐藏的缓冲区**,并且 `file2` 变成已激活缓冲区。 + +使用 `:ls` 我们能够列出所有可以列出的缓冲区。插件缓冲区和帮助缓冲区通常被标记为不可以列出的缓冲区,因为那并不是你经常需要在编辑器中编辑的常规文件。通过 `:ls!` 命令可以显示被放入缓冲区列表的和未被放入列表的缓冲区。 + +**未命名的缓冲区**是一种没有关联特定文件的缓冲区,这种缓冲区经常被插件使用。比如 `:enew` 将会创建一个无名临时缓冲区。添加一些文本然后使用 `:w /tmp/foo` 将他写入到磁盘,这样这个缓冲区就会变成一个**已命名的缓冲区**。 + +## 参数列表 + +[全局缓冲区列表](#缓冲区窗口标签)是 Vim 的特性。在这之前的 vi 中,仅仅只有参数列表,参数列表在 Vim 中依旧可以使用。 + +每一个通过 shell 命令传递给 Vim 的文件名都被记录在一个参数列表中。可以有多个参数列表:默认情况下所有参数都被放在全局参数列表下,但是你可以使用 `:arglocal` 命令去创建一个新的本地窗口的参数列表。 + +使用 `:args` 命令可以列出当前参数。使用 `:next`,`:previous`,`:first`,`:last` 命令可以在切换在参数列表中的文件。通过使用 `:argadd`,`:argdelete` 或者 `:args` 等命令加上一个文件列表可以改变参数列表。 + +偏爱缓冲区列表还是参数列表完全是个人选择,我的印象中大多数人都是使用缓冲区列表的。 + +然而参数列表在有些情况下被大量使用:批处理 +使用 `:argdo`! 一个简单的重构例子: + +```vim +:args **/*.[ch] +:argdo %s/foo/bar/ge | update +``` + +这条命令将替换掉当前目录下以及当前目录的子目录中所有的C源文件和头文件中的“foo”,并用“bar”代替。 + +相关帮助:`:h argument-list` + +## 按键映射 + +使用 `:map` 命令家族你可以定义属于你自己的快捷键。该家族的每一个命令都限定在特定的模式下。从技术上来说 Vim 自带高达12中模式,其中6种可以被映射。另外一些命令作用于多种模式: + +|   递归   |   非递归     | 模式                           | +|-----------|---------------|----------------------------------| +| `:map` | `:noremap` | normal, visual, operator-pending | +| `:nmap` | `:nnoremap` | normal | +| `:xmap` | `:xnoremap` | visual | +| `:cmap` | `:cnoremap` | command-line | +| `:omap` | `:onoremap` | operator-pending | +| `:imap` | `:inoremap` | insert | + +例如:这个自定义的快捷键只在普通模式下工作。 + +```vim +:nmap :echo "foo" +``` + +使用 `:nunmap ` 可以取消这个映射。 + +对于更少数,不常见的模式(或者他们的组合),查看 `:h map-modes`。 + +到现在为止还好,对新手而言有一个问题会困扰他们:`:nmap` 是**递归执行**的!结果是,右边执行可能的映射。 + +你自定义了一个简单的映射去输出“Foo”: + +```vim +:nmap b :echo "Foo" +``` + +但是如果你想要映射 `b` (回退一个单词)的默认功能到一个键上呢? + +```vim +:nmap a b +``` + +如果你敲击a,我们期望着光标回退到上一个单词,但是实际情况是“Foo”被输出到命令行里!因为在右边,`b` 已经被映射到别的行为上了,换句话说就是 `:echo "Foo"`。 + +解决此问题的正确方法是使用一种_非递归_的映射代替: + +```vim +:nnoremap a b +``` + +经验法则:除非递归是必须的,否则总是使用非递归映射。 + +通过不给一个右值来检查你的映射。比如`:nmap` 显示所以普通模式下的映射,`:nmap ` 显示所有以 `` 键开头的普通模式下的映射。 + +如果你想禁止用标准映射,把他们映射到特殊字符 `` 上,例如:`:noremap `。 + +相关帮助: + + :h key-notation + :h mapping + :h 05.3 + +## 快捷键前缀 +## 范围 +## 寄存器 +## 标注 +## 补全 +## 动作,操作符,文本对象 +## 自动命令 +## 变更历史,跳转历史 +## 内容变更历史记录 +## 全局位置信息表,局部位置信息表 +## 宏 +## 颜色主题 +## 折叠 +## 会话 +## 局部化 +# 用法 + +## 获取离线帮助 +## 获取离线帮助(备选) +## 获取在线帮助 +## 执行自动命令 +### 用户自定义事件 +### 内部自带事件 +## 剪贴板 +## 剪贴板使用 (Windows, OSX) +## 剪贴板使用 (Linux, BSD, ...) +## 打开文件时恢复光标位置 +## 备份文件,交换文件,撤销文件以及viminfo文件的处理 +## 编辑远程文件 +## 插件管理 +## 片段插入 +## 使用外部程序和过滤器 +## MatchIt +# 技巧 + +## 聪明的使用n和N +## 聪明的使用命令行历史 +## 智能CTRL-L +## 禁用错误报警声音和图标 +## 快速移动当前行 +## 快速添加空行 +## 快速编辑自定义宏 +## 快速跳转到源(头)文件 +## 在GUI中快速改变字体大小 +## 根据模式改变光标类型 +## 防止水平滑动的时候失去选择 +## 重新载入保存文件 +## 智能当前行 +## 更快的关键字补全 +# 命令 + +## :global - 在所有匹配行执行命令 +## :normal and :execute - 脚本梦之队 +## :redir - 重定向消息 +# 调试 + +## 常规建议 +## 查看启动日志 +## 查看运行时日志 +## 调整日志等级 +## vim脚本调试 +## 语法文件调试 +# 杂项 + +## 附加资源 +## Vim 配置集合 +## 内置插件 +## 将Control映射到CapsLock +## 复活节彩蛋 +## 为何使用hjkl +# 怪癖 + +## 编辑小文件很慢 +## 编辑大文件很慢 +## 新行用于NUL +## 相同部分粘贴 (要不为什么我总要设置‘粘贴’?) +## 在终端使用Esc延时 +## 无法重复函数中执行的搜索 +## 主题列表 + +# 插件列表 + +# Neovim + +## 加入我们 -### 加入我们 可以协助我们核对翻译,或者从[章节列表](CONTRIBUTING.md)中认领章节进行翻译。 -### 致谢: + +## 致谢: - [Linux 中国翻译组](https://github.com/LCTT) - [掘金翻译计划](https://github.com/xitu/gold-miner) diff --git a/contents/minimal-vimrc.vim b/contents/minimal-vimrc.vim new file mode 100644 index 0000000..5c0bdb0 --- /dev/null +++ b/contents/minimal-vimrc.vim @@ -0,0 +1,63 @@ +" +" A (not so) minimal vimrc. +" + +" You want Vim, not vi. When Vim finds a vimrc, 'nocompatible' is set anyway. +" We set it explicitely to make our position clear! +set nocompatible + +filetype plugin indent on " Load plugins according to detected filetype. +syntax on " Enable syntax highlighting. + +set autoindent " Indent according to previous line. +set expandtab " Use spaces instead of tabs. +set softtabstop =4 " Tab key indents by 4 spaces. +set shiftwidth =4 " >> indents by 4 spaces. +set shiftround " >> indents to next multiple of 'shiftwidth'. + +set backspace =indent,eol,start " Make backspace work as you would expect. +set hidden " Switch between buffers without having to save first. +set laststatus =2 " Always show statusline. +set display =lastline " Show as much as possible of the last line. + +set showmode " Show current mode in command-line. +set showcmd " Show already typed keys when more are expected. + +set incsearch " Highlight while searching with / or ?. +set hlsearch " Keep matches highlighted. + +set ttyfast " Faster redrawing. +set lazyredraw " Only redraw when necessary. + +set splitbelow " Open new windows below the current window. +set splitright " Open new windows right of the current window. + +set cursorline " Find the current line quickly. +set wrapscan " Searches wrap around end-of-file. +set report =0 " Always report changed lines. +set synmaxcol =200 " Only highlight the first 200 columns. + +set list " Show non-printable characters. +if has('multi_byte') && &encoding ==# 'utf-8' + let &listchars = 'tab:▸ ,extends:❯,precedes:❮,nbsp:±' +else + let &listchars = 'tab:> ,extends:>,precedes:<,nbsp:.' +endif + +" The fish shell is not very compatible to other shells and unexpectedly +" breaks things that use 'shell'. +if &shell =~# 'fish$' + set shell=/bin/bash +endif + +" Put all temporary files under the same directory. +" https://github.com/mhinz/vim-galore#handling-backup-swap-undo-and-viminfo-files +set backup +set backupdir =$HOME/.vim/files/backup/ +set backupext =-vimbackup +set backupskip = +set directory =$HOME/.vim/files/swap// +set updatecount =100 +set undofile +set undodir =$HOME/.vim/files/undo/ +set viminfo ='100,n$HOME/.vim/files/info/viminfo