星期四, 十月 22, 2020

VIM学习笔记 插件列表 (Plugins)

Best with Vim8 and python3 enabled.

说明:

  • 本列表完全基于作者的主观体验,既不客观也不完整;
  • 建议使用vim-plugVundle等插件管理器,来安装和管理插件;
  • 在“插件”列中的 ★,表示推荐的插件;
  • 在“描述”列中的【详细介绍】,链接到插件配置与使用的详细介绍。

类别

List (🔎 请点击展开/合并)

工具

junegunn/vim-plug  插件管理器【详细介绍
VundleVim/Vundle.vim 插件管理器【详细介绍
machakann/vim-highlightedyank 高亮显示yanked内容
svermeulen/vim-yoink yank历史纪录
DavidFishburn/YankRing.vim yank历史纪录【详细介绍
Shougo/context_filetype.vim 文件类型侦测
vim-scripts/fencview.vim  多编码(Multi-Encodings)格式识别【详细介绍
mhinz/vim-startify 自定义启动页(包含最近使用的文件、书签和保持的会话)
dstein64/vim-startuptime 启动时间分析
MTDL9/vim-verbosity 将verbose信息输出至日志文件
Shougo/vinarise.vim 十六进制(Hex)编辑器

色彩

rafi/awesome-colorschemes Awesome配色方案合辑
romainl/vim-cool 完成搜索后自动禁用高亮显示,再次查询时重新高亮显示
guns/xterm-color-table.vim xterm 256色及RGB值列表
lilydjwg/colorizer ★ 颜色代码的背景色显示相应的色彩【详细介绍

界面

vim-airline/vim-airline 自定义状态栏
powerline/powerline 自定义状态栏
liuchengxu/vim-which-key 在pop-up窗口中显示快捷键定义
mbbill/undotree 视觉化的undo历史
sjl/gundo.vim 视觉化的undo历史
kshenoy/vim-signature 在屏幕最左侧显示标记【详细介绍
nathanaelkane/vim-indent-guides 可视化显示缩进级别
ryanoasis/vim-devicons 根据文件类型显示图标
bagrat/vim-buffet 自定义Tabline显示缓冲区列表
t9md/vim-choosewin 类似TMUX的display-pane快速选择窗口

数据

chrisbra/csv.vim 处理按列存储的数据文件
mechatroner/rainbow_csv 以多种色彩显示CSV文件,并支持类似SQL的查询语言
vim-scripts/VisIncr 增加数值和日期等

语法

hail2u/vim-css3-syntax CSS3 syntax support to vim's built-in syntax/css.vim
cakebaker/scss-syntax.vim Syntax file for scss (Sassy CSS)
othree/html5.vim HTML5 omnicomplete and syntax
plasticboy/vim-markdown Markdown syntax highlighting
rhysd/vim-gfm-syntax GitHub Flavored Markdown syntax highlight extension
pangloss/vim-javascript Enhanced Javascript syntax
heavenshell/vim-jsdoc Generate JSDoc to your JavaScript code
elzr/vim-json Better JSON support
vim-python/python-syntax Enhanced version of the original Python syntax
Vimjas/vim-python-pep8-indent A nicer Python indentation style
vim-jp/syntax-vim-ex Improved Vim syntax highlighting
ekalinin/Dockerfile.vim Syntax and snippets for Dockerfile
tmux-plugins/vim-tmux Plugin for tmux.conf
MTDL9/vim-log-highlighting Syntax highlighting for generic log files
mboughaba/i3config.vim i3 window manager config syntax
jstrater/mpvim Macports portfile configuration files
chr4/nginx.vim Improved nginx syntax and indent
vim-syntastic/syntastic 语法检查
dense-analysis/ale 支持LSP的异步语法检查

Git

jreybert/vimagit 简化Git工作流程
lambdalisue/gina.vim 异部控制Git
airblade/vim-gitgutter 显示和控制Git变更
tpope/vim-fugitive Git plugin for Vim
mattn/vim-gist  管理存储在Gist的代码片段【详细介绍

写作

junegunn/goyo 无干扰(Distraction-free)写作
junegunn/limelight 无干扰(Hyperfocus)写作
reedes/vim-wordy 识别经常被误用的英文单词和短语
mzlogin/vim-markdown-toc 自动生成Markdown目录(TOC)标签
iamcco/markdown-preview.nvim 使用浏览器预览Markdown文件
chrisbra/unicode.vim 输入和查询unicode字符和Digraphs

快速移动

haya14busa/vim-asterisk 增强的*命令
haya14busa/vim-edgemotion 跳转到代码块的边界
easymotion/vim-easymotion 快速移动
terryma/vim-multiple-cursors 多重光标选择

自动完成

othree/csscomplete.vim 增强的CSS自动完成
prabirshrestha/asyncomplete.vim 异步自动完成
prabirshrestha/vim-lsp 异步语言服务器协议插件
mattn/vim-lsp-settings vim-lsp自动配置
ycm-core/YouCompleteMe 代码自动完成

HTML

yyq123/HTML-Editor HTML代码输入和网页预览【详细介绍
alvan/vim-closetag 自动关闭(X)HTML标签
mattn/emmet-vim 类似emmet的HTML代码快速输入

文本对象

wellle/targets.vim 扩展文本对象
kana/vim-operator-user 自定义操作符(operators)
kana/vim-operator-replace 使用寄存器内容进行替换操作
jiangmiao/auto-pairs 自动输入和删除成对出现的括号和引号等
tpope/vim-surround 环绕字符编辑【详细介绍
machakann/vim-sandwich ★ 环绕字符编辑【详细介绍
kana/vim-textobj-user 自定义文本对象
terryma/vim-expand-region 渐进可视化区域选择文本
chrisbra/matchit %命令功能扩展【详细介绍
andymass/vim-matchup %命令功能扩展
AndrewRadev/sideways.vim 匹配函数参数
osyo-manga/vim-textobj-multiblock 处理成对括号
kana/vim-textobj-function 函数相关文本对象

编程辅助

AndrewRadev/splitjoin.vim 拆分/合并行
AndrewRadev/linediff.vim 代码块比较
SirVer/ultisnips 代码片段管理
garbas/vim-snipmate 代码片段管理
honza/vim-snippets 代码片段管理
tyru/caw.vim 注释工具
ludovicchabant/vim-gutentags 管理tag文件
luochen1990/rainbow 多重色彩括号【详细介绍
Rainbow-Parenthsis-Bundle 多重色彩括号【详细介绍
rhysd/devdocs.vim 查询devdocs.io离线文档
rizzatti/dash.vim 查询Dash.app离线文档
KabbAmine/zeavim.vim 查询Zeal离线文档【详细介绍

其它

junegunn/fzf.vim 集成Fzf模糊查询工具
skywind3000/asyncrun.vim 后台异步执行外部命令

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期五, 九月 25, 2020

VIM学习笔记 环绕字符编辑(sandwich)

sandwich 插件可以快速编辑围绕在内容两端的字符(pairs of things surrounding things),比如成对出现的括号、引号,甚至HTML/XML标签等。

sandwich支持vim的文本对象(Text Objects),比如单词、句子和段落等等。同时也支持.重复命令(Dot Command)。

安装配置

推荐您使用vim-plugVundle等插件管理器,来安装GitHub上的sandwich插件。

以下将利用实例来介绍sandwich插件的主要功能,请注意:

  • 在“原始文本”列中,高亮文字表示光标所在位置;
  • 在“命令”列中,为顺序执行的命令序列;
  • 在“更改效果”列中,为命令执行之后的结果。您可以参考实例文件并自行测试。

新增环绕字符

在常规模式和可视化模式下,可以使用sa命令来新增环绕字符:

模式目标
范围
新增
内容
原始文本命令更改效果
常规模式单词字符Hello Worldsaiw*Hello *World*
单词不含标点引号Hello World!saiw'Hello 'World'!
单词包含标点引号Hello World!saiW'Hello 'World!'
单词标签Hello WorldsaiwtstrongHello <strong>World</strong>
单词括号print var1, var2sa3w)print (var1, var2)
行尾括号print var1, var2sa$)print (var1, var2)
查找标签William Shakespeare said,
"Brevity is the soul of wit."
saf"temWilliam Shakespeare said,
<em>"Brevity is the soul of wit."</em>
整行字符Hello World0sa$""Hello World"
整行标签Hello World0sa$tp<p>Hello World</p>
字符可视化模式选中的文本括号print var1, var2veesa)print (var1, var2)
选中的文本标签The passion to save humanity is a
cover for the desire to rule it.
v$jsatp<p>The passion to save humanity is a
cover for the desire to rule it.</p>
行可视化模式整行新行Hello WorldVsa)(
Hello World
)
选中的文本标签
新行
The passion to save humanity is a
cover for the desire to rule it.
Vjsatp<p>
The passion to save humanity is a
cover for the desire to rule it.
</p>
块可视化模式选中的文本标签Item 1
Item 2
Item 3
<Ctrl-Q>$jjsatli<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>

