visual

visual.txt 适用于 Vim 9.0 版本。 最近更新: 2022年7月 VIM 参考手册 by Bram Moolenaar 译者: quhongjun 可视模式 Visual Visual-mode visual-mode 可视模式提供一种灵活易用的方法选择一块文本供操作符使用。它也是选择一个文本列块 的唯一方法。 关于本章的介绍包含在用户手册的 04.4 节中。 1. 使用可视模式 visual-use 2. 进入和退出可视模式 visual-start 3. 改变可视区域 visual-change 4. 操作可视区域 visual-operators 5. 列块操作 blockwise-operators 6. 重复 visual-repeat 7. 示例 visual-examples 8. 选择模式 Select-mode {仅当编译时打开 +visual 特性才有效} {Vim 7.4.200 开始,总是包含 +visual 特性}

1. 使用可视模式 visual-use

使用可视模式包含三个部分: 1. 用 "v"、"V" 或 CTRL-V 标记文本的开始。 当前光标下的字符将被作为标记的起始点。 2. 把光标移到要标记的文本末尾。 起始点和光标之间的文本 (包括当前光标下的字符) 将被高亮显示。 3. 键入操作符命令。 操作符命令将被应用到高亮显示的字符。 'highlight' 选项用来设置可视模式下的高亮显示方式。 'virtualedit' 选项用来设置是否允许光标停留在没有字符的位置。 通常高亮显示的文本包括当前光标下的字符。 然而,如果 'selection' 选项被设置为 "exclusive",并且当前光标位于可视区域之 后,那么光标下的字符将不被包括。 使用 "v" 命令,被高亮的文本将不包括起始点之前和结束点之后的字符。然而,所有的 大写命令和非字母命令 ("~" 和 "U" 除外) 仍将作用在整行上。请参考下面的操作命令 列表。 visual-block 使用 CTRL-V (列块可视模式),高亮区域是从开始点到光标之间的一个矩形区域。然而, 有些操作符仍将作用在整行上 (参见下面的列表)。修改 (c) 和替代 (s) 操作将删除高 亮区域的文本,然后从左上角开始插入。

2. 进入和退出可视模式 visual-start

