Mastering_vim
目录:
- # 1 Preface
- # 2 Chapter 1: Getting Started
- ## 2.1 Technical requirements
- ## 2.2 Let’s start a conversation (about modal interfaces)
- ## 2.3 Installation
- ## 2.4 Vanilla Vim vs gVim
- ## 2.5 Configuring Vim with your .vimrc
- ## 2.6 Common operations (or how to exit Vim)
- ## 2.7 Moving around: talk to your editor
- ## 2.8 Making simple edits in insert mode
- ## 2.9 Persistent undo and repeat
- ## 2.10 Read the Vim manual using :help
- ## 2.11 Summary
- # 3 Chapter 2: Advanced Editing and Navigation
- # 4 Chapter 3: Follow the Leader - Plugin Management
- # 5 Chapter 4: Understanding the Text
- # 6 Chapter 5: Build, Test, and Execute
- ## 6.1 Technical requirements
- ## 6.2 Working with version control
- ## 6.3 Resolving conflicts with vimdiff
- ## 6.4 tmux, screen, and Vim terminal mode
- ## 6.5 Building and testing
- ## 6.6 Summary
- # 7 Chapter 6: Refactoring Code with Regex and Macros
- ## 7.1 Technical requirements
- ## 7.2 Search or replace with regular expressions
- ## 7.3 Recording and playing macros
- ## 7.4 Using plugins to do the job
- ## 7.5 Summary
- # 8 Chapter 7: Making Vim Your Own
- # 9 Chapter 8: Transcending the Mundane with Vimscript
- ## 9.1 Technical requirements
- ## 9.2 Why Vimscript?
- ## 9.3 How to execute Vimscript
- ## 9.4 Learning the syntax
- ### 9.4.1 Setting variables
- ### 9.4.2 Surfacing output
- ### 9.4.3 Conditional statements
- ### 9.4.4 Lists
- ### 9.4.5 Dictionaries
- ### 9.4.6 Loops
- ### 9.4.7 Functions
- ### 9.4.8 Classes
- ### 9.4.9 Lambda expressions
- ### 9.4.10 Map and filter
- ### 9.4.11 Interacting with Vim
- ### 9.4.12 File-related commands
- ### 9.4.13 Prompts
- ### 9.4.14 Using Help
- ## 9.5 A word about style guides
- ## 9.6 Let's build a plugin
- ## 9.7 Further reading
- ## 9.8 Summary
- # 10 Chapter 9: Neovim
- # 11 Chapter 10: Where to Go from Here
- # 12 Other Books You May Enjoy
- # 13 Index
bilibili居然有配套“Mastering Vim: Understanding Vim's Lesser-Known Features for More Effective Editing”的视频,作者Damain Conway。
1. Preface
2. Chapter 1: Getting Started
2.1. Technical requirements
2.2. Let’s start a conversation (about modal interfaces)
2.3. Installation
2.3.1. Setting up on Linux
其实作者用的是Vim8,而公司32号机是Vim7.4,有无必要跟从特定版本。若需跟从,就不能用公司32号机了,无安装权限。
对了,其上介绍了对应不同的linux版本该怎么安装最新的Vim。
书上更新命令似乎无用,换用网上搜索的命令:
sudo add-apt-repository ppa:jonathonf/vim
sudo apt-get update
sudo apt-get install vim
2.3.2. Setting up on MacOS
2.3.2.1. Using Homebrew
2.3.2.2. Downloading a .dmg image
2.3.3. Setting up on Windows
似乎作者说在Windows系统可使用Cygwin和gVim实现Vim的功能,当然,似乎也因操作系统差异有些小问题。
2.3.3.1. Unix-like experience with Cygwin
2.3.3.1.1. Installing Cygwin
2.3.3.1.2. Using Cygwin
2.3.3.2. Visual Vim with gVim
2.3.4. Verifying and troubleshooting the installation
作者说到,也许Vim默认支持python2而非3,他介绍了解决这个问题的办法。
2.4. Vanilla Vim vs gVim
2.5. Configuring Vim with your .vimrc
2.6. Common operations (or how to exit Vim)
2.6.1. Opening files
不管文件存在与否,有则直接打开,无则创建并打开:
vim animal_farm.py
若已打开Vim程序,想在Vim程序中打开文件如animal_farm.py,可:
:e animal_farm.py
注::e
代表edit。
2.6.2. Changing text
进入Vim之后默认在普通模式,此模式下任何键入对应特定某条命令。输入i
可进入插入模式。模式可看底部状态行,如插入模式显示--INSERT--
,普通模式无特别提示。
在插入模式输入以下内容:
#!/usr/bin/python3
"""Our own little animal farm."""
import sys
def add_animal(farm, animal):
farm.add(animal)
return farm
def main(animals):
farm = set()
for animal in animals:
farm = add_animal(farm, animal)
print("We've got some animals on the farm:", ','.join(farm) + '.')
if __name__ == '__main__':
if len(sys.argv) == 1:
print('Pass at least one animal type!')
sys.exit(1)
main(sys.argv[1:])
敲击ESC键回到普通模式。
2.6.3. Saving and closing files
普通模式执行如下命令,可保存文件:
:w
注:
:w
代表write。- 别忘了在输入命令后敲击ENTER键。
- 也可保存到新的文件,如
:w animal_farm_2.py
代表将animal_farm.py
当前内容保存至animal_farm_2.py
。
接下来你应该是要退出文件,可输入:
:q
注::q
代表quit。
也可同时保存并退出,即:
:wq
如文件有更改却想不保存更改直接退出,要使用如下命令强制退出:
:q!
注:
- Vim中许多命令有长短两个版本。例如,
:e
、:w
和:q
是:edit
、:write
和:quit
的短版本。在Vim手册中,命令的可选部分通常用方括号([])标注,例如:w[rite]
和:e[dit]
。
2.6.3.1. A word about swap files
默认情况下,Vim在交换文件中跟踪对文件所做的更改。交换文件是在编辑文件时创建的,用于在Vim、SSH会话或机器崩溃时恢复文件内容。如不清楚退出Vim,屏幕将出现:
...
Swap file ".animal_farm.py.swp" already exits!
[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:
可敲击r
来恢复交换文件内容,或敲击d
删除交换文件并驳回改变。如果您决定恢复交换文件,您可以通过重新打开一个文件并运行:e
,并按d
删除交换文件,来防止下次在Vim中打开文件时出现相同的消息。
默认情况下,Vim在与原始文件相同的目录中创建类似于<filename>.swp
的文件。如果您不希望您的文件系统被交换文件打乱,您可以通过告诉Vim将所有交换文件放在一个目录中来改变这种行为。为此,在.vimrc
中添加以下内容:
set directory=$HOME/.vim/swap//
注:
Windows系统应设置:
directory=%USERDATA%\.vim\swap//
注意最后两斜线方向必须如上所示。
甚至可通过
set noswapfile
完全关闭交换文件。很可能home目录无此文件,可创建并加入此条。
配置时候你可能会写注释,但Vim的注释不能用
#
,而要在需注释行首用"
(英文双引号)。
2.7. Moving around: talk to your editor
Vim允许您比大多数传统编辑器更有效地浏览内容。让我们从基础开始。
你可以使用方向键或字母h
、j
、k
和l
来移动光标。这是最低效和最精确的移动方式:
key | Alternative | Action |
---|---|---|
h | Left arrow 左箭头 |
Move cursor left 光标左移 |
j | Down arrow 右箭头 |
Move cursor down 光标右移 |
k | Up arrow 上箭头 |
Move cursor up 光标上移 |
l | Right arrow 下箭头 |
Move cursor right 光标下移 |
Vi (Vim的前身)是在旧的ADM-3A终端(看其键盘布局无箭头键)上创建的,该终端没有箭头键。键h
、j
、k
和l
用作箭头。
试一试!习惯hjkl
的移动有很大的价值:你的手停留在键盘的主行上。这样你就不需要移动你的手,它会帮助你保持流状态。此外,许多应用程序将hjkl
视为箭头键—您会惊讶于有这么多工具响应这些键。
现在,您可能倾向于多次点击方向键来达到想要的位置,但是有一个更好的方法!您可以在每个命令前面加上一个数字,这将重复该命令的次数。例如,按5j
将光标向下移动5行,而按14l
将光标向左移动14个字符。这适用于您在本书中遇到的大多数命令。
计算您想要移动的确切字符数是相当困难的(而且没有人愿意这样做),所以有一种方法可以通过单词移动。使用w
移动到下一个单词的开头,使用e
移动到最近单词的结尾。要回到单词开头,按b
键。
空格隔断的任何字符,包括大写字母,均应视为文字(word)。这允许您区分希望遍历的内容。
注:
- Vim有两种文字(word)对象:小写“word”和大写“WORD”。在Vim世界中,word是由空格分隔的字母、数字和下划线组成的序列。WORD是由空格分隔的任何非空白字符组成的序列。
让我们来看看下面这行代码:
farm = add_animal(farm, animal)
代码此时光标位置在a。按
w
键会把光标移到(
;而按W
键会转到animal
的开头。按e
键会把光标移到add_animal
的末尾;而按E
键会转到animal
的开头。
大写的W
、E
和B
将把任何被空格分隔在一起的字符作为本WORD。如下表所示:
Key | Action |
---|---|
w | Move forward by word 向前移动一个word |
e | Move forward until the end of the word 向前移动到本word末尾 |
W | Move forward by WORD 向前移动一个WORD |
E | Move forward until the end of the WORD 向前移动到本WORD末尾 |
b | Move backwards to the beginning of the word 后移到本word的开头 |
B | Move backwards to the beginning of the WORD 后移到本WORD的开头 |
下面的表格显示了更多关于每个命令行为的例子:
Key | Initial cursor position | Resulting cursor position |
---|---|---|
w | farm = <a>dd_animal(farm, animal) |
farm = add_animal<(>farm, animal) |
e | farm = add_an<i>mal(farm, animal) |
farm = add_anima<l>(farm, animal) |
b | farm = add_an<i>mal(farm, animal) |
farm = <a>dd_animal(farm, animal) |
W | farm = add_an<i>mal(farm, animal) |
farm = add_animal(farm, <a>nimal) |
E | farm = add_an<i>mal(farm, animal) |
farm = add_animal(farm<,> animal) |
B | farm = add_animal(f<a>rm, animal) |
farm = <a>dd_animal(farm, animal) |
注:
- 用
<>
标注光标位置。
将显示的(通过文字移动)动作与您先前学习的方向动作相结合,以减少按键次数!
在段落中移动也很有用。任何被至少两行隔开的代码都被认为是一个段落,这也意味着每个代码块都是一个段落,如下面的例子所示:
def add_animal(farm, animal):
farm.add(animal)
return farm
def main(animals):
farm = set()
for animal in animals:
farm = add_animal(farm, animal)
print("We've got some animals on the farm:", ', '.join(farm) + '.')
函数add_animal
和main
是两个独立的段落。使用右花括号向前移动,使用左花括号向后移动,具体如下表所示:
Command | Action |
---|---|
{ | Move back by one paragraph 向后移动一段落 |
} | Move forward by one paragraph 向前移动一段落 |
注:
- 区隔段落仅需首尾各一空行。
- 这里空行指除换行符之外的其它字符,空格符也不行。
- 通过
{
和}
在段落间移动,你会好奇光标落脚处。若段落之间区隔为两空行,{
将首先移到本段落的段首,即本段落紧前一空行的行首,之后再{
将移到下一段落的段首。}
将首先移到本段落的段尾,即本段落的紧后一空行的行首,之后再}
将移到下一段落的段尾。若段落之间区隔为一空行,则本段落的段尾即下一段落的段首。
如果你需要移动一个以上的段落,不要忘记把这两个和数字结合起来。
有更多的移动方式,但这些是最重要的基础。我们将在第二章“高级编辑和导航”中介绍更复杂的导航方法。
2.8. Making simple edits in insert mode
在使用Vim时,您通常希望在插入模式上花费尽可能少的时间(除非您正在编写而不是编辑)。由于大多数文本操作都涉及编辑,所以我们将重点讨论编辑。
您已经学会了按i
键进入插入模式。有更多的方法可以进入插入模式。通常情况下,你会想要为另一篇文章修改一段文字,而且有一个针对该的命令c
。change
命令允许您删除部分文本并立即进入插入模式。Change
是一个复合命令,这意味着它后面需要有一个命令告诉Vim需要更改什么。你可以把它和你以前学过的任何动作命令结合起来。以下是一些例子:
Command | Before | After |
---|---|---|
cw | farm = add_animal(<f>arm, animal) |
farm = add_animal(<,> animal) |
c3e (comma counts as a word) | farm = add_animal(fa<r>m, animal) |
farm = add_animal(fa<)> |
cb | farm = add_animal(farm, ani<m>al) |
farm = add_animal(farm, <m>al) |
c4l | farm = add_animal(farm, <a>nimal) |
farm = add_animal(farm, <a>l) |
cW | farm = add_animal(farm, <a>nimal) |
farm = add_animal(farm,<> |
注:
c
后面跟移动的命令,代表删除到移动结束的位置。如cw
指向前移动一个单词并删除,实现表格第一行。farm
、,
和animal
算3个word。- 紧上表格我试验了,确实如此。
- 作为一个奇怪的例外,
cw
表现得像ce
。这是Vim的前身Vi遗留下来的。
当您学习更复杂的动作命令时,您可以将这些命令与快速无缝编辑的更改组合在一起。我们还将介绍一些插件,这些插件将对更改命令进行加速,从而允许进行更强大的编辑,比如更改大括号中的文本,或者替换正在运行的引号类型。
注:
- 所有这些示例都遵循
<command> <number> <movement or a text object>
结构。您可以在<command>
之前或之后放置一个数字。
例如,如果您希望将farm = add_animal(farm, animal)
更改为farm = add_animal(farm, creatures)
,您可以执行以下命令集:
Contents of the line | Action |
---|---|
<f>arm = add_animal(farm, animal) |
Start with a cursor in the beginning of the line 开始时光标位于行首 |
farm = add_animal(farm, <a>nimal) |
Hit 3W to move the cursor three WORDs forward to the beginning of animal 敲击 3W 以使光标移动3个WORD到“animal”的开头 |
farm = add_animal(farm, <)> |
Press cw to delete the word animal and enter the insert mode 按下cw以删除属于一个word的“animal”并进入插入模式 |
farm = add_animal(farm, creature<)> |
Type creature 输入“creature” |
farm = add_animal(farm, creatur<e>) |
Hit the Esc key to return to NORMAL mode 敲击ESC键回到普通模式 |
有时我们只想切东西,不放任何东西,d
就是这样做的。它代表删除。它的行为与c
相似,只是w
和e
的行为更标准一些,如下例所示:
Command | Before | After |
---|---|---|
dw | farm = add_animal(<f>arm, animal) |
farm = add_animal(<,> animal) |
d3e (comma counts as a word) | farm = add_animal(fa<r>m, animal) |
farm = add_animal(fa<)> |
db | farm = add_animal(farm, ani<m>al) |
farm = add_animal(farm, <m>al) |
d4l | farm = add_animal(farm, <a>nimal) |
farm = add_animal(farm, <a>l) |
dW | farm = add_animal(farm, <a>nimal) |
farm = add_animal(farm,<> |
还有两个更漂亮的快捷方式,可以让你改变或删除一整行:
Command | What it does |
---|---|
cc | Clears the whole line and enters insert mode. Preserves current indentation level, which is useful when coding. 清除整行并进入插入模式。保持当前缩进级别,这在编码时很有用。 |
dd | Deletes an entire line. 删除整行。 |
注:
cc
和dd
的差异。cc
将进入插入模式dd
则否。cc
将保持此行之前的缩进状态,而dd
将删除整行并换行符,即被删除行甚至不留下空行。- 如果在选择正确的移动命令时遇到困难,还可以使用可视化模式选择要修改的文本。按
v
键进入可视模式,使用常用的移动命令来调整选择。一旦您对选择满意,就运行所需的命令(如c更改或d删除)。可视化模式可显示选择了什么文本。
2.9. Persistent undo and repeat
与任何编辑器一样,Vim跟踪每个操作。按u
撤消最后一个操作,并按Ctrl + r
重做。
注:
- 要了解更多关于Vim的撤消树(Vim的撤消历史不是线性的!)以及如何导航它,请参阅第4章,高级工作流。
Vim还允许持久化会话之间的撤消历史记录,如果您希望撤消(或记住)几天前完成的某些操作,这是非常好的!
您可以通过在.vimrc中添加以下代码来启用持久撤销:
set undofile
但是,这将为您正在编辑的每个文件添加一个undo文件。您可以将撤销文件合并到一个目录中,如下面的示例所示:
" Set up persistent undo across all files.
set undofile
if !isdirectory("$HOME/.vim/undodir")
call mkdir("$HOME/.vim/undodir", "p")
endif
set undodir="$HOME/.vim/undodir"
注:
- 如果您使用的是Windows,请将目录替换为
%USERPROFILE%\_vim\undodir
(您将更改_vimrc
而不是.vimrc
)。 - 不知为何,会遇到E303错误,所以并未实际完成vim配置,既然
.vimrc
之前是不存在的,那么删除此文件。
现在,您将能够跨会话撤消和重做更改。
2.10. Read the Vim manual using :help
Vim提供的最好的学习工具当然是:help
命令,如下面的截图所示:
help.txt For Vim version 8.1. Last change: 2019 Jul 21
VIM - main help file
k
Move around: Use the cursor keys, or "h" to go left, h l
"j" to go down, "k" to go up, "l" to go right. j
Close this window: Use ":q<Enter>".
Get out of Vim: Use ":qa!<Enter>" (careful, all changes are lost!).
Jump to a subject: Position the cursor on a tag (e.g. bars) and hit CTRL-].
With the mouse: ":set mouse=a" to enable the mouse (in xterm or GUI).
Double-click the left mouse button on a tag, e.g. bars.
Jump back: Type CTRL-O. Repeat to go further back.
Get specific help: It is possible to go directly to whatever you want help
on, by giving an argument to the :help command.
Prepend something to specify the context: help-context
WHAT PREPEND EXAMPLE
Normal mode command :help x
help.txt [Help][RO]
它是一个随Vim安装的巨大的资源和教程的集合。通过使用页面向上和向下键(也可分别使用Ctrl + b
和Ctrl + f
)滚动,有很多有用的信息。
当您遇到问题,或者想要了解更多关于某个特定命令的信息时,请尝试使用:help
(您可以将其缩短为:h
)进行搜索。让我们来搜索一下我们学过的cc
命令:
:h cc
显示为:
"c" command always starts insert mode, even if there
is no text to delete.
cc
["x]cc Delete [count] lines [into register x] and start
insert linewise. If 'autoindent' is on, preserve
the indent of the first line.
C
["x]C Delete from the cursor position to the end of the
line and [count]-1 more lines [into register x], and
start insert. Synonym for c$ (not linewise).
s
["x]s Delete [count] characters [into register x] and start
insert (s stands for Substitute). Synonym for "cl"
(not linewise).
S
["x]S Delete [count] lines [into register x] and start
insert. Synonym for "cc" linewise.
change.txt [Help][RO]
帮助告诉我们命令的工作方式,以及不同的选项和设置如何影响命令(例如自动缩进(autoindent
)设置保留缩进)。
:help
是一个导航一组帮助文件的命令。当您查看帮助文件时,您会注意到某些单词是用颜色高亮显示的。这些都是标记,可以使用:help
命令进行搜索。不幸的是,并非每个标签名称都是直观的。例如,如果我们想学习如何在Vim中搜索字符串,我们可以尝试使用以下方法:
:h search
然而,看起来这个命令把我们带到表达式求值的入口,这并不是我们要找的,如下面的截图所示:
Returns an empty String when row or col is out of range.
Can also be used as a method:
GetRow()->screenstring(col)
search({pattern} [, {flags} [, {stopline} [, {timeout}]]]) search()
Search for regexp pattern {pattern}. The search starts at the
cursor position (you can use cursor() to set it).
When a match has been found its line number is returned.
If there is no match a 0 is returned and the cursor doesn't
move. No error message is given.
{flags} is a String, which can contain these character flags:
'b' search Backward instead of forward
'c' accept a match at the Cursor position
'e' move to the End of the match
'n' do Not move the cursor
'p' return number of matching sub-Pattern (see below)
's' Set the ' mark at the previous location of the cursor
'w' Wrap around the end of the file
eval.txt [Help][RO]
要找到正确的条目,输入:h search
(不要回车),然后按Ctrl + D
。这将为您提供包含子字符串search
的帮助标记列表。其中一个选项是search-commands
,这是我们要找的。完成您的命令,以下列方式进入我们正在寻找的入口:
:h search-commands
下面的显示显示了搜索的正确帮助条目:
8. Composing characters patterns-composing
9. Compare with Perl patterns perl-patterns
10. Highlighting matches match-highlight
==============================================================================
1. Search commands search-commands
/
/{pattern}[/]<CR> Search forward for the [count]'th occurrence of
{pattern} exclusive.
/{pattern}/{offset}<CR> Search forward for the [count]'th occurrence of
{pattern} and go {offset} lines up or down.
linewise.
/<CR>
/<CR> Search forward for the [count]'th occurrence of the
latest used pattern last-pattern with latest used
{offset}.
//{offset}<CR> Search forward for the [count]'th occurrence of the
latest used pattern last-pattern with new
{offset}. If {offset} is empty no offset is used.
pattern.txt [Help][RO]
注:
- 说到搜索功能,您可以使用
/search term
从游标向前搜索,或者使用?search term
向后搜索帮助页面(或Vim中打开的任何文件)。有关如何执行搜索操作的更多信息,请参见第2章高级编辑和导航。
当您有问题或想更好地理解Vim的行为方式时,不要忘记使用Vim的帮助系统。
2.11. Summary
最初的Vi是为了在带宽和速度有限的情况下通过远程终端工作而开发的。这些限制引导Vi建立一个高效的、深思熟虑的编辑过程,这是当今Vi改进的核心。
在本章中,您学习了如何在每个主要平台上安装和更新Vim及其图形化对应的GVim(以比您需要的更多的方式)。
您已经学会了通过修改.vimrc
来配置Vim,当您根据自己的需要定制编辑器时,您常常会回到这个步骤。
您已经掌握了处理文件、移动Vim和进行更改的基础知识。Vim的文本对象(字母、单词、段落)和复合命令(如d2w
-删除两个word)的概念为精确的文本操作提供了支持。
如果你能从这一章中学到一件事,那就是:help
。Vim的内部帮助系统非常详细,它可以回答您可能遇到的大多数问题(如果不是所有问题的话),只要您知道自己在寻找什么。
在下一章中,我们将研究如何从Vim中获得更多信息。您将学习如何导航文件和更好地编辑文本。
3. Chapter 2: Advanced Editing and Navigation
在本章中,您将更轻松地在日常任务中使用Vim。您将使用Python代码库,它应该为您提供一组使用代码的真实场景。如果你有自己的项目,你可以选择使用自己的项目文件来尝试本章的课程;但是,您可能会发现并不是所有的场景都适用于您的代码库。
本章将涉及以下主题:
- 快速和肮脏的方式安装Vim插件
- 在使用缓冲区、窗口、选项卡和折叠处理多个或长文件时,保持工作空间的组织性
- 在复杂的文件树中导航,而不让Vim使用
Netrw
、NERDTree
、Vinegar
或CtrlP
- 在整个文件中进行先进的导航,并涵盖更多类型的文本对象:使用
grep
和ack
寻找文件中的东西,和EasyMotion
,一个闪电速度移动插件 - 利用寄存器的能力复制和粘贴
3.1. Technical requirements
本章将介绍如何使用Python代码库。你可以通过https://github.com/PacktPublishing/MasteringVim/blob/master/Chapter02获取本章将要编辑的代码。
3.2. Installing plugins
本章将首先介绍Vim插件。插件管理是一个相当广泛的主题(在第3章,也跟随领导者-插件管理),但我们开始只有几个插件,所以我们暂不必自己担心那个主题。
首先,让我们来看看一次性设置:
您需要创建一个目录来存储插件。在命令行执行以下操作:
$ mkdir -p ~/.vim/pack/plugins/start
如果你在Windows下使用GVim,你必须在目录用户文件夹下创建vimfiles(通常
C:\Users\<username>
),然后在其中创建pack\plugins\start
。您需要告诉Vim为每个插件加载文档,因为它不会自动加载文档。为此,在
~/.vimrc
中添加以下行:packloadall " Load all plugins. silent! helptags ALL " Load help files for all plugins.
现在,每次你想添加一个插件,你必须:
在GitHub上找到你的插件。例如,让我们安装https://github.com/1. scrooloose/nerdtree。如果已经安装了Git,请找到Git存储库URL(在本例中是https://github.com/scrooloose/nerdtree.git)并运行以下命令:
$ git clone https://github.com/scrooloose/nerdtree.git ~/.vim/pack/plugins/start/nerdtree
如果您没有安装Git,或者安装着Windows下的GVim插件,请导航到插件的GitHub页面,找到一个Clone或download按钮。下载ZIP文件并将其解压缩到Linux的
.vim/pack/plugins/start/nerdtree
,或Windows的vimfiles/pack/plugins/start/nerdtree
。重新启动Vim,插件应该可以使用。
3.3. Organizing workspace
到目前为止,我们只处理了Vim中的一个文件。在处理代码时,您通常必须同时处理多个文件,来回切换,在多个文件之间进行编辑,并在其他地方查找某些数据。幸运的是,Vim提供了一种广泛的方式来处理许多文件:
- 缓冲区是Vim在内部表示文件的方式;它们允许您在多个文件之间快速切换
- 窗口通过显示相邻的多个文件来组织工作空间
- 选项卡是窗口的集合
- 折叠允许您隐藏和展开文件的某些部分,使大型文件更容易导航
下面是一个截图来说明以上几点:
注:
- 暂不知怎么实现如书上两个文档左右排列
让我们来看看截图中的内容:
- 多个文件(标记为farm.py、animals/cat.py和animal_farm.py)作为窗口打开
- 顶部的条(显示3 farm.py和a/dog.py)表示选项卡
- 以+开头的行表示折叠,隐藏文件的一部分
本节将详细讨论窗口、选项卡和折叠,您将能够轻松地处理所需的任何文件。
3.3.1. Buffers
缓冲区是文件的内部表示。您打开的每个文件都有一个相应的缓冲区。让我们从命令行打开一个文件vim animal_farm.py
。现在,让我们看看现有的缓冲区列表:
:ls
注:
- 许多命令都有同义词,
:ls
也是这样,:buffers
和:files
将有同样效果。
以下是:ls
命令输出的情况(看底部三行):
...
~
:ls
1 %a "animal_farm.py" line 23
Press ENTER or type command to continue
状态栏显示了一些关于我们已经打开的缓冲区的信息(我们现在只有一个):
1
是缓冲区号,它在Vim会话期间保持不变%
表示缓冲区在当前窗口中(参见Windows部分)a
表示缓冲区是活动的:它已加载并且是可见的animal_farm.py
是文件名line 1
是当前光标位置
让我们打开另一个文件:
:e animals/cat.py
您可以看到,我们最初打开的文件不见了,已经被当前文件替换。但是,animal_farm.py仍然存储在一个缓冲区中。再次列出所有缓冲区:
:ls
你可以看到两个文件名列出:
...
~
:ls
1 # "animal_farm.py" line 23
2 %a "animals/cat.py" line 4
Press ENTER or type command to continue
那么,我们怎样才能得到文件呢?
Vim通过一个数字和一个名称引用缓冲区,并且在单个会话中这两者都是惟一的(直到您退出Vim)。要切换到一个不同的缓冲区,使用:b
命令,后面跟着缓冲区的数字:
:b 1
注:
- 您可以通过省略
:b
和缓冲区编号之间的空格来缩短命令。
瞧,你又回到了原始文件!由于缓冲区也由文件名标识,所以可以使用部分文件名在它们之间进行切换。下面将打开包含animals/cat.py
的缓冲区:
:b cat
但是,如果有多个匹配项,则会出现错误。尝试寻找一个文件名包含py的缓冲区:
:b py
如下面的截图所示,状态栏显示了一个错误:
:ls
1 # "animal_farm.py" line 23
2 %a "animals/cat.py" line 4
E93: More than one match for py
Press ENTER or type command to continue
这时就可以使用tab补全来遍历可用选项。输入:b py
(不需要回车),然后按Tab键循环查看可用的结果。
您还可以使用:bn
(:bnext
)和:bp
(:bprevious
)在缓冲区循环。
一旦你完成了缓冲区(的使用),你可以删除它,也就是从开放缓冲区的列表中删除它而不退出Vim:
:bd
如果没有保存当前缓冲区,将返回一个错误。因此,您将有机会保存文件而不会意外删除缓冲区。
3.3.2. Plugin spotlight – unimpaired
Tim Pope的vim-unimpaired是一个插件,它为现有的Vim命令(以及一些新命令)添加了大量方便的映射。我每天都使用它,因为我发现映射更直观——]b
和[b
在打开的缓冲区循环,]f
和[f
在一个路径下的文件循环,等等。可从Github地址https://github.com/tpope/vim-unimpaired 得到(参阅本章之前章节安装插件以获得安装指导。)
以下是vim-unimpaired提供的一些映射:
]b
和[b
在缓冲区循环]f
和[f
在与当前缓冲区同路径的文件间循环]l
和[l
在location list间循环(参阅第五章建立、测试和执行的location list小节)]q
和[q
在quickfix list间循环(参阅第五章建立、测试和执行的quickfix list小节)]t
和[t
在标签间循环(参阅第四章理解Text的Meet Exuberant Ctags小节)
这个插件也允许你通过几个按键来切换某些选项,比如切换拼写检查或者切换光标高亮显示。
参见:help unimpaired
完整列表的映射和功能,vim-unimpaired提供。
3.3.3. Windows
Vim将缓冲区加载到windows中。您可以同时在屏幕上打开多个窗口,允许分屏功能。
3.3.3.1. Creating, deleting, and navigating windows
让我们尝试一下使用windows。打开animal_farm.py(从命令行运行$ vim animal_farm.py
或从vim运行:e animal_farm.py
)。
在一个分割窗口打开我们的一个文件:
split animals/cat.py
注:
- 也可将
:split
简化为:sp
。
你可以看到animals/cat.py被打开在当前文件的上方,你的光标被放在那里:
class Cat(animal.Animal):
def __init__(self):
self.kind = 'cat'
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
animals/cat.py 4,25 All
#!/usr/bin/python3
"""Our own little animal farm."""
import sys
def add_animal(farm, animal):
farm.add(animal)
return farm
def main(animals):
farm = set()
for animal in animals:
farm = add_animal(farm, animal)
print("We've got some animals on the farm:", ', '.join(farm) + '.')
if __name__ == '__main__':
if len(sys.argv) == 1:
print('Pass at least one animal type!')
sys.exit(1)
main(sys.argv[1:])
~
animal_farm.py 23,5 All
"animals/cat.py" 4L, 77C
你可以通过运行以下代码来垂直分割窗口:
:vsplit farm.py
注:
:vs
是:vsplit
命令的简化。
您可以将:split
和:vsplit
命令无限地组合在一起,以创建您需要的任意数量的窗口。
到目前为止,您学到的所有命令在这个窗口中都将正常工作,包括更改缓冲区。要在窗口之间移动,请使用Ctrl+w
,然后按方向键:h
、j
、k
或l
。箭头键也可以。
注:
如果你经常使用windows,你可以通过绑定
Ctrl+h
到左边的拆分,Ctrl+j
到底部的拆分,等等。在.vimrc
文件中添加以下内容:" Fast split navigation with <Ctrl> + hjkl. noremap <c-h> <c-w><c-h> noremap <c-j> <c-w><c-j> noremap <c-k> <c-w><c-k> noremap <c-l> <c-w><c-l>
尝试一下Ctrl+w
接着j
会把你移到下面的窗口,然后Ctrl+w
接着k
会把光标移回来。
你可以通过以下方式之一关闭分割窗口:
Ctrl+w
接着q
将关闭当前窗口
:q
将关闭窗口并释放缓冲区,然而,如果只有打开的一个窗口,也将关闭vim
bd
将删除当前缓冲区并关闭当前窗口。
Ctrl+w
接着o
将关闭除当前外的其它窗口
注:
- 当打开了多个窗口,可执行
:qa
来关闭全部窗口并退出vim,可结合:w
来保存所有打开了的文件,也就是:wqa
。
如果你想关闭一个缓冲区而不关闭它所在的窗口,你可以添加以下命令到你的.vimrc
文件:
command! Bd :bp | :sp | :bn | :bd " Close buffer without closing window.
您将能够使用:Bd
关闭缓冲区,同时保持拆分窗口打开。