Mic*_*ber 12 language-agnostic heuristics indentation
我想确定源文件中使用的标签宽度用空格缩进.这对于具有特别规则缩进的文件并不难,其中前导空格仅用于缩进,始终是制表符宽度的倍数,并且缩进在时间上增加一个级别.但是许多文件会偏离这种常规缩进,通常用于某种形式的垂直对齐.因此,我正在寻找一种良好的启发式算法,以估计使用的标签宽度,允许一些不规则缩进的可能性.
这样做的动机是为SubEthaEdit编辑器编写扩展.不幸的是,SubEthaEdit没有使标签宽度可用于编写脚本,所以我将根据文本猜测它.
一个合适的启发式应该:
一些简化因素:
你会采取什么方法,你认为它的优点和缺点是什么?
如果要在答案中提供工作代码,最好的方法可能是使用从脚本文件读取源文件stdin
并将选项卡宽度写入的shell脚本stdout
.伪代码或单词中的清晰描述也会很好.
一些结果
为了测试不同的策略,我们可以对标准库中的文件应用不同的策略来进行语言分发,因为它们可能遵循语言的标准缩进.我将考虑Python 2.7和Ruby 1.8库(系统框架安装在Mac OS X 10.7上),它们的预期宽度分别为4和2.排除的是那些包含以制表符开头的行或者没有以至少两个空格开头的行的文件.
蟒蛇:
Right None Wrong
Mode: 2523 1 102
First: 2169 1 456
No-long (12): 2529 9 88
No-long (8): 2535 16 75
LR (changes): 2509 1 116
LR (indent): 1533 1 1092
Doublecheck (10): 2480 15 130
Doublecheck (20): 2509 15 101
Run Code Online (Sandbox Code Playgroud)
红宝石:
Right None Wrong
Mode: 594 29 51
First: 578 0 54
No-long (12): 595 29 50
No-long (8): 597 29 48
LR (changes): 585 0 47
LR (indent): 496 0 136
Doublecheck (10): 610 0 22
Doublecheck (20): 609 0 23
Run Code Online (Sandbox Code Playgroud)
在这些表中,"Right"应作为语言标准选项卡宽度的确定,"错误"作为非零选项卡宽度不等于语言标准宽度,"无"作为零选项卡宽度或否回答."模式"是选择最常出现的缩进变化的策略; "第一个"是第一个缩进线的缩进; "No-long"是FastA的排除大缩进线并采用该模式的策略,其中数字表示允许的最大缩进变化; "LR"是Patrick87基于线性回归的策略,其变体基于线之间的压痕变化和线的绝对压痕; "Doublecheck"(无法抗拒双关语!)是Mark对FastAl策略的修改,限制了可能的标签宽度,并检查模态值的一半是否也经常出现,两个不同的阈值用于选择较小的宽度.
您的选择(实际上)是 2、3、4、5、6、7、8。
我会使用 @FastAl 建议的内容扫描前 50-100 行左右。我可能倾向于盲目地从任何带有文本的行前面拉出空格计数,并计算空白字符串的长度。如果您有可用的正则表达式,则左修剪线和运行长度两次似乎是一种浪费。另外,我会这样做System.Math.abs(indent - previndent)
,以便您获得取消缩进的数据。正则表达式将是这样的:
row.matches('^( +)[^ ]') # grab all the spaces from line start to non-space.
Run Code Online (Sandbox Code Playgroud)
一旦您获得了 7 个选项中哪一个计数最高的统计数据,就可以将其作为第一个猜测来运行。对于 8、6 和 4,您应该检查 4 和 2、3 或 2 是否也有显着计数(第二位或超过 10% 或其他廉价启发式)。如果有很多 12(或 9)可能暗示 4(或 3)也是比 8(或 6)更好的选择。一次删除或添加超过 2 个级别(通常是折叠的结束括号)的情况非常罕见。
无关紧要的嘟囔
我看到的一个问题是旧的 .c 代码尤其存在这种令人讨厌的模式:
code level 0
/* Fancy comments get weird spacing because there
* is an extra space beyond the *
* looks like one space!
*/
code indent (2 spaces)
/* Fancy comments get weird spacing because there
* is an extra space beyond the *
* looks like three spaces!
*/
code level 0
code indent (2 spaces)
/* comment at indent level 1
With no stars you wind up with 2 spaces + 3 spaces.
*/
Run Code Online (Sandbox Code Playgroud)
恶心。我不知道你是如何对待这样的评论标准的。对于像“c”这样的代码,您可能必须处理 2.0 版本中的特殊注释...但我现在会忽略它。
您的最后一个问题是处理与您的假设不符的行。我的建议是将它们“标签”到深度,然后保留多余的空格。如果你必须纠正我会这样做:rowtabdepth = ceiling((rowspacecount - (tabwidth/2)) / tabwidth)
归档时间: |
|
查看次数: |
582 次 |
最近记录: |