v characterwise-visual [count]v 进入可视模式,以字符为单位选择。 若带 [count],选择的字符数或行数和上次的可视操作使用的 一样,但乘以 [count],且从当前光标位置开始。 如果上次可视模式是基于块的,块宽度与高度同时乘以 [count]。 如果没有上次可视操作,选择 [count] 个字符,就像光标向 右移动 N * [count] (译者注: [count]?) 字符那样。如果 'selection' 不是 "exclusive",少算一个字符。 V linewise-visual V 进入可视模式,以行为单位选择。 若带 [count],从当前光标位置开始,选择上次可视操作使用 的相同行数乘以 [count]。如果没有前次可视操作,选择 [count] 行。 CTRL-V blockwise-visual [count]CTRL-V 进入列块可视模式。备注: 在 Windows 环境中,CTRL-V 可能 被映射为粘贴操作,所以可能无法用来进入列块可视模式。参 见 CTRL-V-alternative[count] 用法同上述 v 。 在可视模式下,按 <Esc>、点击鼠标左键或键入任意一个跳转到另外一个缓冲区的命令, 都会取消当前选择区的高亮显示,不影响任何文本。同时,在字符可视模式按 "v"、列块 可视模式按 "CTRL-V" 以及行可视模式按 "V" 将起到同样效果。按 CTRL-Z 键将终止可 视高亮显示,然后挂起当前编辑器或者启动新的外壳。 CTRL-Z 当键入 "v"、"CTRL-V" 和 "V" 时的模式转换: v_v v_CTRL-V v_V 原有模式 "v" "CTRL-V" "V" 普通 可视 列块可视 行可视 可视 普通 列块可视 行可视 列块可视 可视 普通 行可视 行可视 可视 列块可视 普通 gv v_gv reselect-Visual gv 启动可视模式,重新选择上一次的选择区和相同模式。 在可视模式下,该命令将交换当前和上一次选择区。 在可视模式下使用 "p" 或 "P" 后,本命令选择被粘贴的文 本。 gn v_gn gn 使用前次搜索模式正向搜索,就像 n 一样,并启动可视模 式来选中匹配。 如果光标在匹配上,可视地选择之。 如果有操作符等待,在匹配上进行操作。例如,"dgn" 删除下 一个匹配的文本。 如果可视模式已激活,选择范围扩展到下一个匹配处的尾部。 应用 'wrapscan' 注意: 和 n 不同,搜索方向不取决于前次搜索命令。 gN v_gN gN 类似于 gn 但反向搜索,就像 N 那样。 <LeftMouse> <LeftMouse> 设置当前光标位置。如果处在可视模式,则退出可视模式。此 功能只有在 'mouse' 选项包含 'n' 或 'a' 才可用。如果点 击位置与屏幕最后一行的距离在 'so' 选项设置的范围之内, 屏幕文本将会上滚。同样,如果点击位置与屏幕第一行的距离 在 'so' 选项设置的范围之内,屏幕文本将会下滚。 <RightMouse> <RightMouse> 如果当前不是可视模式,则进入可视模式。光标位置和鼠标点 击位置之间的文本将被高亮显示。如果当前已经处于可视模 式,文本高亮选择区的起点或终点之一将被置为鼠标点击的位 置。起点或终点的选择取决于谁离点击位置更近。此功能只有 在 'mouse' 选项包含 'n' 或 'a' 时才可用。 备注: 当 'mousemodel' 被设为 "popup",本操作将引发 <S-LeftMouse> 动作,而不是 <RightMouse> <LeftRelease> <LeftRelease> 如果 <LeftRelease> 的位置与 <LeftMouse> 不同,那么它的 作用等同于 <LeftMouse>。在旧版本的 xterm 中,鼠标释放 之前是看不到所选择的区域的,除非可以访问 xterm 运行的 显示设置 (通过 DISPLAY 环境变量或 -display 参数)。此功 能只有在 'mouse' 选项包含 'n' 或 'a' 时才可用。 如果可视模式没有激活,同时 "v"、"V" 或 CTRL-V 命令之前包含一个计数 (count),那 么上一次选择区的大小将被作为本次选择操作的参考值。然后你可以移动选择区的结束点 并对选择区进行操作。选择区类型与上次相同 (字符选择,行选择,或列块选择)。 - 行选择模式: 行的数目与计数相乘。 - 列块模式: 行和列的数目分别与计数相乘。 - 普通可视模式,选择区在一行以内: 选择区的字符数与计数相乘。 - 普通可视模式,选择区包含多行: 行的数目与计数相乘,最后一行的字符数目与上一次 选择区相同。 文本的起始点在光标位置。如果上一次的命令中包含了 "$" 命令来扩展高亮文本,那么 选择区将扩展到最长行的最后一列。 如果你想选取和上一次完全一样的选择区,请使用 "gv" gv v_gv 命令。 v_<Esc> <Esc> 可视模式下: 停止可视模式。 v_CTRL-C CTRL-C 可视模式下: 停止可视模式。如果插入模式等待中 (模式信息 显示为 "-- (插入) 可视 --"),插入模式同时被停止。

3. 改变可视区域 visual-change

v_o o 跳到高亮文本的另一端 (Other): 当前光标位置变成高亮文本 的起点,光标移动到高亮文本的另一端。高亮区域保持不变。 v_O O 跳到高亮文本的另一端。同 "o" 命令相似,但是在列块模式 下,光标移动到水平方向的另一个角。如果这个角上的字符占 据了多个屏幕位置 (例如一个 <Tab>),那么高亮的文本区域 会被改变。 v_$ 如果 "$" 命令和列块模式同时使用,那么高亮文本区域的右边界将取决于高亮区域中最 长的行。如果遇到一个不是直上直下的移动命令,那么这个规则将终止。 有很多命令可以移动块的结束点。但是不能使用 Ex 命令,以及其它可能改变或放弃文件 的命令。下面这些命令 (或者以它们开始的命令): "."、"&"、CTRL-^、"Z"、CTRL-]CTRL-TCTRL-RCTRL-ICTRL-O 将会引起铃声,但可视模式保持不变。 当切换到同一缓冲区的另外一个窗口时,目标窗口中的光标位置会被调整,以使相同的可 视区域被选中。这一点特别适合在一个窗口查看可视区域的起点,而在另一个窗口查看它 的终点。这时候可以用鼠标右键 <RightMouse> (或者,当 'mousemodel' 选项置为 "popup" 时,用 <S-LeftMouse>) 来拖拽可视区域两端之一。

4. 操作可视区域 visual-operators

