The Clothed/Naked Maja |
自8.0版本起,包含+timers特性的Vim提供了定时器功能。利用定时器,可以在指定延时之后触发指定操作,也可以按照固定的时间间隔来重复执行任务。
使用timer_start()函数,可以启动定时器并返回定时器ID:
timer_start({time}, {callback} [, {options}])
其中:
使用"repeat"选项,可以控制执行回调函数的次数。缺省为执行"1"次。如果希望无限循环执行,那么可以将此值设置为"-1"。
使用以下命令,设置在状态行中显示时间:
set laststatus=2
if has("win32")
set statusline=%{strftime(\"%I:%M:%S\ \%p,\ %a\ %b\ %d,\ %Y\")}
else
set statusline=%{strftime(\"%l:%M:%S\ \%p,\ %a\ %b\ %d,\ %Y\")}
endif
自定义以下函数,用于更新状态行:
function! UpdateStatusBar(timer)
execute 'let &ro = &ro'
endfunction
使用以下命令启动定时器,回调函数将持续更新状态行的时间显示:
:let timer = timer_start(3000, 'UpdateStatusBar',{'repeat':-1})
使用不带参数的timer_info()函数,可以获取所有定时器的信息:
:echo timer_info()
使用带有ID参数的timer_info()函数,可以获取指定定时器的信息:
:echo timer_info(timer)
函数返回包含详细信息的字典:
项目 | 描述 |
---|---|
id | 该定时器的 ID |
repeat | 定时器还需要重复执行的次数,无限执行则返回 -1 |
remaining | 距定时器启动还剩余的毫秒数 |
time | 计时器时间间隔(毫秒数) |
paused | 暂停状态时返回 1,否则返回 0 |
callback | 回调函数 |
使用timer_pause()函数,并指定第二个参数为非0数值或非空字符串,可以暂停定时器:
:call timer_pause(timer,1)
使用timer_pause()函数,并指定第二个参数为数值0或空字符串,可以对定时器取消暂停:
:call timer_pause(timer,0)
假设启动以下定时器,将在指定延时之后强制退出Vim:
:let timer_id = timer_start(10000, {id -> execute('quit!')})
使用timer_stop()函数,可以取消指定定时器:
:call timer_stop(timer_id)
使用timer_stopall()函数,可以取消所有定时器:
:call timer_stopall()
假设当前脚本文件中包含以下代码:
let s:timeouts = [5000, 10000, 30000, 1000, 1000, 3200, 500, 700]
function! s:noop(timer_id)
let s:timeouts = insert(s:timeouts, remove(s:timeouts, len(s:timeouts) - 1))
normal dd
call timer_start(s:timeouts[0], function('<SID>noop'))
endfunction
call s:noop(0)
使用以下命令执行当前脚本,将从当前行开始,按照设定的时间间隔逐行删除文本:
:so %
?使用以下命令,可以查看关于定时器的帮助信息:
:help timer
timer_start() | 新建定时器 |
timer_info() | 定时器信息 |
timer_pause() | 暂停或继续定时器 |
timer_stop() | 停止定时器 |
timer_stopall() | 停止所有定时器 |
在传统的单线程模式下,运行外部命令时,将中断用户当前的编辑操作,并等待命令完成才可以返回vim。
自8.0版本起,包含+channel和+job特性的Vim将可以支持异步操作。Vim使用作业(job)来启动进程,并利用通道(channel)和其他进程通信。
利用异步支持,可以在后台进行复杂耗时的操作(比如使用外部grep工具查找文本),不必等待外部命令结束即可返回Vim,而不中断前台的正常编辑。在外部命令结束运行时,可以通过回调函数来处理输出结果。
例如使用:!ls
外部命令,将在屏幕底部列示目录内容,并等待用户按回车键以返回常规模式,此时用户无法进行其它操作:
使用job_start()函数,可以异步执行命令,其格式为:
job_start({command} [, {options}])
其中:command,用于指定需要运行的外部系统命令;options,是包含多个键值的字典选项,用于配置和控制作业的行为。
使用以下命令,可以启动作业以执行外部命令,并立刻返回常规模式,不影响用户的后续操作:
:call job_start('ls')
作业采用管道(pipe)将外部命令与vim联接起来,并与标准输入(stdin)、标准输出(stdout)和标准错误(stderr)输出进行交互。
在使用job_start()函数启动作业时,可以注册一个或多个回调函数来处理特定的信息。如果希望静默执行命令,而不关心输出信息,那么也可以不注册任何回调函数。
使用"callback"选项,可以同时捕获标准输出与标准错误输出;也可以分别使用"out_cb"或"err_cb"选项,来单独捕获标准输出或标准错误输出。
首先定义用于捕获输出的回调函数:
func! MyHandler (channel, msg)
echomsg a:msg
endfunc
通过"callback"选项,指定回调函数来处理stdout和stderr的内容:
let job = job_start ('ls', {"callback": "MyHandler"})
通过"out_cb"选项,指定回调函数来处理stdout的内容:
let job = job_start ('ls', {"out_cb": "MyHandler"})
通过"err_cb"选项,指定回调函数来处理stderr的内容:
let job = job_start ('ls', {"err_cb": "ErrHandler"})
在以上回调函数中使用了:echomsg
命令,因此随后可以使用:message
命令来查看信息历史,以确认命令执行结果:
使用"in_io"、"out_io"或"err_io"选项,可以将作业管道重定向到文件或缓冲区。
使用以下命令,可以将标准输出重定向至指定缓冲区:
:let job = job_start('ls', {'out_io': 'buffer', 'out_name': 'mybuffer'})
使用以下命令,则可以打开缓冲区查看输出信息:
:sbuf mybuffer
请注意,首行包含了“Reading from channel output...”的说明文字:
使用以下任一命令,均可以将标准输出重定向至指定文件:
:let job = job_start('ls -al', {'out_io': 'file', 'out_name': '/tmp/file.txt'})
:call job_start(["/bin/sh", "-c", "ls -al > /tmp/file.txt"])
?使用以下命令,可以查看作业选项的帮助信息:
:help job-options
使用job_status()函数,可以返回指定作业的状态:
:echo job_status(job)
状态 | 描述 |
---|---|
run | 作业运行中 |
fail | 作业无法启动 |
dead | 作业启动后结束或被终止 |
使用job_info()函数,则可返回指定作业的详细信息:
:echo job_info(job)
函数将返回包含详细信息的字典:
键 | 描述 |
---|---|
status | job_status()返回值 |
cmd | 启动作业的命令行参数列表 |
stoponexit | Vim结束时给作业发信号(缺省是 "term") |
channel | job_getchannel()返回值 |
process | 进程ID |
tty_in | 终端输入名,如果没有则为空 |
tty_out | 终端输出名,如果没有则为空 |
exitval | "status" 为 "dead" 时才有效 |
exit_cb | 退出时调用的函数 |
termsig | 终止程序的信号(仅用于Unix) 仅当"status"为"dead"时才有意义 |
tty_type | 使用的虚拟控制台类型(仅用于MS-Windows) 可选值是"winpty"或"conpty" |
使用job_stop()函数,可以停止指定的作业:
:call job_stop(job)
实例1:启动Apache HTTP Server服务
:let job = job_start('apachectl start')
使用以下命令载入首页内容,以确认服务启动成功:
:silent r ! curl localhost
实例2:在位置列表中显示命令输出
function! s:on_find(chan, msg)
lgetexpr split(a:msg, '')
endfunction
call job_start('find . -print0', {
\ 'out_mode': 'raw',
\ 'callback': function('<SID>on_find')
\ })
使用以下命令,执行包含以上命令的脚本:
:so %
使用以下命令,将在位置列表(location list)中显示外部find命令输出的文件列表:
:lopen
?使用以下命令,可以查看关于作业的帮助信息:
:help job
job_start() | 启动作业 |
job_status() | 显示作业状态 |
job_info() | 显示作业的详细信息 |
job_stop() | 停止作业 |
通常在使用!
运行外部Shell命令时,将显示提示信息“Press ENTER or type command to continue”,需要用户点击回车键才可以返回常规模式。
如果不希望显示提示信息,那么可以使用:silent
命令:
:silent !echo 'Hello World'
如果需要清除命令本身及其输出信息,那么可以使用Ctrl-L快捷键或:redraw!
命令来重画屏幕。
您可以自定义命令,来合并以上两步操作:
:command! -nargs=1 Silent execute ':silent !'.<q-args> | execute ':redraw!'
使用以下自定义命令,将首先执行外部命令,然后重画屏幕:
:Silent echo 'Hello World'
通过结合:execute
命令,可以生成并执行较复杂的命令:
:silent exec "!command"
定义以下快捷键,在Linux下静默执行命令。比如使用eSpeak将文字转换为语音:
:nnoremap <leader>es :silent exec '!espeak "hello world" &'<CR>
定义以下快捷键,在Windows下使用默认程序打开当前文件。比如使用默认浏览器,打开当前编辑的HTML文档:
:nmap <Leader>x :silent ! start "1" "%:p"<CR>
使用以下命令,可以利用Shell后台执行命令和重定向的能力:
:silent exec "!(ping www.vim.org >ping.out >2&1) &"
>ping.out
,即1>ping.out
,表示将命令的标准输出(stdout)重定向到名为“ping.out”的文件;因为默认值为1,所以可以省略;>2&1
,表示将“2”代表的标准错误(stderr)也重定向至“1”代表的标准输出(stdout);即标准输出和标准错误都输出至名为“ping.out”的文件; &
,表示在后台执行命令。如果不希望外部命令输出任何信息,那么可以将标准输出指向空设备文件“/dev/null”:
:silent exec "!(ping www.vim.org >/dev/null >2&1) &"
也可以静默执行外部命令,并在新建标签页(Tab)内显示命令输出:
:silent exec "!(echo 'Hello World') > test.txt" | :tabedit test.txt
如果希望在分割窗口内显示命令输出,那么可以使用:split命令:
:silent exec "!(echo 'Hello World') > test.txt" | :sp test.txt
使用以下命令,将打开与当前文件同名的PDF文档。由于Zathura窗口在前台显示,所以无法在Vim窗口中继续进行编辑;关闭zathura窗口之后,也需要在Vim中点击回车键以返回常规模式:
:!zathura %:r.pdf
使用以下命令,将打开与当前文件同名的PDF文档。由于zathura窗口在前台显示,所以无法在Vim窗口中继续进行编辑;关闭zathura窗口之后,不需要在Vim中点击回车键即可返回常规模式:
:silent !zathura %:r.pdf
使用以下命令,将在后台打开与当前文件同名的PDF文档。由于zathura窗口在后台显示,所以无需关闭zathura窗口,也无需点击回车键,即可以在Vim窗口中继续进行编辑:
:silent exec '!zathura '.expand("%:r").'.pdf &'
使用以下命令,可以使用Zip压缩当前文件:
:!zip test.zip %:p
屏幕将显示以下信息,并等待用户按回车键以返回常规模式:
使用以下命令,则屏幕不会显示任何信息,并且自动返回常规模式:
:silent !zip test.zip %:p
使用以下命令,可以批量压缩所有打开的文件:
:silent bufdo !zip test.zip %:p
如果希望记忆光标位置和手动折叠(Fold),以便在重新打开文件时恢复到之前的编辑状态。那么可以在vimrc配置文件中,增加以下自动命令:
set viewdir=$HOME/vimfiles/views/
autocmd BufWinLeave * mkview
autocmd BufWinEnter * silent loadview
通过调用system()函数,也可静默执行命令:
:call system('espeak "hello world" &')
函数system()
和!
命令都可以调用外部命令,但system()函数不会切到shell终端,而是仍停留在vim界面。所调用外部命令的输出将会被system()函数捕获,可以将其保存在VimL变量中以供后续使用。
使用以下命令,可以查看更多帮助信息:
:help :silent
:help system()
关于本文中使用的第三方工具,请参阅以下网址:
将所有未标志为“DONE”的行,都在行尾标注“TODO”:
:g!/DONE/s/$/ TODO/
:v/DONE/s/$/ TODO/
从第5行到第10行,在每一行下插入空行:
:5,10g/^/pu _
通过调用:sort
命令,可以对指定范围内的文本进行排序。例如以下命令,将对“{}”包围的CSS属性按字母排序:
:g/{/ .+1,/}/-1 sort
同理,使用以下命令,可以针对“{}”包围的文本增加缩进:
:g/{/ .+1,/}/-1 >
使用以下命令,可以为“Chapter”开头的标题行增加分隔线:
:g/^Chapter/t.|s/./-/g
Chapter 1 --------- Chapter 2 ---------
从以上命令可以看到,通过使用“|
”可以组合执行多条命令。首先使用:t
命令,复制行内容;然后执行:s
命令,将文本替换为横线。
使用以下命令,可以进行多次替换。对于包含“apples”或“cherries”的行,进行两次替换:首先将“apples”替换为“bananas”,然后将“cherries”替换为“oranges”:
:g /apples\|cherries/ substitute /apples/bananas/g | substitute /cherries/oranges/g
首先在vimrc配置文件中,新增以下自定义函数:
" Delete duplicate lines
function! DelDupLine()
if getline(".") == getline(line(".") - 1)
norm dd
endif
endfunction
然后使用以下命令,调用函数来删除文件中重复的行:
:g/^/ call Del()
将所有不是以2个Tab制表符开头的行,增加到文件“top2levels.otl”的末尾:
:g!/^\t\t/.w>>top2levels.otl
首先移动到文件开头,然后执行以下命令,可以搜集相对于指定字符偏移位置的行:
:g /^Chapter/ .+2w >> begin
包含“Chapter”字符的章节号、名称和描述,分处在连续的行中。模式^Chapter将查找以“Chapter”字符开头的行;.+2将定位到匹配处之后的第2行;然后使用:w
命令将其追加到名为“begin”的文件中。
拆分当前文件,将每一行内容,分别保存为一个文本文件(1.txt,2.txt,3,txt依次类推):
:g/^/exe ".w ".line(".").".txt"
将字符串“MARK”替换为文件“tmp.txt”的内容:
:g/^MARK$/r tmp.txt | -d
假设需要从以下代码中,提取所有以“TODO”开头的注释文字:
if ( m && m[2] ) // TODO: something1 return [ m[1].length + m[2].length ]; else { // TODO: something2 return [ 1, "`" ]; }
首先,使用qaq
命令来清除寄存器a的内容,做为存储提取内容的中介位置;
然后,使用以下命令将包含“TODO”的行添加到寄存器a;请注意,使用大写的寄存器编号“A”以表示向寄存器添加内容(而小写字母则表示覆盖内容);
:g/TODO/yank A
如果希望将文本同时放入指定寄存器和系统剪切板,那么可以使用以下命令:
:g/TODO/yank A | :let @+=@a
请注意,在Mac和Windows下,寄存器*和+都用于访问系统剪切板;在Linux下,寄存器+用于访问系统剪切板。
使用以下命令,可以看到内容已经被放入寄存器和剪切板:
:registers a+*
请注意,vim使用“^J”符号表示换行。
使用"ap
命令,即可以将寄存器a中存储的TODO信息粘贴出来:
// TODO: something1 // TODO: something2
:global
全局命令,通常简写为:g
,可以针对匹配模式的行执行编辑命令;通过与正则表达式、寄存器和标记等功能相配合,可以高效地实现复杂的操作。
使用:g
命令,可以针对所有匹配模式的行执行操作。其命令格式为:
:[range]g/{pattern}/[command]
即针对在[range]范围内,所有匹配{pattern}模式的行,执行[command]命令。
命令:g!
及其同义词:v
,则可以针对所有不匹配模式的行执行操作。其命令格式为:
:[range]g!/{pattern}/[command]
即针对在[range]范围内,所有不匹配{pattern}条件的行,执行[command]命令。
如果没有指定[range],则针对文件中的所有行执行命令。也可以使用行地址,把全局搜索限定在指定的行或行范围内。
如果没有指定[command],则执行:print
命令来显示行内容。
使用以下命令,可以查看全局命令的帮助信息:
:h :g
查找并显示文件中所有包含模式pattern的行,并移动到最后一个匹配处:
:g/pattern
查找并显示文件中所有包含模式pattern的行:
:g/pattern/p
查找并显示文件中所有精确匹配单词pattern的行:
:g/\<pattern\>/p
查找并显示第20到40行之间所有包含模式pattern的行:
:20,40g/pattern/p
查找并显示文件中所有不包行模式pattern的行,并显示这些行号:
:g!/pattern/nu
删除包含模式patternn的行:
:g/pattern/d
删除不包含模式pattern的行:
:g!/pattern/d
删除所有空行:
:g/^$/d
删除所有空行以及仅包含空格和Tab制表符的行:
:g/^[ tab]*$/d
删除指定范围内的文本,例如以下文本中的“DESCRIPTION”部分:
:g/DESCRIPTION/,/PARAMETERS/-1d
利用全局命令,可以仅针对符合查询条件的行,进行替换操作。例如使用以下命令,将包含“microsoft antitrust”的行中的“judgment”替换为“ripoff”:
:g/microsoft antitrust/s/judgment/ripoff/
可以在命令中指定查找的范围。比如以下命令,将在包含“microsoft antitrust”的前两行及后两行中进行替换:
:g/microsoft antitrust/-2,/microsoft antitrust/+2s/judgment/ripoff/c
以上命令末尾的c参数,用于提示用户对每一个替换操作进行确认。
假设希望在以“end”结尾的行中,将第1部分文字替换为“The greatest of times;”:
the best of times; the worst of times: end
由于会尽可能多(as much text as possible)的匹配,以下命令将替换至第2个“of”处:
:g/end$/s/.*of/The greatest of/
The greatest of times: end
为了只替换第1部分,则需要更精确的匹配条件:
:g/end$/s/.*of times;/The greatest of times;/
The greatest of times; the worst of times: end
将所有的行按相反的顺序排列。其中,查找模式.*将匹配所有行,m0命令将每一行移动到0行之后:
:g/.*/m0
将指定标记(Mark)之间的行按相反的顺序排列:
:'a,'bg/^/m'b
将以下文本中的“DESCRIPTION”部分,上移到“SYNTAX”之前:
:g /SYNTAX/.,/DESCRIPTION/-1 move /PARAMETERS/-1
首先匹配从包含“SYNTAX”的行到包含“DESCRIPTION”的上一行;然后将这些行移动到包含“PARAMETERS”的上一行。
以下两条命令均可以将所有不是以数字开头的行,移动到文件末尾:
:g!/^[[:digit:]]/m$
:g/^[^[:digit:]]/m$
使用以下命令,可以重复每一行。其中:t
或:copy
为复制命令:
:g/^/t.
将包含模式pattern的行,复制到文件末尾:
:g/pattern/t$
重复每一行,并以“print ''”包围:
:g/./yank|put|-1s/'/"/g|s/.*/Print '&'/
Chapter 1 Print 'Chapter 1'
Best with Vim8 and python3 enabled.
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的异步语法检查 |
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 | 代码自动完成 |
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 | 后台异步执行外部命令 |
sandwich 插件可以快速编辑围绕在内容两端的字符(pairs of things surrounding things),比如成对出现的括号、引号,甚至HTML/XML标签等。
sandwich支持vim的文本对象(Text Objects),比如单词、句子和段落等等。同时也支持.
重复命令(Dot Command)。
推荐您使用vim-plug或Vundle等插件管理器,来安装GitHub上的sandwich插件。
以下将利用实例来介绍sandwich插件的主要功能,请注意:
在常规模式和可视化模式下,可以使用sa
命令来新增环绕字符:
模式 | 目标 范围 | 新增 内容 | 原始文本 | 命令 | 更改效果 |
---|---|---|---|---|---|
常规模式 | 单词 | 字符 | Hello World | saiw* | Hello *World* |
单词不含标点 | 引号 | Hello World! | saiw' | Hello 'World'! | |
单词包含标点 | 引号 | Hello World! | saiW' | Hello 'World!' | |
单词 | 标签 | Hello World | saiwtstrong | Hello <strong>World</strong> | |
单词 | 括号 | print var1, var2 | sa3w) | print (var1, var2) | |
行尾 | 括号 | print var1, var2 | sa$) | print (var1, var2) | |
查找 | 标签 | William Shakespeare said, "Brevity is the soul of wit." | saf"tem | William Shakespeare said, <em>"Brevity is the soul of wit."</em> | |
整行 | 字符 | Hello World | 0sa$" | "Hello World" | |
整行 | 标签 | Hello World | 0sa$tp | <p>Hello World</p> | |
字符可视化模式 | 选中的文本 | 括号 | print var1, var2 | veesa) | 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 World | Vsa) | ( 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> |
从以上屏幕录像中可以看到:
t
表示标签,将在屏幕底部显示提示行,在其中输入的标签名称然后按回车键即可(并不需要输入<>);请注意:
使用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
来指代,既聪明又方便。
随着命令输入,会以高亮显示将被替换的环绕字符,以便在操作之前确认范围是否正确。
使用sd
命令可以删除环绕字符:
新增内容 | 原始文本 | 命令 | 更改效果 |
---|---|---|---|
引号 | 'Hello World' | sdb | Hello World |
括号 | (123+4*56)/2 | sdb | 123+4*56/2 |
标签 | <div>Hello</div> | sdt | Hello |
同样在sd删除命令中,也不需要明确指明环绕字符,而可以通过标识符b
来指代,大大减少了命令的复杂度。
假设需要针对以下文本,添加包含多个属性的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 | 删除环绕字符 |
Originally from Practical Vim by Drew Neal
matchpairs选项,用来控制哪些字符可以通过%
命令进行匹配。此选项的默认值如下:
:set matchpairs=(:),{:},[:]
也就是说,在开括号“(,{,[”上点击%
键,将会自动跳转到对应的闭括号“),},]”上;同理,在闭括号上点击%
键,也会跳转回到对应的开括号上;同时,匹配跳转也能够正确处理括号嵌套的情况。
如果当前光标下并非括号,那么点击%
键,将自动在本行内向前查找并定位到括号之上。
Source: https://catonmat.net/vim-plugins-matchit-vim
如果需要新增匹配类型,例如增加对于HTML文件中的尖括号的匹配,那么可以使用以下命令:
:set mps+=<:>
利用自动命令(autocmd),可以针对特定文件类型设置匹配字符。例如针对C和Java代码,增加对于“=”和“;”的匹配:
:au FileType c,cpp,java set mps+==:;
如果希望在输入闭括号时,短暂地跳转到与之匹配的开括号,那么可以设置以下选项:
:set showmatch
'matchtime'选项,用于控制显示配对括号的时间,其单位为0.1秒,默认值为5,即0.5秒。
如果希望持续显示配对括号1.5秒,那么可以使用以下命令:
:set matchtime=15
matchit插件扩展了%
命令的功能,支持if/else/endif语法结构;支持HTML标签。使用:help matchit-languages
命令,可以查看当前支持的所有语言列表。
从Vim 6.0开始,matchit插件伴随vim发行,内置于$VIMRUNTIME\pack\dist\opt\matchit
目录中,并不需要单独安装。
在vimrc配置文件中增加以下命令,可以启用matchit插件:
packadd! matchit
在HTML标签中,点击%
键,将移动到关闭标签上:
Source: https://catonmat.net/vim-plugins-matchit-vim
使用以下命令,可以查看更多帮助信息:
:help matchit
% | 跳转到匹配字符 |
:set matchpairs | 设置形成配对的字符 |
:set showmatch | 设置是否短暂跳转到匹配括号 |
:set matchtime | 设置显示配对括号的时间长度 |
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" | |
注释 | [* | 反向第一个注释的开始 "/*" |
[/ | ||
]* | 正向第一个注释的结束 "*/" | |
]/ |
如果感觉以上介绍云山雾罩,那么不妨对照以下操作实例,请注意:
Zeal是开源的跨平台软件,用于离线浏览各种开发文档。Zeal使用Dash提供的文档集(Docsets),涵盖近200种开发语言。
Zeavim插件,可以在Vim中调用Zeal来查看离线文档。
推荐您使用vim-plug或Vundle等插件管理器,来安装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中,查找当前光标下的单词:
使用gz
命令,将根据当前文件类型在相应的Docset中,查找文本对象指定的关键词。例如在Vim脚本文件中,使用gziw
命令,将在Vim Docset中查找当前光标下的单词:
使用<leader><leader>z快捷键或:Zeavim!
命令,将根据用户输入,在指定的Docset中,查找指定的关键词:
使用以下命令,可以查看插件的帮助文件:
:help zeavim
如果不希望安装额外的插件,那么也可以用"zeal docset:keyword"的形式直接调用Zeal命令行。例如以下命令,将在Vim文档中查找关键字"endif":
:!zeal vim:endif
定义以下快捷键,将根据当前文件类型在相应的Docset中,查找当前光标下的单词:
:nnoremap <Leader>z :exec "!zeal " . expand(&ft) . ":" . "<cword>"<CR>
使用以下命令,在将信息输出到屏幕的同时,也会保存到指定的文件中:
: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
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'选项,用于控制信息显示的种类和详细程度。其默认值为:
: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'
surround 插件可以快速编辑围绕在内容两端的字符(pairs of things surrounding things),比如成对出现的括号、引号,甚至HTML/XML标签等。
推荐您使用vim-plug或Vundle等插件管理器,来安装GitHub上的surround插件。
以下将利用实例来介绍surround插件的主要功能,请注意:
在常规模式、插入模式和可视化模式下,可以分别使用ys
和S
命令来新增环绕字符:
模式 | 目标 范围 | 新增 内容 | 原始文本 | 命令 | 更改效果 |
---|---|---|---|---|---|
常规模式 | 单词 | 字符 | Hello World | ysiw* | Hello *World* |
单词 | 标签 | Hello World | ysiwt<strong> | Hello <strong>World</strong> | |
单词 | 括号 | print var1, var2 | ys3w) | print (var1, var2) | |
行尾 | 括号 | print var1, var2 | ys$) | 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 World | yss" | "Hello World" | |
整行 | 标签 | Hello World | ysst<p> | <p>Hello World</p> | |
整行 | 新行 | Hello World | ySS" | " Hello World " | |
插入模式 | 引号 | <CTRL-g>s" | "" | ||
标签 | <CTRL-g>S<html> | <html> </html> | |||
字符可视化模式 | 选中的文本 | 括号 | print var1, var2 | veeS) | 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> |
请注意:
使用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)/2 | ds( | 123+4*56/2 |
单词 | 标签 | <div>Hello</div> | dst | Hello |
surround插件主要提供以下命令:
ys | 添加环绕字符 |
yS | 添加环绕字符并拆分新行 |
yss | 为整行添加环绕字符 |
ySS | 为整行添加环绕字符并拆分新行 |
cs | 修改环绕字符 |
cS | 修改环绕字符并拆分新行 |
ds | 删除环绕字符 |
surround插件可以识别并处理以下目标实体:
( )
{ }
[ ]
< >
`
"
'
t
(标签)w
(单词)如果查看surround插件的源码,将会发现快捷键逐一定义在surround.vim文件中:
也就是说,我们可以直接在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
一,舍本逐末。为了输入环绕字符的小需求,而发明碾压一切的大轮子。颇有些杀鸡用牛刀的意味。而且平白多出来的快捷键和命令,不但冗长而且别扭,操作起来总有种有苦难言的感觉。
二,盛名之下,其实难副。对于一个被不断被提及的知名插件,从功能和体验上都差强人意,着实让人失望。也许,这就是见面不如闻名吧。
以上,皆为一家之言,还请自行斟酌。
程序员对于制表符常常有不同的偏好,有的使用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命令的格式
以下为正确的模式行:
/* vim:tabstop=4:expandtabs:shiftwidth=4 */
以下模式行选项中包含空格,将报错“Error E518: Unknown option: */”:
/* vim: noai:ts=4:sw=4 */
(2)包含set命令的格式
以下为正确的模式行:
/* 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 | 设置检查模式行的行数 |
♦ 删除所有行首的空格:
:%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
关于删除换行和空行,请参阅换行(Line Feed)章节。
♦ 将单数单词,替换为复数:
:%s/^Note[□:s]*/Notes:□/g
其中,"Note[□:s]"将匹配"Note□","Notes", 和"Note:";而星号则会匹配零个后缀,即"Note"。
♦ 匹配引号包围的字符串(包含换行):
"\_[^"]*"
♦ 匹配特定单词包围的字符串(包含换行):
\(we\).*\1
其中,"\(we\)"将指定单词捕获为组,然后使用"\1"反向引用捕获组,以定义字符串的边界。
关于捕获组的详细介绍,请参阅捕获组(Groups)章节。
♦ 删除下图中黄色高亮区域,即行头以点分隔的章节号:
:%s/^[1-9][0-9]*\.[1-9][0-9.]*□//
其中,模式末尾的"[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}
其中:
请注意,以上表达式均采用Very Magic模式。
♦ 匹配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]?)
以上表达式分为四段重复的捕获组,每组数字的范围如下图所示: