Nextvi(1) 通用命令手册 Nextvi(1)
NAME Nextvi - 一个小型 vi/ex 终端文本编辑器
SYNOPSIS vi [-aemsv] [file ...]
DESCRIPTION Nextvi 是 vi(1) 命令行文本编辑器的现代克隆版本, 最初由 Bill Joy 于 1976 年为基于 Unix 的系统开发。 Nextvi 基于 vi(1) 的许多标准功能构建,包括 一种独特的模态界面,允许用户在 normal、 insert 和 command 模式之间切换,以高效地操作文本。 其他增强功能包括无限制的宏系统、 语法高亮、键位映射、双向 UTF-8 支持,以及 众多其他功能。Nextvi 依然保持高效、可移植 且易于修改,确保其在未来多年内持续相关且保持高质量。
OPTIONS -a 启用备用终端屏幕 -e 启动时进入 ex 模式 -m 禁用初始文件读取消息 -s 启动时进入原始 ex 模式 -v 取消设置所有选项
MANPAGE NOTATION 一个闭包,其中 x 表示字符字面量 [x] 一个闭包,其中 x 表示可选参数 {x} 一个闭包,其中 x 表示必需参数 "x" 一个闭包,其中 x 表示字符串 <^X> 表示 ctrl 键 X < > 空格分隔闭包中的替代项 # 闭包中的十进制表示 x-y 从 x 到 y 的范围
VI 普通模式 [#]j 向下移动 # 行 [#]k 向上移动 # 行 [#]+ [#]<^M> [#] 向下移动 # 行,光标位于缩进之后 [#]- 向上移动 # 行,光标位于缩进之后 [#]h 向左移动 # 列 [#]l 向右移动 # 列 [#]f{arg} 向前移动 # 次,定位到字符 arg [#]F{arg} 向后移动 # 次,定位到字符 arg [#]t{arg} 向前移动 # 次,直到字符 arg 之前 [#]T{arg} 向后移动 # 次,直到字符 arg 之后 [#], 向后重复上次 移动 # 次 [#]; 向前重复上次 移动 # 次 [#]E 向前移动 # 次,定位到单词末尾,跳过标点 [#]e 向前移动 # 次,定位到单词末尾 [#]B 向后移动 # 次,定位到单词开头,跳过标点 [#]b 向后移动 # 次,定位到单词开头 [#]W 向前移动 # 次,定位到单词开头,跳过标点 [#]w 向前移动 # 次,定位到单词开头 vw 切换 区域的单行模式 [#]( 向下移动 # 次,定位到下一个句子边界 [#]) 向上移动 # 次,定位到下一个句子边界 [#]{ 向下移动 # 次,定位到下一个 <{> 节 [#]} 向上移动 # 次,定位到下一个 <{> 节 [#][ 向下移动 # 次,定位到下一个 节 [#]] 向上移动 # 次,定位到下一个 节 ^ 移动到缩进后的行首 0 移动到行首 $ 移动到行尾 [#]| 跳转到第 # 列 [#] 向前移动 # 个字符 [#]<^H> [#] 向后移动 # 个字符 % 移动到最近的 <] ) } [ ( {> 对 {#}% 移动到第 # 百分比行号 '{} 移动到行标记 `{} 移动到带有光标位置的行标记 gg 跳转到缓冲区第一行 [#]G 跳转到缓冲区最后一行或第 # 行 H 移动到屏幕最高行 L 移动到屏幕最低行 M 移动到屏幕中间行 z. 以光标为中心居中屏幕 z<^M> z 以顶部行为中心居中屏幕 z- 以底部行为中心居中屏幕 [#]<^E> 向下滚动 1 或 # 行,保留 # 和光标位置 [#]<^Y> 向上滚动 1 或 # 行,保留 # 和光标位置 [#]<^D> 向下滚动半屏大小。如果 [#],将滚动设置为 # 行 [#]<^U> 向上滚动半屏大小。如果 [#],将滚动设置为 # 行 <^B> 向上滚动整屏大小 <^F> 向下滚动整屏大小 # 显示全局和相对行号 2# 永久切换显示全局行号 4# 永久切换显示缩进后的相对行号 8# 永久切换显示相对行号 V 切换显示隐藏字符: <^C> 为 切换显示行运动编号 {<1-5>}<^C> 选择行运动编号模式 1-5 <^V> 循环切换行运动编号模式 [#]<^R> 重做 # 次 [#]u 撤销 # 次 <^I> 打开从光标到行尾的文件路径 <^K> 将当前缓冲区写入文件。第二次尝试时强制写入 [#]<^W>{arg} 取消缩进 arg 区域 # 次 [#]<{arg} 向左缩进 arg 区域 # 次 [#]>{arg} 向右缩进 arg 区域 # 次 [#]"{}{cmd} 使用寄存器 arg 执行普通命令 cmd。# 应用于 cmd [#]"{}q 开始录制并将 rr ex 选项设置为 arg 寄存器。# 保留寄存器内容 q 停止录制并将 rr ex 选项设置为 0 R 打印寄存器及其内容 [#]&{} 以非阻塞模式执行 arg 寄存器宏 # 次 [#]@{} 以阻塞模式执行 arg 寄存器宏 # 次 [#]@@ 执行上一个宏 # 次,阻塞 [#]&& 执行上一个宏 # 次,非阻塞 [#]@: [#]&: 将 <:> 寄存器作为 ex 命令执行 # 次 [#]. 重复上一个普通命令 # 次。可重复的命令: x X D C s S Y p P r d c ~ gu gU g~ ! > < ^W i I a A o O ci di J K [#]v. 重复上一个向下移动 # 行的普通命令 [#]Q 递归进入 ex 模式。# 保留当前水平 滚动 : 进入 ex 提示符 [#]!{arg} 基于 # 或 arg 区域进入管道 ex 提示符 vv 进入 ex 提示符,使用历史缓冲区 b-1 中的最后一行 [#]vr 进入 %s/ ex 提示符。从光标处插入 # 个单词 [#]vt[#arg] 进入 .,.+0s/ ex 提示符。从光标处插入 # 行。 从光标处插入 #arg 个单词 [#]v/ 进入 re ex 提示符以设置正则表达式关键字。从光标处 插入 # 个单词 v; 进入 ! ex 提示符 [#]vi 进入 %s/ ex 提示符。包含将空格更改为 制表符的正则表达式。# 修改制表符宽度 [#]vI 进入 %s/ ex 提示符。包含将制表符更改为 空格的正则表达式。# 修改制表符宽度 vo 移除行尾空白和 <\r> 行尾符 <^G> 打印缓冲区状态信息 1<^G> 启用永久状态行 2<^G> 禁用永久状态行 ga 打印字符信息 1ga 启用永久字符信息行 2ga 禁用永久字符信息行 [#]gw 将一行硬换行到 # 列限制。默认:80 [#]gq 将缓冲区硬换行到 # 列限制。默认:80 [#]g~{arg} 切换 arg 区域的字符大小写 # 次 [#]gu{arg} 将 arg 区域转换为小写 # 次 [#]gU{arg} 将 arg 区域转换为大写 # 次 [#]~ 向前切换 # 次字符大小写 i 进入插入模式 I 在行首缩进后进入插入模式 A 在行尾进入插入模式 a 向前 1 个字符处进入插入模式 o 在下方创建新行并进入插入模式 O 在上方创建新行并进入插入模式 [#]s 删除 # 个字符并进入插入模式 [#]S 删除 # 行的所有内容并进入插入模式 [#]c{arg} 删除 arg 区域 # 次并进入插入模式 C 从光标处删除到行尾并进入插入模式 [#]d{arg} 删除 arg 区域 # 次 D 从光标处删除到行尾 [#]x 从光标处向前删除 # 个字符 [#]X 从光标处向后删除 # 个字符 [#]di{} 删除 arg 对内部内容,跳过 # 个匹配 [#]ci{} 删除 arg 对内部内容并进入插入模式。跳过 # 个匹配 [#]r{arg} 从光标处向前用 arg 替换 # 个字符 [#]K 拆分一行 # 次 [#]J 合并 # 行 [#]y{arg} 复制 arg 区域 # 次 [#]Y 复制 # 行 [#]p 在当前行下方或光标位置下方粘贴默认寄存器 # 次 [#]P 在当前行上方或光标位置上方粘贴默认寄存器 # 次 m{} 设置缓冲区局部行标记 <^T> 设置全局行标记 0。全局标记始终有效 {<0 2 4 6 8>}<^T> 设置全局行标记 # {<1 3 5 7 9>}<^T> 切换到全局行标记 # [#]<^7>{<0-9>} [#]<^_>{<0-9>} [#]<^/>{<0-9>} 显示缓冲区列表,并根据提示时的 # 或 0-9 索引进行切换 <^^> <^6> 切换到上一个缓冲区 [#]<^N> 切换到下一个缓冲区,# 在向前和向后之间切换方向 \ 切换到 /fm/ 缓冲区 b-2 {#}\ 刷新 b-2 中的次要目录列表 vb 递归进入 b-1 历史缓冲区。退出时将当前行插入 ex 提示符 z1 将备用键位映射设置为波斯语键位映射 z2 将备用键位映射设置为俄语键位映射 ze 切换到英语键位映射 zf 切换到备用键位映射 zL 将 td ex 选项设置为 2 zl 将 td ex 选项设置为 1 zr 将 td ex 选项设置为 -1 zR 将 td ex 选项设置为 -2 [#]/ 正则搜索提示符,向下移动 1 个或 # 个匹配项 [#]? 正则搜索提示,向上移动 1 或 # 个匹配项 [#]n 重复正则搜索,移动 1 或 # 个匹配项 [#]N 重复正则搜索,反向移动 1 或 # 个匹配项 <^A> 从光标处正则搜索 1 个单词,不居中,环绕移动 向上或向下 * 正则搜索,不居中,环绕移动向上或向下 {#}* {#}<^A> 正则搜索,将关键字设置为从光标处 # 个单词 <^]> 基于 b-2 中的目录列表向前进行文件系统正则搜索 为 <^P> 回退设置全局行标记 0 {#}<^]> 向前进行文件系统正则搜索,将关键字设置为从光标处 # 个单词 [#]<^P> 向后进行文件系统正则搜索 <^Z> 挂起 vi <^L> 强制重绘整个屏幕并更新终端尺寸 [#]Z{} 退出并清理终端,强制退出 # 个递归级别 [#]Zz 退出并提交历史命令,强制退出 # 个递归 级别 ZZ 退出并将未保存的更改写入文件 <ESC ^C> 取消任何待处理的输入或命令
VI 区域 区域是 vi 普通命令,用于定义 vi 运动的 [h v] 范围。 使用“move”一词描述的命令定义了一个区域。
j + <^M> <Enter> - k h l f F t T , ; B E b e W w ( ) { } [ ] ^ 0 $
<Space> <^H> <Backspace> % ' ` G H L M / ? n N * <^A>
所有区域
VI 运动 运动是 vi 普通模式命令,在 [h v] 范围内运行。 使用“区域”一词描述的命令会消耗一个区域。 运动可以前缀或后缀 [#]。
<^W> > < ! c d y g~ gu gU
所有运动
dd yy cc g~~ guu gUU >> << <^W><^W> !!
可以使用 [#] 作为行数的特殊运动
示例:
3d/int 删除文本直到第 3 个 "int" 关键字
3dw 删除 3 个单词(前缀 [#])
d3w 删除 3 个单词(后缀 [#])
"ayl 将一个字符复制到 <a> 寄存器
"Ayw 将一个单词追加到 <a> 寄存器
VI/EX 插入模式 <^H> 删除一个字符,为空时重置 ex 模式 <^U> 删除至 <^X> 标记或全部 <^W> 删除一个单词 <^T> 增加缩进 <^D> 减少缩进 <^]> 在 0-9 寄存器中循环选择粘贴寄存器 <^>{} 选择粘贴寄存器参数。<^> 选择默认寄存器 <^P> 粘贴一个寄存器 <^X> 标记自动补全和 <^U> 起始位置。<^X> 重置 标记 <^G> 为自动补全索引当前缓冲区 <^Y> 重置所有已索引的自动补全数据 <^R> 向后循环自动补全选项 <^N> 向前循环自动补全选项 <^B> 在 vi 插入模式下打印自动补全选项 <^B> 在 ex 提示符中递归进入 b-1 历史缓冲区。退出时 将当前行插入 ex 提示符 <^A> 在历史缓冲区 b-1 中循环行 <^Z> 挂起 vi/ex <^L> 在 vi 模式下重绘屏幕,在 ex 模式下清理终端 <^O> 递归地在 vi 和 ex 模式之间切换 <^E> 切换到英文键盘映射 <^F> 切换到备用键盘映射 <^V>{} 读取一个字面字符参数 <^K>{arg} 读取一个双字符序列参数 <^C> 在 vi 中退出插入模式,在 ex 中重置 <^M> 在 vi 中插入 ,在 ex 中提交命令
EX Ex 是 Unix 系统上的一款强大行编辑器,最初由 Bill Joy 于 1976 年开发。这一基本工具是 vi 的骨干,使其能够执行命令、宏,甚至根据需要转换为纯命令行界面 (CLI)。
EX PARSING 解析遵循以下结构: [][prefix][cmd][][args] Ex 命令由 发起并分隔。字段可以由 或 填充。[prefix] 是被 [cmd] 消耗的字段,它接受 [range] 结构字符。[prefix] 结构内部的填充会被折叠,嵌套块内部除外。[cmd] 和 [args] 之间只能有一个填充。为了避免脚本中的歧义,建议在 [cmd] 和 [args] 之间始终使用一个填充。
示例:
:evi.c
解析为 ":e vi.c"
:efbc
解析为 ":ef bc" 而非 ":e fbc"
:e vi.c
编辑 " vi.c"。需要 <pad>
EX ESCAPES [args] 和 [prefix] 块中的特殊字符在通过 <> 转义后会变为普通字符。转义遵循非 POSIX 奇偶规则:紧邻特殊字符之前的转义会被减半,奇数个转义使特殊字符变为普通字符,其他位置的转义则为字面量。
( ^ ] -
正则表达式 "[]" 表达式中的特殊字符
( ) { + * ? ^ $ [ | \ . \< \>
正则表达式中的特殊字符
\ : % !
ex 中的特殊字符
EX 扩展 <%> 在 [args] 中展开为当前缓冲区的路径名,或者当其后跟随相应的缓冲区编号时,展开为该缓冲区的路径名。 %# 展开为最近交换的缓冲区的路径名。 %@ 展开为指定的寄存器。
示例:复制当前文件并编辑它
:!cp % %_:e %_
示例:插入当前缓冲区的路径名
:&i%
示例:回显 <a> 寄存器的值
:!echo %@97
<!> 在 [args] 中开始并可选地结束一个包含外部命令的块。该块执行并展开为产生的 stdout 和 stderr。
示例:用 $RANDOM 的值替换 "int"
:%s/int/!printf "%s" $RANDOM!
示例:插入 ls shell 命令的输出
:&i!ls
示例:更高效地插入 ls 的输出
:;c!ls!<^V><ESC>
EX 范围 某些 ex 命令可以带有范围前缀。 [range] 前缀实现垂直和水平范围。 [vrange] 前缀实现垂直范围和水平位置。 如果没有 [cmd],[vrange] 替换 [prefix]。
[% |][, ;][#][. $ ' > <][- + * / %][#num]
所有范围结构
{|}{cmd}[|]
Ex 子命令结构
{>}[regex][>]
向前搜索结构
{<}[regex][<]
向后搜索结构
'{#mark}
标记结构
% 从第一行到最后一行的范围 | 开始 ex 子命令块 , 垂直范围分隔符 ; 水平范围分隔符 # 回退到范围结构中的前一个值 . 当前位置 $ 缓冲区最后一行或行尾 ' 开始标记结构 > 开始向前搜索块 < 开始向后搜索块 - 减去后续数字 + 加上后续数字 * 乘以后续数字 / 除以后续数字 % 对后续数字取模 #num 数字或位置
示例: :1,5p 打印第 1 行和第 5 行 :.-5,.+5p 打印当前位置上下各 5 行 :>int>p 打印 "int" 的第一次出现 :<int<p 反向打印 "int" 的第一次出现 :.,>int>p 打印直到找到 "int" :<int<,.p 反向打印直到找到 "int" :> 使用之前设置的正则表达式关键字进行搜索 :'100,'97p 打印从标记 到标记 的行 :%p 打印缓冲区中的所有行 :$p 打印缓冲区中的最后一行 :$*50/100+1 跳转到文件的 50% 处 :;50 跳转到字符偏移量 50 :10;50 跳转到第 10 行字符偏移量 50 :10;.+5 跳转到第 10 行 +5 字符偏移量 :'97;'97 跳转到标记 行偏移量标记 :;$ 跳转到行尾 :5;>int> 在第 5 行搜索 "int" :.;<int< 在当前行反向搜索 "int" :;5;+10= +10 是相对于初始当前偏移量,而不是 5 :;5;#+10= +10 是相对于 5 :;>int>+3;#>>p 打印当前行中由 "int" 包围的文本 :|grp1|;>(a)+>+1|grp|;#>>p 打印由非确定性模式 "a+" 包围的文本
EX 命令 [range]f>[regex] [vrange]f<[regex] 范围搜索
如果未找到目标,则返回错误。
示例:未指定范围,仅当前行 :f>int 示例:反向 :f<int 示例:指定范围 :10,100f>int
[range]f+[regex]
[vrange]f-[regex]
递增范围搜索
等效于 :f> 和 :f< 命令,但后续命令
会越过匹配边界前进。不能原地匹配。
[vrange]f[regex]
模糊搜索提示
进入带有匹配列表的模糊搜索提示。
匹配项前缀为选择编号和行号。
如果匹配项少于 10 个,可以使用数字 0-9 选择匹配项。
<^C> 或 <ESC> 用于中止。
<^M> 或 <Enter> 用于输入大于 9 的选择编号。
未指定范围时评估为 <%> 范围。
未指定范围时最多显示 xrows * 3 个匹配项。
[vrange]g[<Delim>][regex][<Delim>][cmd]
全局命令
对匹配指定正则表达式的行范围执行 ex 命令。
如果没有行匹配该模式,则返回错误。
未指定范围时评估为 <%> 范围,嵌套时评估为 <.> 范围。
示例:删除所有空行
:g/^$/d
示例:打印匹配之前设置的正则表达式的行
:g//p
可以在一个全局命令中链接多个 ex 命令。 要链接命令,必须对 ex 分隔符 <:> 转义一次。
示例:打印并追加匹配 "int" 的行到寄存器 <a>
:g/int/p\:ya+ 97
可以在全局命令内部嵌套全局命令。
第一个全局命令不会在由嵌套全局命令修改的行上执行。
示例:嵌套全局命令
向所有包含 "int" 且以 <;> 结尾的行追加 "has a semicolon"。
:g/int/g/;$/& A has a semicolon
示例:提取/打印 "()" 内的数据
:grp1:err4:g/./;0\:;>(\().+\)>;#>.+(\))>+1p:err1:grp
[vrange]g![<Delim>][regex][<Delim>][cmd]
反转全局命令
[range]re[regex]
设置正则表达式关键字
Range 会转义其文本并将其用作正则表达式。
示例:将关键字设置为 "int"
:re int
示例:从第 1 行到第 3 行设置关键字
:1,3re
[vrange]i[str]
进入 ex 插入模式
[str] 指定插入缓冲区中的初始输入。
在原始 ex 模式下,[str] 会被直接注入并绕过交互模式。
示例:在 vi/ex 中插入 "hello" :i hello<^M> 示例:在 vi/ex 中插入 "hello" 并去除首尾空白 :i hello<^M><^M> 示例:在 vi/ex 中丢弃更改 :i hello<^M><^C> 示例:立即插入 "hello" :i hello<^V> 示例:在指定位置之前插入 "hello" :-1i hello<^V> 示例:在第 1 行之前插入 "hello"(特殊情况) :0i hello<^V> 示例:在原始 ex 模式中插入 "hello" i hello 示例:在原始 ex 模式中插入两行 i hello<^M>world 示例:在原始 ex 模式中插入 "hello"(交互式) i<^M>hello<^M>.<^M>
[range]c[str]
进入 ex 更改模式
结合 seq 和 lim ex 选项,此命令最适合修改非常长的行。
在 32 位构建中,最大插入缓冲区约为 1.33GB。
在 32 位构建中,最大可寻址行大小为 2.0GB。
示例:用 "hello" 替换当前行 :c hello<^M> 示例:用 "hello" 替换第 1-5 行 :1,5c hello<^M> 示例:在当前字符偏移处插入 "hello" :;c hello<^M> 示例:在行尾插入 "hello" :;$c hello<^M> 示例:在第 5 行行尾插入 "hello" :5;$c hello<^M> 示例:从当前位置删除 5 个字符 :;;+5c<^M>
[range]d
删除行
示例:从当前位置删除到缓冲区开头
:1,.;0;d
示例:从当前位置删除到缓冲区末尾
:.,$;;$d
[vrange]j[any]
合并行
任何参数都会激活填充模式。
如果没有可合并的内容,则返回错误。
示例:合并所有行
:%-1j
示例:用空格填充合并所有行
:%-1j x
[range]s[<Delim>][regex][<Delim>][str][<Delim>][<g>][<m>][#reg]
替换
在指定范围的行中,查找并替换与
括号内的正则表达式匹配的文本,替换为括号内的替换字符串。
如果没有执行替换,则返回错误。
示例:范围限定
:1,5;5;5s/term1/term2/
示例:替换之前设置的匹配正则表达式 :%s//term2/
[str] 中的替换反向引用会插入由 \# 指定的匹配组的文本,其中 # 是组号。数字会贪婪地消耗到最高存在的组,其余部分为字面量。
示例:替换反向引用
this is an example text for subs and has int or void
:%s/(int)|(void)/pre\0after
this is an example text for subs and has preintafter or void
:%s/(int)|(void)/pre\2after/g
this is an example text for subs and has prepreafterafter or prevoidafter
示例:使用 <g> 进行全局替换
:%s/term1/term2/g
示例:多行模式 <m>
:.,+1s/term1<^V><^M>term2/term3/m
示例:原地编辑寄存器 <a>
:s/term1/term2/97g
ud 撤销
如果没有可撤销的内容,则返回错误。
rd 重做
如果没有可重做的内容,则返回错误。
[range]p[str]
从缓冲区打印行
无范围时,根据 left ex 选项的值打印一行。
参数打印求值后的参数。
示例:使用字符偏移范围 :1,10;5;5p 示例:交错字符偏移范围 :1;5,10;5p 示例:从偏移 5 到 10 打印当前行 :.;5;10p 示例:打印缓冲区路径名 :p %
[range]=[<0-3 Any>][any]
打印范围编号
参数 0-3 选择特定编号。
任何非<0-3>或额外参数将绕过缓冲区范围检查。
无参数时打印所有范围编号。
示例:仅打印当前字符偏移
:;= 2
示例:打印标记 <a> 的值
:'97=
示例:计算 75 - 100
:,75-100=1p
=?[any]
打印最后错误
任何参数都会转发错误状态。
[range]m{#marks}
设置行标记
标记是由空格分隔的 ID,在范围的起始和结束之间交替设置。
示例:将范围存储在 <a> 和 <s> 中,以便在 :f> 中稍后重用
:>top>,#>bottom>m 97 115:'97,'115f>middle
[range]ya[#reg]
复制到寄存器
无参数时复制到默认寄存器。
示例:使用范围复制到 <a>
:1,5;5;5ya 97
[range]ya+[#reg]
复制并追加到寄存器
示例:追加到寄存器 <1>
:ya+ 49
ya![#reg] 释放寄存器
[range]pu[#reg][any][\!{cmd}]
粘贴或管道传输寄存器
示例:在第 1 行字符偏移 5 处粘贴 <a>
:1;5pu 97
示例:在第 1 行之前粘贴 <a>(特殊情况)
:0pu 97
示例:将默认寄存器复制到 X11 剪贴板
:pu \!xclip -selection clipboard
示例:将寄存器 <a> 复制到 X11 剪贴板
:pu 97 \!xclip -selection clipboard
[#reg]reg[str]
打印寄存器或放入寄存器
前缀选择寄存器,参数替换其内容。
无参数的前缀重新分配默认寄存器。
示例:移动打印位置以查看屏幕外的寄存器部分
:1left:reg
示例:将 "hello" 放入寄存器 <1>
:49reg hello
[#reg]reg+[str]
打印寄存器或追加到寄存器
e[path]
在指定路径打开文件
无参数打开 "unnamed" 缓冲区。
在 32 位构建中,大于 2.0GB 的文件会被截断。
换行发生在第一个空终止符或 EOF 之前。
e![path]
强制在指定路径打开文件
无参数从文件系统重新读取当前缓冲区。
[vrange]ef[regex]
使用模糊搜索提示打开文件
要求 b-2 缓冲区已回填目录列表。
示例:使用 :fd 回填 b-2
:fd
示例:使用 find 回填 b-2
:b-2:%!find .
提示行为与 :f 命令等效。
示例:进入提示并打印整个列表
:ef
示例:搜索包含 "v" 的路径名
:ef v
[vrange]ef![regex]
:ef 的强制版本
[range]r[path]
[range]r[\!{cmd}]
读取文件或管道
范围基于目标计算。
无范围时求值为 <%> 范围。
无参数时求值为当前缓冲区路径。
示例:读取文件
:r vi.c
示例:通过管道输入所有数据
:r \!ls
示例:仅通过管道输入第 3、5 行
:3,5r \!ls
[range]w[path]
[range]w[\!{cmd}]
写入文件或管道
无范围时求值为 <%> 范围。
无参数时求值为当前缓冲区路径。
示例:写入文件
:w vi.c
示例:通过管道输出所有数据到 less
:w \!less
示例:仅通过管道输出前 10 行
:1,10w \!less
[range]w![path]
强制写入文件
[range]wq[path]
[range]wq[\!{cmd}]
写入文件或管道并退出
[range]wq![path] [range]wq![!{cmd}] 强制写入文件或管道并强制退出
[range]x[path]
写入未保存的更改并退出
[range]x![path]
强制写入未保存的更改并强制退出
[#lvl]q[0-255]
退出
前缀退出 [#lvl] 个 ex 递归层级。
参数指定 shell 退出码。
示例:条件性地退出当前层级及其上方 1 层
:%f>marker:??!p no marker\:1q:s/old/new/g:w
[#lvl]q![0-255]
强制退出
前缀强制退出 [#lvl] 个递归层级。
无前缀则退出所有递归层级。
示例:将寄存器 <#0> 在 3 层深处设置为 "hello",强制退出
当前层级及其上方 2 层,并在外部打印该寄存器
:&Q&Q\\\:&Q0reg hello\\\\\\\:2q\\\\\\\!:p %@0
b[#index]
打印缓冲区或切换到某个缓冲区
临时缓冲区与主缓冲区是分开的,
并通过负索引进行选择。
示例:切换到第 5 个缓冲区
:b5
示例:切换到 /hist/ ex 历史缓冲区
:b-1
示例:切换到 /fm/ 目录列表缓冲区
:b-2
示例:切换到 /sc/ 草稿缓冲区
:b-3
bp[path]
设置当前缓冲区路径
bs[any]
设置当前缓冲区已保存
参数重置会清除撤销/重做历史
bx[#] 设置允许的最大缓冲区数量
如果指定的数量小于当前正在使用的缓冲区数量,
多余的缓冲区将被释放。
无参数时重置为默认值 10。
cd[path]
设置工作目录
无参数时,如果当前目录已被删除
或卸载,则重新链接当前目录。
当前打开缓冲区的文件路径将自动调整,
以反映新设置的工作目录。
fp[path]
清除或设置次要目录路径
fd[path]
在 b-2 缓冲区中计算目录列表
无参数时使用次要目录或工作目录路径。
inc[regex]
用于 :fd 计算的包含正则表达式
无参数时禁用该过滤器。
示例:仅包含以 .c 结尾的子模块目录中的文件
:inc submodule.*\.c$
示例:排除 .git 和 submodule 文件夹
:inc (^(?\:(?\!^\.git|^submodule).)+[^/]+$)
[range]![cmd]
运行外部程序
当指定范围时,缓冲区的数据会被管道传输到外部
程序。随后,产生的 stdout 和 stderr 会被管道传回
缓冲区,替换原始范围的内容。
无范围时,如果 shell 退出码不为零,则返回错误。
示例:以臭名昭著的方式对缓冲区进行排序 :%!sort 示例:使用 sed 将 "int" 替换为 "uint" :%!sed -e 's/int/uint/g' 示例:将 ls 命令的结果通过管道输入,不进行行替换 :;$+1!ls 示例:使用 tr 将当前位置的单词大写 :;;>\>>!tr '[:lower:]' '[:upper:]'
&{macro}
全局非阻塞宏
执行原始 vi 输入序列。
非阻塞宏在到达序列末尾时不应等待输入。执行其他
宏的非阻塞宏总会到达终止点。
示例:执行 vi 插入语句
:& ihello
示例:执行 :hello
:& \:hello<^V><^M>
示例:执行 vi "ci(int" 宏
:& ci(int
示例:在非阻塞宏中嵌套阻塞宏
:& \:@ \\\:blocking<^V><^M>i continue in non-blocking
示例:启用永久 vi 行号
:& 2#
@{macro}
全局阻塞宏
执行原始 vi 输入序列。
阻塞宏在到达序列末尾时应等待输入。执行其他宏的
阻塞宏可能导致输入拥塞。
示例:执行 vi 插入语句 :@ ihello 示例:在 <:> vi 提示符中插入 "hello" :@ :hello 示例:执行 vi "ci(int" 宏 :@ ci(int 示例:执行 "ci(int" 并退出插入模式 :@ ci(int<^V><^C> 示例:将 "ci)INT" 作为后续操作执行 :@ ci(int<^V><^C>ci)INT 示例:在用户退出插入模式后执行 vi "dw" 命令 :@i:@dw
[#count <$>]?[cond]
当型循环
重复 [cond] [#count] 次,或使用 [<$>] 无限循环。
一旦 [cond] 返回错误或超出计数,当型循环即被中断。
[cond] 的错误状态会被转发。
无前缀时,[#count] 默认为 1。
示例:尝试使用任意计数连接文件中的每一行
:10000? & J
示例:撤销所有操作
:$? ud
示例:重复执行 ex 命令链 10 次
:10? 1p\:5p\:10p
[#count <$>]?![cond]
反向当型循环
[prefix]??[then]
{prefix}??
条件分支
分支取决于上一条命令的错误状态。
[then] 的错误状态会被转发。
无前缀且无参数时,转发上一条命令的错误状态。
不带参数的前缀会将命令链中该点的当前错误状态 捕获到指定的 id 标签中。 Id 标签在所有嵌套命令上下文中是全局的。
带参数的前缀基于对每个引用 id 的最新捕获值的
DNF 布尔表达式进行分支。
如果 id 没有捕获值,则跳过该分支。
前缀运算符:
数值型 id 标签
, AND(优先级较高)
; OR(优先级较低)
示例:仅当 :cd 成功时计算目录
:cd /blah:?? fd
示例:仅当第 5 个偏移量包含 "int" 时打印该行
:;5;#>^int>:?? p
示例:仅当 vi.c 存在时编辑它
:![ -f ./vi.c ]:??e ./vi.c:mpt1
示例:在 id 5 处捕获错误状态,稍后分支
:>int>:5??:;=:5??p
示例:如果标签从未设置则跳过
:2??.=
示例:AND -- 仅当两个 id 都捕获成功时分支
:f>int:1??:f>void:2??:1,2??p found both
示例:OR -- 如果任一 id 捕获成功则分支
:f>int:1??:f>void:2??:1;2??p found one
示例:DNF -- (1 AND 2) OR (3 AND 4)
:1,2;3,4??p then
[prefix]??![then]
{prefix}??!
反向条件
示例:反向捕获
:f>int:1??!:1??p int was absent
{prefix}??? 评估前缀标签
这是一个空操作命令,用于在评估前缀时计算一个布尔表达式
并返回结果。
示例:控制 while 循环
:$? \%f+int\:1??\:\%f+void\:2??\:1,2??p\:1,2???
ft[filetype]
设置文件类型
无参数时打印当前文件类型。
重新加载高亮 ft,这使得可以重置由 "hlw" 等选项创建的动态
高亮。
cm[keymap]
设置键位映射
无参数时打印当前键位映射名称。
cm![keymap]
设置替代键位映射
ac[regex]
设置自动补全过滤正则表达式
无参数时重置为 led.c 中定义的默认单词过滤正则表达式。
示例:使用缓冲区中的整行进行自动补全
:ac .+
[<0-3>]sc[<esc>][<sep>][<exp>][<exe>]
设置 ex 特殊字符
前缀选择要更改的特定字符。
缺失的参数默认为 <\ : % !>。
示例:将 <%> 更改为 <a>
:2sc a
示例:在单个命令链中使用新设置的分隔符
:|1sc a|: p cmd1 a p cmd2 a|sc|a0?:p cmd3
[<0-3>]sc![<esc>][<sep>][<exp>][<exe>]
设置 ex 特殊字符
缺失的参数默认为 <#0>。
示例:禁用 和 :sc! \:
uc 切换多字节 UTF-8 解码
此命令在编辑具有混合编码、二进制文件,或终端不支持 UTF-8 或缺少显示 UTF-8
字符所需字体时特别有用。它通常与 :ph 命令配合使用,以实现
类似十六进制编辑器的功能。
uz 切换零宽字符占位符
隐藏零宽字符,而不是将其渲染为占位符。
ub 切换多码点序列占位符
将表情符号等多码点序列传递给终端进行原生渲染,而不是替换为占位符。
ph[#clow] [#chigh] [#width] [#blen][<Space>][str]
重新定义占位符
此命令替换 conf.c 中定义的占位符,
后续的 :ph 命令会扩展占位符列表。
示例:将 8 位 ascii (Extended ASCII) 渲染为 <~>
:ph 128 255 1 1~
示例:完美支持 ISO/IEC 8859-1 (latin-1)
:uc:ph 128 160 1 1~
示例:将控制字节 03 渲染为 "^C"
:ph 3 3 2 1^C
示例:重置为 conf.c 中的默认值
:ph
示例:禁用 conf.c 中的默认占位符
:ph:ph0
EX OPTIONS Ex 选项是用于修改全局变量的 ex 命令。 变量存储一个带符号整数。参数设置其值。非数字 参数将返回其第一个字节。未提供参数时,会反转当前 值,除非另有说明。 默认值在下方的参数表示法中显示。
ai[1] 缩进新行
这是一个最大缩进长度乘数:值 * 128
ic[1] 在正则表达式中忽略大小写
ish[0] 交互式 shell
通过交互式 shell 执行每个 <!> 命令。
shell 会在命令执行前加载 .rc 文件。
这使得可以使用 .rc 文件中预定义的函数、别名
和 ENV 变量。
前提条件 1:
.rc 指的是特定 shell 的文件名,例如 Bash 中的 .bashrc
或 Zsh 中的 .zshrc。
前提条件 2:
环境变量 $SHELL 决定默认
shell,否则默认为 /bin/sh。
前提条件 3:
.rc 文件不得产生任何 stdout 或 stderr 输出,
否则 <!> 命令将无法返回预期结果。
grp[0] 正则搜索组
为任何正则搜索操作定义目标搜索组。 当正则搜索的结果需要基于某个组而非默认匹配组时, 这一点变得必要。
示例:位于 "int" 前缀字符之后的位置
:grp 1:%f+int(.):grp
hl[1] 基于 conf.c 中定义的规则高亮文本
hlr[0] 反向高亮文本
hll[0] 基于文件类型 hl 高亮当前行
hlp[0] 基于文件类型 hl 高亮 "[]" "()" "{}" 对
hlw[0] 基于文件类型 hl 高亮当前单词
led[1] 启用所有终端输出
vis[0] 控制启动标志
bit 1: raw ex 模式
bit 2: ex 模式
bit 3: 禁用 :e 消息
bit 4: 备用终端屏幕
示例:启用 raw ex 模式
:vis 3
示例:禁用 raw ex 模式
:vis 2
mpt[0] 控制 vi 提示
当从 vi 调用 ex 命令后设置为 0 或 1 时,禁用
"[按任意键继续]" 提示。
如果 mpt 为负数,提示将保持禁用状态。
示例:阻止提示和最后一次打印
:p:p:p:mpt 0
示例:阻止提示但不阻止最后一次打印
:p:p:p:mpt 1
order[1] 根据 conf.c 中定义的规则重新排列字符 shape[1] 执行阿拉伯文字母连写 pac[0] 即时打印自动补全建议 ts[8] 用于表示制表符的空格数 td[1] 当前文本方向上下文
value 2: 仅从左到右
value 1: 遵循 conf.c 中的 dctxs[],默认从左到右
value -1: 遵循 conf.c 中的 dctxs[],默认从右到左
value -2: 仅从右到左
pr[0] 打印寄存器
使用字符或数字设置一个特殊寄存器。
一旦寄存器被设置,所有传入 ex_print 的数据
都将存储在该寄存器中。
如果寄存器为大写,则添加 <Newline> 个字符
以匹配所打印的确切输出。
当寄存器被分配时,无法使用 R 或 :reg 命令
显示打印寄存器的内容(自引用问题)。
示例:精确粘贴当前缓冲区列表,如同 :b 命令
:pr A:ya! 65: b:pu 65
示例:存储使用 :p 打印的一行
:pr A:ya! 65:p
fr[0] 查找寄存器
使用字符或数字设置寄存器。 寄存器设置后,:f> 和 :f+ 命令将对寄存器的内容 而非当前缓冲区执行多行向前搜索。Range 将匹配映射到 当前缓冲区中的位置。不执行原地匹配的 Range 测试。
示例:在寄存器 <a> 中搜索 "int"
:fr a:f>int:??p yes:??!p no:fr
示例:搜索 "int" 后下一行跟随 "void"
:%ya97:fr 97:%f>int.void:fr
rr[0] 记录寄存器
使用字符或数字设置寄存器。
寄存器设置后,从终端读取的每个字节都会
追加到寄存器中。从寄存器重放的输入不会
被记录,因此重放已记录的寄存器无法记录自身。
示例:将按键记录到寄存器 <a>
:rr a
示例:停止记录
:rr
示例:从寄存器 <a> 重放记录
:& %@97
lim[-1]
行长度渲染限制
设置 vi 模式下非光标行以及 ex 模式下所有行
的渲染截断长度。
在编辑包含一行或多行超长行(每行 1MB+)的文件时,
可提升重绘性能。
示例:合理值 :lim 5000 示例:仅渲染光标行 :lim 0 示例:禁用限制 :lim -1
seq[1] 控制 Undo/Redo
当 seq 为 0 时,多个不同的操作将在单步中执行 undo/redo。
为了在繁重工作负载下优化内存使用,可以通过将 seq 设置为负值来禁用 undo/redo 跟踪。
示例:在单步中测试 undo/redo 操作
:&ocontrol test:seq 0:&a step1:&a step2:&a step3:seq
示例:完全禁用 undo/redo
:seq -1
[hscroll]left[0]
控制水平滚动
无参数时,使用当前字符偏移量计算值。
hscroll 使用以下公式计算值:xcols / 2 * hscroll
err[1] 控制 ex 错误
位 1:打印错误
位 2:提前返回
位 3:忽略错误
示例:静默并忽略错误
:err 4
示例:报告并在第一个错误时返回
:err 3
示例:报告且仅考虑最后一个命令的错误状态
:err 1
EXINIT 环境变量 EXINIT 定义了一组在启动时执行的 ex 命令链, 在所有文件打开后执行一次。这是在 C 或 Unix 管道之外 对 Nextvi 进行脚本化和自定义的唯一方式。 许多标准文本处理工具,如 grep、awk、sed, 都可以用带有 EXINIT 的 Nextvi 来替代。
使用 printf 配合八进制转义是向 EXINIT 中嵌入控制
字符的标准方式。
示例:
export EXINIT='td 2:order 0:lim 5000'
设置 ex 选项以优化长行性能
export EXINIT='b-1:r ./vi.c:b-1'
将 vi.c 加载到历史缓冲区
export EXINIT="$(printf 'e ./vi.c:& i\007\003:bx 1:bx')"
为 vi.c 建立索引以用于自动补全
export EXINIT="$(printf '97reg o{\n}\003kA\n\t')"
在寄存器 <a> 中设置 @ 宏
@a 宏在光标下方创建 <{> 和闭合的 <}>,
并将光标留在花括号之间的插入模式。
export EXINIT='98reg \:mpt-1\:;;$w \\\!xclip -selection clipboard\:mpt'
在寄存器 <b> 中设置 @ 宏
@b 宏将当前行管道传输到 X11 剪贴板。
export EXINIT='rr z:vis 2:&Q:b-3:pu 122:wq! bugreport.txt'
捕获会话以用于错误报告
录制开始写入寄存器 。设置 vis 2 使
直接切换到一个常规 vi 会话,由用户接管。
使用 :q 退出该会话将恢复宏,并将
录制内容写入 bugreport.txt。
REGEX Pikevm 是为 Nextvi 开发的一个快速非回溯 NFA 模拟正则表达式引擎。 它确保正则表达式在恒定空间和 O(n * k) 时间复杂度内求值,其中 是 输入字符串的长度, 表示正则表达式的结构 复杂度(例如,状态转换或交替)。虽然 这并不保证严格的 O(n) 线性运行时性能, 但它确保计算和内存资源在输入上 线性且均匀地分布, 直接影响 常数因子。这一原理类似于 基数排序算法中使用的概念。
Pikevm 的语法类似于 Plan 9 中的 regexp(7)。
请忽略本节中的手册页符号。
. 匹配任意单个字符 [N-M] 匹配 N 到 M 的备选范围集合 {N,M} 匹配 N 到 M 次 () 捕获分组 (?:) 非捕获分组 * 重复零次或多次 + 重复一次或多次 | 并集,备选分支 ? 一次或零次匹配,贪婪 ?? 一次或零次匹配,懒惰 ^ 断言行首 $ 断言行尾 < 断言词首 > 断言词尾 (?=) 断言正向先行 (?!) 断言负向先行 (?>) 断言正向后行 (?<) 断言负向后行 (?#) 后行偏移量(字节)
环视表达式使得创建没有它们就无法构建的正则表达式成为可能。它们可以用在正则表达式的任何位置,但必须考虑一些因素。 方面 1: 环视包含一个完整的正则表达式。 方面 2: 环视可以嵌套环视。 方面 3: 像 (?=^word) 这样的静态环视会被优化,绕过正则表达式引擎。 方面 4: 环视最适合用于断言复杂模式的末尾附近,此时引擎已经缩小了潜在匹配的范围。 方面 5: 没有偏移量或偏移量为 0 的环视从上一个字符开始。 偏移量从当前位置减去指定值开始扫描。负偏移量从字符串的开头开始。
SPECIAL MARKS * 上一个 ex 命令的位置 [ 上一个更改的第一个位置 ] 上一个更改的最后一个位置 ' 上一个行区域的位置 ` 上一个行区域的位置
SPECIAL REGISTERS / 上一个正则表达式关键字 : 上一个 ex 命令 <#0> 默认寄存器 <0> 默认寄存器的上一个值(原子) 原子意味着该操作不包含 。 <1-9> 默认寄存器的上一个值(非原子)
代码地图 +--------------+----------------------+ | 537 kmap.h | 键位映射转换 | | 550 vi.h | 定义/辅助 | +--------------+----------------------+ | 351 term.c | 底层 IO | | 372 conf.c | hl/ft/td 配置 | | 460 ren.c | 定位/语法 | | 615 uc.c | UTF-8 支持 | | 666 lbuf.c | 文件/行缓冲区 | | 735 led.c | 插入模式/输出 | | 751 regex.c | pikevm | | 1897 vi.c | 普通模式/通用 | | 1930 ex.c | ex 选项/命令 | | 7777 total | wc -l *.c|sort | +--------------+----------------------+
编译 export CC='g++ -x c' 设置编译器,g++ 示例 export CFLAGS='-s' 设置 CFLAGS,strip 示例 ./cbuild.sh 构建一次 ./cbuild.sh build 构建 ./cbuild.sh debug 带符号构建,静态分析,动态分析,且无 优化 ./cbuild.sh pgobuild PGO 构建在某些 特定应用任务上可带来显著的性能提升 ./cbuild.sh install 将 vi 安装到 $DESTDIR$PREFIX/bin ./cbuild.sh fetch 合并来自上游仓库的提交 ./cbuild.sh bench 性能基准测试:在 vi.c 上删除 2000 个单词
PHILOSOPHY 大多数文本编辑器都积累了大量的技术债务。它们 无法被快速掌握、深入理解或轻松修改。 Nextvi 围绕三大支柱设计:基础、精简和 灵活。基础意味着一套完整而最小的命令集, 用于无限的文本转换。精简意味着简洁、高效、 连贯的实现,且巴士因子为零。灵活意味着 深度可组合性以及通用、可扩展的 C 代码库。按照 传统观念,这三大支柱会被视为 自相矛盾。同时维持这三者挑战了 文本编辑器必须牺牲其一以成全另一者的观念。Nextvi 证明了 共存不仅是可能的,而且是伟大 文本编辑器所必需的。
“所有软件都很糟糕,但有些比其他更糟糕。”
- Kyryl Melekhin
SEE ALSO 新功能可以通过 patches 分支中提供的 可选补丁获得。如果你有有意义的贡献 并希望将其公开,补丁可以通过 电子邮件或 GitHub pull request 提交。 https://github.com/kyx0r/nextvi/tree/patches
Patch2vi 支持工具
https://github.com/kyx0r/nextvi/tree/patch2vi
单元测试
https://github.com/kyx0r/nextvi/tree/test
用于生成此手册的脚本
https://github.com/kyx0r/nextvi/tree/manual
统一的带标签发布 https://github.com/kyx0r/nextvi/tree/release
原始 Neatvi 仓库
https://github.com/aligrudi/neatvi
Posix vi(1)
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/vi.html
Posix ex(1)
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html
Russ Cox 的 NFA 正则表达式
https://swtch.com/~rsc/regexp/regexp1.html
Plan 9 regexp(7)
https://man.cat-v.org/p9p/7/regexp
AUTHORS Nextvi 由 Kyryl Melekhin k.melekhin@gmail.com 编写。它基于 neatvi(1),后者由 Ali Gholami Rudi ali@rudi.ir 编写。本 手册页受 nepeta nepeta@canaglie.net 启发。
Nextvi 7.4 2026 年 8 月 7 日 Nextvi 7.4