星期五, 十二月 18, 2020

The Clothed/Naked Maja

 

The Clothed/Naked Maja

星期四, 十二月 17, 2020

星期一, 十一月 30, 2020

VIM学习笔记 定时器(timer)

自8.0版本起,包含+timers特性的Vim提供了定时器功能。利用定时器,可以在指定延时之后触发指定操作,也可以按照固定的时间间隔来重复执行任务。

启动定时器

使用timer_start()函数,可以启动定时器并返回定时器ID:

timer_start({time}, {callback} [, {options}])

其中:

  • time,指定时间间隔,单位为毫秒(milliseconds);
  • 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()

timer_info_all

使用带有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()停止所有定时器

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

星期一, 十一月 23, 2020

VIM学习笔记 作业(job)

在传统的单线程模式下,运行外部命令时,将中断用户当前的编辑操作,并等待命令完成才可以返回vim。

自8.0版本起,包含+channel和+job特性的Vim将可以支持异步操作。Vim使用作业(job)来启动进程,并利用通道(channel)和其他进程通信。

利用异步支持,可以在后台进行复杂耗时的操作(比如使用外部grep工具查找文本),不必等待外部命令结束即可返回Vim,而不中断前台的正常编辑。在外部命令结束运行时,可以通过回调函数来处理输出结果。

job_start_version

例如使用:!ls外部命令,将在屏幕底部列示目录内容,并等待用户按回车键以返回常规模式,此时用户无法进行其它操作:

shell_cmd_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命令来查看信息历史,以确认命令执行结果:

job_start_ls_messages

使用"in_io"、"out_io"或"err_io"选项,可以将作业管道重定向到文件或缓冲区。

使用以下命令,可以将标准输出重定向至指定缓冲区:

:let job = job_start('ls', {'out_io': 'buffer', 'out_name': 'mybuffer'})

使用以下命令,则可以打开缓冲区查看输出信息:

:sbuf mybuffer

请注意,首行包含了“Reading from channel output...”的说明文字:

job_start_ls_out_io

使用以下任一命令,均可以将标准输出重定向至指定文件:

: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)

job_info

函数将返回包含详细信息的字典:

描述
statusjob_status()返回值
cmd启动作业的命令行参数列表
stoponexitVim结束时给作业发信号(缺省是 "term")
channeljob_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

job_start_out_mode_raw

使用以下命令,可以查看关于作业的帮助信息:

:help job

函数小结
job_start()启动作业
job_status()显示作业状态
job_info()显示作业的详细信息
job_stop()停止作业

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

星期五, 十一月 13, 2020

VIM学习笔记 静默执行命令(silent)

通常在使用!运行外部Shell命令时,将显示提示信息“Press ENTER or type command to continue”,需要用户点击回车键才可以返回常规模式。

shell_cmd_msg

使用silent静默执行命令

如果不希望显示提示信息,那么可以使用: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

zathura_foreground

使用以下命令,将打开与当前文件同名的PDF文档。由于zathura窗口在前台显示,所以无法在Vim窗口中继续进行编辑;关闭zathura窗口之后,不需要在Vim中点击回车键即可返回常规模式:

:silent !zathura %:r.pdf

使用以下命令,将在后台打开与当前文件同名的PDF文档。由于zathura窗口在后台显示,所以无需关闭zathura窗口,也无需点击回车键,即可以在Vim窗口中继续进行编辑:

:silent exec '!zathura '.expand("%:r").'.pdf &'

实例:静默压缩文件

使用以下命令,可以使用Zip压缩当前文件:

:!zip test.zip %:p

屏幕将显示以下信息,并等待用户按回车键以返回常规模式:

shell_cmd_zip_msg

使用以下命令,则屏幕不会显示任何信息,并且自动返回常规模式:

: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()函数静默执行命令

通过调用system()函数,也可静默执行命令:

:call system('espeak "hello world" &')

函数system()!命令都可以调用外部命令,但system()函数不会切到shell终端,而是仍停留在vim界面。所调用外部命令的输出将会被system()函数捕获,可以将其保存在VimL变量中以供后续使用。

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

:help :silent

:help system()

关于本文中使用的第三方工具,请参阅以下网址:

  • eSpeak, text to speech
  • Zathura, document viewer
  • Zip, compression and file packaging/archive utility

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

星期二, 十一月 03, 2020

VIM学习笔记 全局命令-实例(Global Command-Examples)

执行单条命令

将所有未标志为“DONE”的行,都在行尾标注“TODO”:

:g!/DONE/s/$/ TODO/

:v/DONE/s/$/ TODO/

从第5行到第10行,在每一行下插入空行:

:5,10g/^/pu _

通过调用:sort命令,可以对指定范围内的文本进行排序。例如以下命令,将对“{}”包围的CSS属性按字母排序:

:g/{/ .+1,/}/-1 sort

g_cmd_range_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

g_cmd_sub_multi

调用函数

首先在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”的文件中。

g_cmd_range_lines

拆分当前文件,将每一行内容,分别保存为一个文本文件(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+*

g_cmd_register_append

请注意,vim使用“^J”符号表示换行。

使用"ap命令,即可以将寄存器a中存储的TODO信息粘贴出来:

    // TODO: something1
    // TODO: something2

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

星期一, 十一月 02, 2020

VIM学习笔记 全局命令(Global Command)

: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

g_cmd_range_del

全局替换

利用全局命令,可以仅针对符合查询条件的行,进行替换操作。例如使用以下命令,将包含“microsoft antitrust”的行中的“judgment”替换为“ripoff”:

:g/microsoft antitrust/s/judgment/ripoff/

可以在命令中指定查找的范围。比如以下命令,将在包含“microsoft antitrust”的前两行及后两行中进行替换:

:g/microsoft antitrust/-2,/microsoft antitrust/+2s/judgment/ripoff/c

g_cmd_range

以上命令末尾的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

g_cmd_mark_move

将以下文本中的“DESCRIPTION”部分,上移到“SYNTAX”之前:

:g /SYNTAX/.,/DESCRIPTION/-1 move /PARAMETERS/-1

首先匹配从包含“SYNTAX”的行到包含“DESCRIPTION”的上一行;然后将这些行移动到包含“PARAMETERS”的上一行。

g_cmd_range_move

以下两条命令均可以将所有不是以数字开头的行,移动到文件末尾:

: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'

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

星期四, 十月 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<上一篇 | 目录 下一篇>