2 个版本
0.2.2 | 2022年2月22日 |
---|---|
0.2.1 | 2022年2月22日 |
在 开发工具 中排名第 2248
77KB
1.5K SLoC
spidior
spidior
是一个命令行工具,用于在源代码文件上执行类似 sed
的替换,旨在通过从其操作的代码中解析出的语义信息来增强正则表达式。
状态
构建中
安装最新的稳定版 rust,克隆此仓库,然后运行 cargo build
。
运行
以下是 spidior
的 --help 输出,显示了如何运行它。
spidior 0.1.1
John Westhoff <johnjwesthoff@gmail.com>
USAGE:
spidior [FLAGS] [OPTIONS]
FLAGS:
-d, --dump Whether we should just dump info without replacing
-h, --help Prints help information
-i, --in-place Whether we should edit files in place or print to stdout
-I, --interactive Whether we are are interactively replacing things or not
-n, --nfa Whether we should print info about the regex nfa
-r, --recursive Whether we should search recursively
-V, --version Prints version information
OPTIONS:
-p, --path <path> The path to the files we are reading [default: .]
-q, --query <query> The query string for find/replace for each file we find in the input, required if `dump` is not set
如果使用了 --dump
参数,则 spidior
将不会进行任何替换,而只是打印出从指定路径中的文件运行其轻量级解析的结果。否则,必须使用 -q 或 --query 指定一个查询。
查询
查询非常类似于 sed
s 命令,格式为 ${LOCATION}${COMMAND}/${FIND}/${REPLACE}/${END}。其中 ${LOCATION} 是替换应该允许发生的位置(下面有更多说明),${COMMAND} 总是 s,${FIND} 是一个正则表达式,${REPLACE} 是一个替换,而 ${END} 可以是空或字母 'g',以允许在同一行上进行多次替换。
位置
位置可以是以下几种之一
%
- 在任何包含路径指定符的文件中的任何位置<path_suffix>
- 在任何以 path_suffix 结尾的文件中的任何位置{function}
- 在任何名为 function 的函数中的任何文件中的任何位置cA-B
- 在任何文件的A字符(含)到B字符(不含)之间lA-B
- 在任何文件的A行(含)到B行(不含)之间
位置也可以通过括号分组,使用 |
进行并集,使用 &
进行交集,使用 ^
进行取反。为什么用 ^ 而不是 !?因为我觉得在大多数正则表达式解释器中,集合使用 ^ 进行取反,所以在这里也很有意义。
正则表达式
正则表达式遵循类似于 sed
的语法,并支持以下操作
- 基本正则表达式操作(连接、合取和星号[以及加号])
- 使用括号进行分组
- 集合和负集合,但仅限于范围和显式字符(例如 [a-z] 或 [^xyz],但不能是 \w 或 [[:upper:]])
- 最重要的是,对输入程序中的标识符的特殊查询
- 目前,这些查询被放在双大括号之间,用逗号分隔的列表表示条件
- 支持的准则包括
name=$NAME
,其中 $NAME 是你正在搜索的标识符的名称,type=$TYPE
,其中 $TYPE 是你正在搜索的标识符的类型,以及pos=$POS:$LEN
,其中 $POS 是匹配长度的起始位置,$LEN。
- 支持的准则包括
- 目前,这些查询被放在双大括号之间,用逗号分隔的列表表示条件
替换
替换是一个字符串字面量,可以包含对组的后向引用,使用反斜杠后跟一个数字。
示例
考虑以下输入文件,identifiers.java
public class LightningOvercharge extends Lightning {
int charge = 0;
public LightningOvercharge() {
charge = 0;
}
double number;
@Override
public void onSpawn(Session me) {
number = 1;
me.x = 0;
}
}
在 onSpawn
方法中,Session
输入参数的名称不应为 me
,因此让我们将其更改为 sess
。我们可以运行以下命令:spidior -p identifiers.java '%s/[[type=Session]]/sess/g
此命令的结果将是
public class LightningOvercharge extends Lightning {
int charge = 0;
public LightningOvercharge() {
charge = 0;
}
double number;
@Override
public void onSpawn(Session sess) {
number = 1;
sess.x = 0;
}
}
同样,我们可以运行:spidior -.java '%s/[[type=double,name=number]]/spawnFlag/g
将前面的结果更改为
public class LightningOvercharge extends Lightning {
int charge = 0;
public LightningOvercharge() {
charge = 0;
}
double spawnFlag;
@Override
public void onSpawn(Session sess) {
spawnFlag = 1;
sess.x = 0;
}
}
请注意,这更改了变量的声明和用法 number
。
轻量级解析器
为 spidior
提供动力的是一组特定语言的轻量级解析器。目前,spidior
需要能够解析函数声明和标识符声明 及其 使用,以支持操作语言。目前,只编写了一个类似于 "C-like" 的解析器,它非常过于热情 - 它将许多不是标识符的东西识别为标识符。在实践中,这最终是可行的,因为它的错误包括关键字作为名称的类型或标识符的名称,所以实际的替换操作不会因为这种过分的热情而受阻。
以下是一个示例,运行 spidior --dump -p identifiers.java
的结果。
[{"filename":"identifiers.java","functions":[{"name":"LightningOvercharge","start":507,"end":534},{"name":"onSpawn","start":605,"end":671}],"identifiers":[{"name":"com","type_name":"static","start":67,"end":70},{"name":"com","type_name":"static","start":232,"end":235},{"name":"com","type_name":"static","start":273,"end":276},{"name":"com","type_name":"static","start":316,"end":319},{"name":"com","type_name":"static","start":361,"end":364},{"name":"LightningOvercharge","type_name":"class","start":414,"end":433},{"name":"charge","type_name":"int","start":462,"end":468},{"name":"charge","type_name":"int","start":517,"end":523},{"name":"number","type_name":"double","start":547,"end":553},{"name":"me","type_name":"Session","start":601,"end":603},{"name":"number","type_name":"double","start":615,"end":621},{"name":"me","type_name":"Session","start":635,"end":637},{"name":"me","type_name":"Session","start":635,"end":637}]}]
它正确地识别了源文件中的两个函数,但它找到的变量比实际的多得多——它找到了很多“变量” com
的“类型” static
的使用。在现实中,你永远不会试图替换类型为 static
的标识符,因为这根本不是一个类型,所以这不是一个直接的问题。
依赖项
~5–15MB
~176K SLoC