plugin_sandwich_saiwt

从以上屏幕录像中可以看到:

  • 插件提供了友好的视觉反馈。将根据指定的文本对象,自动高亮显示命令将影响的操作范围。例如输入saiw命令时,将高亮显示当前单词;当在可视化模式下操作多行字符时,视觉提示将使用户更加胸有成竹。
  • 命令中的t表示标签,将在屏幕底部显示提示行,在其中输入的标签名称然后按回车键即可(并不需要输入<>);

请注意:

  1. 插入模式下,并没有专门用于输入环绕字符的快捷键。
  2. 可视化模式下的操作:
    • 首先使用快捷键进入不同类型的可视化模式。
      比如在Windows下,使用CTRL-Q键进入块视化模式;
    • 然后使用j等移动命令来选中文本;
    • 最后点击sa键,并输入环绕字符或标签。

修改环绕字符

使用sr命令可以修改环绕字符:

替换内容原始文本命令更改效果注释
引号"Hello World"srb''Hello World'使用标识符b来指代环绕字符
标签'Hello World'srbTp<p>Hello World</p>使用标识符T来输入包含尖括号的完整标签
标签<p>Hello World</p>srtth1<h1>Hello World</h1>使用标识符t来指代尖括号之内的标签名称
标签<h1>Hello World</h1>srT)(Hello World)使用标识符T来指代包含尖括号的完整标签
括号(1,2,3)srb][1,2,3]使用闭括号替换环绕字符
括号及空格(1,2,3)srb[[ 1,2,3 ]使用自定义开括号替换环绕字符并增加间隔空格

从以上sr命令可以看到,并不需要明确指明环绕字符,而可以通过标识符b来指代,既聪明又方便。

随着命令输入,会以高亮显示将被替换的环绕字符,以便在操作之前确认范围是否正确。

plugin_sandwich_srbT

删除环绕字符

使用sd命令可以删除环绕字符:

新增内容原始文本命令更改效果
引号'Hello World'sdbHello World
括号(123+4*56)/2sdb123+4*56/2
标签<div>Hello</div>sdtHello

同样在sd删除命令中,也不需要明确指明环绕字符,而可以通过标识符b来指代,大大减少了命令的复杂度。

HTML标签

假设需要针对以下文本,添加包含多个属性的HTML标签:

Hello World

可以使用以下命令,简化标签的录入:

sa$tp.class1#id1

<p class="class1" id="id1">Hello World</p>

假设需要针对以下文本段落,添加<blockquote>标签:

The passion to save humanity is a
cover for the desire to rule it.

可以使用以下命令,针对整个段落进行操作:

sa}tblockquote

<blockquote>The passion to save humanity is a
cover for the desire to rule it.</blockquote>

自定义快捷键

根据帮助文件,建议在vimrc配置文件中取消当前s键配置:

nmap s <Nop>

xmap s <Nop>

请注意,在日常操作中可以使用cl命令来代替s功能。

如果频繁使用srtt快捷键来修改标签,那么建议映射为较短的srt快捷键:

nmap srt <Plug>(operator-sandwich-replace)<Plug>(textobj-sandwich-query-a)tt

如果希望使用surround风格的快捷键,那么可以参照surround keymappings进行配置。

自定义环绕字符

