editing

editing.txt 适用于 Vim 9.0 版本。 最近更新: 2023年2月 VIM 参考手册 by Bram Moolenaar 译者: Willis 编辑文件 edit-files 1. 简介 edit-intro 2. 编辑单个文件 edit-a-file 3. 参数列表 argument-list 4. 写入 writing 5. 写入并退出 write-quit 6. 对话框 edit-dialogs 7. 当前目录 current-directory 8. 编辑二进制文件 edit-binary 9. 加密 encryption 10. 修改时间 timestamps 11. 文件搜索 file-searching

1. 简介 edit-intro

用 Vim 编辑一个文件意味着: 1. 把该文件读到缓冲区 2. 用编辑器命令修改缓冲区 3. 把缓冲区内容写回文件 current-file 只要你不保存缓冲区,原来的文件保持不变。如果你开始编辑一个文件 (把它的内容读到 缓冲区里),该文件名被认作 "当前文件名",或者说当前缓冲区的名字。命令行上,可以 用 "%" 来引用它 :_% alternate-file 如果已经有了另外一个当前文件名,它会成为轮换文件名。命令行上,可以用 "#" 引用 它 :_# 。你还可以用 CTRL-^ 命令在当前和轮换文件之间切换。不过,轮换文件名在 使用 :keepalt 期间不予改变。 每个窗口分别记住自己的轮换文件名。 :keepalt :keepa :keepalt {cmd} 执行 {cmd},在此期间保持当前轮换文件名不变。注意 间接 调用的命令 (比如通过函数) 仍然可以设置轮换文件名。 所有文件名都会被记录在缓冲区列表里。在你输入文件名以便编辑 (例如,用 ":e 文件 名") 或者写回 (例如,用 ":w 文件名") 时,此文件名被加入该列表。你可以用缓冲区 列表来记住编辑过什么文件并用 CTRL-^ 命令快速的从一个文件切换到另一个 (例如,以 便复制文本)。先敲入文件的编号再敲入 CTRL-^CTRL-G CTRL-G :f :fi :file :f[ile] 显示当前文件名 (如同输入的那样,除非使用过 ":cd")、光 标位置 (除非置位了 'ruler' 选项) 和文件状态 (只读、已 修改、读入错误、新文件)。参见 'shortmess' 选项,了解如 何可以简化该消息。 :f[ile]! 和 :file 类似,但即使 'shortmess' 要求截短文件名,也 不这么做。 {count}CTRL-GCTRL-G 类似,但显示当前文件名的完整路径。如果计数大 于 1,则同时给出当前缓冲区号。 g_CTRL-G word-count byte-count g CTRL-G 显示当前光标位置,以五种方式表达: 列、行、单词、字符和 字节计数。如果字符数和字节数相同,省略字符位置。 如果当前行有字符占据多于一个位置 (<Tab> 或其他特殊字 符),或每列占用超过一字节 ('encoding' 为 utf-8 时高于 0x7F 的字符),同时显示字节列和屏幕列,以连字号分隔。 另见 'ruler' 选项和 wordcount() 函数。 v_g_CTRL-G {Visual}g CTRL-G 和 "g CTRL-G" 类似,但显示可视选择区域的单词、字符、行 和字节计数。在面向列块模式里,列数也同时显示。(关于 {Visual}Visual-mode 。) :file_f :f[ile][!] {name} 设置当前文件名为 {name}。可选的 ! 避免截短消息,就像 :file 那样。 如果缓冲区已有名字,该名字成为 alternate-file 轮换 文件名。新建一个列表外缓冲区来记住这个旧名字。 :0file :0f[ile][!] 删除当前缓冲区的名字。可选的 ! 避免截短消息,就像 :file 那样。 :buffers :files :ls 列出当前已知的文件名。见 'windows.txt' :files :buffers :ls 。 vim 会记住你输入文件名的完整路径。大多数情况下,文件名只以你输入的方式显示。但 ":cd" 命令 :cd 使用后,就会看到完整路径名。 home-replace 如果设置了环境变量 $HOME,而文件名以该字符串开始,它的显示会把 HOME 替换成 "~"。这么做是为了使文件名的显示较为简洁。在读写文件时仍然使用完整路径名,"~" 只供显示文件名用。如果要替换名字实质上只有 "~" 的文件,会使用 "~/" (为了避免 设为 $HOME 的选项和设为 '~' 时的 'backupext' 混淆)。 保存缓冲区时,缺省使用当前文件名。这样,如果你给出 "ZZ" 或者 ":wq" 命令,原有 的文件被覆盖。如果你不想如此,给 ":write" 命令给出一个文件名参数,你可以把缓冲 区写到另外一个文件里。例如: vim testfile [用编辑器命令修改缓冲区] :w newfile :q 这会建立文件 "newfile",它是 "testfile" 经过修改的版本。"testfile" 文件保持不 变。无论如何,如果置位 'backup' 选项,Vim 会在原来的文件被覆盖之前改名或复制。 如果你以后发现你需要原来的版本,你可以用这个备份文件。也可参见 'patchmode' 选 项。备份文件名通常是原来的文件加上 'backupext' 后缀。缺省的 "~" 比较奇特,目的 是为了防止意外覆盖现存的文件。如果你喜欢 ".bak",修改 'backupext' 选项。在 MS-Windows 机器上,当 Vim 检测到正在使用的是 MS-DOS 兼容的文件系统 (例如, messydos 或者 crossdos) 或者打开了 'shortname' 选项,多余的点号被替换成 '_'。 通过设置 'backupdir',备份文件也可存在别的目录下。 auto-shortname 技术上: 在 Amiga 上文件名可以长达 30 个字符。但在 MS-DOS 兼容的文件系统上只能 用 8+3 个字符。Vim 试图在创建 .swp 文件的时候检测文件系统的类型。如果 怀疑是一个 MS-DOS 兼容的文件系统,则置位一个标志位,它和设置 'shortname' 选项有相同的效果。一旦你开始编辑一个新文件,该标志位被复 位。在根据当前文件名创建 ".swp" 和 ".~" 文件时,该标志位起作用。但如果 你在一个正常的文件系统上编辑文件,而写到一个 MS-DOS 兼容的文件系统,该 标志位不会被置位。这种情况下,创建 ".~" 文件可能会失败,你会得到一个错 误消息。这种情况下,用 'shortname' 选项。 当你开始编辑而不给出文件名,会给出 "No File" 消息。如果 ":write" 命令带一个文 件名参数,当前文件名被设为那个名字。这只有在 'cpoptions' 里带 'F' 标志位 (缺省 的确是如此) 时才会发生 cpo-F 。这对在空缓冲区里编辑文本后写入到文件有用。如果 'cpoptions' 里包含 'f' 标志位 (缺省 包含) cpo-f ,在执行 ":read file" 时, 文件名被设置。这可用来先不带参数启动 Vim 再用 ":read file" 编辑文件。 如果设置了文件名而 'filetype' 为空,激活文件类型检测的自动事件。 not-edited 因为设置文件名并不是真正编辑该文件,你不会覆盖它。这可由设置 "notedited" 标志 位来完成。你可由 CTRL-O 或 ":file" 命令看到该标志位是否设置。如果 "notedited" 标志位已设置,它会包括 "[Not edited]"。当将缓冲区写回当前文件名 (用 ":w!") 时,"notedited" 标志位被重设。 abandon Vim 记住你是否修改了缓冲区。你所作的修改不会不小心丢失。如果试图不写回而退出, 或开始编辑别的文件,Vim 会拒绝。要绕过这重保护,在命令后加上 '!'。这样,修改就 会丢失。例如: ":q" 在缓冲区修改后不会工作,但 ":q!" 会。要知道缓冲区是否修改, 用 "CTRL-G" 命令。如果缓冲区被修改,消息里会有字符串 "[Modified]" 或者 "+", 后者如果 'shortmess' 有 'm' 标志位。 如果你想不经提示而自动写回改动,打开 'autowriteall' 选项。'autowrite' 是相关的 Vi-兼容选项,它并非对所有命令有效。 如果想保留修改了的缓冲区但不写回,打开 'hidden' 选项。参见 hidden-buffer 。有 些命令即便 'hidden' 没有置位也会如此,具体须参见各个命令的帮助。

2. 编辑单个文件 edit-a-file

:e :edit reload :e[dit] [++opt] [+cmd] 编辑当前文件。可用于在它被 Vim 之外的程序所改变的时候 重新编辑当前文件。 如果当前缓冲区已经被修改而且没有置 位 'autowriteall',或者文件不能被写入,本命令失败。 另见 ++opt+cmd :edit! discard :e[dit]! [++opt] [+cmd] 总是编辑当前文件。放弃当前缓冲区任何已有的改变。如果你 想从头来过,这就会很有用。 另见 ++opt+cmd :edit_f :e[dit] [++opt] [+cmd] {file} 编辑文件 {file}。 如果当前缓冲区已被修改,这会失败,除非置位了 'hidden' 或者 'autowriteall' 并且文件能够写入。 另见 ++opt+cmd :edit!_f :e[dit]! [++opt] [+cmd] {file} 总是编辑文件 {file}。放弃当前缓冲区任何已有的改变。 另见 ++opt+cmd :edit_# :e# :e[dit] [++opt] [+cmd] #[count] 编辑第 [count] 个缓冲区 (根据 :files 显示的结果)。 该命令和 [count] CTRL-^ 一样,但是 ":e #" 在轮换缓冲区 没有文件名时不能工作,而 CTRL-^ 则可以。 另见 ++opt+cmd :ene :enew :ene[w] 编辑一个新的无名缓冲区。如果当前缓冲区已被修改,这会失 败,除非置位了 'hidden' 或者 'autowriteall' 并且文件能 够写入。 如果 'fileformats' 非空,其给出的第一个格式将用于新的 缓冲区上。如果 'fileformats' 为空,则使用当前缓冲区的 'fileformat' :ene! :enew! :ene[w]! 编辑新的无名缓冲区。放弃当前缓冲区任何已有的改变。 'fileformat' 的设置类似于 :enew :fin :find :fin[d][!] [++opt] [+cmd] {file}'path' 里找到 {file},然后编辑 :edit 它。 :{count}fin[d][!] [++opt] [+cmd] {file} 和 ":find" 类似,但使用 'path' 的第 {count} 个匹配。这 样,":2find file" 会找到 'path' 里的第二个 "file"。如 果 'path' 里文件的匹配不足所需之数,你会得到一个错误消 息。 :ex :ex [++opt] [+cmd] [file]:edit 相同。 :vi :visual :vi[sual][!] [++opt] [+cmd] [file] 用于 Ex 模式时: 退出 Ex-mode ,回到普通模式。否则和 :edit 相同。 :vie :view :vie[w][!] [++opt] [+cmd] file 用于 Ex 模式时: 退出 Ex-mode ,回到普通模式。否则和 :edit 相同,但为本缓冲区置位 'readonly' 选项。 CTRL-^ CTRL-6 CTRL-^ 编辑轮换文件。 多数情况下,轮换文件就是上次编辑的文件。这是切换两个文 件的一个快速方法。这和 ":e #" 等价,但也能用在没有文件 名的情况。 如果 'autowrite''autowriteall' 选项打开并且缓冲区 被修改,则写入文件。 大多数情况下,^ 字符在键 6 之上,同时按 CTRL 和 6 会给 出我们叫 CTRL-^ 的键码。但在有的非-US 的键盘上 CTRL-^ 须以不同的方式生成。 [count]CTRL-^ 编辑缓冲区列表里第 [count] 个文件 (和 ":e #[count]" 等 价)。这是切换文件的一个快速方法。 详情见上面 CTRL-^[count]]f ]f [f [count][f 和 "gf" 一样。它本身已被淘汰。 gf E446 E447 [count]gf 编辑光标之上或之后的文件名对应的文件。 助记: "goto file"。 使用 'isfname' 选项来决定组成文件名的字符。拖尾的标点 符号 ".,:;!" 被忽略。空格的转义 "\ " 缩为一个空格。 在 'path' 选项组成的目录名列表查找文件。关于相对路径和 通配符,可见 'path' 选项。 设置 'suffixesadd' 选项可以用来查找文件所要附加的后 缀。如果文件找不到,用 'includeexpr' 来修改名字,然后 再试一次。 如果给出 [count]'path' 里找到的第 count 个文件被编 辑。 如果 Vim 拒绝放弃 abandon 当前文件,该命令失败。 如果你想在新窗口里编辑文件,用 CTRL-W_CTRL-F 。 如果你想编辑新文件,用: :e <cfile> 想使得 gf 总是如此工作,可以如此: :map gf :e <cfile><CR> 如果名字是一个超文本链接,也就是看来像 "type://machine/path" 这样的,你需要 netrw 插件。 对 Unix 而言,'~' 字符被扩展,比如在 "~user/file" 的场 合。环境变量也得到扩展 expand-env v_gf {Visual}[count]gf 和 "gf" 相同,但是高亮文本被用来作为要编辑的文件名。 'isfname' 被忽略。开头的空白被忽略,除此以外,所有的空 白和特殊字符被包括在文件名里。 ({Visual} 可参见 Visual-mode 。) gF [count]gF 和 "gf" 相同,但如果文件名后面跟随着数值,那么光标将定 位在该文件名的该行上。 文件名和数值之间必须以一个非文件名 (见 'isfname') 和非 数字字符分隔。也能识别 " line ",就像 `:verbose command UserCmd` 的输出那样。文件名、分隔符 和数值之间的空白被忽略。 例如: eval.c:10 eval.c @ 20 eval.c (30) eval.c 40 v_gF {Visual}[count]gF 和 "v_gf" 相同。 这些命令用来开始编辑单独一个文件。这意味着该文件被读入缓冲区里并设置当前文件 名。打开哪个文件和当前目录有关,见 :cd 。 关于文件读入以后给出的消息,参见 read-messages 。 如果你把缓冲区内容弄乱了想从头开始编辑,你可以用 ":e!" 命令。":e" 命令只有在你 改变当前文件名的时候有用。 :filename {file} 除了这里说明的事项以外, cmdline-special 也提到更多特殊项目,它们在期待文件名 时可用。 注意 除了 Unix 以外的系统: 在使用接受单个文件名的名字时 (如 ":edit file"),文 件名里可以有空格,但是拖尾的空格被忽略。这可用于允许文件名有内含的空格的系统 (如 MS-Windows 和 Amiga)。示例: 命令 ":e Long File Name " 会编辑文件 "Long File Name"。在使用能接受多于一个文件名的命令时 (如 ":next file1 file2"),内含 的空格必须以反斜杠转义。 wildcard wildcards {file} 里的通配符被扩展,但和文件补全一样,也适用 'wildignore''suffixes'。 具体支持什么通配符由系统决定。以下是一些通用的字符: ? 匹配一个字符 * 匹配任何东西,包括什么都没有 ** 匹配任何东西,包括什么都没有,递归进入目录 [abc] 匹配 'a'、'b' 或 'c' 要避免通配符的特殊含义,在前面加上反斜杠。不过,在 MS-Windows 上,反斜杠是路径 分隔符,"path\[abc]" 在 'isfname' 选项里有 "[" 的时候还是被看作通配符。一个简 单避免该问题的方法是用 "path\[[]abc]"。这样这匹配文件名 "path[abc]"。 starstar-wildcard 在 Unix、Win32、macOS 和一些其它系统上,可以扩展 "**"。它允许你在目录树里搜 索。最大深度可以到 100 层目录。 注意 有些命令的工作方式略有不同。见 file-searching 。 例如: :n **/*.txt 找到文件: aaa.txt subdir/bbb.txt a/b/c/d/ccc.txt 紧接着 "**" 之前或之后使用的非通配字符,只匹配第一层目录,而不用于匹配树结构其 下的目录。例如: :n /usr/inc**/types.h 找到文件: /usr/include/types.h /usr/include/sys/types.h /usr/inc/old/types.h 注意 之所以带 "/sys" 的路径,是因为那一层的名字不需要匹配 "/inc"。也就是说, 这相当于匹配 "/usr/inc*/*/*...",而不是 "/usr/inc*/inc*/inc*"。 backtick-expansion `-expansion 在 Unix 和一些其它系统上你可以用反引号代替文件名参数。例如: :next `find . -name ver\\*.c -print` :view `ls -t *.patch \| head -n1` Vim 会用 'shell' 来执行反引号内的命令,其标准输出作为给定 Vim 命令的参数 (但外 壳命令的错误信息会被丢弃)。 要看到 Vim 执行的外壳命令,设置 'verbose' 选项为 4。如果外壳命令返回非零退出 码,会显示错误信息并异常中止 Vim 命令。如果不想如此,须保证外壳命令永远返回零 值。可以这样: :next `find . -name ver\\*.c -print \|\| true` 星号之前需要有反斜杠,以防 "ver*.c" 在执行 find 程序之前被外壳先扩展。在外壳管 道符号 "|" 之前的反斜杠使 Vim 不会把它解析为命令的终止。 该功能对于多数其他系统也使用,但要求反引号必须包围整个项目。你不能在第一个之前 和最后一个反引号之后有别的文本。 `= E1083 在第一个反引号之后紧跟等号,可以使得反引号用来作 Vim 表达式,而非外部命令来扩 展。例如 :e `=tempname()` 该表达式里可以包含任何东西,因而可以用来避免 '"'、'|'、'%' 和 '#' 的特殊含义。 不过,和其它通配符一样,'wildignore' 也适用。 表达式里的环境变量在执行表达式前先扩展,所以可以这样: :e `=$HOME .. '/.vimrc'` 此处 $HOME 如果在字符串里,会被按本义使用,这大概不是你想要的: :e `='$HOME' .. '/.vimrc'` 如果表达式结果为字符串,名字以换行符分隔。如果结果是 List ,每个项目用作一个 名字。换行符也分隔名字。 注意 这样的表达式只有在 Ex 命令期待文件名参数的地方才有效。 ++opt [++opt] [++opt] 参数可以用来为某个命令强制指定 'fileformat''fileencoding''binary' 的值,并指定遇到坏字符的行为。其形式是: ++{optname} 或: ++{optname}={value} 其中 {optname} 是以下之一: ++ff ++enc ++bin ++nobin ++edit ff 或 fileformat 超越 'fileformat' 之值 enc 或 encoding 超越 'fileencoding' 之值 bin 或 binary 置位 'binary' nobin 或 nobinary 复位 'binary' bad 指定坏字符的行为 edit 只用于 :read : 保持选项的值,就像编辑文件那样 {value} 不能包含空白。它可以是这些选项任何可取之值。例如: :e ++ff=unix 再次编辑相同的文件,但指定 'fileformat' 为 "unix"。 :w ++enc=latin1 newfile 把当前缓冲区写入到 "newfile",以 latin1 编码。 当 'fileencoding' 或 ++enc 指定的值不同于 'encoding' 时,写入文件时给出的消息 会显示 "[已转换]"。 可以用多个 ++opt 参数,以空格分隔。它们都必须在任何 +cmd 参数之前。 ++bad 参数 "++bad=" 指定遇到不能转化或者包含非法字节的字符时的行为。它可以是以下三种 形式之一: ++bad=X 单字节的字符,替代每个坏字符。 ++bad=keep 保留坏字符,不予转化。注意 这可能使得你的文本里出现非法字节! ++bad=drop 删除坏字符。 缺省就像用了 "++bad=?" 一样: 每个坏字符被问号代替。有些地方会使用一个倒转的问 号 (0xBF)。 注意 不是所有的命令都接受 ++bad 参数,但也不会报错,例如 :write注意 在读入文件时,'fileformat''fileencoding' 选项会被设为实际所用的格式。 在写回时,这不会发生。因此下一次写会使用选项的旧值。'binary' 选项也同样如此。 +cmd [+cmd] [+cmd] 参数可以用来在新打开的文件定位光标或执行任何其他命令: + 从最后一行开始。 +{num} 从第 {num} 行开始。 +/{pat} 从匹配 {pat} 的第一行开始。 +{command} 打开新文件以后执行 {command}{command} 可以是任何 Ex 命令。 要在 {pat}{command} 里包含空白,在它之前加上反斜杠。反斜杠本身则要加倍。 :edit +/The\ book file :edit +/dir\ dirname\\ file :edit +set\ dir=c:\\\\temp file 注意 最后一个例子里反斜杠减半两次: 一次用于 "+cmd" 参数,一次用于 ":set" 命 令。 file-formats 'fileformat' 选项指定文件里的换行符 (<EOL>) 风格: 'fileformat' 字符 名字 "dos" <CR><NL><NL> DOS 格式 DOS-format "unix" <NL> Unix 格式 Unix-format "mac" <CR> Mac 格式 Mac-format 以前还使用 'textmode' 。现在已经废弃了。 在读入文件时,以上列出的字符被解释为换行符。DOS 格式 (Win32 缺省值) 把 <CR><NL><NL> 都解释为换行符。 注意 在以 DOS 格式写入文件时,会在每个单独的 <NL> 之后加上 <CR> 字符。另见 file-read 。 当写入文件时,换行符用以上列出的字符写入。DOS 格式使用 <CR><NL>。另见 DOS-format-write 。 你可以从 DOS 格式读入文件再以 Unix 格式写回。这样所有的 <CR><NL> 对会被换成 <NL> (假设 'fileformats' 包括 "dos"): :e file :set fileformat=unix :w 反之,如果你从 Unix 格式读入文件再以 DOS 格式写回。所有的 <NL> 字符会被换成 <CR><NL> (假设 'fileformats' 包括 "unix"): :e file :set fileformat=dos :w 如果你开始编辑新文件而 'fileformats' 选顶非空 (缺省),Vim 会测试文件以何种格式 分隔行。如果设为 "unix,dos",Vim 会检查每行是带 <NL> (Unix 和 Amiga) 还是带 <CR><NL> 对 (MS-Windows)。只有当 所有 行都以 <CR><NL> 结尾,'fileformat' 才被 设为 "dos",否则,它被设为 "unix"。如果 'fileformats' 包含 "mac" 而且文件不含 <NL> 字符,'fileformat' 设为 "mac"。 如果 'fileformat' 选项在非 MS-Windows 的系统上设为 "dos",消息 "[dos format]" 会提示你发生了不同寻常的事情。 在 MS-Windows 系统上,如果 'fileformat' 设为 "unix",你也会得到消息 "[unix format]"。除了 Macintosh 以外的所有的系统中,如 果 'fileformat' 设为 "mac",你会得到消息 "[mac format]"。 如果 'fileformats' 选项为空而使用了 DOS 格式,但是在读入文件时发现某些行不以 <CR><NL> 结尾,"[CR missing]" 会在文件消息里列出。 如果 'fileformats' 选项为空而使用了 Mac 格式,但是在读入文件时发现某些行有 <NL>,"[NL missing]" 会在文件消息里列出。 如果新文件不存在,则当 'fileformats' 为空时使用当前缓冲区的 'fileformat',否则 使用 'fileformats' 的第一个格式。 在开始编辑二进制、可执行或 Vim 脚本文件时,你应该置位 'binary' 选项。一个简单 的方式是以 "-b" 选项启动 Vim。该选项可以避免使用 'fileformat'。如果不设,你会 有单个 <NL> 字符被莫名其妙地换成 <CR><NL> 的风险。 你可以用 'key' 选项在写回时给文件加密。它提供了相当安全性,防止别人读到你的文 件。 encryption 行 尾 和 文 件 尾 eol-and-eof Vim 有若干选项控制文件格式: 'fileformat' <EOL> 风格: Unix、DOS、Mac 'endofline' 末行是否以 <EOL> 结尾 'endoffile' 文件是否以 CTRL-Z 结尾 'fixendofline' 是否修正行尾和文件尾 头三个值一般是在读取文件时自动检测的,在写回文本到文件时使用。缓冲区在编辑时, 用户的感受则总是好像每行都有行尾且不存在 CTRL-Z (置位 'binary' 时例外,此时处 理方式不同)。 'fixendofline' 选项用于选择如何写回。通过修改选项值,也可用来和读取方式不同的 写回方法。 以下给出一些使用这些选项的实例。 要使用 Unix 格式 (每行都以 NL 结尾) 的文件: setl ff=unix fixeol 所有类 Unix 的系统大致都应如此设置。现代的 MS-Windows 系统也倾向于较好地支持这 类文件。建议 Vim 脚本总是使用此种格式。 要在现代环境下使用古老的 MS-DOS 文件,修正行尾并删除 CTRL-Z,但保持 <CR><NL> 风格的 <EOL>: setl ff=dos fixeol 这适用于许多 MS-Windows 程序,因为它们一般都期待 <CR><NL> 的行尾。 要删除末尾的 <EOL> 并加上末尾的 CTRL-Z (如用于 CP/M 这样的老式系统): setl ff=dos nofixeol noeol eof 要保留文件格式,包含所有的结尾 <EOL> 和结尾 CTRL-Z,原样不变: setl nofixeol

3. 参数列表 argument-list arglist

如果你在启动 Vim 的时候给出多个文件名,这些文件将被记住,即参数列表。你可以跳 转到该列表里的任何一个文件。 不要把它和 :buffers 命令里的缓冲区列表混淆。参数列表在 Vi 里已经存在,但 缓冲区列表是 Vim 新加入的。参数列表里的文件名也会在缓冲区列表里存在 (除非你用 :bdel:bwipe 将其删除),但不在参数列表而出现在缓冲区列表的名字很常见。 该主题在用户手册的 07.2 一节已有介绍。 只有一个全局参数列表,所有窗口缺省都使用它。但可以创建局部于窗口的新参数列表, 见 :arglocal 。 下面的命令使用参数列表,还有表达式函数 argc()argv() 。他们均作用于当前 窗口的参数列表。 :ar :arg :args :ar[gs] 显示参数列表,当前文件以方括号表示。 :ar[gs] [++opt] [+cmd] {arglist} :args_f 定义 {arglist} 为新的参数列表并编辑其中的第一个。如果 已经作了修改而 vim 不能放弃 abandon 当前的缓冲区,该 命令失败。 另见 ++opt+cmd 。 :ar[gs]! [++opt] [+cmd] {arglist} :args_f! 定义 {arglist} 为新的参数列表并编辑其中的第一个。忽略 任何对当前缓冲区的改动。 另见 ++opt+cmd 。 :[count]arge[dit][!] [++opt] [+cmd] {name} .. :arge :argedit 将一或多个 {name} 加到参数列表里,并编辑之。 如果 {name} 已经在参数列表里存在,只编辑之。 这和用 :argadd 然后 :edit 类似。 文件名里的空格需用 "\" 转义。 [count] 的用法和 :argadd 一样。 如果当前文件不能被放弃 abandon{name} 等仍会被加入 到参数列表中,但不进行编辑。不检查重复项。 另见 ++opt+cmd 。 :[count]arga[dd] {name} .. :arga :argadd E479 :[count]arga[dd] E1156 将若干文件名 {name} 等加到参数列表里。如果 {name} 省 略,把当前缓冲区名字加入参数列表。 如果忽略 [count]{name} 等加入到参数列表的当前项之 后。不然,加到第 [count] 个文件之后。如果参数列表是 "a b c",而 "b" 是当前参数,那么以下命令会导致: 命令 新的参数列表 :argadd x a b x c :0argadd x x a b c :1argadd x a x b c :$argadd x a b c x 在末项之后: :+2argadd y a b c x y 这里不会检查重复项,因此一个文件可能加入参数列表两次。 可以在其后用 :argdedupe 来修正: :argadd *.txt | argdedupe 不改变当前编辑的文件。 注意: 你也可以使用这个方法: :args ## x 这会加入 "x" 项并对新的列表排序。 :argded[upe] :argded :argdedupe 删除参数列表里的重复文件名。如果当前文件是重复项,当前 文件会被改为原始文件的索引。 :argd[elete] {pattern} .. :argd :argdelete E480 E610 从参数列表里删除匹配 {pattern} (可有多个) 的文件。 {pattern} 为文件模式,见 file-pattern 。"%" 可以用来 删除当前项。 即使该命令从参数列表里删除了当前编辑文件,该文件保持被 编辑。 例如: :argdel *.obj :[range]argd[elete] 从参数列表里删除 [range] 范围里的文件。 例如: :10,$argdel 删除第 10 个和其后的参数,保留 1-9。 :$argd 只删除最后一个。 :argd :.argd 删除当前参数。 :%argd 删除参数列表里所有文件。 如果该范围的最后一个数字过大,删除直到最后一个参数为 止。 :argu :argument :[count]argu[ment] [count] [++opt] [+cmd] 编辑参数列表里的第 [count] 个文件。在忽略 [count] 的时 候,编辑当前项。如果已经作了修改而 vim 不能放弃 abandon 当前的缓冲区,该命令失败。 另见 ++opt+cmd 。 :[count]argu[ment]! [count] [++opt] [+cmd] 编辑参数列表里的第 [count] 个文件。忽略任何对当前缓冲 区的已有修改。在忽略 [count] 的时候,编辑当前项。 另见 ++opt+cmd 。 :[count]n[ext] [++opt] [+cmd] :n :ne :next E165 E163 编辑向后第 [count] 个文件。如果已经作了修改而 vim 不能 放弃 abandon 当前的缓冲区,该命令失败。另见 ++opt+cmd 。 :[count]n[ext]! [++opt] [+cmd] 编辑向后第 [count] 个文件。忽略任何对当前缓冲区的已有 修改。另见 ++opt+cmd 。 :n[ext] [++opt] [+cmd] {arglist} :next_f :args_f 相同。 :n[ext]! [++opt] [+cmd] {arglist}:args_f! 相同。 :[count]N[ext] [count] [++opt] [+cmd] :Next :N E164 编辑向前第 [count] 个文件。如果已经作了修改而 vim 不能 放弃 abandon 当前的缓冲区,该命令失败。另见 ++opt+cmd 。 :[count]N[ext]! [count] [++opt] [+cmd] 编辑向前第 [count] 个文件。忽略任何对当前缓冲区的已有 修改。另见 ++opt+cmd 。 :[count]prev[ious] [count] [++opt] [+cmd] :prev :previous 和 :Next 相同。另见 ++opt+cmd :rew :rewind :rew[ind] [++opt] [+cmd] 开始编辑参数列表的第一个文件。如果已经作了修改而 vim 不能放弃 abandon 当前的缓冲区,该命令失败。另见 ++opt+cmd 。 :rew[ind]! [++opt] [+cmd] 开始编辑参数列表的第一个文件。忽略任何对当前缓冲区的已 有修改。另见 ++opt+cmd :fir :first :fir[st][!] [++opt] [+cmd] ":rewind" 的别名。 :la :last :la[st] [++opt] [+cmd] 开始编辑参数列表的最后一个文件。如果已经作了修改而 vim 不能放弃 abandon 当前的缓冲区,该命令失败。另见 ++opt+cmd 。 :la[st]! [++opt] [+cmd] 开始编辑参数列表的最后一个文件。忽略任何对当前缓冲区的 已有修改。另见 ++opt+cmd :wn :wnext :[count]wn[ext] [++opt] 写回当前文件并开始编辑向后第 [count] 个文件。另见 ++opt+cmd 。 :[count]wn[ext] [++opt] {file} 写入当前文件到 {file} 并开始编辑向后第 [count] 个文 件,除非 {file} 已经存在并且 'writeany' 选项被关闭。另 见 ++opt+cmd 。 :[count]wn[ext]! [++opt] {file} 写入当前文件到 {file} 并开始编辑向后第 [count] 个文 件。另见 ++opt+cmd 。 :[count]wN[ext][!] [++opt] [file] :wN :wNext :[count]wp[revious][!] [++opt] [file] :wp :wprevious 和 :wnext 相同,向前编辑而不是向后。 以上命令的 [count] 缺省为一。对有些命令可以使用两个计数。后者 (右面那个) 被使 用。 如果没有给出 [+cmd] 参数,光标定位于文件最后一个已知的位置。如果置位了 'startofline',光标会定位于该行第一个非空白字符,不然,则使用最后一个已知列。 如果没有最后已知的光标位置,光标会定位在第一行 (Ex 模式下则是最后一行)。 {arglist} 参数列表里的通配符会扩展,文件名会排序。这样你可以用命令 "vim *.c" 编辑所有的 C 文件。在 Vim 里面,":n *.c" 命令会做同样的事。 空白用来分隔文件名。在空格或制表前加上反斜杠可以在文件名里使用它们。例如,要编 辑单个文件 "foo bar": :next foo\ bar 在 Unix 和一些其它系统上你还可以使用反引号,例如: :next `find . -name \\*.c -print` 星号之前的反斜杠是必要的,它用来防止 "*.c" 在执行 find 程序之前被外壳扩展。 arglist-position 如果有参数列表,你可以在窗口的标题上看到正在编辑哪个文件 (如果有一个窗口,而且 'title' 被置位),或者通过 "CTRL-G" 命令,在文件消息里看到。你会看到类似于 (file 4 of 11) 的东西。如果 'shortmess' 包含 'f',它会成为 (4 of 11) 如果你还没有编辑参数列表当前位置的文件,它会是 (file (4) of 11) 这表示你在参数列表的第四个位置,不过还没有开始编辑之。这发生于你刚做 ":e file" 的时候。 局 部 参 数 列 表 :arglocal :argl[ocal] 复制一个全局参数列表的局部备份。并不开始编辑另外一个文 件。 :argl[ocal][!] [++opt] [+cmd] {arglist} 定义一个新的局部于当前窗口的参数列表。除此以外,和 :args_f 列表。 :argglobal :argg[lobal] 当前窗口使用全局参数列表。并不开始编辑另外一个文件。 :argg[lobal][!] [++opt] [+cmd] {arglist} 当前窗口使用全局参数列表。和 :args_f 一样,定义一个 新的全局参数列表。所有使用全局参数列表的窗口都会看到这 个新的列表。 可以有多个参数列表。他们可以在窗口之间共享。如果他们共享,在其中一个窗口修改参 数列表就会改变另一个窗口的列表。 如果一个窗口被分割,新的窗口从原来的窗口继承参数列表。两个窗口因而共享该列表, 直到其中一个窗口使用 :arglocal:argglobal 来使用另外一个参数列表。 使 用 参 数 列 表 :argdo :[range]argdo[!] {cmd} 对参数列表里的每个文件执行 {cmd}。如果给出 [range],只 对给出范围内的参数执行。 它的工作方式大致如下: :rewind :{cmd} :next :{cmd} 等等 如果当前文件不能被放弃 abandon 而且不存在 [!],该命 令失败。 如果一个文件检测到错误,参数列表里的其余文件将不再被操 作。 参数列表里的最后一个文件 (或发生错误的那个) 成为当前文 件。 {cmd} 可以包含 '|',从而连接多个命令。 {cmd} 不可修改参数列表。 注意: 当命令执行时,Syntax 自动命令事件被加到 'eventignore' 里,从而被屏蔽。这样显著提高了编辑每个文 件的速度。 另见 :windo:tabdo:bufdo:cdo:ldo:cfdo:lfdo 示例: :args *.c :argdo set ff=unix | update 它把 'fileformat' 选项设为 "unix",并写回现在已改变的所有的 *.c 文件。 示例: :args *.[ch] :argdo %s/\<my_foo\>/My_Foo/ge | update 它把所有 *.c 和 *.h 文件里的单词 "my_foo" 换成 "My_Foo"。"e" 标志位使得 ":substitute" 命令对没有使用 "my_foo" 的文件不提示错误。":update" 只有在发生改 变的时候才写入文件。

4. 写入 writing save-file

注意: 如果 'write' 选项关闭,你不能写入任何文件。 :w :write E502 E503 E504 E505 E512 E514 E667 E949 :w[rite] [++opt] 将整个缓冲区写入当前文件。这是保存文件更动最普通的方 式。如果置位了 'readonly' 选项或者其他原因不能写入文 件,它会失败。 关于 ++opt 可见 ++opt ,但只有 ++bin、++nobin、++ff 和 ++enc 有效。 :w[rite]! [++opt] 和 ":write" 类似,但即使 'readonly' 已置位或者有其他原 因写入被拒绝,还是强制写入。 注意: 这可能会改变文件的权限和所有者,或者破坏 (符号) 连接。在 'cpoptions' 里加上 'W' 标志位可以避免这一点。 :[range]w[rite][!] [++opt] 将指定行写入当前文件。这是很特别的,因为文件里将不会包 含缓冲区的所有行。 :w_f :write_f :[range]w[rite] [++opt] {file} 将指定行写入文件 {file},除非该文件已存在并且未置位 'writeany' 选项。 :w! :[range]w[rite]! [++opt] {file} 将指定行写入文件 {file}。覆盖已存在的文件。 :w_a :write_a E494 :[range]w[rite][!] [++opt] >> 将指定行附加到当前文件后。 :[range]w[rite][!] [++opt] >> {file} 将指定行附加到文件 {file} 之后。'!' 强制写入,即使该文 件还不存在。 :w_c :write_c :[range]w[rite] [++opt] !{cmd} 执行命令 {cmd},以 [range] 指定的行作为它的标准输入。 (注意 ! 之前的空格)。{cmd} 以 ":!{cmd}" 类似的方式被执 行,任何 '!' 被替换成前一个命令 :! 。 ":w" 命令缺省的 [range] 是整个缓冲区 (1,$)。如果写回整个缓冲区,缓冲区不再被认 为已改变。用 ":w somefile" 写到别的文件的情形则取决于 'cpoptions' 的 "+" 标志 位。如果包含,即便缓冲区本身和其关联的文件可能已不同,该写命令还是复位 "modified" 标志位。 如果 ":w" 给出一个文件名,它成为轮换文件。这可以用来,比如说,当写入失败而你想 再迟些再试一次: ":w #"。该功能可以通过从 'cpoptions' 选项里去掉 'A' 标志位来关 闭。 注意 'fsync' 选项如果置位,写操作会变慢 (但更安全)。 :sav :saveas :sav[eas][!] [++opt] {file} 用文件名 {file} 保存当前缓冲区,并设置当前缓冲区的文件 名为 {file}。前一个名字用作轮换文件名。[!] 用以覆盖已 存在的文件。 如果 'filetype' 为空,在写入文件前用新名字进行文件类型 检测。 如果写操作成功,复位 'readonly' :up :update :[range]up[date][!] [++opt] [>>] [file] 和 ":write" 类似,但只有在缓冲区已修改的时候才写入。 写 入 多 个 缓 冲 区 buffer-write :wa :wall :wa[ll] 保存所有已修改的缓冲区。没有文件名的缓冲区会报错。只读 的缓冲区不会被写入。 :wa[ll]! 保存所有已修改的缓冲区,包括只读的。没有文件名的缓冲区 不会写入并报错。 如果你试图覆盖在别的地方修改的文件,Vim 会警告你。参见 timestamp backup E207 E506 E507 E508 E509 E510 如果你写入已存在的文件 (但非附加) 而打开了 'backup''writebackup' 或者 'patchmode' 选项,原来文件的一个备份会被建立。该文件或者由复制,或者由换名得 到 (见 'backupcopy')。在文件被成功写入后,当置位 'writebackup' 选项而没有置位 'backup' 时,该备份文件被删除。当 'patchmode' 选项打开时,备份文件可能被改名。 backup-table 'backup' 'writebackup' 动作 关 关 没有备份 关 开 备份当前文件,写入后删除 (缺省) 开 关 删除旧的备份,备份当前文件 开 开 删除旧的备份,备份当前文件 当 'backupskip' 模式匹配被写入的文件名,备份文件不会被创建。此时,'backup''writebackup' 被忽略。 如果 'backup' 选项置位,旧的备份文件 (与新的备份文件同名) 被删除。如果没有置位 'backup' 但置位了 'writebackup',已有的备份文件不会被删除。文件写入时使用的是 另外一个文件名。 有些文件系统的崩溃可能导致备份文件和新写入的文件同时丢失 (可能还在但包含不正确 数据)。这种情况下可以尝试修复功能 :recover ,因为交换文件在盘上保持一个同步的 备份,可能还有用。 'backupdir' 选项给出的目录用于存放备份文件 (缺省在写入文件的相同目录)。 不管备份文件是否新建,它是否原始文件复制还是换名得来由 'backupcopy' 选项决定。 该选项的描述解释了何时使用复制,何时使用换名。 如果备份文件创建失败,写入不会进行。除非命令中加上 '!'。 write-permissions 写入新文件时其权限设为可读写。unix 上的掩码是 0o666 外加 umask。写入已经读入的 文件时,Vim 保留原有权限,但清除 s 位。 write-readonly 如果 'cpoptions' 选项里包含 'W',Vim 拒绝覆盖只读文件。如果没有该标志位,":w!" 可以用来覆盖只读文件, 如果系统支持的话 (目录本身必须是可写的)。 write-fail 如果新文件写入失败,要小心不要同时丢失了你的修改内容 原始的文件。如果没有 备份文件而写入新文件失败的话,原始的文件已经没有了!除 非 你 写 了 文 件,不 要 退 出 VIM!如果创建了备份,它保存了原始文件的内容 (如果可能的话)。如果你退 出 Vim 并丢失了修改的部分,原始的文件很有可能还在。如果原始文件的保存也失败的 话,你会得到一个错误信息,提示丢失了原始文件。 DOS-format-write 如果 'fileformat' 为 "dos",<CR><NL> 用作换行符 <EOL>。这是 Win32 的缺省行为。 在其他系统中,"[dos format]" 信息会提示你使用了不同寻常的 <EOL> Unix-format-write 如果 'fileformat' 为 "unix",<NL> 用作换行符 <EOL>。在 Win32 上会显示 "[unix format]"。 Mac-format-write 如果 'fileformat' 为 "mac",<CR> 用作换行符 <EOL>。在非 Mac 的系统上会显示 "[mac format]" 消息。 另见 file-formats'fileformat' 以及 'fileformats' 选项。 ACL ACL 代表访问控制表 (Access Control List)。这是控制文件访问权限一个高级方法。在 新的 MS-Windows 和 Unix 系统上,如果有文件系统的支持,可以使用之。 Vim 试图在写入文件时保留 ACL 信息。备份文件会用和原始文件相同的 ACL 信息。 ACL 信息也用来检查文件是否只读 (在打开文件时)。 read-only-share 当 MS-Windows 共享网络驱动器时,可以指定其为只读。这意味着即使文件本身没有只读 属性,你也不能写入该文件。Win32 平台上的 Vim 会检测只读的网络驱动器,并标记其 上的文件为只读。你不能用 :write 修改。 write-device 如果文件名其实是设备名,Vim 不会建立备份 (这也不可能)。你需要使用 "!",因为设 备已经存在。Unix 上的示例: :w! /dev/lpt0 MS-Windows 上: :w! lpt0 Unix 上当文件名不引用一个普通文件或者目录时,检测为设备。fifo 和命令管道对 Vim 而言视同设备。MS-Windows 上以下名字检测为设备: AUX CON CLOCK$ NUL PRN COMn n=1,2,3... 等 LPTn n=1,2,3... 等 名字大小写均可。

5. 写入并退出 write-quit

:q :quit :q[uit] 退出当前窗口。如果是最后的一个 edit-window ,退出 Vim。如果已经有修改而且 Vim 拒绝放弃 abandon 当前的 缓冲区,或者如果参数列表的最后一个文件还没有被编辑,该 操作失败。 如果有其它标签页,并且退出的是当前标签页的最后一个窗 口,关闭当前标签页 tab-page 。 激活 QuitPre 自动命令事件。 参见 CTRL-W_q 用来退出其它窗口。 :conf[irm] q[uit] 退出,但如果已经有修改或者参数列表的最后一个文件还未被 编辑,给出提示。参见 :confirm'confirm'。 :q[uit]! 退出不保存,即使当前缓冲区发生了修改也是。缓冲区被卸 载,包括置位 'hidden' 了的。 如果是最后一个窗口并有修改过的隐藏缓冲区,放弃当前缓冲 区,第一个修改过的隐藏缓冲区成为当前缓冲区。 为了保证总能退出,用 ":qall!"。 :cq[uit] 在任何情形下,退出不保存,并返回一个错误代码。参见 :cq 。此功能可用于 Manx 的快速修复模式 (参见 quickfix )。 :wq :wq [++opt] 写回当前的文件并且关闭窗口。如果是最后的一个 edit-window ,Vim 退出。 如果文件只读或者该缓冲区无名,写回操作失败。如果参数列 表的最后一个文件还没有编辑,则退出操作失败。 :wq! [++opt] 写回当前的文件并且关闭窗口。如果是最后的一个 edit-window ,Vim 退出。如果当前缓冲区无名,则写回操 作失败。 :wq [++opt] {file} 写入到 {file} 并且关闭窗口。如果是最后的一个 edit-window ,Vim 退出。如果参数列表的最后一个文件还 没有编辑, 则退出操作失败。 :wq! [++opt] {file} 写入到 {file} 并且关闭窗口。如果是最后的一个 edit-window ,Vim 退出。 :[range]wq[!] [++opt] [file] 同上,但只写入 [range] 界定的那些行。 :x :xit :[range]x[it][!] [++opt] [file] 和 ":wq" 类似, 但只有文件已修改时写入才会实际进行。 如果 'hidden' 被设置并且还有其他窗口,当前缓冲区会在 写入后被隐藏。 此命令在 Vim9 脚本里不支持,因为它太容易和变量名混淆 了。 :exi :exit :[range]exi[t][!] [++opt] [file] 同 :xit。 ZZ ZZ 如果文件被修改,写回当前文件。然后关闭当前窗口。(和 :x 相同)。 如果有当前文件有多个窗口,只有当前窗口会被关闭。 ZQ ZQ 退出,不检查是否发生了修改 (同 ":q!")。 多 个 窗 口 和 缓 冲 区 window-exit :qa :qall :qa[ll] 退出 Vim,除非存在修改过的缓冲区。(可以使用 ":bmod" 跳转 到下一个修改过的缓冲区)。如果置位了 'autowriteall',所有 被修改的缓冲区将被保存,一如调用了 :wqall 。 :conf[irm] qa[ll] 退出 Vim。如果存在修改过的缓冲区,给出提示。参见 :confirm 。 :qa[ll]! 退出 Vim,不会保存任何的修改。 另见 :cquit ,功能相同但使用非零的退出值。 :quita :quitall :quita[ll][!] 同 ":qall"。 :wqa[ll] [++opt] :wqa :wqall :xa :xall :xa[ll] 保存所有修改过的缓冲区并退出 Vim。如果其中有无名的、只读的、 其他原因写入失败的缓冲区,或者有还在运行作业的终端,Vim 不会退 出。 :conf[irm] wqa[ll] [++opt] :conf[irm] xa[ll] 保存所有修改过的缓冲区并退出 Vim。如果其中有只读或者其他原因 写入失败的缓冲区,给出提示。参看 :confirm 。 :wqa[ll]! [++opt] :xa[ll]! 保存所有修改过的缓冲区,甚至包括只读的,然后退出 Vim。不过, 如果有无名或者其他原因写入失败的缓冲区,Vim 仍然不会退出。

6. 对话框 edit-dialogs

:confirm :conf :conf[irm] {command} 执行 {command},如果有操作需要确认,显示对话框。可用于 ":q"、":qa" 和 ":w" 命令 (后者用于超越只读的设定),和 其他会以类似方式失败的命令,如 :only:buffer:bdelete 等。 示例: :confirm w foo 如果 "foo" 存在请求确认。 :confirm q 如果有改变请求确认。 :confirm qa 如果有任何修改过的未保存的缓冲区存在,对其中的每个缓冲区提示是保存还是 放弃。还可以选择 "save all" (保存所有) 或 "abandon all" (放弃所有)。 如果你希望总是用 ":confirm",置位 'confirm' 选项。 :browse :bro E338 :bro[wse] {command}{command} 的参数显示文件选择对话框。目前这可用于 :e:w:wall:wq:wqall:x:xall:exit:view:sview:r:saveas:sp:mkexrc:mkvimrc:mksession:mkview:split:vsplit:tabe:tabnew:cfile:cgetfile:caddfile:lfile:lgetfile:laddfile:diffsplit:diffpatch:open:pedit:redir:source:update:visual:vsplit ,还有如果置位 'confirm' 的话, :qall 。 {仅对 Win32、Motif、GTK 和 Mac GUI 有效,对控制台 FileExplorer 自动命令组存在时则 `browse edit` 有效} 如果不可用 ":browse",你会得到错误消息。如果 +browse 特性不存在或者 {command} 不支持该 (浏览) 功能,不显示 对话框,如常执行 {command}。 ":browse set" 和 :options 类同。 关于 ":browse oldfiles",另见 :oldfiles 。 该语法最好通过若干范例说明之: :browse e $vim/foo 在 $vim/foo 目录里打开浏览器并编辑选择的文件。 :browse e'browsedir' 指定的目录里打开浏览器并编辑选择的文件。 :browse w 在当前缓冲区所在的目录里打开浏览器。缺省使用当前缓冲区的文件 名。把缓冲区写入到指定的文件。 :browse w C:/bar 在 C:/bar 目录里打开浏览器,缺省使用当前缓冲区的文件名,把缓冲 区写入到指定的文件。 另见 'browsedir' 选项。 如果所用的 Vim 版本不支持浏览,该命令照原样执行。 browsefilter 对 MS-Windows 和 GTK 而言,你可以修改浏览对话框的过滤 (filter)。设置 g:browsefilter 或 b:browsefilter 变量,你可以修改全局或局部于缓冲区的过滤设 置。该变量应设为符合如下格式的字符串 "{过滤标签}\t{pattern};{pattern}\n",其中 的 {过滤标签} 是出现 "Files of Type" 组合框里应出现的文字,而 {pattern} 是过滤 文件名的模式。可以给出多个模式,以 ";" 分隔。 Motif 使用相同的格式,但只使用第一个模式 (Motif 只提供一个模式,但可以编辑)。 例如,要使得对话框里只显示 Vim 文件,你可以用以下命令: let g:browsefilter = "Vim Scripts\t*.vim\nVim Startup Files\t*vimrc\n" 你可以通过在某个缓冲区上设置 b:browsefilter 变量超越全局过滤的设置。最有可能的 情况是在文件类型插件里设置 b:browsefilter,以便浏览对话框只显示和当前编辑的文 件所属类型相关的项目。缺点是: 无法编辑一个新的不同类型的文件。要克服这一点,你 可以加上 "All Files\t*.*\n" 作为最后的过滤。用户从而拥有访问任何类型文件的选 择。 如果 Vim 不能实际支持时不想设置 browsefilter,可以测试 has("browsefilter"): if has("browsefilter") let g:browsefilter = "你要的值" endif

7. 当前目录 current-directory

你也可以用 :cd:tcd:lcd 命令换到别的目录,所以你可以不用总是在文件 名前输入目录名。这也影响到外部命令的执行,例如 ":!ls"。 如果当前缓冲区被修改、'cpoptions' 里有 '.' 标志位而命令又不使用 "!",那么改变 目录会失败。 :cd E747 E472 :cd[!] 在非 Unix 系统上且 'cdhome' 关闭时: 显示当前目录名。 否则,切换当前目录到主 (home) 目录。清除任何局部于窗口 的目录。 在所有的系统上,用 :pwd 可以显示当前目录。 :cd[!] {path} 切换当前目录为 {path}。如果 {path} 是相对路径,则在 'cdpath' 列出的目录搜索之。 清除任何局部于窗口的目录。 这不会改变已经打开的文件,因为记住的是它们的完整路径。 但 arglist 里的文件则可能会改变! MS-Windows 上这会同时改变当前的驱动器。 要改变到当前文件的目录: :cd %:h :cd- E186 :cd[!] - 切换到上一个当前目录 (在上个 ":cd {path}" 命令之前)。 :chd :chdir :chd[ir][!] [path]:cd 相同。 :tc :tcd :tc[d][!] {path}:cd 类似,但只为当前标签页设置当前目录。其它标签 页上的窗口和当前标签页上有自己局部于窗口的目录的窗口的 当前目录保持不变。 :tcd- :tc[d][!] - 切换到上次 ":tcd {path}" 命令之前的当前目录。 :tch :tchdir :tch[dir][!] 和 :tcd 相同。 :lc :lcd :lc[d][!] {path}:cd 类似,但只在光标在当前窗口时设置当前目录。别 的窗口的当前目录保持不变,切换到其它窗口会停止使用 {path} :lcd- :lcd[!] - 切换到上次 ":lcd {path}" 命令之前的当前目录。 :lch :lchdir :lch[dir][!] 和 :lcd 相同。 :pw :pwd E187 :pw[d] 显示当前目录名。 另见 getcwd() :pwd-verbose 如果 'verbose' 非零, :pwd 也会显示当前目录设置时所在 的作用域。例如: " 由 :cd 设置 :verbose pwd [global] /path/to/current " 由 :lcd 设置 :verbose pwd [window] /path/to/current " 由 :tcd 设置 :verbose pwd [tabpage] /path/to/current 只要没有用过 :lcd:tcd 命令,所有窗口共享同一个当前目录。切换到别的窗口 的命令因此不会改变当前目录。 当某个窗口用了 :lcd 命令,所指定的目录成为该窗口的当前目录。没用过 :lcd 的 窗口还是和全局或局部于标签页的当前目录同步。跳转到另一个窗口时,当前目录成为它 上次指定的本地当前目录。如果没有指定过,则使用全局或局部于标签页的当前目录。新 建的窗口继承当前窗口的本地目录。 当某个标签页用了 :tcd 命令,所指定的目录成为当前标签页和当前窗口的当前目录。 其它标签页上的当前目录不受影响。跳转到另一个标签页时,当前目录成为上次指定的局 部于那个标签页的当前目录。如果没有指定过,则使用全局的当前目录。 如果使用 :cd 命令,当前窗口和标签页会丢失它的本地当前目录,并从此以后使用全 局当前目录。 :cd 的完整路径名用于其后的文件读写。在某些网络文件系统中,这可能会引起麻烦。 使用完整路径名的结果是当前使用的文件名还是指向相同的文件。例如: 如果你有文件 a:test 和 目录 a:vim。命令 ":e test" ":cd vim" ":w" 会覆盖文件 a:test 而不是 a:vim/test。但如果你使用 ":w test" 文件 a:vim/test 会被覆盖,因为你给出一个新 的文件名,因而与 ":cd" 之前所指向的文件业已不同。

8. 编辑二进制文件 edit-binary

尽管 Vim 是用来编辑文本文件的,它也可用来编辑二进制文件。Vim 的 -b 参数 (b 代表二进制 (binary)) 使 Vim 以二进制模式进行文件读写操作,并设置二进制文件编辑 相关的一些选项 ('binary' 打开,'textwidth' 为 0,'modeline' 关闭,'expandtab' 关闭)。置位 'binary' 选项效果相同。不要忘记应在读入文件之前进行该操作。 编辑二进制文件时要注意以下几点: - 在编辑可执行文件时,不要修改字节数。只用 "R" 或 "r" 命令来修改文本。不要用 "x" 或退格键删除字符。 - 设置 'textwidth' 选项为 0。不然,行会被意外的截为两段。 - 如果 <EOL> 符不多,行会很长。如果你希望编辑屏幕显示不下的行,重设 'wrap' 选 项,使用横向滚动。如果一行过长 (Amiga 上超过 32767 个字节,32 位或 64 位系统 中则大得多,见 limits ),该行不能编辑。它在读入时会被截断。读入文件时,也可 能发生 "out of memory" 错误。 - 确保在读入文件 置位 'binary' 选项。不然,<CR><NL><NL> 都被认为行尾, 从而在写回时,<NL> 会被 <CR><NL> 取代。 - <Nul> 字符会在屏幕上显示为 ^@。你可以用 "CTRL-V CTRL-@" 或 "CTRL-V 000" 输入 之 - 插入 <NL> 字符会截断一行。在将缓冲区写入到文件时,<NL> 会作为 <EOL> 被写入。 - 如果文件尾没有 <EOL>,Vim 通常会自己加上。置位 'binary' 选项会禁止这一行 为。你也可以读取该选项的值来知道最后一行是否有 <EOL> (文本上你是看不到的)。

9. 加密 encryption

Vim 可用加密的方式写入文件并读回。没有正确的密钥,加密文本不能被读取。 {仅当编译时加入 +cryptv 功能才有效} E833 交换文件和撤销文件的文本也被加密。 E843 不过,这是分块进行的,这样可能缩短破解密钥的时间。可以关闭交换文件,但任何崩溃 会丢失你之前的成果。关闭撤销文件但没有什么大损失。 :set noundofile :noswapfile edit secrets 注意: 内存里的文本是不加密的。系统管理员因此可以在你编辑时看到你的文本。用 ":!filter" 或者 ":w !command" 过滤的文本也是不加密的,这些都可能造成文本泄露。 'viminfo' 文件也不加密。 要编辑极度机密的文本: :set noundofile viminfo= :noswapfile edit secrets.txt 牢记没有交换文件意味着你冒崩溃、停电等事件时丢失工作成果的风险。 _警告_: 如果在输入密钥时发生错误而且写入文件后退出,这些文本就永远丢失了。 使用加密的通常方法是用 ":X" 命令,它会提示你输入一个密钥。其后的一个写入命令会 使用该密钥加密文件。如果你以后编辑该文件,Vim 会要求你输入密钥。如果你的输入正 确,文件是可读的,不然,文本会显示为乱码。 :X :X 提示加密密钥。输入时不会反显输入的内容。别人即使看到屏幕,也不能看见你 的密钥。输入的字符保存在 'key' 选项里,它的值用来在写入文件时加密该文 件。 在写入之前,该文件保持不变。注意 除非有其他改动, :xitZZ 这样的 命令并 写入文件。 另见 -x'key' 选项里的值在文件写入时使用。如果该选项非空,写入的文件会用它的值作为密钥 加密。加密过的文件的头部有个魔术数字,使得 Vim 可以识别这是加密文件。 要关闭加密,复位 'key' 选项为空值: :set key= 使用 'cryptmethod' 选项来选择加密方法为以下之一: :setlocal cm=zip " 较弱的加密方法,后向兼容 :setlocal cm=blowfish " 有漏洞的方法 :setlocal cm=blowfish2 " 中等强度的方法 必须在写入文件前进行。读入加密文件时,自动设置该选项为文件写入时选择的方法。写 入前改变 'cryptmethod' 就可以改变使用的加密方法。 要设置用于新文件的缺省方法,在 vimrc 文件中放入: set cm=blowfish2 强烈推荐使用 "blowfish2"。只有在不支持它的旧版本的 Vim 上才用其它方法。 读写文件给出的信息会显示 "[crypted]" 对应 zip,"[blowfish]" 对应 blowfish,等 等。 写入撤销文件时,撤销文件的文本使用相同的密钥和方法。 persistent-undo 。 要测试有无 blowfish 支持,使用以下条件: has('crypt-blowfish') has('crypt-blowfish2') 尽管更早时就有 blowfish 支持,这只可用于 Vim 7.4.1099 开始的版本。所以此条件的 失败不意味着不支持 blowfish。可以这么测试 blowfish: v:version >= 703 对 blowfish2 则可以用: v:version > 704 || (v:version == 704 && has('patch401')) 如果确信你的 Vim 包含了 patch 7.4.237,更简单的检查是: has('patch-7.4.401') E817 E818 E819 E820 如果加密过程有错,文本可以写到文件里,但再不能正确读回来了。为此准备了一项测试 以确定加密顺利完成。如果看到这些错误其中之一,不要以加密方式写入文件!要修正 之,你需要重新编译 Vim 程序。 E831 这是一个内部错误,"不应该发生"。如果你能重现该错误,请向开发者报告。 读入加密文件时如果 'key' 选项非空,它被用作解密的密钥。如果该值为空,你会得到 提示,输入密钥。如果你不输密钥或者密钥不符,该文件以未解密的形式被编辑。使用错 误的密钥不会有警告 (以增加暴力破解密钥的难度)。 如果要以不同的密钥读入别的文件,设置 'key' 选项为空串,从而让 Vim 给出提示输入 新值。不要用 ":set" 命令输入该值,否则别人在你身后就能看到了。 因为 'key' 选项的值应该是个秘密,永远不要看它的值,也不要在 vimrc 文件里设置。 如果你把如下诸行加到 "/etc/magic"、"/usr/share/misc/magic" 或者你系统支持的 "magic" 文件里,你的加密文件可以被 "file" 命令识别: 0 string VimCrypt~ Vim encrypted file >9 string 01 - "zip" cryptmethod >9 string 02 - "blowfish" cryptmethod >9 string 03 - "blowfish2" cryptmethod 注意: - 如果用 'charconvert' 转换,不能实施加密。 - 你复制或者删除的文本保存在编号的寄存器中。寄存器可以保存在 .viminfo 文件里, 从而可以读到。修改你的 'viminfo' 选项以确保安全。 - 如果你走开一会儿,别入可能在 Vim 里输入命令,他不可能得到你的密钥。 - 如果你输入密钥时发生错误,你就无法取回你的文本了! - 如果你用 ":set key=value" 命令输入密钥,它会保存在历史里,从而在 viminfo 文 件里显示 'key' 的值。 - 没有 100% 的安全。Vim 的加密算法没有经过健壮性的严格测试。 - 用于 'cryptmethod' 的 "zip" 算法是可以破解的。一个 4 字符的密钥需要大概一个 小时,6 字符的密钥需要一天 (在一台 Pentinum 133 PC 上)。这需要你知道文件里一 定会出现的若干文本。 专家可以依此方法破解任何密钥,如果文本已经被解密,则密钥可以被推算出,而其他 以相同密钥加密的文件也能被解出。 - Pkzip 使用和 'cryptmethod' 的 "zip" 相同的加密方法,美国政府对其出口不持异 议。Pkzip 的公共文件 APPNOTE.TXT 详细描述了这一算法。 - 'cryptmethod' 的 "blowfish" 实现有漏洞。可以破解文件的前 64 个字节,在有些情 况下,甚至更多。不推荐,但 Vim 7.3 和 7.4 里还是最强的方法。"zip" 方法更弱。 - Vim 起源于荷兰。这是源代码的出处。因此,加密代码并非从美国出口。

10. 修改时间 timestamp timestamps

Vim 记住文件开始编辑时的修改时间、模式和大小。这用来防止 (在你自己知道之前) 你 有同一个文件的不同版本。 在执行了外壳命令 ( :!cmd suspend :read! K ) 以后,Vim 会对窗口里的所有缓 冲区的修改时间、模式和大小进行比较。Vim 会对在此期间被修改的文件执行相关的 FileChangedShell 自动命令或者显示警告。GUI 上,在 Vim 取回输入焦点的时候也会 发生。 E321 E462 如果你想自动重新载入在 Vim 之外被修改的文件的新内容,置位 'autoread' 选项。如 果你已经在 Vim 里修改过这个文件,这不会工作。 ignore-timestamp 如果你不想被询问,也不想自动载入文件,可以这样: set buftype=nofile 或者,从外壳启动 gvim: gvim file.log -c "set buftype=nofile" 注意 如果定义了 FileChangedShell 自动命令,你不会得到警告信息或者提示。该自动 命令应负责处理。 对目录的修改也不会有警告 (例如用 netrw-browse ),除非你开始编辑一个新文件,但 它在外部被建立为一个目录。 当 Vim 注意到一个文件的修改时间被修改并且该文件正在缓冲区里等待编辑但还未经修 改,会先检查文件内容是否相同,这是通过再次读入该文件 (到一个隐藏缓冲区,该缓冲 区事后被立即删除),并比较两个缓冲区的文本完成的。如果相同,你不会得到警告。 如果你觉得警告不够及时或不够充分,你可以使用如下命令。 :checkt :checktime :checkt[ime] 检查是否有缓冲区在 Vim 之外被改变。 该命令检查你是否有 文件的两个版本并给出警告。 如果它在自动命令、":global" 命令或者任何非键盘输入中调 用,实际的检查会延迟,直到副作用 (重新读入文件) 不会有 任何问题。 每个已读入的缓冲区会检查相关的文件是否被改变。如果是, 则 Vim 会采取行动。如果缓冲区没有修改过而且置位了 'autoread',缓冲区被重新读入。否则,你会被询问是否重新 读入文件。如果文件被删除,你会得到一个错误信息。如果文 件过去不存在但现在已经存在,你会得到一个警告。 一旦检查过某个文件,他的修改时间被重置。因而,你不会被 重复警告。 语法高亮、位置标记、比较的状态以及 'fileencoding''fileformat''binary' 选项不作改动。如果要重新设置 这些,可见 v:fcs_choice (例如,如果代码排版工具修改 了文件)。 :[N]checkt[ime] {filename} :[N]checkt[ime] [N] 检查某个特定缓冲区的修改时间。该缓冲区可以用名字、编号 或者模式指定。 E813 E814 如果你指定 Vim 重载缓冲区,如果某可见窗口包含了该缓冲区,重载会在该窗口的上下 文中进行。否则,会使用一个特殊窗口,这使得大多数的自动命令可以执行。你不能关闭 这个窗口,还有一些其它特殊的限制。最好不要涉及到本缓冲区之外的对象。例如,设置 局部于窗口的选项可能会选错窗口。分割窗口来做一些操作,然后关闭新分割的窗口应该 没问题 (假定其它自动命令没有副作用)。但关闭不相关的窗口和缓冲区就不好了。 在你写入文件的时候,修改时间被检查。如果发生了改变,Vim 会提示你是否要真的覆盖 该文件: WARNING: The file has been changed since reading it!!! Do you really want to write to it (y/n)? 如果你按 'y',Vim 会继续写入文件。如果你按 'n',写入操作被取消。如果你用 ":wq" 或者 "ZZ",Vim 因而不会退出。从而你还有机会写入文件。 通常,该消息意味着有人在编辑会话开始后,写入到该文件里。这可能是别人,这时你可 能想检查你的修改和别人的修改是否可以合并。将文件写到别的名字然后比较两者的差 异 (可以用 "diff" 程序)。 当然也有可能你自己在另外一个编辑会话中或者用别的命令 (例如一个过滤命令) 修改了 该文件。这样,你自己知道希望保留文件的哪个版本。 时间检查的精度取决于文件系统。Unix 上通常是亚秒级的。旧的文件系统和 MS-Windows 上通常是秒级的。`has('nanotime')` 可用来判断是否有亚秒级的时间戳检查。 有一个情况即使在没有任何错误的时候也会得到消息: Win32 系统在夏令时开始的时候。 Win32 库的一些细节使得 Vim 对小时的变化有些混淆。第二天问题就没有了。

11. 文件搜索 file-searching

文件搜索目前用于 'path''cdpath''tags' 选项和 finddir()findfile() 。其他命令使用 wildcards ,则略有不同。 有三种不同类型的搜索: 1) 向下搜索: starstar 向下搜索使用 '*'、'**' 或其他操作系统支持的通配符。'*' 和 '**' 是由 Vim 内 部处理的,以适用于所有操作系统。注意 "**" 只在文件名开始处才被当作特殊的通 配符。 '*' 的使用很简单: 匹配 0 个或更多字符。如果用搜索模式,应该是 ".*"。但注意 文件搜索不使用 "." 元字符。 '**' 则复杂的多: - 匹配目录。 - 匹配缺省最多可达 30 层的目录。所以你可以用它整个目录树里查找 - 最大匹配的层数可以通过在 '**' 之后给出数字限定。 这样,'/usr/**2' 可以匹配: /usr /usr/include /usr/include/sys /usr/include/g++ /usr/lib /usr/lib/X11 .... 匹配 '/usr/include/g++/std',因为这已到了第三层。 允许的数字范围是 0 ('**0' 被直接去掉) 到 100。如果给定的数字小于 0,则 缺省为 30。如果大于 100,则使用 100。系统本身还有路径长度的上限,通常 是 256 或 1024 字节。 - '**' 只能用于路径的尾部,或者后面紧跟一个路径分隔符,或者后面紧跟一个 数字加一个路径分隔符。 你可以用任何顺序混合 '*' 和 '**': /usr/*/sys/** /usr/*tory/sys/** /usr/**2/sys/* 2) 向上搜索: 这里,你可以给出一个目录,然后沿着目录树向上搜索一个文件。你可以给出若干终 止目录来限制搜索的范围。终止目录附加于路径 (对 'path' 选项而言) 或文件名 (对 'tags' 选项而言) 之后,中间以 ";" 分隔。如果需要多个终止目录,一一列 出,以 ';' 分隔。如果你不想要终止目录 (搜索直到根目录),只要用 ";"。 /usr/include/sys;/usr 会在以下位置搜索: /usr/include/sys /usr/include /usr 如果你用相对路径,则向上搜索始于 Vim 的当前目录或当前文件的目录 (如果相对路 径始于 "./" 并且 'cpoptions' 里不含 'd' 的话)。 如果 Vim 的当前路径是 /u/user_x/work/release 而你用 :set path=include;/u/user_x 然后用 gf 搜索文件,则文件在如下位置搜索: /u/user_x/work/release/include /u/user_x/work/include /u/user_x/include 注意: 如果 'path' 设置包含了不存在的目录,Vim 会跳过那些目录,向上搜索也不 会搜索那些目录的父目录。 3) 混合向上/向下搜索 如果 Vim 当前路径是 /u/user_x/work/release 而你用 set path=**;/u/user_x 然后用 gf 搜索文件,则文件在如下位置搜索: /u/user_x/work/release/** /u/user_x/work/** /u/user_x/** 要小心 !这会消耗大量时间,因为对 '/u/user_x/**' 的搜索包括 '/u/user_x/work/**' 和 '/u/user_x/work/release/**'。因此 '/u/user_x/work/release/**' 被搜索三遍而 '/u/user_x/work/**' 被搜索两遍。 因而,在上例中你可能想如此设置 path: :set path=**,/u/user_x/** 这会搜索: /u/user_x/work/release/** /u/user_x/** 它会搜索相同的目录群,但顺序不同。 注意 ":find"、":sfind" 和 ":tabfind" 命令的补全目前不接受包含 URL、使用带 深度限定的双星记号 (/usr/**2) 或向上搜索 (;) 记号的 'path' 项目。 vim:tw=78:ts=8:noet:ft=help:norl: