16

我有一个看起来像这样的文件:

dog{{{
blah blah blah
}}}
cat{{{
blah blah
}}}
aardvark{{{
blah blah blah blah
}}}

在我的 vimrc 中,我有set foldmethod=marker, 以便文件的内容全部折叠在花括号处。我的问题是,如何根据折叠标题对文件进行排序?我希望该aarvaark部分首先出现,然后是cat,然后是dog

一些折叠部分内还有其他折叠。我不想对那些较低的折叠级别进行排序。该文件应仅按 1 级折叠排序。

4

4 回答 4

5

关闭所有折叠(zM:set foldlevel=0)后,您可以使用删除dd和粘贴p来手动移动折叠的块。这适用于少量文本。

对于大文本,您必须自己编写排序函数,因为 Vim 不提供此类功能。可以使用以下算法:

  1. 使用文本中不存在的分隔符将所有折叠行连接在一起(例如<Nul>)。
  2. 执行:sort命令。
  3. 取消加入特殊分隔符上的范围。

对于错误处理和极端情况,这实际上是相当多的实施工作。我在这里做了一个尝试:https ://gist.github.com/4145501

于 2012-11-25T19:24:43.647 回答
1

一种方法如下:

  1. 搜索并替换行尾,使一级折叠都在一行上(即用一个不会出现在文件其他地方的唯一字符串替换行尾)。

  2. 像往常一样用于:sort对文件中的行进行排序。

  3. 从步骤 1 反转搜索和替换以重新引入行尾。

这都可以记录为 Vim 宏。

如果没有嵌套折叠,或者如果有一种简单的方法可以将顶级折叠与嵌套折叠区分开来(例如,如果一级 {{{ 和 }}} 行向左齐平并且其他有领先空间)。如果不是这种情况,它可能仍然是可能的,但要困难得多。

于 2012-11-25T19:50:56.363 回答
1

我会使用 Vim 宏的强大功能。

假设您的文件中除了记录之外没有任何其他人员,第一条记录从第一行开始。并且您没有第 1 级的起点和终点在同一行。并且您的所有 {} 都匹配得很好。

转到第一个条目并录制一个宏以注册一个(qa-开始录制q-停止)

/{^MV%k:s/\n/EEEEEE/^Mj^

复制我的或更好地自己记录:(^M - 代表文字输入)

  • /{^M 查找下一个 {
  • V%k 选择线虎钳直到第 1 级结束,但不使用 }}} 结束行
  • :s/\n/EEEEEE/^M 将符号“行尾”更改为所选内容中的某个唯一字符串
  • j^ 往下走一行,然后到行的开头,以防之前的记录有前导空格。

从第二行开始运行宏(假设在录制宏时已经处理了第一行。)在正常模式下 100000@a - 使用大于记录数的任何数字。如果第一条记录在文件的第一行中,则宏将在处理完所有行时自行停止。作为副作用,它将在视觉上选择第一行 - 取消选择它。

对文件进行排序

:sort

恢复行尾::%s/EEEEEE/^M/g

注意 ^M 应该是文字输入。要键入它,请使用 Ctrl-V Enter

它适用于嵌套级别,因为 % 跳转到匹配的结束 }。这就是为什么让所有的 {} 匹配好很重要的原因。

当无法上去时,宏将停止,k这就是为什么你必须在第一行有第一条记录。宏将忽略空行或任何不是记录之间的记录。

上述方法应该适用于您的文件。如果您想要更通用的折叠方法,请在宏中使用以下命令而不是 /{ 和 %

首先打开所有折叠

zj - 转到下一个打开折叠的开头

]z - 转到当前折叠的末尾。

宏的其余部分是相同的。这种方法更通用,但我发现它不太可靠,因为它依赖于所有折叠打开、折叠启用等。

于 2012-11-25T19:56:13.777 回答
0

有一个vim-sort-folds插件看起来是专门为此而设计的。

于 2019-10-25T15:26:54.867 回答