7 个稳定版本
2.2.0 | 2023 年 3 月 2 日 |
---|---|
2.1.2 | 2023 年 1 月 12 日 |
2.1.1 | 2023 年 1 月 2 日 |
2.0.3 | 2022 年 12 月 29 日 |
2.0.2 | 2022 年 12 月 27 日 |
#1626 在 命令行实用程序
每月 27 次下载
38KB
784 行
superdiff
您正在努力从文件中删除类似或重复的代码吗?您怀疑某些代码块可能是复制粘贴的,但略有不同,以至于正常的 diff
方法不起作用吗?您厌倦了逐个检查代码中的重复块了吗?
如果是这样,这可能正是您需要的工具!
功能
- 查找重复的代码片段
- 查找相似足够的代码片段
JSON
报告以实现jq
集成- 足够快(17k 代码行,块大小为 10,Levenshtein 阈值为 10 需要 00:01:12)
- 可以在多个文件中检查重复的代码
- Vim 集成!
- 多线程
限制
- 对于大文件不是即时完成的
- 多线程仅适用于多个文件(单个文件运行时没有区别)
简短示例
$ superdiff -l 1 -b 5 examples/really-bad-code.py
=== MATCH ===
File: examples/really-bad-code.py
Lines: [5, 11]
Size: 5
$ find src vim-superdiff -type f | superdiff -l 1 -b 7 --worker-threads 4
=== MATCH ===
File: src/types.rs
Lines: [87, 185]
Size: 7
=== MATCH ===
File: vim-superdiff/autoload/superdiff.vim
Lines: [136, 152]
Size: 7
用法
假设您有一些文件 examples/really-bad-code.py
,您想要检查。
examples/really-bad-code.py
#!/usr/bin/env python
class SomeClass:
def __init__(self):
self.alpha = 12
self.beta = 14
self.gamma = 16
self.is_bad = True
def reset(self):
self.alpha = 12
self.beta = 14
self.gamma = 16
self.is_bad = True
def do_something(self):
d = {}
import random
for i in range(20):
if i % 3 == 0: continue
d[i] = random.randrange(1, 1001)
d[i ** 2] = d[i] ** 2
d[d[i]] = i
def do_something_else(self):
d = {}
import random
for i in range(21):
if i % 3 == 1: continue
d[i] = random.randrange(1, 1001)
d[i ** 2] = d[i]
d[d[i]] = i
inst = SomeClass()
inst.reset()
您有一种感觉,这可能很糟糕,所以您使用了这个工具。
$ superdiff -b 4 examples/really-bad-code.py
=== MATCH ===
File: "examples/really-bad-code.py"
Lines: [5, 11]
Size: 5
A total of 1 unique match(es) were found in the 1 file(s).
哇!您找到了这个真是太好了!但也许文件中有一些地方不是完全相同的副本,但相似度足够高。
$ superdiff -b 4 -t 5 examples/really-bad-code.py
=== MATCH ===
File: "examples/really-bad-code.py"
Lines: [16, 26]
Size: 10
=== MATCH ===
File: "examples/really-bad-code.py"
Lines: [5, 11]
Size: 5
嗯,显然有一个相似度很高的重复函数!现在(假设函数的输出相当长,而不是可笑的短),您想知道第 30 行是否涉及到重复的代码,所以您这样做
$ superdiff --reporting-mode json -b 5 -t 5 examples/really-bad-code.py > output.json
$ cat output.json | jq
{
"files": {
"examples/really-bad-code.py": {
"count_blocks": 4
}
},
"matches": [
{
"blocks": {
"examples/really-bad-code.py": [
{
"block_length": 5,
"starting_line": 11
},
{
"block_length": 5,
"starting_line": 5
}
]
},
"files": {
"examples/really-bad-code.py": {
"count_blocks": 2
}
}
},
{
"blocks": {
"examples/really-bad-code.py": [
{
"block_length": 10,
"starting_line": 26
},
{
"block_length": 10,
"starting_line": 16
}
]
},
"files": {
"examples/really-bad-code.py": {
"count_blocks": 2
}
}
}
],
"version": "2.1.2"
}
$ cat output.json | jq '.matches | map(select((.blocks."examples/really-bad-code.py" | any(.starting_line <= 30 and .starting_line + .block_length >= 30))))'
[
{
"files": {
"examples/really-bad-code.py": {
"count_blocks": 2
}
},
"blocks": {
"examples/really-bad-code.py": [
{
"starting_line": 16,
"block_length": 10
},
{
"starting_line": 26,
"block_length": 10
}
]
}
}
]
注意:如果有人发现更好的 jq
查询方法,请提交拉取请求并/或告诉我。
Vim 集成
目前还处于开发中,但以下是我们拥有的
- 使用
:SDLoad
加载 JSON(确保您在运行superdiff
的同一目录中) - 打开一个文件进行编辑
- 运行
:SDLocal
以突出显示匹配的代码块 - 对匹配的块运行
:SDQuery
以查找其他类似的代码块
检查 vimdocs 以获取更多选项和命令。
基准测试
这些数字是为了给出一个粗略估计,说明在某些文件的情况下需要多长时间。这不是科学的。我只是简单地将 time
添加到开始处并复制了 real
时间。
本基准测试所使用的数据可以在 scripts/populate-data.sh
中找到。
版本 | 测试名称 | 参数 | 时间 |
---|---|---|---|
2.0.3 | TerrariaClone | -b5 -t5json |
40.284秒 |
2.0.3 | TerrariaClone | -b5json |
0.489秒 |
2.1.2 | TerrariaClone | -b5 -t5json |
27.876秒 |
2.1.2 | TerrariaClone | -b5json |
0.473秒 |
2.2.0 | TerrariaClone | -b5 -t5 --worker-threads4json |
13.409秒 |
2.2.0 | TerrariaClone | -b5 --worker-threads4json |
0.348秒 |
依赖项
~1.6–2.6MB
~51K SLoC