Repository navigation
Expand file tree
/
Copy pathRuleSet.cpp
More file actions
205 lines (165 loc) · 6.26 KB
/
Copy pathRuleSet.cpp
File metadata and controls
205 lines (165 loc) · 6.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include "RuleSet.hpp"
#include <filesystem>
namespace fs = std::filesystem;
#include "toolset.h"
#include <windows.h>
// Global reference
_Filter RuleSet;
_Filter::_Filter()
: m_filename((getExecutableDir()/"filter.json").string())
{
}
bool _Filter::setFileName(const std::string &filename)
{
m_filename = filename;
return fs::exists(m_filename);
}
void _Filter::load()
{
if (!fs::exists(m_filename)) {
// 文件不存在,静默重置
resetRuleSet();
return;
}
try {
doc = scl2::json::fromFile(m_filename);
} catch (const std::exception& e) {
// 文件无法加载,或者无法解析
MessageBoxA(NULL, ("无法加载或解析规则集: " + std::string(e.what())).c_str(), "警告", MB_ICONWARNING);
resetRuleSet();
}
parseRuleSet();
}
void _Filter::save()
{
doc.toFile(m_filename);
}
bool _Filter::match(const std::string &windowClass, const std::string &windowTitle, ApplyTo type) const
{
// 检查规则集,如果含有匹配则返回 true。
// 由于这个规则集并没有动作的概念(只要匹配就是确认过滤),所以顺序并不重要,
// 只会在大量规则时对性能有影响。性能影响很大程度上可以通过优化 Regex 规避。
// 检查临时规则集
for (const FilterRule& rule : tempRuleSet) {
const std::string& targetString = (rule.key == PatternKey::Class) ? (windowClass) : (windowTitle);
if (rule.match(targetString) && (rule.applyTo == ApplyTo::All || rule.applyTo == type)) return true;
}
// 检查规则集
for (const FilterRule& rule : ruleSet) {
const std::string& targetString = (rule.key == PatternKey::Class) ? (windowClass) : (windowTitle);
if (rule.match(targetString) && (rule.applyTo == ApplyTo::All || rule.applyTo == type)) return true;
}
// 没有匹配项目
return false;
}
void _Filter::parseRuleSet()
{
int errorCount = 0;
ruleSet.clear();
if (doc.has_key("ruleset") && doc["ruleset"].is_array()) {
for(const auto& rule : doc["ruleset"].as_array()) {
// 规则单元格式:
// { "pattern": "<regex_expression>", "key": "c lass|title"}.
if(rule.has_key("pattern") && rule.has_key("key") && rule["pattern"].is_string() && rule["key"].is_string()) {
FilterRule fr;
if (rule.has_key("applyTo") && rule["applyTo"].is_string()) {
const std::string& applyToString = rule["applyTo"].as_string();
if (applyToString == "topLevel") {
fr.applyTo = ApplyTo::TopLevel;
} else if (applyToString == "children") {
fr.applyTo = ApplyTo::Children;
} else if (applyToString == "all") {
fr.applyTo = ApplyTo::All;
} else {
// 无效的 applyTo 值,忽略。
errorCount++;
continue;
}
} else {
// 缺少 applyTo 字段(旧格式),默认对所有窗口生效以保持向后兼容
fr.applyTo = ApplyTo::All;
}
fr.pattern = rule["pattern"].as_string();
const std::string& key = rule["key"].as_string();
if (key == "class") {
fr.key = PatternKey::Class;
} else if (key == "title") {
fr.key = PatternKey::Title;
} else {
// 无效的规则单元,忽略。
errorCount++;
continue;
}
if (rule.has_key("description") && rule["description"].is_string()) {
fr.description = rule["description"].as_string();
}
ruleSet.push_back(fr);
} else {
// 无效的规则单元,忽略。
errorCount++;
}
}
} else {
// 规则集不存在或者无效,恢复默认规则集。
// 在那之前,先备份当前规则集。
MessageBoxA(NULL, "待加载的规则集无效。", "警告", MB_ICONWARNING);
backupRuleSet();
resetRuleSet();
}
// 警告用户
if (errorCount > 0) {
MessageBoxA(NULL, std::string("在加载过滤规则集时遇到了 " + std::to_string(errorCount) + " 个错误。").c_str(), "警告", MB_ICONWARNING);
}
}
void _Filter::backupRuleSet()
{
fs::copy(m_filename, m_filename + ".bak");
}
void _Filter::resetRuleSet()
{
// 将规则集重置到默认状态
ruleSet.clear();
doc["ruleset"].clear_as_array();
// 这里是默认规则集
// 如果有建议新的规则,可以提交 issue 或者 pull request。
// 注意,这些规则仅用于过滤一些已知、无害、大量的窗口,以避免过度干扰查看列表模式。
// 不应滥用于过滤已知窗口,因为本工具的核心设计理念之一是 “自由”。
insertRule("^tooltips?_class32$", PatternKey::Class, ApplyTo::TopLevel, "工具提示");
insertRule("^(MSCTF)?IME( UI)?$", PatternKey::Class, ApplyTo::TopLevel, "输入法");
insertRule("^ThumbnailDeviceHelperWnd$", PatternKey::Class, ApplyTo::TopLevel, "缩略图设备帮助程序");
insertRule("^ForegroundStaging$", PatternKey::Class, ApplyTo::TopLevel, "前景暂存");
// insertRule("^$", PatternKey::Class);
// insertRule("^$", PatternKey::Class);
}
void _Filter::insertRule(const std::string &pattern, PatternKey key, ApplyTo applyTo, std::optional<std::string> description)
{
FilterRule newRule;
newRule.pattern = pattern;
newRule.applyTo = applyTo;
newRule.key = key;
newRule.description = description;
// 向 ruleSet 中插入新建的规则
ruleSet.push_back(newRule);
// 向 doc 中插入新建的规则 (增量)
scl2::json_value newRuleVal;
newRuleVal["pattern"] = pattern;
newRuleVal["applyTo"] = (applyTo == ApplyTo::TopLevel) ? "topLevel" : ((applyTo == ApplyTo::Children) ? "children" : "all");
newRuleVal["key"] = (key == PatternKey::Class) ? "class" : "title";
if (description) {
newRuleVal["description"] = *description;
}
doc["ruleset"].push_back(newRuleVal);
}
void _Filter::insertTempRule(const std::string &pattern, PatternKey key, ApplyTo applyTo)
{
FilterRule newRule;
newRule.pattern = pattern;
newRule.applyTo = applyTo;
newRule.key = key;
// 向 tempRuleSet 中插入新建的临时规则
tempRuleSet.push_back(newRule);
}
bool FilterRule::match(const std::string &target) const
{
return std::regex_search(target, pattern);
}