Vim 配置

打印信息

  • :echo:打印信息,但是信息不会保存
  • :echom:打印信息会保存在:messages
  • :messages:查看:echom保存的信息

设置选项

  • 设置选项方式

    • 命令行一次设置多个选项::set number numberwidth=6
    • 本地缓冲区设置::setlocal nonumber
  • 设置 bool 选项

    • :set <name>:打开选项
    • :set no<name>:关闭选项
    • :set <name>!:切换选项
    • :set <name>?:查看选项值(返回或no
  • 设置键值选项

    • :set <name>=value:设置选项值
    • :set <name>?:查看选项值
    • 键值选项支持运算:+=

statusline 状态栏设置

  • 状态栏代码通用格式:%-0{minwid}.{maxwid}{item}

    • -:左对齐
    • 0:使用”0”填充
    • %=:切换到状态栏右侧

    • %f:文件名

    • %F:完整路径文件名
    • %y:文件类型([text],[python])
    • %Y:文件类型(TEXT,PYTHON)

    • %l:当前行号

    • %L:总行数
    • %v/%V:列号
    • %c:字符列号
    • %p:文件位置百分比

    • %n:buffer number

    • %{&ff}:文件格式(DOS、UNIX)
    • %b:当前字符ACSII码
    • %B:当前字符16进制值
    • %m:modified flag([+],[-]表示不可修改)
  • 设置状态栏显式格式,既可以一行完成配置,也可以分开配置

    1
    2
    3
    4
    5
    6
    set statusline=%f\ -\ filetype:\ %y
    set statusline=%f
    set statusline+=%=
    set statusline+=%l
    set statusline+=/
    set statusline+=%L
    • 中间空格需要用“\“转义,“%%”转义“%”
  • laststatus:设置状态栏显示模式

    • 1:默认值,两个以上窗口才显示
    • 2:一直显示

折叠设置

  • foldmethod
    • manual:手动折叠选中的行(默认 zf 触发)
    • marker{{{` 到 `}}} 标记待折叠行(默认 za 触发)
    • indent:折叠缩进
    • syntax:语法折叠
  • foldlevel=<num>:设置 indent 折叠起始水平(zm 触发),即从 <num> 水平开始尝试折叠
  • foldlevelstart=<num>:设置文件打开时默认折叠水平
    • -1:初始不折叠
  • foldcolumn=<num>:用 <num> 行表示可可折叠状态

一些常用关键字

  • iskeyword=@,_,48-57,192_255:指定关键字

    • 下划线
    • ASCII 码位在 48-57 之间的字符(0-9)、192-255之间的字符
  • conceallevel=0:隐藏等级

    • 1
    • 2

键盘映射

1
:<mode>map <mark> {lhs} {rhs}
  • 注意:映射后不能跟注释,vim会认为整行都是命令

映射工作模式

  • 映射的工作模式可区分 6 种
    • normal 模式:输入命令时
    • visual 模式:可视区域高亮并输入命令时
    • select 模式:类似可视模式,但键入的字符对选择区替换
    • operator-pending 模式:操作符等待中
    • insert 模式:包括替换模式
    • command-line 模式:输入 :/ 命令时

映射命令设置

  • 映射命令设置的模式如下,对应都有如下非递归、取消命令

    • <mode>noremap[!]:非递归映射,即不会在其他映射中再次被展开
    • <mode>unmap[!]:取消映射
    • <mode>mapclear[!]

    |命令|模式| |——-|——-| |:map|normalvisualselectoperator-pending| |:nmap|normal| |:vmap|visualselect| |:smap|selection| |:xmap|visual| |:omap|operator-pending| |:map!|insertcommand-line| |:imap|insert| |:lmap|insertcommand-lineLang-Arg| |:cmap|command-line| |:tmap|终端作业|

特殊参数

  • 映射特殊参数

    • <buffer>:映射将局限于当前缓冲区
      • 优先级比全局映射高
      • 清除映射时同样需要添加参数
      • 可使用 <leader> 替代 <localleader> 可工作,但是不推荐
    • <nowait>:存在较短映射时,失效以其作为前缀的较长映射
    • <silent>:映射不在命令行上回显
    • <special>:特殊键可以使用<>记法
    • <script>:映射只使用通过以<SID>开头来定义的脚本局部映射来重映射优右值中的字符
    • <unique>:若存在相同命令、缩写则定义失败
      • 定义局部映射时,同样会检查全局映射
    • <expr>:映射的右值将被作为表达式被计算
  • 特殊参数说明

    • 特殊参数的尖括号<>是本身具有的,必须紧跟命令后面
    • 有些特殊参数在取消映射时同样需注明

omap

  • 应用方法:operator (操作) + operator-pending (移动、范围选择)
  • 预定义的 operator-pending 映射如 wawi(t,

    |按键 |操作 |移动 | |———-|———————-|———————-| |dw |删除(delete) |到下一个单词 | |ci( |修改(change) |在括号内 | |yt, |复制 |到逗号前 |

  • 自定义的 operator-pending 映射则需要

    • 选取一定范围:可同时指定开头、结尾(一般通过进入 visual 模式下选择范围)

      1
      2
      3
      4
      5
      6
      7
      " 下个括号内内容
      onoremap in( :<c-u>normal! f(vi(<cr>
      " 当前括号内容
      onoremap il( :<c-u>normal! f)vi(<cr>`
      " 选取使用 `===` 标记 markdown 标题
      onoremap ih :<c-u>execute "normal! ?^==\\+$\r:nohlsearch\rkvg_"<cr>
      onoremap ah :<c-u>execute "normal! ?^==\\+$\r:nohlsearch\rg_vk0"<cr>
    • 指定光标位置:光标当前位置为开头、指定位置为结尾

      1
      2
      " 移动至 `return` 前一行
      onoremap b /return<cr>

leaderslocalleader

leaderlocalleader:作为“前缀”的不常用的按键,后接其他字符作为整体映射

  • 用途

    • 避免覆盖太多按键原始功能
    • 约定俗成的规范,容易理解
    • 方便更改 <leader><localleader> 作为前缀设置
      • <leader>:对全局映射而设置的映射的前缀
      • <localleader>:只对某类(个)文件而设置的映射的前缀
    • <leader><localleader> 除了设置不同以外,没有太大区别,应用场合时约定规范,不是强制性的
  • <leader><localleader> 设置

    1
    2
    3
    4
    :let mapleader = "-"
    :nnoremap <leader>d dd
    :let maplocalleader = "\\"
    :nnoremap <buffer> <localleader>c I#<esc>
    • vim 会对 mapleadermaplocalleader 进行特殊的处理,不是简单的声明

Abbreviations 缩写

  • iabbrev:紧跟缩写输入非关键字后,缩写会替换为相应的完整字符串
    • 相较于映射
      • iabbrev 用于 insertreplacecommand-line 模式
      • iabbrev 会注意缩写前后的字符,只在需要的时候替换
    • iabbrev 同样支持特殊参数
      • <buffer>:仅限本地缓冲区
1
2
3
4
5
6
7
8
" 纠错
iabbrev waht what
" 简化输入
iabbrev @@ xyy15926@gmail.com
" 替换 `----` 为前个单词
iabbrev <buffer> ---- &mdash
" 替换 `return` 为 null
iabbrev <buffer> return nopenopenope
  • :set iskeyword? 即可查看关键字字符

Autocmd 自动命令

autocmd 使用

  • autocmd 注意事项

    • 同时监听多个事件,使用 , 分隔,中间不能有空格
    • 一般同时监听 bufnewfilebufread,这样打开文件时无论文件是否存在都会执行命令
    • 所有事件后面都需要注明适用场景,可用*表示全部场景,中间也不能有空格
    • autocmd 是定义命令,不是执行命令
      • 每次执行都会定义命令,而vim 不会忽略重复定义
      • 如::autocmd bufwrite * :sleep 200m,每次执行时都会重复定义命令
  • 缓冲区事件

    1
    2
    3
    4
    autocmd bufnewfile * :write
    autocmd bufnewfile *.txt :write
    autocmd bufwritepre *.html :normal gg=g
    autocdm bufnewfile,bufread *.html setlocal nowrap
  • filetype 事件(vim 设置缓冲区 filetype 时触发)

    1
    2
    3
    4
    autocmd filetype javascript nnoremap <buffer> <localleader>c i//<esc>
    autocmd filetype python nnoremap <buffer> <localleader>c i#<esc>
    autocmd filetype javascript :iabbrev <buffer> iff if ()<left>
    autocmd filetype python :iabbrev <buffer> iff if:<left>

augroup 自动命令组

  • 自动命令组

    1
    2
    3
    4
    augroup cmdgroup
    autocmd bufwrite * :echom "foo"
    autocmd bufwrite * :echom "bar"
    augroup end
  • 注意事项

    • 类似 autocmdvim 不会忽略重复定义,但是可以通过 :autocmd! 清除一个组

      :augroup cmdgroup : autocmd! : autocmd bufwrite :echom “foo” : autocmd bufwrite :echom “bar” :augroup end

Vim安装

安装选项

1
2
3
4
5
6
7
8
$ ./configure --with-features=huge\
--enable-multibyte \
--enable-python3interp \
--with-python3-config-dir=/usr/lib64/python3.4/config-3.4m/ \
--enable-pythoninterp \
--with-python-config-dir=/usr/lib64/python2.7/config/ \
--prefix=/usr/local
--enable-cscope
  • 按照以上命令配置,编译出的Vim版本中是动态支持 +python/dyn+python3/dyn

  • 此时Vim看似有python支持,但是在Vim内部 :echo has("python"):echo has("python3")都返回0

  • 之后无意中尝试去掉对python的支持,编译出来的Vim就是 可用的python3,不直到为啥

Vim KeyMapper CMD

Vim模式

Normal模式

Insert模式

Visual模式

Quickfix模式

quickfix模式主要思想时保存一个位置列表,然后提供一系列命令, 实现在这个位置列表中的跳转

  • 位置列表来源

    • 编译器输出信息
    • grep命令输出信息(cscope命令)
    • :vimgrep命令
  • quickfix中常用的命令有

    • :copen/:cw:打开quickfix模式窗口
    • :cclose:关闭quickfix窗口
    • :cc:显示详细错误信息
    • :cp:跳至下一个错误
    • :cn:跳至上一个错误
    • :cl:列出所有错误
    • :cw:如果有错误列表,则打开quickfix窗口
    • :colder/col:到前一个旧错误列表
    • :cnewer/cnew:到后一个新错误列表

Ex模式

底层编辑模型,normal下Q进入

Paste模式

Motion快捷键

normal模式下移动,visual模式下选取,无特殊说明visual和normal 模式通用

固定移动

基本

  • hjkl:左、上、下、右
  • gj/gk:虚上、虚下(光标移动排版意义上行) (可以尝试noremap交换和j/k的逻辑方便使用)
  • M:窗口中间行首各非空白字符
  • H/L:窗口顶/底scrolloff处行首各非空白字符
  • <c-i>/<c-o>:跳至下一个/上一个编辑处 (可以跨文件)

行内

  • w:下个单词开头
  • aw:整个单词
  • b/e:当前单词首/尾
  • W/B:下/上个非空格开头
  • E: 下个非空格结尾
  • g_:行尾,visual模式下不包括换行符
  • $:行尾,visual模式下包括换行符
  • 0:行首
  • ^:非空白字符行首
  • |:当前行第一列
  • <int>|:当前行第n列(不是字符)

全文

  • gg:文件首
  • G:文件尾
  • <int>G:第<int>
  • '<:之前visual模式选取起始行(一直保存直至下次选取)
  • '>:之前visual模式选取结束行
  • {/}:下/上一个空行
  • .:当前行
  • %:全文选取???

组合

这些快捷键的效果取决于当前状态

行内

  • f/F:向前/后移动到某字符(;,同向、反向重复)
  • t/T:till,向前/后移动到某字符前
  • i:在某个区域((), [], {}, w等)内(显然不能单独用 于normal)

全文

  • //?:命令行向前、向后查找(nN同向、反向重复)
  • */#:向前、向后查找当前单词
  • g*/g#:向前、向后查找当前字符串,包括非单独单词

Operation快捷键

区域进行操作可以和motion连用

内容修改

插入

  • i:insert进入insert模式
  • I(normal):行首insert进入insert模式
  • I(visual block):选中区域同时插入
  • a:add进入insert模式
  • A:行尾add进入insert模式
  • <c-e>:insert模式下复制下行当前位置字符至当前行

删除

  • d:删除选取区域
  • c:删除(修改)选中区域,进入insert模式
  • x/X:删除当前/前一个字符
  • s:删除字符,进入insert模式
  • dd:删除当前行
  • D:normal模式删除当前位置至行尾
  • <c-h>/<m-h>:insert模式backspace

复制、粘贴

  • ["<reg>]y:复制选中区域至寄存器<reg>,默认 "<reg>
  • yy:复制当前行
  • ["<reg>]p:粘贴"<reg>寄存器中内容,默认"<reg>

其他

  • J:合并下一行,<space>分隔
  • u/U(visual):转换为小、大写
  • ~(normal):当前字符大、小写切换(光标移动至下个字符)
  • ~(visual):选中区域大、小写切换
  • gu/gU(normal)区域转换为小、大写
  • g~区域大、小写切换
  • [num]>/<:右/左移动区域num个shiftwidth单位
  • =区域格式化(修改为标准缩进)
  • <c-d>/<c-i>:insert模式减少/增加缩进
  • gc(visual/normal):选中区域按行注释/取消注释 (应该是按vim的filetype确定注释格式)
  • <c-a>/<c-x>:将光标下数字增加/减少1,支持多种进制

功能性

记录

  • q<reg>:宏记录,记录行为于寄存器<reg>中,按下q则 停止记录
  • @<reg>:调用寄存器<reg>中的宏操作(不一定是q<reg> 记录的结果)
  • m<char>:记录当前位置于<char>中(不是寄存器中未知)
  • `\:回到<char>中记录的位置

撤销、redo

  • .:重复上一个操作
  • u:撤销上一个操作
  • <c-r>:继续执行,撤销u
  • <c-m>:等同于<cr>

外部功能

  • K:对当前单词调用keywordprg设置的外部程序,默认“man”

Diff

  • ]c/[c:比较窗口中移至下个不同的为止
  • do/dp:将当前比较窗口中不同区域,同步为/至另一个 窗口该位置

其他

  • q::vim命令历史窗口

界面变动

窗口

Window

  • <c-w-h/j/k/l>:切换至左/下/上/右窗口
  • <c-w-w>:轮换窗口(切换活动窗口)
  • <c-w-t/b/p>:切换至最左上/右下/前个窗口
  • <c-w-+/->:竖直方向扩展/收缩当前窗口
  • <c-w->/<>:水平方向扩展/收缩当前窗口
  • <c-w-=>:恢复当前窗口高度
  • <c-w-H/J/K/L>:移动窗口至tab左/下/上/右,占据全部高/宽
  • <c-w-T>:移动窗口至新tab
  • <c-w-r/x>:交换窗口位置(具体逻辑未知)
  • ZZ:保存退出
  • ZQ:放弃保存退出

Tab

  • [n]gt/gT:下/上一个tab;第n个tab

内容

折叠

  • foldmethod=marker{{{`、`}}}标记折叠区域(各花括号之间无空格)

    • zf:创建折叠(在选中区域前后添加标记)
      • zf[n]G:创建当前行至第n行折叠
      • [n]zf[+]:创建当前行至后n行折叠
      • [n]zf[-]:创建当前行至前n行折叠
    • zd:删除 包含 当前位置折叠
    • zD递归 删除包含当前位置折叠、及子折叠
    • zE:删除窗口中所有折叠
    • za:折叠 toggle
    • zo:折叠展开
    • zc:折叠
  • foldmethod=indent:缩进标记折叠

    • zc:折叠
    • zC递归 折叠
    • zo:展开折叠
    • zO:递归展开折叠
    • [z:移至当前折叠开始
    • ]z:移至当前折叠末尾
    • zj:移至下个折叠开始(包括关闭折叠)
    • zk:移至上个折叠结束(包括开闭折叠)
    • zm:提高折叠水平,即依次折叠当前最高水平缩进
    • zr:降低折叠水平,即依次展开当前最高水平缩进
    • zn:禁用折叠
    • zN:启用折叠
  • foldmethod=manual:手动折叠

    • zf<range>:折叠选中区域
      • zf70j:折叠之后70行
      • zfa(:折叠 ( 包围区域
  • mkview:保存折叠状态

  • loadview:载入折叠状态

Vim Cmd常用命令

内容相关

查找

//?

:/foo向下查找,:?foo向上查找

  • set ingorecase时,不敏感查找;set smartcase时,如果 查找中有大写字符则敏感;
  • :/foo\c手动强制大小写不敏感,:/foo\C强制敏感
  • nN重复同向、反向之前查找
:vimgrep

文件间搜索

1
:vim[grep] /pattern/[g][j] files
  • 选项

    • g:全局匹配(匹配每行全部)
    • j:查找完毕后,进更新quickfix列表,光标不跳转
  • files

    • %:当前文件
    • *:当前目录
    • **/*:仅子目录
    • **/xxxx:当前目录及子目录所有满足xxxx模式文件
    • pattern:满足pattern的文件
global
  • [range]范围(默认整个文件)中查找{pattern},标记 匹配行
  • 对匹配行执行命令{command}(默认print命令)
    • 若标记行在被操作之前已经被删除、移动、合并等而消失, 则不对器执行操作
1
:[range]g[lobal][!]/{pattern}/{command}
  • 选项
    • [!]:对不匹配者执行草在
1
2
3
4
5
6
7
8
9
10
11
12
:g/^/m 0
# 将文件反序
:g/^/+1 d
:%normal jdd
# 删除偶数行
:g/^/d|m.
:%normal jkdd
# 删除奇数行
:g!/aaa/d
# 删除不包含`aaa`行
:g/aaa/"ay
# 复制包含`aaa`行至寄存器`"`

替换

:s
1
:[start,end]s/foo/bar[/i][I][g]
  • 替换区域:默认只替换当前行
    • 手动指定具体行号::2,4s/foo/bar(左闭右开)
    • 特殊符号
      • 全文替换%:%s/foo/bar
      • 第一行^:^,4s/foo/bar
      • 当前行.:.,6s/foo/bar
      • 末尾行$:4,$s/foo/bar
    • visual模式下,手动选择区域命令行自动补全为:'<,'>
  • 替换标志
    • 大小写不敏感/i\c:%s/foo/bar/i:%s/foo\c/bar
    • 大小写敏感/I\C%s/foo/bar/I:%s/foo\C/bar
    • 全局替换/g(替换每行全部模式)::%s/foo/bar/g
      • 默认情况下只替换首个模式:foo,foobar被替换为 bar,foobar
      • 全局替换模式下:foo,foobar被替换为bar,barbar
  • 交互(确认)替换::%s/foo/bar/c,每次替换前会询问
  • 超级变量
    • &:代表被替换模式字串

文本移动

>/<
1
2
:[range]>
:[range]<
  • 范围内文本块右、左移动1个shiftwidth
  • 移动num个shiftwidth添加num个>/<
move
1
:[range]m[ove] [n]
  • 移动范围内行至第[n]
1
2
:m0
# 移动当前行至首行
t
1
:[range]t [n]
  • 复制范围内至第[n]
1
2
:t.
# 复制当前行至下行

文件相关

放弃修改、重新加载、保存

  • :w[rite]:保存此次修改
  • :e!:放弃本次修改(和:q!不同在于不会退出vim)
  • :bufdo e!:放弃vim所有已打开文件修改
  • :e:重新加载文件
  • :e#:当前窗口加上个buffer(反复切换)
  • :bufdo e:重新加载vim所有已打开文件
  • :saveas new_file_name:另存为,不删除原文件
  • :sb[n]:split窗口加载第n个buffer
  • :b[n]:当前窗口加载第n个buffer
  • :n[n]:当前窗口加载下/第n个buffer

Window

  • :sp[lit]:水平分割当前窗口,展示当前文件
  • :vs[plit]:竖直分割当前窗口,展示当前文件
  • :new:水平分割当前窗口,新文件
  • :vnew:竖直分割当前窗口,新文件
  • :sview:水平分割当前窗口,只读[缺省当前]文件
  • :[n]winc >/<:水平方侧扩展/收缩
  • :[n]winc +/-:竖直方向扩展/收缩
  • :res+/-[n]:竖直方向扩展/收缩
  • :vertical res+/-[n]:水平方向扩展/收缩
  • :ressize[n]:高度设置为n单位
  • :vertical res[n]:宽度设置为n单位
  • :q[uit][!]:退出当前窗口
    • !:强制退出,修改不保存
  • :close:关闭当前窗口(不能关闭最后窗口)
  • :only:关闭其他窗口
  • :qa:退出所有窗口
  • :wq:保存、退出当前窗口
  • :x:类似于wq,但是未修改则不写入

注:

  • 水平方向:扩张优先左侧变化,收缩右侧变化
  • 竖直方向:扩展收缩均优先下侧变化

Tab

  • :tabnew [opt] [cmd] [file_name]:打开新tab
  • :tabc:关闭当前tab
  • :tabo:关闭其他tab
  • :tabs:vim cmd区域查看所有打开的tab信息
  • :tabp:查看前一个tab
  • :tabfirst/:tablast:第一个/最后一个tab
  • :tabn [num]:查看下一个/第num个tab

Diff

  • :diffsplit [filename]:上下分割窗口和当前窗口比较

    • 默认同当前文件进行diff
  • :difft:将当前窗口变为比较窗口

    • 若没有其他比较窗口,则没有明显变化
    • 若存在其他比较窗口,则加入比较
  • :diffu[pdate][!]:更新当前比较窗口

    • 比较状态下修改当前文件后,重新生成比较信息
    • !:重新载入文件后更新(外部修改文件)
  • :diffo[!]:关闭当前窗口比较状态

    • !:关闭所有窗口比较状态

Session

  • :mksession[!] <session-file-name>:将当前状态写入 session 文件
  • :source <session-file-name>:载入已有 session 文件

其他

多行语句

“|”管道符可以用于隔开多个命令:echom "bar" | echom "foo"

:vertical

:vertical基本可以用所和窗口有关命令之前,表示左右(分割)

  • :vert split/:vs:左右分割窗口
  • :vert sb[n]:左右分割窗口载入buff[n]
  • :vert diffs file_name:左右分割窗口diffs
  • :vert res +/-[n]:调整窗口大小

其他CMD命令

编辑过程中使用shell

  • :!{shell command}即可直接执行shell命令并暂时跳出vim

    • :r !{shell command}可以将输出结果读取到当前编辑
    • :w !{sheel command}可以将输出结果输出到vim命令行
  • :shell即可暂时进入到shell环境中,$exit即可回到vim中

  • <c-z>暂时后台挂起vim回到shell环境中,$fg即可回到之前 挂起的进程(此时为vim,详见fg命令)

读取结果

  • :read cmd:读取cmd结果至光标下一行
    • :read !date:读取系统date命令结果

交换文件处理

  • 确认需要恢复:直接恢复R

  • 确认丢弃:直接删除D

  • 没有明确目标:只读打开O

  • 比较交换文件、现在文件差别

    • 恢复打开R
    • 另存为其他文件:saveas filname.bak
    • 与当前文件对比:diffsplit filename
  • 一般不会直接Eedit anyway

Vim命令行参数

vim

  • $ vim [filname]:打开一般窗口
    • -r [filename]:常看交换文件(特定文件对应交换文件)
    • -R [filename]:只读方式打开文件
    • -S session-file:打开session的方式启动vim
      • 需要 :mksession[!] <session-file> 先创建 session 文件

vimdiff

  • $ vimdiff [file1] [file2]:打开比较窗口
    • -u:合并模式比较
    • -c:上下文模式比较
  • 后面两个模型可常用于输出重定向至新文件

Vim 内建函数、变量

文件、路径相关函数

  • expand(option):根据参数返回当前文件相关信息
  • fnamemodify(file_name, option):返回当前文件夹下文件 信息
  • globpath(dir, type):返回的dir下符合type的文件 列表值字符串,使用,分隔,type**时将递归的列出 文件夹及文件

特殊变量

command-line模式的特殊变量,在执行命令前会将其替换为相应的 变量

  • <cword>:光标处单词
  • <cWORD>:光标处单词大写形式

寄存器

寄存器相关快捷键、命令

  • <c-r><reg>:insert模式下直接输入<reg>中的值

一般寄存器

Readonly Register

Expression Register("=

"=实际上并不是一个寄存器,这是使用命令表达式的一种方法, 按下=之后,光标会移动到命令行,此时可以输入任何表达式, (不只有"=才会激活命令行,<c-m>"也能激活) 输入表达式之后

  • 按下<esc>,表达式值被丢弃
  • 按下<cr>,表达式值计算后存入"=
    1
    2
    :nnoremap time "=strftime("%c")<cr>p
    :inoremap time <c-r>strftime("%c")<cr>

之后:put或者按下p将粘贴"=中的值

寄存器中的值一定是字符串,如果是其他类型变量,会被强制 转换之后存入"=寄存器中

Vim特殊

换行

  • \0:空转义序列(ASCII码位0)<Nul>

    • <c-v> 000:输入<Nul>
    • Vim在内存中使用<NL>存储<Nul>,在读、写文件时即 发生转换
    • Vi无法处理<Nul>,应该是为了兼容Vi
  • \n:换行转义序列<NL>

    • <c-v><c-j>:输入<NL>,会被替换为输入<Nul>, 等同于<c-v> 000
    • 在搜索表达式中:字面意义的newline序列被匹配
    • 在替换表达式中:在内部被替换为<Nul>被输入,即 不再表示newline
  • \r:回车转义序列<CR>

    • 被Vim视为为换行,可在替换表达中表示<NL>
    • <c-v><c-j>:输入<CR>字符本身
  • vim在内存换行应该同一使用<CR>,在读、写时,根据当前 fileformat设置自动转换换行字符(序列)

Vimscripts 编程

变量

普通变量

创建变量、变量赋值都需要用到let关键字

1
2
3
4
let foo = "bar"
echo foo
let foo = "foo"
echo foo

数字

  • Number32位带符号整形(整形之间除法同c)

    • :echo 0xef:16进制
    • :echo 017:8进制(鉴于以下,不建议使用)
    • :echo 019:10进制(9不可能出现,vim自动处理)
  • Float

    • :echo 5.1e-3:科学计数法)
    • :echo 5.0e3:科学计数法中一定要有小数点

类型转换:Number和Float运算时会强制转换为Float

字符串

类型转换
  • +if这些“运算”中,vim会强制转换变量类型

    • 数字开头的字符串会转为相应Number(即使符合Float也 会舍弃小数点后)
    • 而非数字开头 则转换为0
  • 连接.

    • .连接时vim可以自动将Number转换为字符串然后连接
    • 但是对于 Float,vim不能自动转换
  • 转义\

    • 注意echom "foo\nbar"类似的输出时,echom不会像 echo一样输出两行,而是将换行输出为vim默认 (即使设置了listchars)的“换行符”
  • 字符串字面量''

    • 所见即所得(py中r’’),注意连续两个单引号表示单引号
  • 内建字符串函数

    • strlen(str)(len(str)效果对字符串同)
    • split(str, token=" ")
    • join([str], token=" ")
    • tolower(str)
    • toupper(str)
  • 字符串比较====?==#

    • ==:对字符串比较是否大小写敏感取决于设置

      1
      2
      3
      4
      5
      6
      7
      8
      9
      set noignorecase
      if "foo"=="Foo"
      echo "bar"(不会输出)
      endif

      set ignorecase
      if "foo"=="Foo"
      echo "bar"(会输出)
      endif
    • ==?:对字符串比较大小写永远不敏感

    • ==#:对字符串比较大小写永远敏感

  • <>:同上,也有3种

集合类型变量

列表

vim列表特点

  • 有序、异质
  • 索引从0开始,可以使用负数索引,使用下标得到对应元素
  • 支持切割
    • 是闭区间(这个和python不同)
    • 可以负数区间切割
    • 可以忽略起始/结尾索引表示从0开始/末尾截至
    • 切割区间越界是安全的

      字符串可以像列表一样切割、索引,但是不可以使用负数 索引,却可以使用负数切割

  • +用于连接两个列表

列表内建函数

  • add(list, item):添加新元素
  • len(list):列表长度
  • get(list, index, default_val):获取列表元素,越界则 返回default_val
  • index(list, item):返回元素索引,不存在返回-1
  • join(list, token):将列表中元素转换为字符串后,使用 toke连接,缺省为<space>
  • reverse(list):反转列表

字典

字典特性

  • 值是异质的,键可以不是字符串,但是会被强制转换为字符串, 因此,在查找值时也可以使用非字符串dict[100],同样会被 强制转换为字符串dict["100"]之后查找

  • 支持属性.查找,甚至可以后接Number

  • 添加新元素就和普通赋值一样:let dict.100 = 100

  • 移除字典中的元素

    • remove(dict, index)
    • unlet dict.index/unlet dict[index] 移除不存在的元素事报错

允许定义时多一个,

内建函数
  • get(dict, index, default_val):同列表

  • has_key(dict, index):检查字典中是否有给定键,返回 1(真)或0(假)

  • item(dict):返回字典键值对,和字典一样无序

  • keys(dict):返回字典所有键

  • values(dict):返回字典所有值

作为变量的选项

  • bool选项输出0、1

    1
    2
    :set wrap
    :set nowrap
  • 键值选项

    1
    2
    :set textwidth=80
    :echo &textwidth
  • 本地选项(l:作用域下)

    1
    let &l:number=1
  • 选项变量还可以参与运算

    1
    2
    let &textwidth=100
    let &textwidht = &textwidth + 10

作为变量的寄存器

1
2
3
4
let @a = "hello"
echo @a
echo @"
echo @/

变量作用域

<char>:开头表示作用域变量

  • 变量默认为全局变量
  • b::当前缓冲区作用域变量
  • g::全局变量

语句

条件语句

vim中没有not关键字,可以使用!表示否定

  • !:否
  • ||:或
  • &&:与
1
2
3
4
5
6
7
8
if "1one"
echo "one"(会输出)
endif
if ! "one"
echo "one"(会输出)
else
echo "two"
endif

finish关键字

finally时结束整个vimscripts的运行

循环语句

for语句

1
2
3
4
5
let c = 0
for i in [1,2,3]
let c+=i
endfor
echom c

while语句

1
2
3
4
5
6
7
let c = 1
let total = 0
while c<=4
let total+=c
let c+=1
endwhile
echom total

函数

没有作用域限制的vimscripts函数必须以大写字母开头 (有作用域限制最好也是大写字母开头)

1
2
3
4
5
6
7
8
func Func(arg1,...)
echo "Func"
echo a:arg1(arg1)
echo a:0(额外(可变)参数数量)
echo a:1(第一个额外参数)
echo a:000(所有额外参数的list
return "Func"
endfunction

function后没有紧跟!时,函数已经被定义,将会给出 错误,而function!时会直接将原函数替换,除非原函数正在 执行,此时仍然报错

  • 调用方式

    • :call Func():call直接调用(return值会被直接丢弃)
    • :echo Func():表达式中调用
  • 函数结束时没有return,隐式返回0

  • 函数参数:最多20个

    • 参数全部位于a:参数作用域下

      • a:arg1:一般参数
      • a:0:额外(可变)参数数量
      • a:n:第n个额外参数
      • a:000:包含额外参数list
    • 参数不能重新赋值

vim中函数可以赋值给变量,同样的此时变量需要大写字母开头, 当然可以作为集合变量的元素,甚至也可以作为参数传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function! Reversed(l)
let nl = deepcopy(a:l)
call reverse(nl)
return nl
endfunction

let Myfunc = function("Reversed")

function! Mapped(func, l)
let nl = deepcopy(a:l)
call map(nl, string(a:func) . '(v:val)')
return nl
endfunction

call Mapped(function("Reversed"), [[3,2], [1,2]])

let funcs = [function("Reversed"), function("Mapped")]

更多函数参见functions.vim(如果完成了)

Execute、Normal

  • :execute:把字符串当作vimscript命令执行(命令行输入) :execute "echom 'hello, world'"<cr>

    大多数语言中应该避免使用”eval”之类构造可执行字符串,但是 vimscripts代码大部分只接受用户输入,安全不是严重问题, 使用:execute命令能够极大程度上简化命令

    :execute命令用于配置文件时,不要忽略结尾的<cr>, 表示“执行命令”

  • :normal:接受一串键值,并当作是normal模式接受按键

    • :normal后的按键会执行映射,:normal!忽略所有映射

    • :normal无法识别“”这样的特殊字符序列 :normal /foo<cr> 这样的命令并不会搜索,因为“没有按回车”

  • :execute和:normal结合使用,让:normal接受按下 “无法打印”字符(<cr><esc>等),execute能够接受 按键

    1
    2
    :execute "normal! gg/foo\<cr>dd"
    :execute "normal! mqA;\<esc>`q"

正则表达式

vim有四种不同的解析正则表达式的“模式”

  • 默认模式下\+表示“一个或多个之前字符”的正常+意义, 其他的符号如{,},*也都需要添加转义斜杠表示正常意义, 否则表示字符字面意

    • :execute "normal! gg/for .\\+ in .\\+:\<cr>: execute接受字符串,将\\转义,然后正则表达式解析, 查找pythonfor语句

    • :execute "normal! gg".'/for .\+ in .\+:'."\<cr>": 使用字符串字面量避免\\,但是注意此时\<cr>也不会 被转义为按下回车\n才是换行符),所以需要分开 书写、连接

  • \v模式下,vim使用“very magic”正常正则解析模式

    • :execute "normal! gg".'/\vfor .+ in .+:'."\<cr>"