通过自定义receipe,可以设置用户特有的环绕字符。例如在vimrc文件中增加以下命令,以使用 ( [ { 来指定在括号之后附带一个间隔空格:

" if you have not copied default recipes
let g:sandwich#recipes = deepcopy(g:sandwich#default_recipes)

" add spaces inside bracket
let g:sandwich#recipes += [
      \   {'buns': ['{ ', ' }'], 'nesting': 1, 'match_syntax': 1, 'kind': ['add', 'replace'], 'action': ['add'], 'input': ['{']},
      \   {'buns': ['[ ', ' ]'], 'nesting': 1, 'match_syntax': 1, 'kind': ['add', 'replace'], 'action': ['add'], 'input': ['[']},
      \   {'buns': ['( ', ' )'], 'nesting': 1, 'match_syntax': 1, 'kind': ['add', 'replace'], 'action': ['add'], 'input': ['(']},
      \   {'buns': ['{\s*', '\s*}'],   'nesting': 1, 'regex': 1, 'match_syntax': 1, 'kind': ['delete', 'replace', 'textobj'], 'action': ['delete'], 'input': ['{']},
      \   {'buns': ['\[\s*', '\s*\]'], 'nesting': 1, 'regex': 1, 'match_syntax': 1, 'kind': ['delete', 'replace', 'textobj'], 'action': ['delete'], 'input': ['[']},
      \   {'buns': ['(\s*', '\s*)'],   'nesting': 1, 'regex': 1, 'match_syntax': 1, 'kind': ['delete', 'replace', 'textobj'], 'action': ['delete'], 'input': ['(']},
      \ ]
	

使用:help textobj-sandwich命令,可以查看sandwich文本对象的帮助信息,使用:help operator-sandwich命令,可以查看sandwich操作符的帮助信息。

使用以下命令,可以查看插件的帮助文件:

:help sandwich

使用感受

一,相较surround重新发明一系列新概念,sandwich更多地重用了已经存在的元素,比如Vim的文本对象(Text Objects)重复命令(Dot Command),以此保证操作的一致性,并大大降低学习成本。

二,sandwich提供了非常友好的视觉辅助。对于相隔较远或者多层嵌套的环绕字符,随着命令的输入将会高亮显示被影响的字符,这使用户在执行操作之前,能有机会确认命令执行范围是否准确。

我个人更喜欢sandwich的举重若轻,而不是surround的举轻若重。此诚为一家之言,还请自行斟酌。

命令小结
sa添加环绕字符
sr修改环绕字符
sd删除环绕字符

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期三, 九月 16, 2020

VIM学习笔记 匹配成对字符(Match Pairs)

motion_Ninja
Originally from Practical Vim by Drew Neal

'matchpairs'选项

matchpairs选项,用来控制哪些字符可以通过%命令进行匹配。此选项的默认值如下:

:set matchpairs=(:),{:},[:]

也就是说,在开括号“(,{,[”上点击%键,将会自动跳转到对应的闭括号“),},]”上;同理,在闭括号上点击%键,也会跳转回到对应的开括号上;同时,匹配跳转也能够正确处理括号嵌套的情况。

如果当前光标下并非括号,那么点击%键,将自动在本行内向前查找并定位到括号之上。

matchit-vim-example
Source: https://catonmat.net/vim-plugins-matchit-vim

如果需要新增匹配类型,例如增加对于HTML文件中的尖括号的匹配,那么可以使用以下命令:

:set mps+=<:>

利用自动命令(autocmd),可以针对特定文件类型设置匹配字符。例如针对C和Java代码,增加对于“=”和“;”的匹配:

:au FileType c,cpp,java set mps+==:;

'showmatch'选项

如果希望在输入闭括号时,短暂地跳转到与之匹配的开括号,那么可以设置以下选项:

:set showmatch

'matchtime'选项

'matchtime'选项,用于控制显示配对括号的时间,其单位为0.1秒,默认值为5,即0.5秒。

如果希望持续显示配对括号1.5秒,那么可以使用以下命令:

:set matchtime=15

matchit插件

matchit插件扩展了%命令的功能,支持if/else/endif语法结构;支持HTML标签。使用:help matchit-languages命令,可以查看当前支持的所有语言列表。

从Vim 6.0开始,matchit插件伴随vim发行,内置于$VIMRUNTIME\pack\dist\opt\matchit目录中,并不需要单独安装。

vimrc配置文件中增加以下命令,可以启用matchit插件:

packadd! matchit

在HTML标签中,点击%键,将移动到关闭标签上:

matchit-vim-example
Source: https://catonmat.net/vim-plugins-matchit-vim

使用以下命令,可以查看更多帮助信息:

:help matchit

命令小结
%跳转到匹配字符
:set matchpairs设置形成配对的字符
:set showmatch设置是否短暂跳转到匹配括号
:set matchtime设置显示配对括号的时间长度

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期一, 八月 10, 2020

VIM学习笔记 在文本对象间移动(motion-object)

motion_Ninja
 Originally from Practical Vim by Drew Neal

使用以下命令,可以按照文本对象(Text Objects)为单位来快速移动;同时,对于浏览C、Java代码和HTML、Markdown等标签语言文档,也更加友好和高效。当然,以下命令也接受[count]参数,以跳转多个对象。

按文本对象移动

对象命令描述
句子(反向一个句子
)正向一个句子
段落{反向一个段落
}正向一个段落
小节]]正向一个小节或到后一个出现在首列的 '{'
][一个小节或到后一个出现在首列的 '}'
[[反向一个小节或到前一个出现在首列的 '{'
[]反向一个小节或到前一个出现在首列的 '}'

句子(sentence),是以 '.'、'!' 或者 '?' 结尾并紧随着一个换行符、空格或者制表符。结束标点和空白字符之间可以出现任何数量的闭括号和引号: ')'、']'、'"' 和 '''。段落和小节的边界也视为句子的边界。

段落(paragraph),是以每个空行或段落宏命令开始,段落宏由 'paragraphs' 选项里成对出现的字符所定义。它的缺省值为 "IPLPPPQPP TPHPLIPpLpItpplpipbp",也就是宏 ".IP"、".LP"等 (这些是 nroff 宏,所以句号一定要出现在第一列)。小节边界也被视为段落边界。注意,空白行不是段落边界。

小节(section),是以每个首列出现的换页符(<C-L>,<FF>)或小节宏命令开始。小节宏由 'sections' 选项里成对出现的字符所定义。它的缺省值是 "SHNHH HUnhsh",也就是宏 ".SH"、".NH"、".H"、".HU"、".nh" 和 ".sh"。

按其他对象移动

对象命令描述
括号[{反向第一个的未匹配的 '{'
]{正向第一个的未匹配的 '{'
[}反向第一个的未匹配的 '}'
]}正向第一个的未匹配的 '}'
[(反向第一个的未匹配的 '('
](正向第一个的未匹配的 '('
[)反向第一个的未匹配的 ')'
])正向第一个的未匹配的 ')'
方法
(method)
[m反向第一个方法的开始处
[M反向第一个方法的结束处
]m正向第一个方法的开始处
]M正向第一个方法的结束处
#if #else
#endif
[#反向第一个未匹配的 "#if" 或 "#else"
]#正向第一个未匹配的 "#else" 或 "#endif"
注释[*反向第一个注释的开始 "/*"
[/
]*正向第一个注释的结束 "*/"
]/

操作实例

如果感觉以上介绍云山雾罩,那么不妨对照以下操作实例,请注意:

  • 绿色,标志光标初始位置;
  • 红色,标志光标移动到的目的位置;
  • 橙色,标志光标移动的轨迹;
  • 图片来源于of-vim-and-vigor.blogspot.com

motion_large_objects

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期五, 七月 31, 2020

VIM学习笔记 Zeavim离线文档查看器

Zeal是开源的跨平台软件,用于离线浏览各种开发文档。Zeal使用Dash提供的文档集(Docsets),涵盖近200种开发语言。

Zeavim插件,可以在Vim中调用Zeal来查看离线文档。

安装配置

推荐您使用vim-plugVundle等插件管理器,来安装GitHub上的Zeavim插件。

建议vimrc配置文件中增加以下设置,以利用前缀键(leader)来调用Zeavim功能:

nmap <leader>z <Plug>Zeavim
vmap <leader>z <Plug>ZVVisSelection
nmap gz <Plug>ZVOperator
nmap <leader><leader>z <Plug>ZVKeyDocset

查询文档

使用<leader>z快捷键或:Zeavim命令,将根据当前文件类型在相应的Docset中,查找当前光标下的单词:

plugin_zeavim_leaderZ

使用gz命令,将根据当前文件类型在相应的Docset中,查找文本对象指定的关键词。例如在Vim脚本文件中,使用gziw命令,将在Vim Docset中查找当前光标下的单词:

Zeavim

使用<leader><leader>z快捷键或:Zeavim!命令,将根据用户输入,在指定的Docset中,查找指定的关键词:

Zeavim

使用以下命令,可以查看插件的帮助文件:

:help zeavim

使用命令行调用Zeal

如果不希望安装额外的插件,那么也可以用"zeal docset:keyword"的形式直接调用Zeal命令行。例如以下命令,将在Vim文档中查找关键字"endif":

:!zeal vim:endif

定义以下快捷键,将根据当前文件类型在相应的Docset中,查找当前光标下的单词:

:nnoremap <Leader>z :exec "!zeal " . expand(&ft) . ":" . "<cword>"<CR>

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期五, 七月 24, 2020

VIM学习笔记 重定向(redir)

重定向到文件

使用以下命令,在将信息输出到屏幕的同时,也会保存到指定的文件中:

:redir > {file}

如果指定的文件以及存在,那么需要使用!参数进行强制覆盖:

:redir! > {file}

如果希望信息被追加到文件末尾,那么可以使用以下命令:

:redir >> {file}

假设需要查询大量的信息输出(例如:version命令),或者保存调试信息,那么信息重定向就会非常有价值。

使用以下命令,可以停止信息的重定向:

:redir END

重定向到寄存器

我们可以将信息输出重定至寄存器之中,比如剪贴板寄存器(+)、命名寄存器(a-z,A-Z)和未命名寄存器(")。

使用以下命令,可以将信息输出重定向至剪贴板寄存器:

:redir @+

这样您就可以使用"+p命令, 将信息输出粘贴到当前文本。

使用以下命令,可以将命令历史记录粘贴到当前文件中:

:redir @+
:set nomore
:history
:put +
:set more
:redir END

其中,:set nomore命令用于暂定显示“--More--”信息,否则在分页显示命令历史记录时,需要点击按键以继续下一页的显示。

使用以下命令,可以查看更多帮助信息:

:help :redir

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期五, 七月 17, 2020

VIM学习笔记 信息(message)

Vim将默认记录近200次的信息显示。

查看信息

使用以下命令,可以查看上一个命令的输出信息:

g<

使用以下命令,在显示信息的同时,也会将其存储在信息历史(message-history)之中:

:echom "Hello World"

使用以下命令,可以查看所有信息:

:messages

而使用以下命令,则可以查看最近一条报错信息(error-messages):

:echo errmsg

E16: Invalid range

清除信息

7.4.1735版本开始,可以使用以下命令清除信息历史:

:messages clear

信息语言

使用以下命令,可以查看显示信息的语言:

:language message

通过以下变量,也可以查看显示信息的语言:

:echo LC_MESSAGES

在vimrc文件中使用以下命令,可以指定信息使用中文显示:

:language message zh_CN.UTF-8

建议使用英文显示信息,以便在互联网上进行查找相关资源:

:language message en_US.UTF-8

使用以下命令,可以查看更多帮助信息:

:help :messages

'shortmess'选项

'shortmess'选项,用于控制信息显示的种类和详细程度。其默认值为:

:set shormess=filnxtToOS

以下为主要标志位的含义(灰色行为默认值中的标志位):

标志位存在时的意义
f用 "(3 of 5)" 代替 "(file 3 of 5)"
i用 "[noeol]" 代替 "[Incomplete last line]"
l用 "999L, 888C" 代替 "999 lines, 888 characters"
m用 "[+]" 代替 "[Modified]"
n用 "[New]" 代替 "[New File]"
r用 "[RO]" 代替 "[readonly]"
w用 "[w]" 代替文件写入消息的 "written";
用 "[a]" 代替 ':w >> file' 命令的 "appended"
x用 "[dos]" 代替 "[dos format]";
用 "[unix]" 代替 "[unix format]";
还有用 "[mac]" 代替 "[mac format]"
a所有以上的缩写
t如果文件消息不能完整显示,则从开头截短该消息。最左列给出"<"。
T如果其它消息不能完整显示,则从中间截短该消息。中间给出"<"。
o后续文件的读入信息覆盖文件的写回消息 (:wn或打开autowrite时有用)
O文件的读入信息覆盖任何前面消息,包括快速修复消息 (比如,":cn")
s不显示 "search hit BOTTOM, continuing at TOP";
不显示 "search hit TOP, continuing at BOTTOM";
使用搜索计数时不在计数信息后显示 "W" (见下 S)
S搜索时不显示搜索计数,如 "[1/5]"

如果不希望使用信息缩写,那么可以使用以下命令:

:set shm=

如果希望使用缩写,但不截短信息,那么可以使用以下命令:

:set shm=a

如果希望使用缩写,并在必要时截短信息,那么可以使用以下命令:

:set shm=at

8.1.1270版本开始,在vimrc配置文件中增加以下设置,可以在屏幕底部,显示匹配搜索结果的总数,以及当前所处第几个匹配结果:

set shortmess-=S

使用以下命令,可以查看更多帮助信息:

:help 'shortmess'

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期四, 七月 09, 2020

VIM学习笔记 环绕字符编辑(surround)

surround 插件可以快速编辑围绕在内容两端的字符(pairs of things surrounding things),比如成对出现的括号、引号,甚至HTML/XML标签等。

安装配置

推荐您使用vim-plugVundle等插件管理器,来安装GitHub上的surround插件。

以下将利用实例来介绍surround插件的主要功能,请注意:

  • 在“原始文本”列中,高亮文字表示光标所在位置;
  • 在“命令”列中,为顺序执行的命令序列。
  • 在“更改效果”列中,为命令执行之后的结果。您可以实例文件并自行测试。

新增环绕字符

在常规模式、插入模式和可视化模式下,可以分别使用ysS命令来新增环绕字符:

模式目标
范围
新增
内容
原始文本命令更改效果
常规模式单词字符Hello Worldysiw*Hello *World*
单词标签Hello Worldysiwt<strong>Hello <strong>World</strong>
单词括号print var1, var2ys3w)print (var1, var2)
行尾括号print var1, var2ys$)print (var1, var2)
查找标签William Shakespeare said,
"Brevity is the soul of wit."
ysf"t<em>William Shakespeare said,
<em>"Brevity is the soul of wit."</em>
整行字符Hello Worldyss""Hello World"
整行标签Hello Worldysst<p><p>Hello World</p>
整行新行Hello WorldySS""
Hello World
"
插入模式引号<CTRL-g>s"""
标签<CTRL-g>S<html><html>

</html>
字符可视化模式选中的文本括号print var1, var2veeS)print (var1, var2)
行可视化模式选中的文本标签The passion to save humanity is a
cover for the desire to rule it.
VjS<p><p>The passion to save humanity is a
cover for the desire to rule it.</p>
块可视化模式选中的文本标签Item 1
Item 2
Item 3
<Ctrl-Q>$jjS<li><li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>

请注意:

  1. 插入模式下的操作:
    • 首先同时按下CTRL-g键;
    • 然后松开CTRL键;
    • 最后点击sS键,并输入环绕字符或标签。
  2. 可视化模式下的操作:
    • 首先使用快捷键进入不同类型的可视化模式。
      比如在Windows下,使用CTRL-Q键进入块视化模式;
    • 然后使用j等移动命令来选中文本;
    • 最后点击S键,并输入环绕字符或标签。

修改环绕字符

使用cs命令可以修改环绕字符:

目标范围替换内容原始文本命令更改效果
单词引号"Hello World"cs"''Hello World'
单词标签及新行'Hello World'cS'<p><p>
Hello World
</p>
单词标签<p>Hello World</p>cst<h1><h1>Hello World</h1>
单词引号Hello World!csw'Hello 'World'!
单词及标点引号Hello World!csW'Hello 'World!'
单词括号(1,2,3)cs)][1,2,3]
单词括号及空格(1,2,3)cs)[[ 1,2,3 ]

删除环绕字符

使用ds命令可以删除环绕字符:

目标范围新增内容原始文本命令更改效果
单词引号'Hello World'ds'Hello World
单词括号(123+4*56)/2ds(123+4*56/2
单词标签<div>Hello</div>dstHello

surround插件主要提供以下命令:

命令小结
ys添加环绕字符
yS添加环绕字符并拆分新行
yss为整行添加环绕字符
ySS为整行添加环绕字符并拆分新行
cs修改环绕字符
cS修改环绕字符并拆分新行
ds删除环绕字符

surround插件可以识别并处理以下目标实体:

  • ( )
  • { }
  • [ ]
  • < >
  • `
  • "
  • '
  • t(标签)
  • w(单词)

自定义快捷键

如果查看surround插件的源码,将会发现快捷键逐一定义在surround.vim文件中:

plugin_vim_searchindex

也就是说,我们可以直接在vimrc配置文件中,重置或取消插件预定义的快捷键:

" 不定义任何快捷键
let g:surround_no_mappings = 1
" 从plugin/surround.vim复制快捷键定义
” 并按需要进行修改
nmap ds <Plug>Dsurround
nmap cs <Plug>Csurround
nmap cS <Plug>CSurround
nmap ys <Plug>Ysurround
nmap yS <Plug>YSurround
nmap yss <Plug>Yssurround
nmap ySs <Plug>YSsurround
nmap ySS <Plug>YSsurround
" 取消不需要的快捷键
"xmap S   <Plug>VSurround
"xmap gS  <Plug>VgSurround
"imap   <C-S> <Plug>Isurround
imap    <C-G>s <Plug>Isurround
imap    <C-G>S <Plug>ISurround

假设需要输入以下包含多个环绕字符的文本:

{{ nginx_root }}

由于surround插件并不支持.重复命令,如果想要新增多个成对字符,那么需要安装额外的repeat.vim插件。而死板繁琐的替代方案是,自定义快捷键来重复执行命令:

nmap <C-J> ysiw}lysiw{

使用以下命令,可以查看插件的帮助文件:

:help surround

使用感受

一,舍本逐末。为了输入环绕字符的小需求,而发明碾压一切的大轮子。颇有些杀鸡用牛刀的意味。而且平白多出来的快捷键和命令,不但冗长而且别扭,操作起来总有种有苦难言的感觉。

二,盛名之下,其实难副。对于一个被不断被提及的知名插件,从功能和体验上都差强人意,着实让人失望。也许,这就是见面不如闻名吧。

以上,皆为一家之言,还请自行斟酌。

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期日, 六月 28, 2020

VIM学习笔记 模式行(Modeline)

程序员对于制表符常常有不同的偏好,有的使用8个空格,而有的则使用4个空格。可以想见,如果使用不同设置的用户操作相同的文件,必将对文本格式造成影响。

如果希望针对特定文件应用特定的设置,那么修改全局性的vimrc配置文件就显得小题大做了;而使用模式行(modeline),则可以将选项设置配置在文件本身当中。

例如将以下模式行放置到文件开头,将在打开该文件时设置制表符为4个空格:

/* vim:set tabstop=4: */

启用模式行

默认设置下,‘modeline’选项是打开的,Vim将会在文件的开头5行和结尾5行中查找模式行:

:set modeline

如果希望改变扫描的行数,那么可以设置‘modelines’选项:

:set modelines=1

定义以下快捷键,可以启用模式行并自动应用到当前文件,而不需要重新打开文件:

:nnoremap <leader>ml :setlocal invmodeline <bar> doautocmd BufRead<cr>

模式行主要有以下两种格式:

(1)不包含set命令的格式

  • [text{white}]{vi:|vim:|ex:}[white]{options}
  • 模式行将持续到行尾处结束;
  • 选项之间不能包含空格。

以下为正确的模式行:

/* vim:tabstop=4:expandtabs:shiftwidth=4 */

以下模式行选项中包含空格,将报错“Error E518: Unknown option: */”:

/* vim: noai:ts=4:sw=4 */

(2)包含set命令的格式

  • [text{white}]{vi:|vim:|Vim:|ex:}[white]se[t] {options}:[text]
  • 模式行将在第二个“:”处结束;
  • 模式行的开头和结尾可放置任意字符,建议使用“/* */”;
  • 开头字符之后的空格为必需的分隔符,不可以省略;
  • 选项之间以空格分隔。

以下为正确的模式行:

/* vim: set ai tw=75: */

以下模式行开头字符之后缺少空格,将无法生效,但不会报错:

/*vim: set tabstop=4: */

模式行实例

在Vim帮助文件的末尾,将发现以下模式行:

vim:tw=78:ts=8:noet:ft=help:norl:

其中,tw(textwidth)选项设置最大文本宽度为78;ts(tabstop)选项设置制表符为8个空格;noet(noexpandtab)选项设置为不扩展制表符;ft(filetype)选项设置文件类型为help;norl(norightleft)选项设置文本从左向右显示。

在Apache配置文件中,包含以下模式行:

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

其中,"#"标记本行为注释;syntax选项设置语法为apache;sw(shiftwidth)选项设置缩进为4个字符;sts(softtabstop)选项设置插入Tab时算作4个空格;sr(shiftround)选项设置缩进取整到'shiftwidth'的倍数。

通过使用模式行,可以确保文本被按照正确的格式展示,而不受本地设置的干扰。

禁用模式行

使用以下设置,Vim将不会查找模式行:

:set nomodeline

帮助信息

使用以下命令,可以查看当前设置:

:verbose set modeline? modelines?

使用以下命令,可以查看帮助信息:

:help 'modeline'

:help 'modelines'

命令小结
:set modeline启用模式行
:set modelines设置检查模式行的行数

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期六, 六月 20, 2020

VIM学习笔记 正则表达式-实例(Regex-Examples)

匹配空格

♦ 删除所有行首的空格:

:%s/^□□*\(.*\)/\1/

其中,使用^□□*查找行首的一个或多个空格;而\(.*\)将行中的其它内容捕获为组;在替换部分使用\1来恢复捕获组。

♦ 删除所有行尾的空格:

:%s/\(.*\)□□*$/\1/

其中,使用□□*$查找行尾的一个或多个空格;而\(.*\)将行中的其它内容捕获为组;在替换部分使用\1来恢复捕获组。

♦ 将多个空格替换为一个空格:

:%s/□□*/□/g

其中,第一个□代表一个实际的空格,而□*则会匹配零个或多个空格。

♦ 将冒号或句点之后的多个空格,替换为一个空格:

:%s/\([:.]\)□□*/\1□/g

其中,方括号内的的特殊字符(比如.)并不需要转义。

请在实际使用以上命令时,将其中“□”的替换为空格“ ”。

匹配换行

♦ 如果想要查找的内容之中包含换行符,那么可以使用"\n"通配符。执行以下命令,将匹配以"the"结尾的行,和以"word"开头的下一行:

/the\nword

♦ 如果希望同时匹配包含换行,以及不包含换行(但包含一个空格)的"the word",那么可以使用"\_s"匹配空格或换行:

/the\_sword

♦ 如果希望同时匹配包含多个空格以及换行的"the word",那么可以使用"+"通配符来匹配一次或多次:

/the\_s\+word

Regex_example_the_word

关于删除换行和空行,请参阅换行(Line Feed)章节。

匹配单复数

♦ 将单数单词,替换为复数:

:%s/^Note[□:s]*/Notes:□/g

其中,"Note[□:s]"将匹配"Note□","Notes", 和"Note:";而星号则会匹配零个后缀,即"Note"。

Regex-Examples-Singular

匹配包围的字符串

♦ 匹配引号包围的字符串(包含换行):

"\_[^"]*"

♦ 匹配特定单词包围的字符串(包含换行):

\(we\).*\1

其中,"\(we\)"将指定单词捕获为组,然后使用"\1"反向引用捕获组,以定义字符串的边界。

关于捕获组的详细介绍,请参阅捕获组(Groups)章节。

匹配章节编号

♦ 删除下图中黄色高亮区域,即行头以点分隔的章节号:

:%s/^[1-9][0-9]*\.[1-9][0-9.]*□//

Regex_example_remove_section_headings

其中,模式末尾的"[0-9.]*"可以继续匹配更多层级的章节号。

匹配序列号

♦ 匹配最少3个字符,最多16个字符,由字母和数字组成的用户名:

^[a-zA-Z0-9_-]{3,16}$

♦ 查找类似“1MGU103”的序列号。即由1个数字,3个大写字符和3个数字组成的字符串。可以使用以下几种不同的模式:

[0-9][A-Z]{3}[0-9]{3}

\d\u{3}\d{3}

\d\u\u\u\d\d\d

[[:digit:]][[:upper:]]{3}[[:digit:]]{3}

其中:

  • "[0-9]","\d","[:digit:]",均可匹配数字;
  • "[A-Z]","\u","[:upper:]",均可匹配大写字母;
  • "{3}",用于精确匹配3次。

Regex_example_serial_number

请注意,以上表达式均采用Very Magic模式。

匹配IP地址

♦ 匹配IPv4网络地址。即从"0.0.0.0"到"999.999.999.999"范围内的,以点分割的四段数字。

/\v([0-9]{1,3}[\.]){3}[0-9]{1,3}

但是以上命令,并不会判断数字串是否是一个有效的IP地址。比如"256.60.124.136"也会被匹配。但有效的IP地址中,每段数字均应为"0-255"。

♦ 匹配有效的IP地址。

/\v(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

Regex_example_ipv4

以上表达式分为四段重复的捕获组,每组数字的范围如下图所示:

Regex_example_ipv4_group

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期日, 六月 14, 2020

VIM学习笔记 正则表达式-(vimgrep/grep)

在UNIX问世的前一年,1969年,Ken Thompson将正则表达式整合入QED文本编辑器。在Linux文本编辑器ed中,如果你希望显示包含字母“re”的行时,需要使用命令g/re/p,而grep也因此得名。可以看作此操作的缩写:g (globally), / (search), re (regular expression), / (delimit search), p (print)。

Vim提供以下两种grep(globally search a regular expression and print)搜索工具:

  • :vimgrep 使用Vim内置的grep实现;
  • :grep 调用外部的grep工具。

:grep命令会运行由选项grepprg所指定的程序。在Linux系统上,grepprg默认是grep -n:

grep_linux

在Windows系统上,grepprg默认是findstr /n

findstr

:vimgrep命令使用vim内置的搜索引擎,与/命令功能一致,但速度相对较慢。

由此可见,使用:vimgrep命令在不同平台上将获得一致的体验。而:grep命令则是与操作系统相关的,在不同平台会有不同的行为。

:grep:vimgrep命令,都将在QuickFix中显示搜索结果。

:lgrep:lvimgrep命令实现相同的功能,但使用地址列表(Location List)来显示匹配结果。

使用:copen命令打开的Quickfix,是全局性的。而使用:lopen打开的Location List,则是独立存在于各个窗口中的。

对于Quickfix,使用:cp命令,跳转到上一个匹配处;使用:cn命令,跳转到下一个匹配处。

对于Location List,使用:lpre命令,跳转到上一个匹配处;使用:lnext命令,跳转到下一个匹配处。

:vimgrep

使用以下命令,可以在当前目录下查找指定字符串:

:vimgrep grep *

如果希望在当前目录及其子目录中进行查找,那么可以使用**通配符:

:vimgrep blue **

以下命令将在当前目录及其子目录中的所有HTML文件中,查找指定字符串:

:vim blue **/*.html

请注意,:vimgrep命令可以缩写为:vim

首先在常规模式下,使用*命令查找光标下的单词;然后使用以下命令,可以重用之前的查找:

:vim // *.html

默认情况下,将自动跳转至第一个匹配处;如果希望停留在当前位置,那么可以在命令中使用j参选:

:vimgrep /foo/j **/*.md

使用以下命令,可以查看更多帮助信息:

:help :vimgrep

:grep

使用以下命令,将在当前目录下查找所有文件:

:grep block *.*

默认情况下,grep是区分大小写的,可以使用-i选项来忽略大小写:

:grep -i word filename

使用-o选项,将只显示匹配的字符,而不是整行内容:

:grep -o [[:punct:]] filename

使用以下命令,可以查看更多帮助信息:

:help :grep

请注意,递归搜索子目录的 **/*.* 通配符,对于Linux下的:vimgrep和:grep命令有效;但对于Windows下的:grep命令不起作用。

'grepprg'选项

使用以下命令,可以查看'grepprg'选项的当前设置:

:set grepprg?

在不同的操作系统下,Vim将默认使用不同的外部grep工具:

  • 在Windows下
    grepprg=findstr /n
  • 在Linux下
    grepprg=grep -n $* /dev/null

如果希望默认查询当前目录以及其子目录,那么可以使用以下设置:

  • 在Windows下
    set grepprg=findstr /S /n
  • 在Linux下
    set grepprg=grep -nR $* /dev/null

请注意,您可以使用:pwd命令来查看当前目录。

如果您在Windows中已经安装了GitCygwin,那么只需要在环境变量PATH中增加相应目录,即可调用其自带的grep命令:

  • C:\Program Files\Git\usr\bin
  • D:\cygwin64\bin

在Windows命令行中,可以使用以下命令进行验证:

$ grep --version

grep_version_win

然后在vimrc配置文件中,使用以下设置:

set grepprg=grep\ -rnIH\ --exclude-dir=.git

通过以上设置,可以在Windows环境中使用Linux风格的grep程序。

帮助信息

使用以下命令,可以查看更多帮助信息:

:help 'grepprg'

:help pattern

关于正则表达式的更多信息,可以参考以下网站:

使用以下网站,可以视觉化正则表达式,以便分步理解复杂的表达式:

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期日, 六月 07, 2020

VIM学习笔记 增减数值(CTRL-A/CTRL-X)

常规模式下的CTRL-A/CTRL-X

Vim可以对文本进行简单的算术运算。在常规模式下,使用CTRL-A快捷键,可以将当前光标下的数字加1;使用CTRL-X快捷键,可以将当前光标下的数字减1。

通过在命令之前指定次数,可以增加或减少指定的数字。例如当前光标下数字为1,依次输入5Ctrl-A,数字将变为6(=1+5)。

如果在当前光标下未发现数值,那么将继续在本行内向后查找并执行增减操作。

使用以下命令,可以查看相关帮助信息:

:help CTRL-A

其它模式下的CTRL-A/CTRL-X

自Vim8以后,在可视化模式和选择模式下,也可以使用CTRL-ACTRL-X来增减数值(:help new-items-8)。

例如希望在第1条之后插入一个新的条目,那么就意味着需要调整后续各个条目的序号:

Article 1: 3 Steps To Enable Thesaurus Option
Article 2: Steps to Add Custom Header
Article 3: Automatic Word Completion
Article 4: How To Record and Play Macro
Article 5: Make Vim as Your C IDE

进入可视化模式,或者直接选择2-5行,然后点击CTRL-A即可对选中各行中的序号分别加1:

Article 1: 3 Steps To Enable Thesaurus Option
Article 3: Steps to Add Custom Header
Article 4: Automatic Word Completion
Article 5: How To Record and Play Macro
Article 6: Make Vim as Your C ID

在命令行中执行CTRL-A,也可以将第2行及之后各行中的序号分别加1:

:2,$g/\d\+/exe "normal! \<C-a>"

另外,您也可以使用替换字符串中的submatch()功能,实现相同的效果。

使用以下命令,可以查看相关帮助信息:

:help v_CTRL-A

'nrformats'选项

'nrformats'选项,用于控制CTRL-A和CTRL-X所识别的数字格式。

使用以下默认设置,Vim可以正确识别二进制和十六进制数;而十进制数,在所有设置下都可以被正确识别:

:set nrformats=bin,hex

使用以下命令清空选项,将所有数字识别为十进制:

:set nrformats=

如果希望只识别八进制数,那么可以使用以下命令:

:set nrformats=octal

如果在选项中增加"alpha",那么也可以选择上一个和下一个字母:

:set nrformats+=alpha

以下表格,列示了针对“原始值”,分别点击CTRL-ACTRL-X所产生的效果:

选项值CTRL-X原始值CTRL-A说明
十进制012以1-9开头的数值
-2-10
二进制bin0b01110b10000b1001以"0b"或"0B"开头的数值
八进制octal006007010以0开头的数值
十六进制hex0x0ff0x1000x101以"0x"或"0X"开头的数值
字母alphaBCD
AAB针对第一个字母"A"执行CTRL-X无作用
YZZ针对最后一个字母"Z"执行CTRL-A无作用

使用以下命令,可以查看相关帮助信息:

:help 'nrformats'

自定义CTRL-A/CTRL-X键盘映射

在Windows下的Vim中,使用以下命令可以看到vimrc自动加载了mswin.vim文件,CTRL-A已经被映射为选择全部,而CTRL-X则被映射为剪切:

:verbose map <C-a>

verbose_map_CTRL-A

使用以下命令,可以取消针对CTRL-A的键盘映射,以恢复其增加数值的功能:

:unmap <C-a>

如果希望保留当前Windows习惯的键盘映射,那么可以新增以下基于前缀键(leader)的定义:

:vnoremap <leader>a <C-a>

:vnoremap <leader>x <C-x>

命令小结
CTRL-A增加数值
CTRL-X减少数值
:set nrformats控制CTRL-A和CTRL-X所识别的数字格式

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期三, 五月 27, 2020

VIM学习笔记 工具箱-大写锁定键(Caps)映射为Esc

今天要处理一起拆迁事件 — 把地处黄金地段的大写锁定键Caps Lock更换为Esc键。

至于,为什么地处偏僻的Esc被时常造访,而位置绝佳的Caps Lock却长期空置?根据考古发现,很可能是由于远古程序员使用了以下布局的祖传键盘:

keyboard_esc

Windows

下载并安装Microsoft PowerToys;在“Keyboard Manager”设置中,点击“Remap a key”,然后将Caps Lock映射为Esc

Caps2Esc_Win_PowerToys

如果您不需要PowerToys提供的窗口管理、批量重命名和快速应用启动等众多功能,那么可以下载Uncap;它没有任何图形界面,只需要后台运行单一的“uncap.exe”文件,即可将Caps Lock映射为Esc

如果需要在系统启动时自动完成键盘映射,那么可以在Windows注册表的以下节点中增加启动项:

Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

Caps2Esc_Win_Uncap

Linux

下载并安装GNOME Tweak tool;在“Keyboard & Mouse”设置中,点击“Additional Layout Options”;在“Caps Lock behavior”列表中选择“Caps Lock an additionnal Esc”。

Caps2Esc_Linux_GnomeTweakTool

Mac

打开“系统偏好设置”,进入“键盘”选项,点击“修饰键...”按钮,将大写锁定键的行为更改为Escape

Caps2Esc_Mac_Keyboard

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期日, 五月 24, 2020

VIM学习笔记 4种Magic模式

根据对于特殊元字符的不同解释方式,Vim正则表达式可以分为四种模式:magic,no magic,very magic和very nomagic。

  • magic模式,使用\m前缀,其后模式的解释方式为'magic'选项。^$.*[]等字符含有特殊意义;而+?()、和{}等其它字符则按字面意义解释。magic为默认设置,表达式中的\m前缀可以省略;
  • no magic模式,使用\M前缀,其后模式的解释方式为'nomagic'选项。除了^$之外的特殊字符,都将被视为普通文本;
  • very magic模式,使用\v前缀,其后模式中除 '0'-'9','a'-'z','A'-'Z' 和 '_' 之外的字符都当作特殊字符解释;
  • very nomagic模式,使用\V前缀,其后模式中只有反斜杠(\)具有特殊意义。

不同模式之间的区别,在于哪些特殊字符需要使用反斜杠(\)进行转义。例如星号(*),在magic和very magic模式下视为特殊修饰符;而在no magic和very nomagic模式下则被视为普通字符,必须使用“\*”恢复其特殊作用。

对于简单的正则表达式,使用“\”对特殊字符进行转义,可能并不会造成困扰;但在复杂的正则表达式中,对大量特殊字符的重复转义,将使得表达式过于繁琐且难以阅读。

例如在默认的magic模式下,使用以下命令查找十六进制色彩值。其中,使用()构建捕获组;使用{}匹配6位和3位十六进制值。因为有多种特殊字符需要进行转义,造成表达式过于冗长:

/\m#\(\x\{6\}\|\x\{3\}\)

而使用very magic模式,则可以简化表达式:

/\v#(\x{6}|\x{3})

4种Magic模式的差异和用法,可以简单总结如下:

模式前缀特殊字符示例适用场景
magic\m^$.*[]匹配每行中的任意内容/^.*$默认模式
nomagic\M^$/\M^\.\*$查找字符串中包含特殊字符
very magic\v除'0-9','a-z','A-Z','_'之外匹配十六进制色彩值/\v#(\x{6}|\x{3})使用较多特殊字符的复杂正则表达式
very nomagic\V\匹配正则表达式本身/\V^.*$进行精确的完整匹配
查找字符串中包含特殊字符

以下表格,列示了常用特殊字符在不同模式下的应用。其中,黄色高亮表示为特殊字符,而不需要转义:

very magicmagicnomagicvery nomagic用途
\v\m\M\V
^^^\^匹配行首
$$$\$匹配行尾
..\.\.匹配任何字符
**\*\*匹配任意次数
~~\~\~最近替代字符串
[][]\[]\[]匹配列表范围内的字符
{}\{\}\{\}\{\}匹配重复次数
()\(\)\(\)\(\)匹配组
<>\<\>\<\>\<\>匹配词首与词尾
+\+\+\+匹配一次或多次
?\?\?\?匹配零次或一次
|\|\|\|可选分支
\a\a\a\a字母字符
其它特殊字符元素
\\\\\\\\反斜杠 (字面意义)

magic默认模式

建议始终将'magic'选项保持在缺省值。

建议在模式之前,通过使用“\v“或“\M“等前缀,来明确激活特定模式。

如果希望始终使用Very magic模式,那么请在vimrc中定义以下键盘映射,将在查找和替换时自动激活very magic模式:

nnoremap / /\v
vnoremap / /\v
cnoremap %s/ %s/\v
nnoremap :g/ :g/\v

模式转换

你甚至可以在表达式当中改变模式。例如以下命令,开头使用very magic模式,之后转换为magic模式,整体表达式将匹配“foo(bar)”:

/\vfoo\(\mbar)

当然,非常不建议采用此种易引起误解的表达式写法。我们可以将其改写为very nomagic模式:

/\Vfoo(bar)

请使用以下命令,查看更多帮助信息:

:help /magic

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期六, 五月 16, 2020

VIM学习笔记 正则表达式(Regex-VeryMagic)

假设希望在以下CSS代码中,查找所有颜色代码:

body { color: #3c3c3c; }
strong { color: #000; }

在默认的Magic模式下,使用以下命令可以匹配以“#”开头的十六进制色彩值:

/#\([0-9a-fA-F]\{6}\|[0-9a-fA-F]\{3}\)

在以上正则表达式中,[]用于指定可选字符范围,但不需要转义;()用于构建捕获组(Groups),需要使用\进行转义;{}用于指定重复次数,但只需要对开括号进行转义,与之对应的闭括号可以不用转义。由此可见,在Magic模式下,需要对很多特殊符号进行转义,而且转义的方式也欠缺一致性。在编写较复杂的正则表达式时,显得琐碎且难以阅读。

使用\v激活Very Magic模式,则可简化为更加友好的正则表达式:

/\v#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})

body { color: #3c3c3c; }
strong { color: #000; }

Very magic

在模式开头使用\v激活very magic模式,其后除下划线(_)、大小写字母以及数字之外的所有字符都具有特殊含义。这样可以避免重复输入大量的转义符(\),也使得正则表达式更加清晰易读。

假设在以下文本中,希望搜索单引号包围的内容:

you have mocking some 'bird of the year'.
you have mocking some 'the year's bird'.

在默认的magic模式下,使用以下模式来处理单词中的单引号:

/'\('\w\|[^']\)\+'

you have mocking some 'bird of the year'.
you have mocking some 'the year's bird'.

如果使用VeryMagic模式,命令则可以简化为:

/\v'('\w|[^'])+'

假设在以下文本中,希望仅保留英文字母:

12345aaa678
12345bbb678
12345ccc678

使用以下替换命令,可以删除其中的数字部分:

:%s/\d\{5\}\(\D\+\)\d\{3\}/\1/

aaa
bbb
ccc

如果使用VeryMagic模式,命令则可以简化为:

:%s/\v\d{5}(\D+)\d{3}/\1/

由此可见,Very magic模式为使用正则表达式提供了极大的便利。但很不幸,我们并无法将Very magic模式设置为默认选项。潜在的替代方案是,定义以下键盘映射,在查找时自动激活very magic模式:

:noremap / /\v

使用以下命令,可以查看更多帮助信息:

:help /\v

Very No Magic

在模式开头使用\V指定Very No Magic模式,将使得其后模式中只有反斜杠(\)具有特殊意义,而()[]|.*?等等元字符都将被视为普通文本。

如果您需要精确的完整匹配,并且查找字符串中包含特殊字符时,那么可以使用Very nomagic模式。

例如以下命令,将查找字符串“Fun.test(*args)” 。也就是说,其中的“*”和“.”都被视为普通字符,而不需要进行转义:

/\VFun.test(*args)

假设需要在以下文本中查找“a.k.a”:

The N key searches backward
the \v pattern switch (a.k.a. very magic)

因为“.”在正则表达式中具有特殊含义,它将会匹配任意字符,所以使用以下命令,将会同时匹配单词“backward”中的部分字符:

/a.k.a

The N key searches backward
the \v pattern switch (a.k.a. very magic)

当然,可以使用转义符来消除“.”的特殊含义:

/a\.k\.a\.

而更简单的方法是,在命令中使用\V激活very nomagic模式:

/\Va.k.a.

此时,将只会按字面匹配到单词“a.k.a”:

The N key searches backward
the \v pattern switch (a.k.a. very magic)

使用以下命令,可以查看更多帮助信息:

:help /\V

小结

我们可以将 very magic 和 very nomagic 模式,理解为对于正则表达式的两种极端处理方式。需要构建较复杂正则表达式时,推荐使用very magic模式;需要按字面意义查找文本时,则推荐使用very nomagic 模式。

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期一, 五月 11, 2020

VIM学习笔记 编译源码(Compile Code)-Python

Python作为一种解释型编程语言,需要解释器来编译并执行Python代码。

测试Python

对于Linux和Mac操作系统,均已预装Python。而在Windows下,可以使用安装包或者直接解压版zip文件。

使用以下命令,可以查看当前Python版本:

$ python --version

python-version

设置动态调用库

新版本的Vim已经默认支持Python。可以使用:version命令,确认是否包含“+python/dyn”和“+python3/dyn”特性。

version_python3

其中dyn,即dynamic,表示可以通过'pythondll'和'pythonthreedll'选项动态调用Python库。

使用set pythonthreedll?命令,可以查看当前动态调用的Python库。以下为Fedora31下的默认设置:

set pythonthreedll=libpython3.7m.so.1.0

如果您的Vim不支持动态调用Python库,那么以上命令将会报错。

如果您仅是下载并解压程序包(而不是进行安装),那么同时需要设置pythonthreehome选项。例如以下命令,在Windows下设置Python3环境:

set pythonthreehome=C:\tools\Python3
set pythonthreedll=C:\tools\Python3\python38.dll

以下命令,可以在Mac下设置Python环境:

" for python 3.X
set pythonthreehome=/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7
set pythonthreedll=/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/libpython3.7m.dylib
" for python 2.X
set pythonhome=/System/Library/Frameworks/Python.framework/Versions/2.7
set pythondll=/System/Library/Frameworks/Python.framework/Versions/2.7/Python

请注意,在您的环境中Python所处的路径可能会不同。请在操作系统中使用以下命令,查看Python系统路径:

$ python -c "import sys; print(sys.path)"

python_sys_path

请使用以下命令,查看更多帮助信息:

:help python-dynamic
:help 'pythonhome'
:help 'pythonthreehome'

设置编译器

使用以下命令,设置'makeprg'选项为python3命令:

set makeprg=python3\ %

通过在vimrc文件中增加以下自动命令,可以为Python源码文件设置编译快捷键:

augroup make_python
 au!
 au FileType python set makeprg=python3\ %
 au FileType python map <buffer> <leader><space> :w<cr>:make<cr>
augroup end

编译Python代码

使用以下命令,将根据'makeprg'选项编译并执行Python文件:

:make

如果编译出现错误,将在QuickFix中显示错误列表,并自动跳转到第一个错误处:

python_error_quicklist_multiple

启用以下内置的编译器,再执行:make编译命令,报错信息将被整合为一行:

:compiler pyunit

python_error_quicklist_single

如果希望在编译时保持当前光标位置不变,那么可以使用以下命令:

:make!

使用:cw命令,将打开quickfix窗口。使用:cp命令,跳转到上一个错误;使用:cn命令,跳转到下一个错误。关于QuickFix操作的更多信息,请参阅QuickFix章节。

在修复错误并成功编译之后,将显示命令输出:

python_success_output

使用以下命令,将解释执行当前文件:

:!python3 %

如果执行不带任何参数的python3命令,那么将进入交换模式的python shell,您可以在其中直接执行python命令:

:!python3

Python3_i

使用以下命令,可以退出交换模式的python shell:

import sys; sys.exit()

您也可以直接使用Vim内置的:python3命令来执行代码:

:py3 print('hello world')

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期日, 五月 03, 2020

VIM学习笔记 替换字符串中的submatch()

submatch({nr})函数,只用于 :substitute 命令或 substitute() 函数中。它将返回匹配文本的第{nr}个子匹配。如果{nr}为0,则返回整个匹配文本。

将submatch()和其它函数相结合,可以对替换文本进行更丰富的操作。使用:help submatch()命令,可以查看更多帮助信息。

更新列表序号

如果希望在第1条之后插入一个新的条目,那么就意味着需要调整后续各个条目的序号:

Article 1: 3 Steps To Enable Thesaurus Option
Article 2: Steps to Add Custom Header
Article 3: Automatic Word Completion
Article 4: How To Record and Play Macro
Article 5: Make Vim as Your C IDE

使用以下命令,将第2行及之后各行中的序号分别加1:

:2,$s/\d\+/\=submatch(0) + 1/

Article 1: 3 Steps To Enable Thesaurus Option
Article 3: Steps to Add Custom Header
Article 4: Automatic Word Completion
Article 5: How To Record and Play Macro
Article 6: Make Vim as Your C ID

请注意,替换命令中并没有使用/g标志,因此将仅仅替换第一个匹配字符,以避免条目文本中的数字也被更改。

转换单词大小写

假设需要在以下条目中,将首个单词的首个字母转换为大写:

The following activities can be done using vim:
a. source code walk through,
b. record and play command executions,
c. making the vim editor as ide

使用以下命令,将匹配“.”及空格之后的单词字符(0-9A-Za-z),并替换为大写:

:%s/\.\s*\w/\=toupper(submatch(0))/g

The following activities can be done using vim:
a. Source code walk through,
b. Record and play command executions,
c. Making the vim editor as ide

替换文件路径

将当前光标下的相对路径名,替换为完整的绝对路径名:

:s/\f*\%#\f*/\=fnamemodify(submatch(0), ':p')/

其中,\= 表示使用表达式作为替换字符串(请参考帮助信息:help sub-replace-expression);\f*\%#\f* 将匹配文件名(请参考帮助信息:help /\f) 。

如果希望将可视化模式下选中的文件名,替换为完整的绝对路径名,那么在命令中使用\%V参数:

:s/\%V.*\%V/\=fnamemodify(submatch(0), ':p')/

数据补零

将每行数据中不满8位的字符串,向右对齐并在前部以0补足8位:

:%s/.*/\=printf('%08s',submatch(0))/g

submatch_08s

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期五, 四月 24, 2020

VIM学习笔记 正则表达式-捕获组(Regex-Groups)

()用于保证需要作为整体而组合出现的字符。例如表达式a\(XY\)*b将会匹配ab, aXYb, aXYXYb, aXYXYXYb。

逆向引用(Back Reference)表达式\n,用于引用之前定义的第n个捕获组。其中n为数字1–9。

例如对于文本“he fly fly flies”,表达式\(fly\) \1将匹配“fly fly”。因为\1再次引用了第一个捕获组“fly”,所以将匹配2个“fly”。

捕获组匹配


示例格式
(800)555-1212(3位数字)3位数字-4位数字
(800) 555-1212(3位数字)3位数字-4位数字
(800)-555-1212(3位数字)-3位数字-4位数字
800-555-12123位数字-3位数字-4位数字
555-12123位数字-4位数字

假设需要查找以上多种格式的电话号码,其中:

  • 可能包含区号,也可能没有区号;
  • 区号由3位数字组成;
  • 区号可能被括号包围,也可能没有括号;
  • 区号和号码之间,可能有横线或者空格相连,也可能没有任何连接符;
  • 号码由3位数字,横线连接符,和4位数字组成。

使用以下命令,可以满足以上格式需求:

/\((\d\{3})[- ]\?\|\d\{3}-\)\?\d\{3}-\d\{4}

我们将在下表中按照命令中的色彩标识,来分步理解命令中的表达式:

颜色表达式作用
\( to \)匹配区号及其后的连接符的捕获组
\?匹配0个或1个捕获组(即区号部分)
\d\{3}-\d\{4}匹配不包括区号的电话号码
\|或操作,匹配区号的多种形式
绿(\d\{3})[- ]\?匹配由括号包围的区号及之后的分隔符
\d\{3}-匹配没有括号包围的区号

由此可见,将区号及其后的连接符作为一个整体捕获为组,这样就可以通过后续的 \? 表达式来匹配0个或1个捕获组,以实现匹配包含区号和不包含区号的多种情况。

捕获组嵌套

以下文本中包含FIRSTNAME LASTNAME格式的姓名信息:

Prepared by Tommas Young
Prepared by Tommy Young

使用以下命令,可以将其转换为LASTNAME, FIRSTNAME格式:

:%s/\(Tom\%(mas\|my\)\) \(Young\)/\2, \1/g

Prepared by Young, Tommas
Prepared by Young, Tommy

从以上命令可以看到,捕获组是可以嵌套的;\%(\) 指定的组将不会被计数,这可以允许我们使用更多的组,并且查找速度也更快。

捕获组替换

假设需要将以下文本中的单引号替换为双引号:

The string contains a 'quoted' word.
The string contains 'two' quoted 'words'.
The 'string doesn't make things easy'.
The string doesn't contain any quotes, isn't it.

通过以下命令中的嵌套捕获组来完成替换操作:

:%s/\s'\(\('\w\|[^']\)\+\)'/ "\1"/g

The string contains a "quoted" word.
The string contains "two" quoted "words".
The "string doesn't make things easy".
The string doesn't contain any quotes, isn't it.

其中,\s' 用于匹配紧跟在空格之后即单词开头的单引号;\('\w\|[^']\) 则将非开头的单引号视为单词的一部分,以防止其被替换位双引号。

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期一, 四月 13, 2020

VIM学习笔记 过滤器(Filter)

过滤程序是一个接受文本作为标准输入(stdin),然后进行某些处理,并把结果放置到标准输出(stdout)的程序。可以理解为,Vim将当前缓冲区同时作为输入和输出,并借助外部程序进行文字处理。例如使用外部sort命令进行排序,然后用输出结果替换当前文本内容。

过滤器命令

使用以下格式的过滤器命令,可以利用外部程序 {filter} 过滤 {motion} 跨越的多行:

:{range}!{motion}{filter}

使用%指代整个文件,可以将所有行的字母转换为大写:

:%!tr [:lower:] [:upper:]

filter_all_lines_tr

连续点击!!键,将转到屏幕底部继续输入针对当前行的:.!命令。以下命令将本行的字母转换为大写:

:.!tr [:lower:] [:upper:]

filter_curr_lines_tr

使用以下命令,将指定行的字母转换为大写:

:4,6!tr [:lower:] [:upper:]

filter_range_lines_tr

通过在命令之前增加数字前缀,也可以实现相同的功能。首先将光标移动到第4行,然后连续点击3!!键,将转到屏幕底部继续输入针对行范围:.,.+2!的命令。以下命令,将本行及后续2行(共计3行)的字母转换为大写:

:.,.+2!tr [:lower:] [:upper:]

使用以下命令,可以将指定标记(Mark)之间的行的字母转换为大写:

:'a,'b!tr [:lower:] [:upper:]

在可视化模式下,也可以使用外部程序 {filter} 过滤高亮选中的行。例如选中文本之后,点击!键,将转到屏幕底部继续输入针对选中范围'<,'>!的命令。以下命令,将注释选中的行:

'<,'>! perl -nle 'print "\#".$_'

请注意,过滤程序将对整行进行处理,所以请使用V命令进入的行可视化模式(Linewise visual mode)。

文本处理

使用以下命令,将按照数字顺序对当前文本进行排序。请注意,此处的外部sort命令,与Vim内部的:sort命令是不同的。

:%!sort -n

使用以下命令,将在行首增加行号:

:%!cat -n

filter_cat_n

例如在当前文件中,包含以逗号分隔的多列文本:

One,Two,Three,Four,Five
arborist,apple,artichoke,ant,author
branch,banana,broccoli,bee,book

使用以下Linux命令cut,可以仅保留其中的2-3列文本:

:%!cut -f2-3 -d,

Two,Three
apple,artichoke
banana,broccoli

生成并执行Shell命令

shell环境(比如sh和cmd),也可以作为过滤器来执行外部命令。

使用以下命令,可以将当前目录下的文件列表读取到当前文件中:

:r! ls *.html

利用替代命令,可以针对文件列表组合出需要的Shell命令。例如生成mv命令,将所有HTML文件重命名为XHTML文件:

:%s/\(.*\).html/mv & \1.xhtml

使用以下命令,则可以调用Shell来执行当前文件中的命令:

:!sh

可以看到,利用过滤器可以灵活生成并执行操作系统命令,以完成例如文件复制备份等批处理操作。

假设当前文件中包含以下Windows命令:

ping -n 1 1.1.1.1
ping -n 1 1.1.1.2
ping -n 1 1.1.1.3

使用以下命令,将用文件中ping命令的输出来替换当前文本:

%!cmd

Microsoft Windows [Version 10.0.18362.720]
(c) 2019 Microsoft Corporation. All rights reserved.

D:\Temp>ping -n 1 1.1.1.1

Pinging 1.1.1.1 with 32 bytes of data:
Reply from 1.1.1.1: bytes=32 time=148ms TTL=54

Ping statistics for 1.1.1.1:
Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 148ms, Maximum = 148ms, Average = 148ms
...

在以上命令的执行过程中可以看到,Vim会将文本行保存为临时文件,然后调用外部程序进行过滤处理,然后再用输出结果替换当前文本。

filter_windows_tempdir

过滤器使用的临时文件,通常保存在以下位置:

  • Windows:$TMP、$TEMP、c:\TMP、c:\TEMP;
  • Linux:$TMPDIR、/tmp、当前目录、$HOME。

请注意,Vim将依次检查以上目录,请确保有足够的权限读写这些目录。

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>