From 38ef00548ad1e4ad2215f4a09af1de3a5567e336 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sun, 25 May 2025 21:08:52 +0200 Subject: [PATCH] impr: Speed up Import Pattern popup Closes #2264 --- .../content/views/view_pattern_editor.hpp | 48 ++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/plugins/builtin/include/content/views/view_pattern_editor.hpp b/plugins/builtin/include/content/views/view_pattern_editor.hpp index e9ee87b5f..52982a926 100644 --- a/plugins/builtin/include/content/views/view_pattern_editor.hpp +++ b/plugins/builtin/include/content/views/view_pattern_editor.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -350,26 +351,51 @@ namespace hex::plugin::builtin { } } + auto createRuntime = [this, provider] { + auto runtime = std::make_shared(); + ContentRegistry::PatternLanguage::configureRuntime(*runtime, provider); + + return runtime; + }; + ui::PopupNamedFileChooser::open( basePaths, paths, std::vector{ { "Pattern File", "hexpat" } }, false, - [this, provider](const std::fs::path &path, const std::fs::path &adjustedPath) mutable -> std::string { - auto it = m_patternNames.find(path); - if (it != m_patternNames.end()) { + [this, provider, runtime = createRuntime()](const std::fs::path &path, const std::fs::path &adjustedPath) mutable -> std::string { + if (auto it = m_patternNames.find(path); it != m_patternNames.end()) { return it->second; } const auto fileName = wolv::util::toUTF8String(adjustedPath.filename()); m_patternNames[path] = fileName; - pl::PatternLanguage runtime; - ContentRegistry::PatternLanguage::configureRuntime(runtime, provider); - runtime.addPragma("description", [&](pl::PatternLanguage &, const std::string &value) -> bool { - m_patternNames[path] = hex::format("{} ({})", value, fileName); - return true; - }); - wolv::io::File file(path, wolv::io::File::Mode::Read); - std::ignore = runtime.preprocessString(file.readString(), pl::api::Source::DefaultSource); + pl::api::Source source(file.readString()); + + // Only run the lexer on the source file and manually extract the #pragma description to make this + // process as fast as possible. Running the preprocessor directly takes too much time + auto result = runtime->getInternals().lexer->lex(&source); + if (result.isOk()) { + const auto tokens = result.unwrap(); + for (auto it = tokens.begin(); it != tokens.end(); ++it) { + if (it->type == pl::core::Token::Type::Directive && std::get(it->value) == pl::core::Token::Directive::Pragma) { + ++it; + if (it != tokens.end() && it->type == pl::core::Token::Type::String) { + auto literal = std::get(it->value); + auto string = std::get_if(&literal); + if (string != nullptr && *string == "description") { + ++it; + if (it != tokens.end() && it->type == pl::core::Token::Type::String) { + literal = std::get(it->value); + string = std::get_if(&literal); + if (string != nullptr) { + m_patternNames[path] = hex::format("{} ({})", *string, fileName); + } + } + } + } + } + } + } return m_patternNames[path]; },