feat: Added support for filtering patterns by value
This commit is contained in:
parent
d12f5016e4
commit
4fc2fb7a6f
2
lib/external/pattern_language
vendored
2
lib/external/pattern_language
vendored
@ -1 +1 @@
|
||||
Subproject commit d70f027c015b784140b3e8be60370df3e58c4fa6
|
||||
Subproject commit ecef9505afe9833f14e1ef80c2de64dd1e3d40f0
|
@ -3,6 +3,7 @@
|
||||
#include <hex/api/task.hpp>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <pl/core/lexer.hpp>
|
||||
#include <pl/patterns/pattern.hpp>
|
||||
#include <pl/pattern_visitor.hpp>
|
||||
|
||||
@ -81,6 +82,13 @@ namespace hex::plugin::builtin::ui {
|
||||
void traversePatternTree(pl::ptrn::Pattern &pattern, std::vector<std::string> &patternPath, const std::function<void(pl::ptrn::Pattern&)> &callback);
|
||||
std::string getDisplayName(const pl::ptrn::Pattern& pattern) const;
|
||||
|
||||
struct Filter {
|
||||
std::vector<std::string> path;
|
||||
std::optional<pl::core::Token::Literal> value;
|
||||
};
|
||||
|
||||
std::optional<Filter> parseRValueFilter(const std::string &filter) const;
|
||||
|
||||
private:
|
||||
std::map<const pl::ptrn::Pattern*, u64> m_displayEnd;
|
||||
std::vector<pl::ptrn::Pattern*> m_sortedPatterns;
|
||||
@ -95,7 +103,7 @@ namespace hex::plugin::builtin::ui {
|
||||
std::string m_lastVisualizerError;
|
||||
|
||||
std::string m_filterText;
|
||||
std::vector<std::string> m_filter;
|
||||
Filter m_filter;
|
||||
std::vector<std::string> m_currPatternPath;
|
||||
std::map<std::vector<std::string>, std::unique_ptr<pl::ptrn::Pattern>> m_favorites;
|
||||
std::map<std::string, std::vector<std::unique_ptr<pl::ptrn::Pattern>>> m_groups;
|
||||
|
@ -154,28 +154,52 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> parseRValueFilter(const std::string &filter) {
|
||||
std::vector<std::string> result;
|
||||
}
|
||||
|
||||
if (filter.empty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.emplace_back();
|
||||
for (char c : filter) {
|
||||
if (c == '.')
|
||||
result.emplace_back();
|
||||
else if (c == '[') {
|
||||
result.emplace_back();
|
||||
result.back() += c;
|
||||
} else {
|
||||
result.back() += c;
|
||||
}
|
||||
}
|
||||
std::optional<PatternDrawer::Filter> PatternDrawer::parseRValueFilter(const std::string &filter) const {
|
||||
Filter result;
|
||||
|
||||
if (filter.empty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.path.emplace_back();
|
||||
for (size_t i = 0; i < filter.size(); i += 1) {
|
||||
char c = filter[i];
|
||||
|
||||
if (i < filter.size() - 1 && c == '=' && filter[i + 1] == '=') {
|
||||
try {
|
||||
pl::core::Lexer lexer;
|
||||
|
||||
auto source = filter.substr(i + 2);
|
||||
auto tokens = lexer.lex(filter.substr(i + 2), filter.substr(i + 2));
|
||||
|
||||
if (!tokens.has_value() || tokens->size() != 2)
|
||||
return std::nullopt;
|
||||
|
||||
auto literal = std::get_if<pl::core::Token::Literal>(&tokens->front().value);
|
||||
if (literal == nullptr)
|
||||
return std::nullopt;
|
||||
|
||||
result.value = *literal;
|
||||
} catch (pl::core::err::LexerError &error) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (c == '.')
|
||||
result.path.emplace_back();
|
||||
else if (c == '[') {
|
||||
result.path.emplace_back();
|
||||
result.path.back() += c;
|
||||
} else if (c == ' ') {
|
||||
continue;
|
||||
} else {
|
||||
result.path.back() += c;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PatternDrawer::isEditingPattern(const pl::ptrn::Pattern& pattern) const {
|
||||
@ -813,8 +837,21 @@ namespace hex::plugin::builtin::ui {
|
||||
this->m_currPatternPath.push_back(pattern.getVariableName());
|
||||
ON_SCOPE_EXIT { this->m_currPatternPath.pop_back(); };
|
||||
|
||||
if (matchesFilter(this->m_filter, this->m_currPatternPath, false))
|
||||
pattern.accept(*this);
|
||||
if (matchesFilter(this->m_filter.path, this->m_currPatternPath, false)) {
|
||||
if (this->m_filter.value.has_value()) {
|
||||
auto patternValue = pattern.getValue();
|
||||
if (patternValue == this->m_filter.value)
|
||||
pattern.accept(*this);
|
||||
else if (!matchesFilter(this->m_filter.path, this->m_currPatternPath, true))
|
||||
pattern.accept(*this);
|
||||
else if (patternValue.isPattern() && this->m_filter.value->isString()) {
|
||||
if (patternValue.toString(true) == this->m_filter.value->toString(false))
|
||||
pattern.accept(*this);
|
||||
}
|
||||
} else {
|
||||
pattern.accept(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PatternDrawer::drawArray(pl::ptrn::Pattern& pattern, pl::ptrn::IIterable &iterable, bool isInlined) {
|
||||
@ -1062,7 +1099,8 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - ImGui::GetTextLineHeightWithSpacing() * 9.5);
|
||||
if (ImGui::InputTextIcon("##Search", ICON_VS_FILTER, this->m_filterText)) {
|
||||
this->m_filter = parseRValueFilter(this->m_filterText);
|
||||
if (auto result = parseRValueFilter(this->m_filterText); result.has_value())
|
||||
this->m_filter = *result;
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user