fix: Make syncing pattern code not erase pattern code as often
This commit is contained in:
parent
e5c7e52d72
commit
0d0dd7d57c
@ -7,15 +7,10 @@
|
|||||||
#include <pl/pattern_language.hpp>
|
#include <pl/pattern_language.hpp>
|
||||||
#include <pl/core/errors/error.hpp>
|
#include <pl/core/errors/error.hpp>
|
||||||
|
|
||||||
#include <content/providers/memory_file_provider.hpp>
|
|
||||||
|
|
||||||
#include <ui/hex_editor.hpp>
|
#include <ui/hex_editor.hpp>
|
||||||
#include <ui/pattern_drawer.hpp>
|
#include <ui/pattern_drawer.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string_view>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include <TextEditor.h>
|
#include <TextEditor.h>
|
||||||
@ -24,6 +19,36 @@ namespace pl::ptrn { class Pattern; }
|
|||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
|
class PatternSourceCode {
|
||||||
|
public:
|
||||||
|
const std::string& get(prv::Provider *provider) {
|
||||||
|
if (m_synced)
|
||||||
|
return m_sharedSource;
|
||||||
|
|
||||||
|
return m_perProviderSource.get(provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(prv::Provider *provider, std::string source) {
|
||||||
|
source = wolv::util::trim(source);
|
||||||
|
|
||||||
|
m_perProviderSource.set(source, provider);
|
||||||
|
m_sharedSource = std::move(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSynced() const {
|
||||||
|
return m_synced;
|
||||||
|
}
|
||||||
|
|
||||||
|
void enableSync(bool enabled) {
|
||||||
|
m_synced = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_synced = false;
|
||||||
|
PerProvider<std::string> m_perProviderSource;
|
||||||
|
std::string m_sharedSource;
|
||||||
|
};
|
||||||
|
|
||||||
class ViewPatternEditor : public View::Window {
|
class ViewPatternEditor : public View::Window {
|
||||||
public:
|
public:
|
||||||
ViewPatternEditor();
|
ViewPatternEditor();
|
||||||
@ -166,14 +191,13 @@ namespace hex::plugin::builtin {
|
|||||||
std::atomic<bool> m_dangerousFunctionCalled = false;
|
std::atomic<bool> m_dangerousFunctionCalled = false;
|
||||||
std::atomic<DangerousFunctionPerms> m_dangerousFunctionsAllowed = DangerousFunctionPerms::Ask;
|
std::atomic<DangerousFunctionPerms> m_dangerousFunctionsAllowed = DangerousFunctionPerms::Ask;
|
||||||
|
|
||||||
bool m_syncPatternSourceCode = false;
|
|
||||||
bool m_autoLoadPatterns = true;
|
bool m_autoLoadPatterns = true;
|
||||||
|
|
||||||
std::map<prv::Provider*, std::function<void()>> m_sectionWindowDrawer;
|
std::map<prv::Provider*, std::function<void()>> m_sectionWindowDrawer;
|
||||||
|
|
||||||
ui::HexEditor m_sectionHexEditor;
|
ui::HexEditor m_sectionHexEditor;
|
||||||
|
|
||||||
PerProvider<std::string> m_sourceCode;
|
PatternSourceCode m_sourceCode;
|
||||||
PerProvider<std::vector<std::string>> m_console;
|
PerProvider<std::vector<std::string>> m_console;
|
||||||
PerProvider<bool> m_executionDone = true;
|
PerProvider<bool> m_executionDone = true;
|
||||||
|
|
||||||
|
@ -90,7 +90,6 @@ namespace hex::plugin::builtin {
|
|||||||
EventProviderOpened::subscribe([](hex::prv::Provider *provider) {
|
EventProviderOpened::subscribe([](hex::prv::Provider *provider) {
|
||||||
if (provider != nullptr && ImHexApi::Provider::get() == provider)
|
if (provider != nullptr && ImHexApi::Provider::get() == provider)
|
||||||
RequestUpdateWindowTitle::post();
|
RequestUpdateWindowTitle::post();
|
||||||
EventProviderChanged::post(nullptr, provider);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
RequestOpenFile::subscribe(openFile);
|
RequestOpenFile::subscribe(openFile);
|
||||||
|
@ -206,7 +206,7 @@ namespace hex::plugin::builtin {
|
|||||||
static float height = 0;
|
static float height = 0;
|
||||||
static bool dragging = false;
|
static bool dragging = false;
|
||||||
|
|
||||||
auto availableSize = ImGui::GetContentRegionAvail();
|
const auto availableSize = ImGui::GetContentRegionAvail();
|
||||||
auto textEditorSize = availableSize;
|
auto textEditorSize = availableSize;
|
||||||
textEditorSize.y *= 3.5 / 5.0;
|
textEditorSize.y *= 3.5 / 5.0;
|
||||||
textEditorSize.y -= ImGui::GetTextLineHeightWithSpacing();
|
textEditorSize.y -= ImGui::GetTextLineHeightWithSpacing();
|
||||||
@ -222,7 +222,7 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginPopup("##pattern_editor_context_menu")) {
|
if (ImGui::BeginPopup("##pattern_editor_context_menu")) {
|
||||||
bool hasSelection = m_textEditor.HasSelection();
|
const bool hasSelection = m_textEditor.HasSelection();
|
||||||
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.cut"_lang, Shortcut(CTRLCMD + Keys::X).toString().c_str(), false, hasSelection)) {
|
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.cut"_lang, Shortcut(CTRLCMD + Keys::X).toString().c_str(), false, hasSelection)) {
|
||||||
m_textEditor.Cut();
|
m_textEditor.Cut();
|
||||||
}
|
}
|
||||||
@ -354,7 +354,7 @@ namespace hex::plugin::builtin {
|
|||||||
insertPos(runtime.getLastWriteAddress(), ImGuiExt::GetCustomColorU32(ImGuiCustomCol_ToolbarRed));
|
insertPos(runtime.getLastWriteAddress(), ImGuiExt::GetCustomColorU32(ImGuiCustomCol_ToolbarRed));
|
||||||
insertPos(runtime.getLastPatternPlaceAddress(), ImGuiExt::GetCustomColorU32(ImGuiCustomCol_ToolbarGreen));
|
insertPos(runtime.getLastPatternPlaceAddress(), ImGuiExt::GetCustomColorU32(ImGuiCustomCol_ToolbarGreen));
|
||||||
|
|
||||||
auto drawList = ImGui::GetWindowDrawList();
|
const auto drawList = ImGui::GetWindowDrawList();
|
||||||
for (const auto &[progress, color] : m_accessHistory) {
|
for (const auto &[progress, color] : m_accessHistory) {
|
||||||
if (progress <= 0) continue;
|
if (progress <= 0) continue;
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ namespace hex::plugin::builtin {
|
|||||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (auto max = runtime.getMaximumPatternCount(); max >= std::numeric_limits<u32>::max()) {
|
if (const auto max = runtime.getMaximumPatternCount(); max >= std::numeric_limits<u32>::max()) {
|
||||||
ImGuiExt::TextFormatted("{}", runtime.getCreatedPatternCount());
|
ImGuiExt::TextFormatted("{}", runtime.getCreatedPatternCount());
|
||||||
} else {
|
} else {
|
||||||
ImGuiExt::TextFormatted("{} / {}",
|
ImGuiExt::TextFormatted("{} / {}",
|
||||||
@ -389,7 +389,6 @@ namespace hex::plugin::builtin {
|
|||||||
if (m_textEditor.IsTextChanged()) {
|
if (m_textEditor.IsTextChanged()) {
|
||||||
m_hasUnevaluatedChanges = true;
|
m_hasUnevaluatedChanges = true;
|
||||||
ImHexApi::Provider::markDirty();
|
ImHexApi::Provider::markDirty();
|
||||||
m_sourceCode = m_textEditor.GetText();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_hasUnevaluatedChanges && m_runningEvaluators == 0 && m_runningParsers == 0) {
|
if (m_hasUnevaluatedChanges && m_runningEvaluators == 0 && m_runningParsers == 0) {
|
||||||
@ -438,7 +437,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
m_consoleEditor.SetCursorPosition({ int(lineCount + 1), 0 });
|
m_consoleEditor.SetCursorPosition({ int(lineCount + 1), 0 });
|
||||||
|
|
||||||
auto linesToAdd = m_console->size() - lineCount;
|
const auto linesToAdd = m_console->size() - lineCount;
|
||||||
for (size_t i = 0; i < linesToAdd; i += 1) {
|
for (size_t i = 0; i < linesToAdd; i += 1) {
|
||||||
m_consoleEditor.InsertText(m_console->at(lineCount + i));
|
m_consoleEditor.InsertText(m_console->at(lineCount + i));
|
||||||
m_consoleEditor.InsertText("\n");
|
m_consoleEditor.InsertText("\n");
|
||||||
@ -536,8 +535,8 @@ namespace hex::plugin::builtin {
|
|||||||
ImGui::BeginDisabled(envVars.size() <= 1);
|
ImGui::BeginDisabled(envVars.size() <= 1);
|
||||||
{
|
{
|
||||||
if (ImGuiExt::IconButton(ICON_VS_REMOVE, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
if (ImGuiExt::IconButton(ICON_VS_REMOVE, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||||
bool isFirst = iter == envVars.begin();
|
const bool isFirst = iter == envVars.begin();
|
||||||
bool isLast = std::next(iter) == envVars.end();
|
const bool isLast = std::next(iter) == envVars.end();
|
||||||
envVars.erase(iter);
|
envVars.erase(iter);
|
||||||
|
|
||||||
if (isFirst)
|
if (isFirst)
|
||||||
@ -677,7 +676,7 @@ namespace hex::plugin::builtin {
|
|||||||
if (patternProvider->isReadable() && *m_executionDone) {
|
if (patternProvider->isReadable() && *m_executionDone) {
|
||||||
return runtime.getPatterns(id);
|
return runtime.getPatterns(id);
|
||||||
} else {
|
} else {
|
||||||
static const std::vector<std::shared_ptr<pl::ptrn::Pattern>> empty;
|
constexpr static std::vector<std::shared_ptr<pl::ptrn::Pattern>> empty;
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
@ -724,12 +723,12 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
|
|
||||||
void ViewPatternEditor::drawDebugger(ImVec2 size) {
|
void ViewPatternEditor::drawDebugger(ImVec2 size) {
|
||||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||||
auto &evaluator = runtime.getInternals().evaluator;
|
auto &evaluator = runtime.getInternals().evaluator;
|
||||||
|
|
||||||
if (ImGui::BeginChild("##debugger", size, true)) {
|
if (ImGui::BeginChild("##debugger", size, true)) {
|
||||||
const auto &breakpoints = evaluator->getBreakpoints();
|
const auto &breakpoints = evaluator->getBreakpoints();
|
||||||
auto line = m_textEditor.GetCursorPosition().mLine + 1;
|
const auto line = m_textEditor.GetCursorPosition().mLine + 1;
|
||||||
|
|
||||||
if (!breakpoints.contains(line)) {
|
if (!breakpoints.contains(line)) {
|
||||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_BREAKPOINT, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) {
|
if (ImGuiExt::IconButton(ICON_VS_DEBUG_BREAKPOINT, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) {
|
||||||
@ -760,7 +759,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
if (evaluator->getScopeCount() > 0) {
|
if (evaluator->getScopeCount() > 0) {
|
||||||
ImGui::SetNextItemWidth(-1);
|
ImGui::SetNextItemWidth(-1);
|
||||||
auto &currScope = evaluator->getScope(-m_debuggerScopeIndex);
|
const auto &currScope = evaluator->getScope(-m_debuggerScopeIndex);
|
||||||
if (ImGui::BeginCombo("##scope", displayValue(currScope.parent, m_debuggerScopeIndex).c_str())) {
|
if (ImGui::BeginCombo("##scope", displayValue(currScope.parent, m_debuggerScopeIndex).c_str())) {
|
||||||
for (size_t i = 0; i < evaluator->getScopeCount(); i++) {
|
for (size_t i = 0; i < evaluator->getScopeCount(); i++) {
|
||||||
auto &scope = evaluator->getScope(-i);
|
auto &scope = evaluator->getScope(-i);
|
||||||
@ -776,7 +775,7 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_resetDebuggerVariables) {
|
if (m_resetDebuggerVariables) {
|
||||||
auto pauseLine = evaluator->getPauseLine();
|
const auto pauseLine = evaluator->getPauseLine();
|
||||||
|
|
||||||
(*m_debuggerDrawer)->reset();
|
(*m_debuggerDrawer)->reset();
|
||||||
m_resetDebuggerVariables = false;
|
m_resetDebuggerVariables = false;
|
||||||
@ -786,7 +785,7 @@ namespace hex::plugin::builtin {
|
|||||||
m_textEditor.SetCursorPosition({ int(pauseLine.value() - 1), 0 });
|
m_textEditor.SetCursorPosition({ int(pauseLine.value() - 1), 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &currScope = evaluator->getScope(-m_debuggerScopeIndex);
|
const auto &currScope = evaluator->getScope(-m_debuggerScopeIndex);
|
||||||
(*m_debuggerDrawer)->draw(*currScope.scope, &runtime, size.y - ImGui::GetTextLineHeightWithSpacing() * 4);
|
(*m_debuggerDrawer)->draw(*currScope.scope, &runtime, size.y - ImGui::GetTextLineHeightWithSpacing() * 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -814,7 +813,7 @@ namespace hex::plugin::builtin {
|
|||||||
if (!m_lastEvaluationResult) {
|
if (!m_lastEvaluationResult) {
|
||||||
if (m_lastEvaluationError->has_value()) {
|
if (m_lastEvaluationError->has_value()) {
|
||||||
const auto message = [this]{
|
const auto message = [this]{
|
||||||
auto message = (*m_lastEvaluationError)->message;
|
const auto &message = (*m_lastEvaluationError)->message;
|
||||||
auto lines = wolv::util::splitString(message, "\n");
|
auto lines = wolv::util::splitString(message, "\n");
|
||||||
|
|
||||||
std::ranges::transform(lines, lines.begin(), [](auto line) {
|
std::ranges::transform(lines, lines.begin(), [](auto line) {
|
||||||
@ -827,7 +826,7 @@ namespace hex::plugin::builtin {
|
|||||||
return wolv::util::combineStrings(lines, "\n");
|
return wolv::util::combineStrings(lines, "\n");
|
||||||
}();
|
}();
|
||||||
|
|
||||||
TextEditor::ErrorMarkers errorMarkers = {
|
const TextEditor::ErrorMarkers errorMarkers = {
|
||||||
{ (*m_lastEvaluationError)->line, message }
|
{ (*m_lastEvaluationError)->line, message }
|
||||||
};
|
};
|
||||||
m_textEditor.SetErrorMarkers(errorMarkers);
|
m_textEditor.SetErrorMarkers(errorMarkers);
|
||||||
@ -852,11 +851,6 @@ namespace hex::plugin::builtin {
|
|||||||
if (!m_autoLoadPatterns)
|
if (!m_autoLoadPatterns)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Copy over current pattern source code to the new provider
|
|
||||||
if (!m_syncPatternSourceCode) {
|
|
||||||
*m_sourceCode = m_textEditor.GetText();
|
|
||||||
}
|
|
||||||
|
|
||||||
pl::PatternLanguage runtime;
|
pl::PatternLanguage runtime;
|
||||||
ContentRegistry::PatternLanguage::configureRuntime(runtime, provider);
|
ContentRegistry::PatternLanguage::configureRuntime(runtime, provider);
|
||||||
|
|
||||||
@ -873,7 +867,7 @@ namespace hex::plugin::builtin {
|
|||||||
foundCorrectType = true;
|
foundCorrectType = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return !std::all_of(value.begin(), value.end(), isspace) && !value.ends_with('\n') && !value.ends_with('\r');
|
return !std::ranges::all_of(value, isspace) && !value.ends_with('\n') && !value.ends_with('\r');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Format: [ AA BB CC DD ] @ 0x12345678
|
// Format: [ AA BB CC DD ] @ 0x12345678
|
||||||
@ -889,7 +883,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
value = value.substr(1);
|
value = value.substr(1);
|
||||||
|
|
||||||
auto end = value.find(']');
|
const auto end = value.find(']');
|
||||||
if (end == std::string::npos)
|
if (end == std::string::npos)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
@ -905,7 +899,7 @@ namespace hex::plugin::builtin {
|
|||||||
if (value.empty())
|
if (value.empty())
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
auto start = value.find('@');
|
const auto start = value.find('@');
|
||||||
if (start == std::string::npos)
|
if (start == std::string::npos)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
@ -1040,7 +1034,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
this->evaluatePattern(code, provider);
|
this->evaluatePattern(code, provider);
|
||||||
m_textEditor.SetText(code);
|
m_textEditor.SetText(code);
|
||||||
m_sourceCode = code;
|
m_sourceCode.set(provider, code);
|
||||||
|
|
||||||
TaskManager::createBackgroundTask("Parse pattern", [this, code, provider](auto&) { this->parsePattern(code, provider); });
|
TaskManager::createBackgroundTask("Parse pattern", [this, code, provider](auto&) { this->parsePattern(code, provider); });
|
||||||
}
|
}
|
||||||
@ -1050,23 +1044,23 @@ namespace hex::plugin::builtin {
|
|||||||
m_runningParsers += 1;
|
m_runningParsers += 1;
|
||||||
|
|
||||||
ContentRegistry::PatternLanguage::configureRuntime(*m_parserRuntime, nullptr);
|
ContentRegistry::PatternLanguage::configureRuntime(*m_parserRuntime, nullptr);
|
||||||
auto ast = m_parserRuntime->parseString(code);
|
const auto &ast = m_parserRuntime->parseString(code);
|
||||||
|
|
||||||
auto &patternVariables = m_patternVariables.get(provider);
|
auto &patternVariables = m_patternVariables.get(provider);
|
||||||
|
|
||||||
patternVariables.clear();
|
patternVariables.clear();
|
||||||
|
|
||||||
if (ast) {
|
if (ast.has_value()) {
|
||||||
for (auto &node : *ast) {
|
for (auto &node : *ast) {
|
||||||
if (auto variableDecl = dynamic_cast<pl::core::ast::ASTNodeVariableDecl *>(node.get())) {
|
if (const auto variableDecl = dynamic_cast<pl::core::ast::ASTNodeVariableDecl *>(node.get())) {
|
||||||
auto type = variableDecl->getType().get();
|
const auto type = variableDecl->getType().get();
|
||||||
if (type == nullptr) continue;
|
if (type == nullptr) continue;
|
||||||
|
|
||||||
auto builtinType = dynamic_cast<pl::core::ast::ASTNodeBuiltinType *>(type->getType().get());
|
const auto builtinType = dynamic_cast<pl::core::ast::ASTNodeBuiltinType *>(type->getType().get());
|
||||||
if (builtinType == nullptr)
|
if (builtinType == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PatternVariable variable = {
|
const PatternVariable variable = {
|
||||||
.inVariable = variableDecl->isInVariable(),
|
.inVariable = variableDecl->isInVariable(),
|
||||||
.outVariable = variableDecl->isOutVariable(),
|
.outVariable = variableDecl->isOutVariable(),
|
||||||
.type = builtinType->getType(),
|
.type = builtinType->getType(),
|
||||||
@ -1155,6 +1149,7 @@ namespace hex::plugin::builtin {
|
|||||||
case Info: line = hex::format("I: {}", line); break;
|
case Info: line = hex::format("I: {}", line); break;
|
||||||
case Warning: line = hex::format("W: {}", line); break;
|
case Warning: line = hex::format("W: {}", line); break;
|
||||||
case Error: line = hex::format("E: {}", line); break;
|
case Error: line = hex::format("E: {}", line); break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_console->emplace_back(line);
|
m_console->emplace_back(line);
|
||||||
@ -1205,42 +1200,33 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
RequestSetPatternLanguageCode::subscribe(this, [this](const std::string &code) {
|
RequestSetPatternLanguageCode::subscribe(this, [this](const std::string &code) {
|
||||||
m_textEditor.SetText(code);
|
m_textEditor.SetText(code);
|
||||||
m_sourceCode = code;
|
m_sourceCode.set(ImHexApi::Provider::get(), code);
|
||||||
m_hasUnevaluatedChanges = true;
|
m_hasUnevaluatedChanges = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
EventSettingsChanged::subscribe(this, [this] {
|
EventSettingsChanged::subscribe(this, [this] {
|
||||||
m_syncPatternSourceCode = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.sync_pattern_source", false);
|
m_sourceCode.enableSync(ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.sync_pattern_source", false));
|
||||||
m_autoLoadPatterns = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.auto_load_patterns", true);
|
m_autoLoadPatterns = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.auto_load_patterns", true);
|
||||||
});
|
});
|
||||||
|
|
||||||
EventProviderOpened::subscribe(this, [this](prv::Provider *provider) {
|
EventProviderOpened::subscribe(this, [this](prv::Provider *provider) {
|
||||||
m_shouldAnalyze.get(provider) = true;
|
m_shouldAnalyze.get(provider) = true;
|
||||||
m_envVarEntries->push_back({ 0, "", 0, EnvVarType::Integer });
|
m_envVarEntries->emplace_back(0, "", i128(0), EnvVarType::Integer);
|
||||||
|
|
||||||
m_debuggerDrawer.get(provider) = std::make_unique<ui::PatternDrawer>();
|
m_debuggerDrawer.get(provider) = std::make_unique<ui::PatternDrawer>();
|
||||||
});
|
});
|
||||||
|
|
||||||
EventProviderChanged::subscribe(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) {
|
EventProviderChanged::subscribe(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) {
|
||||||
if (!m_syncPatternSourceCode) {
|
if (oldProvider != nullptr)
|
||||||
if (oldProvider != nullptr)
|
m_sourceCode.set(oldProvider, m_textEditor.GetText());
|
||||||
m_sourceCode.get(oldProvider) = m_textEditor.GetText();
|
|
||||||
|
|
||||||
if (newProvider != nullptr) {
|
if (newProvider != nullptr)
|
||||||
m_consoleEditor.SetTextLines(m_console.get(newProvider));
|
m_textEditor.SetText(m_sourceCode.get(newProvider));
|
||||||
m_textEditor.SetText(wolv::util::trim(m_sourceCode.get(newProvider)));
|
|
||||||
} else {
|
|
||||||
m_textEditor.SetText("");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_hasUnevaluatedChanges = true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
EventProviderClosed::subscribe(this, [this](prv::Provider *) {
|
EventProviderClosed::subscribe(this, [this](prv::Provider *) {
|
||||||
if (m_syncPatternSourceCode && ImHexApi::Provider::getProviders().empty()) {
|
if (ImHexApi::Provider::getProviders().empty()) {
|
||||||
m_textEditor.SetText("");
|
m_textEditor.SetText("");
|
||||||
m_sourceCode = "";
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1271,14 +1257,14 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ViewPatternEditor::appendVariable(const std::string &type) {
|
void ViewPatternEditor::appendVariable(const std::string &type) {
|
||||||
auto selection = ImHexApi::HexEditor::getSelection();
|
const auto &selection = ImHexApi::HexEditor::getSelection();
|
||||||
|
|
||||||
appendEditorText(hex::format("{0} {0}_at_0x{1:02X} @ 0x{1:02X};", type, selection->getStartAddress()));
|
appendEditorText(hex::format("{0} {0}_at_0x{1:02X} @ 0x{1:02X};", type, selection->getStartAddress()));
|
||||||
AchievementManager::unlockAchievement("hex.builtin.achievement.patterns", "hex.builtin.achievement.patterns.place_menu.name");
|
AchievementManager::unlockAchievement("hex.builtin.achievement.patterns", "hex.builtin.achievement.patterns.place_menu.name");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewPatternEditor::appendArray(const std::string &type, size_t size) {
|
void ViewPatternEditor::appendArray(const std::string &type, size_t size) {
|
||||||
auto selection = ImHexApi::HexEditor::getSelection();
|
const auto &selection = ImHexApi::HexEditor::getSelection();
|
||||||
|
|
||||||
appendEditorText(hex::format("{0} {0}_array_at_0x{1:02X}[0x{2:02X}] @ 0x{1:02X};", type, selection->getStartAddress(), (selection->getSize() + (size - 1)) / size));
|
appendEditorText(hex::format("{0} {0}_array_at_0x{1:02X}[0x{2:02X}] @ 0x{1:02X};", type, selection->getStartAddress(), (selection->getSize() + (size - 1)) / size));
|
||||||
}
|
}
|
||||||
@ -1354,10 +1340,10 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto &types = m_parserRuntime->getInternals().parser->getTypes();
|
const auto &types = m_parserRuntime->getInternals().parser->getTypes();
|
||||||
bool hasPlaceableTypes = std::any_of(types.begin(), types.end(), [](const auto &type) { return !type.second->isTemplateType(); });
|
const bool hasPlaceableTypes = std::ranges::any_of(types, [](const auto &type) { return !type.second->isTemplateType(); });
|
||||||
|
|
||||||
if (ImGui::BeginMenu("hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom"_lang, hasPlaceableTypes)) {
|
if (ImGui::BeginMenu("hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom"_lang, hasPlaceableTypes)) {
|
||||||
auto selection = ImHexApi::HexEditor::getSelection();
|
const auto &selection = ImHexApi::HexEditor::getSelection();
|
||||||
|
|
||||||
for (const auto &[typeName, type] : types) {
|
for (const auto &[typeName, type] : types) {
|
||||||
if (type->isTemplateType())
|
if (type->isTemplateType())
|
||||||
@ -1365,7 +1351,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
createNestedMenu(hex::splitString(typeName, "::"), [&, this] {
|
createNestedMenu(hex::splitString(typeName, "::"), [&, this] {
|
||||||
std::string variableName;
|
std::string variableName;
|
||||||
for (char &c : hex::replaceStrings(typeName, "::", "_"))
|
for (const char c : hex::replaceStrings(typeName, "::", "_"))
|
||||||
variableName += static_cast<char>(std::tolower(c));
|
variableName += static_cast<char>(std::tolower(c));
|
||||||
variableName += hex::format("_at_0x{:02X}", selection->getStartAddress());
|
variableName += hex::format("_at_0x{:02X}", selection->getStartAddress());
|
||||||
|
|
||||||
@ -1398,7 +1384,7 @@ namespace hex::plugin::builtin {
|
|||||||
if (m_runningEvaluators != 0)
|
if (m_runningEvaluators != 0)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||||
|
|
||||||
std::optional<ImColor> color;
|
std::optional<ImColor> color;
|
||||||
|
|
||||||
@ -1418,17 +1404,17 @@ namespace hex::plugin::builtin {
|
|||||||
hex::unused(data, size);
|
hex::unused(data, size);
|
||||||
|
|
||||||
if (TRY_LOCK(ContentRegistry::PatternLanguage::getRuntimeLock())) {
|
if (TRY_LOCK(ContentRegistry::PatternLanguage::getRuntimeLock())) {
|
||||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||||
|
|
||||||
auto patterns = runtime.getPatternsAtAddress(address);
|
auto patterns = runtime.getPatternsAtAddress(address);
|
||||||
if (!patterns.empty() && !std::all_of(patterns.begin(), patterns.end(), [](const auto &pattern) { return pattern->getVisibility() == pl::ptrn::Visibility::Hidden; })) {
|
if (!patterns.empty() && !std::ranges::all_of(patterns, [](const auto &pattern) { return pattern->getVisibility() == pl::ptrn::Visibility::Hidden; })) {
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
|
|
||||||
for (const auto &pattern : patterns) {
|
for (const auto &pattern : patterns) {
|
||||||
if (pattern->getVisibility() != pl::ptrn::Visibility::Visible)
|
if (pattern->getVisibility() != pl::ptrn::Visibility::Visible)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto tooltipColor = (pattern->getColor() & 0x00FF'FFFF) | 0x7000'0000;
|
const auto tooltipColor = (pattern->getColor() & 0x00FF'FFFF) | 0x7000'0000;
|
||||||
ImGui::PushID(pattern);
|
ImGui::PushID(pattern);
|
||||||
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
@ -1452,10 +1438,9 @@ namespace hex::plugin::builtin {
|
|||||||
.basePath = "pattern_source_code.hexpat",
|
.basePath = "pattern_source_code.hexpat",
|
||||||
.required = false,
|
.required = false,
|
||||||
.load = [this](prv::Provider *provider, const std::fs::path &basePath, const Tar &tar) {
|
.load = [this](prv::Provider *provider, const std::fs::path &basePath, const Tar &tar) {
|
||||||
std::string sourceCode = tar.readString(basePath);
|
const auto sourceCode = tar.readString(basePath);
|
||||||
|
|
||||||
if (!m_syncPatternSourceCode)
|
m_sourceCode.set(provider, sourceCode);
|
||||||
m_sourceCode.get(provider) = sourceCode;
|
|
||||||
|
|
||||||
if (provider == ImHexApi::Provider::get())
|
if (provider == ImHexApi::Provider::get())
|
||||||
m_textEditor.SetText(sourceCode);
|
m_textEditor.SetText(sourceCode);
|
||||||
@ -1463,15 +1448,10 @@ namespace hex::plugin::builtin {
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
.store = [this](prv::Provider *provider, const std::fs::path &basePath, const Tar &tar) {
|
.store = [this](prv::Provider *provider, const std::fs::path &basePath, const Tar &tar) {
|
||||||
std::string sourceCode;
|
|
||||||
|
|
||||||
if (provider == ImHexApi::Provider::get())
|
if (provider == ImHexApi::Provider::get())
|
||||||
m_sourceCode.get(provider) = m_textEditor.GetText();
|
m_sourceCode.set(provider, m_textEditor.GetText());
|
||||||
|
|
||||||
if (m_syncPatternSourceCode)
|
const auto &sourceCode = m_sourceCode.get(provider);
|
||||||
sourceCode = m_textEditor.GetText();
|
|
||||||
else
|
|
||||||
sourceCode = m_sourceCode.get(provider);
|
|
||||||
|
|
||||||
tar.writeString(basePath, wolv::util::trim(sourceCode));
|
tar.writeString(basePath, wolv::util::trim(sourceCode));
|
||||||
return true;
|
return true;
|
||||||
@ -1479,8 +1459,8 @@ namespace hex::plugin::builtin {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ShortcutManager::addShortcut(this, Keys::F8 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.add_breakpoint", [this] {
|
ShortcutManager::addShortcut(this, Keys::F8 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.add_breakpoint", [this] {
|
||||||
auto line = m_textEditor.GetCursorPosition().mLine + 1;
|
const auto line = m_textEditor.GetCursorPosition().mLine + 1;
|
||||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||||
|
|
||||||
auto &evaluator = runtime.getInternals().evaluator;
|
auto &evaluator = runtime.getInternals().evaluator;
|
||||||
auto &breakpoints = evaluator->getBreakpoints();
|
auto &breakpoints = evaluator->getBreakpoints();
|
||||||
@ -1501,14 +1481,14 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
/* Continue debugger */
|
/* Continue debugger */
|
||||||
ShortcutManager::addGlobalShortcut(SHIFT + Keys::F9 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.continue_debugger", [this] {
|
ShortcutManager::addGlobalShortcut(SHIFT + Keys::F9 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.continue_debugger", [this] {
|
||||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||||
if (runtime.isRunning())
|
if (runtime.isRunning())
|
||||||
m_breakpointHit = false;
|
m_breakpointHit = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Step debugger */
|
/* Step debugger */
|
||||||
ShortcutManager::addGlobalShortcut(SHIFT + Keys::F7 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.step_debugger", [this] {
|
ShortcutManager::addGlobalShortcut(SHIFT + Keys::F7 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.step_debugger", [this] {
|
||||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||||
if (runtime.isRunning()) {
|
if (runtime.isRunning()) {
|
||||||
runtime.getInternals().evaluator->pauseNextLine();
|
runtime.getInternals().evaluator->pauseNextLine();
|
||||||
m_breakpointHit = false;
|
m_breakpointHit = false;
|
||||||
@ -1517,7 +1497,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
// Generate pattern code report
|
// Generate pattern code report
|
||||||
ContentRegistry::Reports::addReportProvider([this](prv::Provider *provider) -> std::string {
|
ContentRegistry::Reports::addReportProvider([this](prv::Provider *provider) -> std::string {
|
||||||
auto patternCode = m_sourceCode.get(provider);
|
const auto &patternCode = m_sourceCode.get(provider);
|
||||||
|
|
||||||
if (wolv::util::trim(patternCode).empty())
|
if (wolv::util::trim(patternCode).empty())
|
||||||
return "";
|
return "";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user