对可视区域可以使用的操作符包括: ~ 切换大小写 v_~ d 删除 v_d c 修改 (4) v_c y 抽出 v_y > 右移 (4) v_> < 左移 (4) v_< ! 通过外部命令过滤 (1) v_! = 通过 'equalprg' 选项的命令过滤 (1) v_= gq 按照 'textwidth' 指定的宽度排版行 (1) v_gq 可用的对象包括: aw 一个单词 (包括空格) v_aw iw 内含单词 v_iw aW 一个字串 (包括空格) v_aW iW 内含字串 v_iW as 一个句子 (包括空格) v_as is 内含句子 v_is ap 一个段落 (包括空格) v_ap ip 内含段落 v_ip ab 一个 () 块 (包括小括号) v_ab ib 内含 () 块 v_ib aB 一个 {} 块 (包括大括号) v_aB iB 内含 {}v_iB at 一个 <tag> </tag> 块 (包含 tag) v_at it 内含 <tag> </tag> 块 v_it a< 一个 <> 块 (包括 <>) v_a< i< 内含 <>v_i< a[ 一个 [] 块 (包括 []) v_a[ i[ 内含 [] 块 v_i[ a" 一个双引号字符串 (包括引号) v_aquote i" 内含双引号字符串 v_iquote a' 一个单引号字符串 (包括引号) v_a' i' 内含单引号字符串 v_i' a` 一个反引号字符串 (包括反引号) v_a` i` 内含反引号字符串 v_i` 其它可以使用的命令: : 为高亮的行启动 Ex 命令 v_: r 修改 (4) v_r s 修改 v_s C 修改 (2) (4) v_C S 修改 (2) v_S R 修改 (2) v_R x 删除 v_x D 删除 (3) v_D X 删除 (2) v_X Y 抽出 (2) v_Y p 放置 v_p P 放置而不覆盖寄存器 v_P J 连接 (1) v_J U 变成大写 v_U u 变成小写 v_u ^] 查找标签 v_CTRL-] I 列块插入 v_b_I A 列块添加 v_b_A (1): 总是应用到整行,见 :visual_example 。 (2): 如果不是使用 CTRL-V,应用到整行。 (3): 如果不是使用 CTRL-V,应用到整行。如果使用 CTRL-V,删除到行尾。 (4): 如果使用 CTRL-V,只对列块操作。 注意 ":vmap" 可以进行可视模式下的键盘映射。例如,如果你不想让 "/" 命令扩展选择 区,而是将高亮的文本作为关键字进行搜索,可以这样映射: :vmap / y/<C-R>"<CR> (<> 记法要求逐字键入它的内容 <> ,同时必须在 'cpoptions' 选项中移去 'B' 和 '<' 标志位) 如果你想用 """ 命令指定一个寄存器,只须将寄存器命令加在操作符之前: "v{move-around}"xd" 如果你想给命令加上计数,只须将数字加在操作符之前: "v{move-around}3>" (向右缩进 3 次)。 {move-around} {move-around} 是任何移动命令的组合。注意 它与 {motion} 的区别,后者只代表 一个 移动命令。 对可视区域的另一种操作方法是用模式中的 /\%V 项。例如,要在可视区域中把 '(' 全部替代为 '#': :'<,'>s/\%V(/#/g 注意 在可视模式中按 ":" 时,"'<,'>" 部分会自动出现。

5. 列块操作 blockwise-operators

提醒: 尝试打开 'virtualedit' 选项,以便列块选择的起点和终点可以超越一行的结尾 或位于制表符的中间。 列块插入 v_b_I 对一个列块可视模式下的选择区,I{string}<ESC> 命令将会从选择区开始的位置在每一 行插入字符串 {string}。但是只有那些和选择区有交集的行才会被插入,因此过短的行 将不受影响。如果选择区包含制表符,制表符将会被分开,以维持选择区的可视列不变。 只适用于给一行增加文本,而不是删除。见 v_b_I_example 。 列块添加 v_b_A 对一个列块可视模式下的选择区,A{string}<ESC> 命令将会从选择区结束处开始在每一 行插入字符串 {string}。当行的长短不同的时候,将导致选择区的右边界不是直线,这 时候列块添加操作的行为就会有所不同: 1. 如果列块是用 <C-v>$ 命令产生的: 这种情况下字符串被附加到每一行的结尾。 2. 如果列块是用 <C-v>{move-around} 命令产生的: 这种情况下字符串将被附加到每一行列块的结尾。对于比较短的行,行尾和列块结尾 列之间将以空白填充。 见 v_b_A_example备注: 对于那些由于过短而没有扩展到选择区的行,"I" 和 "A" 的操作结果是不同的。 这样的设计是有意的,以便你能够选择自己所希望的操作。 只适用于给一行增加文本,而不是删除。见 v_b_I_example 。 列块修改 (c) v_b_c 选择区的所有文本将被相同的字符串代替。当使用 "c" 命令的时候选择区的文本将被删 除,然后进入插入模式。这时候你可以键入不带回车的文本。当你按 <Esc> 的时候所键 入的文本将被插入选择区的每一行。 列块修改 (C) v_b_C 同 "c" 命令,但是选择区将扩展到每一行的结尾。 v_b_< 列块平移 v_b_> 列块按照 'shiftwidth' 指定的单位移动。与块的右边界无关。块的左边界决定了从哪一 点开始右移,填充的空白根据 'ts''et' 设置的宽度最优化制表符的使用方式。而块 的左边界决定了左移的终止点。 见 v_b_>_example 。 见 v_b_<_example 。 列块替换 v_b_r 高亮区域的每个字符被同一个字符代替。制表符将被分割,虚拟空白字符也将被替换,以 保持屏幕布局。 见 v_b_r_example

6. 重复 visual-repeat

当重复一个可视模式操作时,该操作将被应用到与上次操作相同数量的文本上: - 行可视模式: 相同数量的行。 - 列块可视模式: 相同数量的行和列。 - 选择区在一行之内的普通可视模式: 相同数量的字符。 - 跨越多行的普通可视模式: 相同数量的行,最后一行的字符数与上次相同。 重复操作的起始点在当前光标位置。如果重复的命令中包含 "$" 命令来扩展选择区,那 么重复操作将应用到最长行的最右一列。不使用传递给 . 命令的计数。

7. 示例 visual-examples

:visual_example 目前 ":" 命令只能作用在一整行。当你选择某一行的一部分,执行一个类似 ":!date" 的命令,命令输出将替换当前行的全部。如果你只想让它替换行的一部分,则必须做一个 映射。在将来的版本中,":" 可能可以作用于行的一部分。 下面这个示例能够用 "date" 命令的输出替换所选择的文本: :vmap _a <Esc>`>a<CR><Esc>`<i<CR><Esc>!!date<CR>kJJ (<> 记法要求逐字键入它的内容 <> ,同时必须在 'cpoptions' 选项中移去 'B' 和 '<' 标志位) 它所做的是: <Esc> 停止可视模式 `> 移动到可视区域的结尾 a<CR><Esc> 在可视区域的结尾断行 `< 跳到可视区域的开始 i<CR><Esc> 在可视区域的起点断行 !!date<CR> 通过 date 命令过滤可视文本 kJJ 把行重新连接起来 visual-search 下面这个键盘映射能够将当前的选择区作为关键字进行搜索: :vmap X y/<C-R>"<CR> (<> 记法要求逐字键入它的内容 <> ,同时必须在 'cpoptions' 选项中移去 'B' 和 '<' 标志位) 注意 某些特殊字符 (例如 '.' 和 '*') 可能会引起问题。 列块可视模式示例 blockwise-examples 在下面的示例中,我将说明列块操作命令以及命令所执行的结果。在所有的示例中,光标 起始点位于测试文本第一行的 'a' 字符上。 假定使用模式行的设置为: ":ts=8:sw=4:"。 另外,进行这样的设置将有助于显示操作细节: :set hls /<TAB> 这里的 <TAB> 是一个真正的 TAB (即按下 Tab 键)。 测试文本是: abcdefghijklmnopqrstuvwxyz abc defghijklmnopqrstuvwxyz abcdef ghi jklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz 1. fo<C-v>3jISTRING<ESC> v_b_I_example abcdefghijklmnSTRINGopqrstuvwxyz abc STRING defghijklmnopqrstuvwxyz abcdef ghi STRING jklmnopqrstuvwxyz abcdefghijklmnSTRINGopqrstuvwxyz 2. fo<C-v>3j$ASTRING<ESC> v_b_A_example abcdefghijklmnopqrstuvwxyzSTRING abc defghijklmnopqrstuvwxyzSTRING abcdef ghi jklmnopqrstuvwxyzSTRING abcdefghijklmnopqrstuvwxyzSTRING 3. fo<C-v>3j3l<.. v_b_<_example abcdefghijklmnopqrstuvwxyz abc defghijklmnopqrstuvwxyz abcdef ghi jklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz 4. fo<C-v>3j>.. v_b_>_example abcdefghijklmn opqrstuvwxyz abc defghijklmnopqrstuvwxyz abcdef ghi jklmnopqrstuvwxyz abcdefghijklmn opqrstuvwxyz 5. fo<C-v>5l3jrX v_b_r_example abcdefghijklmnXXXXXXuvwxyz abc XXXXXXhijklmnopqrstuvwxyz abcdef ghi XXXXXX jklmnopqrstuvwxyz abcdefghijklmnXXXXXXuvwxyz

8. 选择模式 Select Select-mode

选择模式看起来与可视模式非常相似,但是在选择模式所接受的命令与可视模式有很大不 同。它类似于 Microsoft Windows 上的选择模式。如果 'showmode' 选项打开,处于选 择模式的时候在屏幕底端会显示 "-- 选择 --"。 进入选择模式的几种方法: - 使用鼠标选择一片区域,同时 'selectmode' 选项包含 "mouse"。'mouse' 必须包含对 应当前模式的标志位。 - 在按下 Shift 键的同时,键入不可显示的光标移动命令,同时 'selectmode' 选项包 含 "key"。例如: <S-Left><S-End>'keymodel' 选项也必须包含 "startsel"。 - 键入 "v"、"V" 或 CTRL-V 命令,同时 'selectmode' 选项包含 "cmd"。 - 在普通模式键入 "gh"、"gH" 或 "g_CTRL-H" 命令。 - 在可视模式,键入 CTRL-G v_CTRL-G 选择模式的命令: - 所有可显示字符、<NL><CR> 将删除当前的选择区,然后进入插入模式。插入键入 的字符。 - 键入不可显示移动命令的同时,按下 Shift 键,将扩展当前的选择区。 'keymodel' 选项必须包含 "startsel"。 - 键入不可显示移动命令的同时, 没有 按下 Shift 键,将退出选择模式。 'keymodel' 选项必须包含 "stopsel"。 - 按 ESC 键退出选择模式。 - CTRL-O 临时切换到可视模式执行一个命令。 v_CTRL-O - CTRL-G 切换到可视模式。 - CTRL-R {register} 选择键入文本时文本被删除的寄存器。 v_CTRL-R 除非指定的是 "_" (黑洞) 寄存器,无名寄存器也被覆盖。 除此之外,所有键入字符的处理方式与可视模式相同。 如果选择模式是按行选择,那么在选择模式使用操作符时,所选中的行将被作为操作对 象,但是作用的方式与按字符选择相同。举例来说: 如果删除了一整行,之后它可以被粘 贴到另一行的中间。 选择模式中的键盘映射和菜单 Select-mode-mapping :vmap:vmenu 命令定义的映射和菜单可以同时用于可视模式和选择模式。如果用 于选择模式,Vim 自动切换到可视模式,以便执行与可视模式相同的操作。如果你不希望 这样,可以使用 :xmap 或者 :smap 。 一个特别的特例: :vnoremap <C-K> <Esc> 在可视模式下,这会结束可视模式,但在选择模式下却不行,因为选择模式在执行完映射 键后会恢复选择模式。为此,要用: :snoremap <C-K> <Esc> 用户一般期待可显示字符会替代选择区域。所以,要避免选择模式下映射可显示字符。也 可以在 :map:vmap 之后用 :sunmap 来撤销选择模式下的映射。 当键盘映射或菜单命令执行完毕,Vim 回到选择模式,选择区被重新激活。除非选择区域 被删除,切换到另外一个缓冲区,或者窗口布局被改变。 当键入一个字符,将引起当前选择区被删除从而进入插入模式。插入模式的键盘映射将应 用到这个刚刚键入的字符。这可能会引起一些混淆,因为它意味着在选择模式输入的字符 使用了插入模式的映射。语言的映射与此相同。 gV v_gV gV 当一个选择模式的键盘映射或菜单命令被执行完毕后,不再自 动选择可视区域。把 gV 放在键盘映射或菜单命令的结尾即 可。或者至少应该在任何对选择区操作的命令之后。 gh gh 启动字符方式的选择模式。同 "v" 命令类似,但是启动的是 选择模式,而不是可视模式。 助记: "get highlighted"。 gH gH 启动按行选择的选择模式。同 "V" 命令类似,但是启动的是 选择模式,而不是可视模式。 助记: "get Highlighted"。 g_CTRL-H g CTRL-H 启动列块方式的选择模式。同 CTRL-V 命令类似,但是启动的 是选择模式,而不是可视模式。 助记: "get Highlighted"。 vim:tw=78:ts=8:noet:ft=help:norl: