<< Back to man.ChinaUnix.net

USR_28

*usr_28.txt*    For Vim version 6.3.    最近更新:2005年3月

                     VIM 用户手册 - Bram Moolenaar 著
                  译者: Chimin Yen http://vimcdoc.sf.net

                                   折叠


结构化的文本可以分为许多节。而一节之内可以再分小节。折叠允许你将一节显示为一行,
并为那一节提供一个综述。本章将解释各种实现折叠的方法。

|28.1|  什么是折叠?
|28.2|  手动折叠
|28.3|  对折叠的操作
|28.4|  存储和恢复折叠
|28.5|  依缩进折叠
|28.6|  依标记折叠
|28.7|  依语法折叠
|28.8|  依表达式折叠
|28.9|  折叠未被改动的行
|28.10| 使用哪种折叠办法呢?

       下一章: |usr_29.txt|  在代码间移动
       前一章: |usr_27.txt|  查找命令及模式
         目录: |usr_toc.txt|


*28.1*  什么是折叠?

折叠用于把缓冲内某一范围内的文本行显示为屏幕上的一行。就像一张纸,要它短些,
可以把它折叠起来:

        +------------------------+
        | 行 1          |
        | 行 2          |
        | 行 3          |
        |_______________________ |
        \                        \
         \________________________\
         / 被折叠的行                /
        /________________________/
        | 行 12                 |
        | 行 13                 |
        | 行 14                 |
        +------------------------+

那些文本仍然在缓冲内而没有改变。受到折叠影响的只是文本行显示的方式。

折叠的好处是,通过把多行的一节折叠成带有折叠提示的一行,会使你更好地了解对文本的
宏观结构。


*28.2*  手动折叠

试一试: 把光标置于某一段落内,并键入:

        zfap

你将会看到该段落被一行加亮的文本所代替。你已经创建了一个折叠了。 |zf| 是个操作符,
而 |ap| 是一个文本对象。你可以将 |zf| 操作符跟任何一个移动命令联用,为所经之处的
文本创建一个折叠。 |zf| 也能在可视模式下使用。

若要再阅读那些文本,可以键入以下命令以打开该折叠:

        zo

你还可以用以下命令再关闭该折叠:

        zc

所有的折叠命令都以 'z' 开头。展开你的想像力,这个字母看起来就像一张折叠起来的纸
的侧面。而 "z" 后面可用的字母,由于采用了帮助记忆方法选择,很容易记得住:

        zf      F-old creation (创建折叠)
        zo      O-pen a fold (打开折叠)
        zc      C-lose a fold (关闭折叠)

折叠可以嵌套: 一个含有折叠的文本区可以被再次折叠。例如,你可以折叠本节内每一段
落,然后折叠本章内所有的节。试试看。你将注意到,打开全章的折叠,会将节的折叠
还原得跟以前一样,有些打开,而有些关闭。

假定你已经创建了若干折叠,而现在需要阅览全部文本。你可以移到每个折叠处,并键
入 "zo"。若要做得更快,可以用这个命令:

        zr

这将减少 (R-educe) 折叠。相反的操作是:

        zm

这将折叠更多 (M-ore)。你 可以重复 "zr" 和 "zm" 来打开和关闭若干层嵌套的折叠。

如果你有一个嵌套了好几层深的折叠,你可以用这个命令把它们全部打开:

        zR

这将减少折叠直至一个也不剩。而用下面这个命令你可以关闭所有的折叠:

        zM

这将增加折叠,直至所有的折叠都关闭了。

你可以用 |zn| 命令快速禁止折叠功能。然后 |zN| 恢复原来的折叠。|zi| 切换于两者之
间。以下步骤是一种实用的操作方法:
- 创建折叠,以获取你的文件的总揽
- 移动到你要操作的地方
- 执行 |zi| 以便一边看着文本,一边编辑
- 再执行 |zi|  以便移动到另一处

在参考手册中有更多关于手动折叠的内容: |fold-manual|


*28.3*  对折叠的操作

当一些折叠关闭时,移动命令,如 "j" 和 "k" 会轻松的移过折叠,就像它是个简单的空
行一样。这允许你快速移过折叠了的文本。

你可以向对待单行一样复制,删除和粘贴折叠。当你要改动某个程序里的函数的先后次序
时,这是很实用的。首先,为 'foldmethod' 选择一个正确的折叠方法,以保证每个折叠
包含了整个函数 (或稍缺一点儿)。然后,用 "dd" 命令删除该函数,移动光标,并用 "p"
命令粘贴。如果函数中某些行在折叠之上,或之下,你可以利用可视模式下的选择方法:
- 把光标置于被移文本的首行
- 击 "V" 键开始可视模式
- 把光标置于被移文本的末行
- 击 "d" 键删除被选中的行。
- 把光标移到新位置,并击 "p" 键把文本粘贴在那儿。

有时候,查看或记住一个折叠在哪儿,挺不容易的。更别说用 |zo| 命令来打开了。要查看
那些已定义的折叠:

        :set foldcolumn=4

这个命令将在窗口左边显示一小栏来标识各个折叠。一个 "+" 表示某个关闭的折叠。一
个 "-" 表示每个打开的折叠的开头,而 "|" 则表示该折叠内其余的行。

你可以在折叠栏内用鼠标点击 "+" ,以打开一个折叠。点击 "-" ,或在它之下的某个
"|" ,将关闭一个打开的折叠。

打开所有光标行上的折叠用 |zO|。
关闭所有光标行上的折叠用 |zC|。
删除一个光标行上的折叠用 |zd|。
删除所有光标行上的折叠用 |zD|。

当你进入插入模式后,光标行上的折叠永远不会关闭。那是要让你看见你打的什么字!

当光标前后跳转至折叠,或在折叠上左右移动时,折叠就会自动打开。例如,零命令
"0" 打开光标下的折叠 (假设 'foldopen' 包含 "hor",即默认设置)。'foldopen'
选项可以修改,为指定的某一类命令打开折叠。如果你要光标遇到折叠,折叠就打开,
那么可以这么做:

        :set foldopen=all

警告: 你将因此无法移到一个关闭的折叠上。你也许只想临时用一用这个命令,然后把
它设回默认值:

        :set foldopen&

你可以在移开折叠时自动关闭折叠:

        :set foldclose=all

这个命令将重新把折叠水平 'foldlevel' 作用到所有的不含光标的折叠。你必须自己
试试看你会不会喜欢这各设置。用 |zm| 折叠更多的层次,并用 |zr| 折叠更少的层次
(减少折叠的层次)。

折叠是限于本地窗口的。这允许你为同一缓冲打开两个窗口,一个带折叠,而另一个
不带折叠。或者,一个让所有的折叠关闭,而另一个则让所有的折叠打开。


*28.4*  存储和恢复折叠

当你放弃一个文件时 (开始编辑另一个),其折叠状态就丢失了。如果你稍后再回来编辑
同一文件,那么,所有手动打开和关闭的折叠,全都恢复到它们的默认状态了。如果折叠
是用手动方式创建的,则所有的折叠都消失了! 为了保存折叠,可以用 |:mkview| 命令:

        :mkview

这将储存那些影响文件视的设定及其它内容。你可以利用 'viewoptions' 选项修改储
存的范围。当你稍后回到同一文件时,你可以重新载入这个视:

        :loadview

你可以为一个文件储存多至十个视。例如,把当前设置储存为第三个视,并载入第
二个视:

        :mkview 3
        :loadview 2

注意 当你插入或删除一些文本行时,视可能变得无效。还得检查 'viewdir' 选项,
它指定视图文件储存在哪儿。你可能时不时需要删除旧的视文件。


*28.5*  依缩进折叠

使用 |zf| 来定义一个折叠很费事。如果你的文本依循一种结构,以较多的缩进表示较
低的层次,那么,你可以采用缩进折叠的方法。这将为每一系列有相同缩进的行创建一个
折叠。缩进较多的行将成为嵌套的折叠。缩进折叠适用于许多编程语言。

我们来试试这个方法。先设定 'foldmethod' 选项:

        :set foldmethod=indent

然后你可以用 |zm| 和 |zr| 命令增加和减少折叠。在下面这个例文上很容易看明白:

本行没有缩进
        本行被缩进一次
                本行被缩进两次
                本行被缩进两次
        本行被缩进一次
本行没有缩进
        本行被缩进一次
        本行被缩进一次

注意 缩进多少和折叠深度之间的关系倚赖于 'shiftwidth' 选项。每个 'shiftwidth'
选项规定的缩进宽度,在折叠深度上加一。这被称为一个折叠水平。

当你使用 |zr| 和 |zm| 命令时,你实际上是在增加或减少 'foldlevel' 选项。你也可
以直接设置它:

        :set foldlevel=3

这意味着,所有缩进等于或大于 'shiftwidth' 三倍的折叠将被关闭。折叠水平设定得越低,
越多的折叠将被关闭。当 'foldlevel' 为零时,所有的折叠都将被关闭。
|zM| 把 'foldlevel' 设为零。相反的命令 |zR| 把 'foldlevel' 设为文件中最深的折
叠水平。

因此,有两种方法开启和关闭折叠:
(A) 设定折叠水平。
    这提供了一种极快的 "缩小" 方法来查看文本结构,移动光标,以及重新 "放大"
    文本。

(B) 利用 |zo| 和 |zc| 命令打开和关闭指定的折叠。
    这个方法允许你仅仅打开那些你要打开的折叠,而不影响其它的折叠。

这两种方法可以结合起来用: 你可以先用几次 |zm| 以关闭大多数折叠,然后用 |zo|
打开一个指定的折叠。或者,用 |zR| 打开所有的折叠,然后用 |zc| 关闭指定的折叠。

但是,当折叠方法 'foldmethod' 的值为 "indent" 时,你不能手动定义折叠。因为那样会
引起缩进宽度和折叠水平之间的冲突。

在参考手册中有更多关于缩进折叠的内容: |fold-indent|


*28.6*  依标记折叠

文本中的标记用于指定一个折叠区的起点和终点。标记折叠可以精确地控制一个折叠究
竟包含哪些行文本。缺点是那些文本需要改动。

试试这个:

        :set foldmethod=marker

以下列 C 程序片段为例:

        /* foobar () {{{ */
        int foobar()
        {
                /* return a value {{{ */
                return 42;
                /* }}} */
        }
        /* }}} */

请注意,折叠行将显示位于标记符之前的文字。这正好用来说明该折叠包含了什么。

令人十分困扰的是,当某些文本行移动后,标记不再正确地配对。这种局面可以利
用编号标记来避免。例如:

        /* global variables {{{1 */
        int varA,varB;

        /* functions {{{1 */
        /* funcA() {{{2 */
        void funcA() {}

        /* funcB() {{{2 */
        void funcB() {}
        /* }}}1 */

每一个编号标记表示一个编号指定水平的折叠的开始。这将使任何较高层次的折叠在此
结束。你可以只用编号标记的开始符定义所有的折叠。只有当你要明确地在另一个开始
前结束一个折叠时,你才需要加一个标记停止符。

在参考手册中有更多关于标记折叠的内容: |fold-marker|


*28.7*  依语法折叠

Vim 为每一种不同的语言使用一个不同的语法文件。语法文件为文件中各种不同语法项定
义颜色。如果你正用 Vim 在一个支持色彩的终端上阅读本文,你所看见的色彩就是由
语法文件 "help" 定制的。
   在语法文件中,你可以加入一些带有 "fold" 参数的语法项。这些语法项将定义折
叠区。这要求写一个语法文件,把这些项目加入其中。编写这样一个文件是不容易的。
但是一旦写成,所有折叠的创建就变成自动的了。
   在此,我们将假定你正使用一个已经写好的语法文件。这样的话,就没更多解释的
必要了。你可以像以上解释过的那样打开和关闭折叠。你也可以在编辑文件时自动创
建和删除那些折叠。

在参考手册中有更多关于语法折叠的内容: |fold-syntax|


*28.8*  依表达式折叠

表达式折叠类似于缩进折叠,但并非利用文本行的缩进,而是调用一个函数来计算一行
的折叠水平。当文本的一部分表明那些行属于同一组时,你可以使用这个方法。一个例子
是电子邮件,其中引述的文本由行首的 ">" 来表示。要折叠这些引文,可以用以下命令:

        :set foldmethod=expr
        :set foldexpr=strlen(substitute(substitute(getline(v:lnum),'\\s','',\"g\"),'[^>].*','',''))

你可以在这段文本上试式看:

> quoted text he wrote
> quoted text he wrote
> > double quoted text I wrote
> > double quoted text I wrote

以下是上例中 'foldexpr' 的解释 (自里至外):
   getline(v:lnum)                      读取当前行
   substitute(...,'\\s','','g')         从当前行删除所有空白字符
   substitute(...,'[^>].*','',''))      删除行首那些 '>' 之后的任何字符
   strlen(...)                          计数字符串的长度,即 '>' 的个数

注意 在 ":set" 命令中,每一个空格,双引号和反斜线符之前,必须插入一个反斜杠。
如果这会把你搞糊涂,那么就执行

        :set foldexpr

来检查所产生的实际值。为了修正一个复杂的表达式,请使用命令行补全:

        :set foldexpr=<Tab>

其中 <Tab> 是一个真实的 Tab 键。Vim 将填入以前的值,然后你可以编辑它。

当该表达式变得相对复杂时,你应当将其放入一个函数。然后设定 'foldexpr'
来调用该函数。

在参考手册中有更多关于表达式折叠的内容: |fold-expr|


*28.9*  折叠未被改动的行

当你在同一窗口也设定 'diff' 选项时,这种折叠方法就很有用。|vimdiff| 命令为
你设定好了使用未改行折叠。例如:

        setlocal diff foldmethod=diff scrollbind nowrap foldlevel=1

在显示同一文件的不同版本的每个窗口内执行这个命令。你将清楚地看到不同文件间的
区别,因为那些没改动的文本都被折叠起来了。
。

更多细节参见 |fold-diff|。


*28.10* 使用哪种折叠办法呢?

所有这些可能性让你感到纳闷,你究竟应该选择哪种方法。不幸的是,没有放之四海皆准
的法则。这里只给出一些提示。

如果存在一个语法文件,其中定义的折叠符合你正在使用的程序语言,那么,语法折叠
应该是最好的选择。否则,你也许得试着写一个。这要求你相当的了解关于查找模式知识。
这并非易事。但一旦写成,你将不必以手动的方式定义折叠了。

键入命令,手动折叠一个个文本区的方法可用于无结构特点的文本。然后用 |:mkview|
命令来储存和还原折叠状态。

标记折叠法要求你修改文件。如果你与它人共享这个文件,或不得不遵守公司规定的标准,
那么你也许得不到许可给文件加标记。
   标记折叠的主要优点是,你可以精确的把标记放在你要的位置。那样就避免了那种在
你剪切和粘贴折叠时漏了几行文本的情况。并且,你还可以加个注释,说明该折叠包含
些什么。

缩进折叠法是那种在许多文件里都用的着。但并不是每次都能成功。当你无法采用其它
方法时,就用这种。然而,缩进折叠在做提纲时特别有用。你必须为每一层嵌套折叠特意
的使用用同一缩进宽度 'shiftwidth'。

表达式折叠法能够在几乎任何依循某种格式的文本中创建折叠。这种方法相当简单,尤其
当折叠的开始和结束处能容易地被识别的时候。
   如果你用 "expr" 方法来定义折叠而无法得到完全满意的结果。那么你可以切换到手动
方法 "manual" 。这么做不会删除那些已经定义好了的折叠。之后你便可以手动删除或增
加折叠了。


下一章: |usr_29.txt|  在代码间移动

版权: 参见 |manual-copyright|  vim:tw=78:ts=8:ft=help:norl:

Generated by vim2html on Wed Mar 2 23:09:35 GMT 2005