VIM 排序

当Ex命令与 :global一起组合使用时,也可以为[cmd]单独指定范围。Vim允许以 :g/{pattern} 为参考点,动态地设定范围。接下来,看看如何利用这一点,将CSS文件中每一条规则的所有属性均按照字母顺序排列。

用以下 CSS 文件作为演示。

global/unsorted.css

Line 1 html {
       -   margin: 0;
       -   padding: 0;
       -   border: 0;
       5   font-size: 100%;
       -   font: inherit;
       -   vertical-align: baseline;
       - }
       - body {
      10   line-height: 1.5;
       -   color: black;
       -   background: white;
       - }

假设想把每一组规则内的属性都按照字母顺序排序。借助Vim的内置命令 :sort(参见:h :sort ![]),就可以实现这一功能。

0.1 对单条规则的属性进行排序

先用 :sort命令在该文件的子集上练练手(参见表15-1)。

首先,使用文本对象 vi{,可以轻易地选中一段由 {} 所围的文本块。然后,运行 :'<,'>sort,便可以将这些文本行按照字母顺序重新排列了。如果每次仅对一条规则进行排序,此法完全可以胜任,但假设我们遇到的是一个包含数百条规则的样式表呢?如果能把这一过程自动化岂不更好么?

表15-1 对文件的子集进行排序

按键操作 缓冲区内容
html {  margin: 0;  padding: 0;  border: 0;  font-size: 100%;  font: inherit;  vertical-align: baseline; }
vi{ html {  margin: 0;  padding: 0;  border: 0;  font-size: 100%;   font: inherit;  vertical-align: baseline; }
:'<,'>sort html {  border: 0;  font-size: 100%;  font: inherit;  margin: 0;  padding: 0;  vertical-align: baseline; }

0.2 对所有规则的属性进行排序

其实,可以用一条 :global 命令对文件中所有规则的属性进行排序。假设在本例的样式表中运行以下命令。

➾ :g/{/ .+1,/}/-1 sort

最终会得到以下结果。

html {
  border: 0;
  font-size: 100%;
  font: inherit;
  margin: 0;
  padding: 0;
  vertical-align: baseline;
}
body {
  background: white;
  color: black;
  line-height: 1.5;
}

这条排序命令会在每条规则的{} 块内执行。尽管本例中的样式表仅仅包含十几行文本,但对于内容更多的CSS文件,此法也同样适用。

这条命令很复杂,但掌握其机理后,将会由衷地赞叹 :global命令的强大。:global命令的标准格式如下。

:g/{pattern}/[cmd]

请牢记,Ex命令通常都会接受“范围”作为其参数(正如技巧28讨论的那样)。对于:global命令内部的 [cmd],该规则依然有效。因此,可以将命令的模板扩展成以下形式。

:g/{pattern}/[range][cmd]

实际上,可以用 :g/{pattern} 匹配作为参考点,动态设置 [cmd][range]。. 符号通常表示光标所在行,但在 :global命令的上下文中,它则表示 {pattern} 的匹配行。

可以把原有的命令拆分成两条单独的Ex命令进行讲解,先分析命令的后半部分。以下是一条有效的Ex命令。

➾ :.+1,/}/-1 sort

如果去掉范围中的偏移,该范围可简化为 .,/}/,其含义是“从当前行开始,一直到匹配模式 /}/ 的那一行为止”。偏移值 +1 与 —1 仅仅用于缩小操作范围,让我们把目光集中在 {} 之间的内容上面。对于排序前的原始CSS文件,如果把光标置于第1行或第9行,以上这条Ex命令将会对相应 {} 之内的规则按照字母顺序重新排序。

也就是说,只需将光标置于每个{} 块的起始位置,再运行 :.,/}/ sort 命令,即可将其中的规则按照字母顺序重新排序了。明白了么?现在,试着用 :global命令中的 {pattern} 执行一次查找。

➾ /{/

以上命令会将光标置于某个 {} 块的起始位置,即我们的目标所在。现在,再重新将 :global 与 Ex命令 [cmd]组合在一起。

➾ :g/{/ .+1,/}/—1 sort

其中,模式 { 会匹配每个 {} 块的起始行。而对于每个匹配行,:sort会在匹配行到 {} 块的结尾这个[range] 范围内执行。最终,每一条规则的CSS属性都会按照字母顺序排列整齐。