From 179e222919d8fe3f9f834879d28c498300f41962 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Mon, 8 Feb 2021 19:56:04 +0100 Subject: [PATCH] Fixed command palette and added /web command --- include/views/view_command_palette.hpp | 25 ++++++- .../content/command_palette_commands.cpp | 13 +++- .../include/hex/api/content_registry.hpp | 5 +- plugins/libimhex/include/hex/views/view.hpp | 1 + .../libimhex/source/api/content_registry.cpp | 4 +- plugins/libimhex/source/helpers/crypto.cpp | 2 +- source/views/view_command_palette.cpp | 75 +++++++++++-------- source/window.cpp | 4 +- 8 files changed, 87 insertions(+), 42 deletions(-) diff --git a/include/views/view_command_palette.hpp b/include/views/view_command_palette.hpp index 71fab0e79..e6f86cb39 100644 --- a/include/views/view_command_palette.hpp +++ b/include/views/view_command_palette.hpp @@ -22,6 +22,7 @@ namespace hex { void drawContent() override; void drawMenu() override; bool isAvailable() override { return true; } + bool shouldProcess() override { return true; } bool handleShortcut(int key, int mods) override; @@ -30,12 +31,32 @@ namespace hex { ImVec2 getMaxSize() override { return ImVec2(400, 100); } private: + enum class MatchType { + NoMatch, + InfoMatch, + PartialMatch, + PerfectMatch + }; + + struct CommandResult { + std::string displayResult; + std::string matchedCommand; + std::function executeCallback; + }; + + bool m_commandPaletteOpen = false; bool m_justOpened = false; + bool m_focusInputTextBox = false; + std::vector m_commandBuffer; - std::vector m_lastResults; + std::vector m_lastResults; std::string m_exactResult; - std::vector getCommandResults(std::string_view command); + void focusInputTextBox() { + this->m_focusInputTextBox = true; + } + + std::vector getCommandResults(std::string_view command); }; } \ No newline at end of file diff --git a/plugins/builtin/source/content/command_palette_commands.cpp b/plugins/builtin/source/content/command_palette_commands.cpp index ba7ceb4b5..788ab624c 100644 --- a/plugins/builtin/source/content/command_palette_commands.cpp +++ b/plugins/builtin/source/content/command_palette_commands.cpp @@ -18,7 +18,8 @@ namespace hex::plugin::builtin { try { result = evaluator.evaluate(input); - } catch (std::runtime_error &e) {} + } catch (std::exception &e) {} + if (result.has_value()) return hex::format("#%s = %Lf", input.data(), result.value()); @@ -26,6 +27,16 @@ namespace hex::plugin::builtin { return hex::format("#%s = ???", input.data()); }); + hex::ContentRegistry::CommandPaletteCommands::add( + hex::ContentRegistry::CommandPaletteCommands::Type::KeywordCommand, + "/web", "Website lookup", + [](auto input) { + return hex::format("Navigate to '%s'", input.data()); + }, + [](auto input) { + hex::openWebpage(input); + }); + } } \ No newline at end of file diff --git a/plugins/libimhex/include/hex/api/content_registry.hpp b/plugins/libimhex/include/hex/api/content_registry.hpp index 31895b0cb..a4a5b7d09 100644 --- a/plugins/libimhex/include/hex/api/content_registry.hpp +++ b/plugins/libimhex/include/hex/api/content_registry.hpp @@ -74,10 +74,11 @@ namespace hex { Type type; std::string command; std::string description; - std::function callback; + std::function displayCallback; + std::function executeCallback; }; - static void add(Type type, std::string_view command, std::string_view description, const std::function &callback); + static void add(Type type, std::string_view command, std::string_view description, const std::function &displayCallback, const std::function &executeCallback = [](auto){}); static std::vector& getEntries(); }; diff --git a/plugins/libimhex/include/hex/views/view.hpp b/plugins/libimhex/include/hex/views/view.hpp index 60ded8641..78f8c8c80 100644 --- a/plugins/libimhex/include/hex/views/view.hpp +++ b/plugins/libimhex/include/hex/views/view.hpp @@ -25,6 +25,7 @@ namespace hex { virtual void drawMenu(); virtual bool handleShortcut(int key, int mods); virtual bool isAvailable(); + virtual bool shouldProcess() { return this->isAvailable() && this->getWindowOpenState(); } static void openFileBrowser(std::string title, imgui_addons::ImGuiFileBrowser::DialogMode mode, std::string validExtensions, const std::function &callback); static void doLater(std::function &&function); diff --git a/plugins/libimhex/source/api/content_registry.cpp b/plugins/libimhex/source/api/content_registry.cpp index eac85e222..31290265b 100644 --- a/plugins/libimhex/source/api/content_registry.cpp +++ b/plugins/libimhex/source/api/content_registry.cpp @@ -127,8 +127,8 @@ namespace hex { /* Command Palette Commands */ - void ContentRegistry::CommandPaletteCommands::add(ContentRegistry::CommandPaletteCommands::Type type, std::string_view command, std::string_view description, const std::function &callback) { - getEntries().push_back(ContentRegistry::CommandPaletteCommands::Entry{ type, command.data(), description.data(), callback }); + void ContentRegistry::CommandPaletteCommands::add(ContentRegistry::CommandPaletteCommands::Type type, std::string_view command, std::string_view description, const std::function &displayCallback, const std::function &executeCallback) { + getEntries().push_back(ContentRegistry::CommandPaletteCommands::Entry{ type, command.data(), description.data(), displayCallback, executeCallback }); } std::vector& ContentRegistry::CommandPaletteCommands::getEntries() { diff --git a/plugins/libimhex/source/helpers/crypto.cpp b/plugins/libimhex/source/helpers/crypto.cpp index 59bad05f7..2079c718f 100644 --- a/plugins/libimhex/source/helpers/crypto.cpp +++ b/plugins/libimhex/source/helpers/crypto.cpp @@ -55,7 +55,7 @@ namespace hex::crypt { } u32 crc32(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init) { - auto table = [polynomial] { + const auto table = [polynomial] { std::array table = {0}; for (uint32_t i = 0; i < 256; i++) { diff --git a/source/views/view_command_palette.cpp b/source/views/view_command_palette.cpp index 4e2a1c9a3..4121390be 100644 --- a/source/views/view_command_palette.cpp +++ b/source/views/view_command_palette.cpp @@ -6,7 +6,6 @@ namespace hex { ViewCommandPalette::ViewCommandPalette() : View("Command Palette") { this->m_commandBuffer.resize(1024, 0x00); - this->m_lastResults = this->getCommandResults(""); } ViewCommandPalette::~ViewCommandPalette() { @@ -15,17 +14,14 @@ namespace hex { void ViewCommandPalette::drawContent() { - if (!this->getWindowOpenState()) return; + if (!this->m_commandPaletteOpen) return; - auto windowPos = SharedData::windowPos; - auto windowSize = SharedData::windowSize; - auto paletteSize = this->getMinSize(); - ImGui::SetNextWindowPos(ImVec2(windowPos.x + (windowSize.x - paletteSize.x) / 2.0F, windowPos.y), ImGuiCond_Always); + ImGui::SetNextWindowPos(ImVec2(SharedData::windowPos.x + SharedData::windowSize.x * 0.5F, SharedData::windowPos.y), ImGuiCond_Always, ImVec2(0.5F,0.0F)); if (ImGui::BeginPopup("Command Palette")) { if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape))) ImGui::CloseCurrentPopup(); - ImGui::PushItemWidth(paletteSize.x - ImGui::GetStyle().WindowPadding.x * 2); + ImGui::PushItemWidth(-1); if (ImGui::InputText("##nolabel", this->m_commandBuffer.data(), this->m_commandBuffer.size(), ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_EnterReturnsTrue, [](ImGuiInputTextCallbackData *callbackData) -> int { auto _this = static_cast(callbackData->UserData); @@ -33,24 +29,36 @@ namespace hex { return 0; }, this)) { + if (!this->m_lastResults.empty()) { + auto &[displayResult, matchedCommand, callback] = this->m_lastResults.front(); + callback(matchedCommand); + } ImGui::CloseCurrentPopup(); } ImGui::PopItemWidth(); if (this->m_justOpened) { - ImGui::SetKeyboardFocusHere(0); + focusInputTextBox(); + this->m_lastResults = this->getCommandResults(""); + std::memset(this->m_commandBuffer.data(), 0x00, this->m_commandBuffer.size()); this->m_justOpened = false; } + if (this->m_focusInputTextBox) { + ImGui::SetKeyboardFocusHere(0); + this->m_focusInputTextBox = false; + } + ImGui::Separator(); - for (const auto &result : this->m_lastResults) { - ImGui::TextUnformatted(result.c_str()); + for (const auto &[displayResult, matchedCommand, callback] : this->m_lastResults) { + if (ImGui::Selectable(displayResult.c_str(), false, ImGuiSelectableFlags_DontClosePopups)) + callback(matchedCommand); } ImGui::EndPopup(); } else { - this->getWindowOpenState() = false; + this->m_commandPaletteOpen = false; } } @@ -62,9 +70,9 @@ namespace hex { bool ViewCommandPalette::handleShortcut(int key, int mods) { if (key == GLFW_KEY_P && mods == (GLFW_MOD_SHIFT | GLFW_MOD_CONTROL)) { View::doLater([this] { - this->m_justOpened = true; ImGui::OpenPopup("Command Palette"); - this->getWindowOpenState() = true; + this->m_commandPaletteOpen = true; + this->m_justOpened = true; }); return true; } @@ -72,15 +80,8 @@ namespace hex { return false; } - enum class MatchType { - NoMatch, - InfoMatch, - PartialMatch, - PerfectMatch - }; - - std::vector ViewCommandPalette::getCommandResults(std::string_view input) { - constexpr auto matchCommand = [](std::string_view currCommand, std::string_view commandToMatch) -> std::pair { + std::vector ViewCommandPalette::getCommandResults(std::string_view input) { + constexpr auto MatchCommand = [](std::string_view currCommand, std::string_view commandToMatch) -> std::pair { if (currCommand.empty()) { return { MatchType::InfoMatch, "" }; } @@ -98,23 +99,33 @@ namespace hex { } }; - std::vector results; + std::vector results; - for (const auto &[type, command, description, callback] : ContentRegistry::CommandPaletteCommands::getEntries()) { + for (const auto &[type, command, description, displayCallback, executeCallback] : ContentRegistry::CommandPaletteCommands::getEntries()) { + + auto AutoComplete = [this, &currCommand = command](auto) { + focusInputTextBox(); + std::strncpy(this->m_commandBuffer.data(), currCommand.data(), this->m_commandBuffer.size()); + this->m_lastResults = this->getCommandResults(currCommand); + }; if (type == ContentRegistry::CommandPaletteCommands::Type::SymbolCommand) { - if (auto [match, value] = matchCommand(input, command); match != MatchType::NoMatch) { + if (auto [match, value] = MatchCommand(input, command); match != MatchType::NoMatch) { if (match != MatchType::PerfectMatch) - results.emplace_back(command + " (" + description + ")"); - else - results.emplace_back(callback(input.substr(command.length()).data())); + results.push_back({ command + " (" + description + ")", "", AutoComplete }); + else { + auto matchedCommand = input.substr(command.length()).data(); + results.push_back({ displayCallback(matchedCommand), matchedCommand, executeCallback }); + } } } else if (type == ContentRegistry::CommandPaletteCommands::Type::KeywordCommand) { - if (auto [match, value] = matchCommand(input, command + " "); match != MatchType::NoMatch) { + if (auto [match, value] = MatchCommand(input, command + " "); match != MatchType::NoMatch) { if (match != MatchType::PerfectMatch) - results.emplace_back(command + " (" + description + ")"); - else - results.emplace_back(callback(input.substr(command.length() + 1).data())); + results.push_back({ command + " (" + description + ")", "", AutoComplete }); + else { + auto matchedCommand = input.substr(command.length() + 1).data(); + results.push_back({ displayCallback(matchedCommand), matchedCommand, executeCallback }); + } } } diff --git a/source/window.cpp b/source/window.cpp index b28141613..a7f72b33c 100644 --- a/source/window.cpp +++ b/source/window.cpp @@ -150,7 +150,7 @@ namespace hex { for (auto &view : ContentRegistry::Views::getEntries()) { view->drawAlwaysVisible(); - if (!view->isAvailable() || !view->getWindowOpenState()) + if (!view->shouldProcess()) continue; auto minSize = view->getMinSize(); @@ -264,7 +264,7 @@ namespace hex { if (auto &[key, mods] = Window::s_currShortcut; key != -1) { for (auto &view : ContentRegistry::Views::getEntries()) { - if (view->getWindowOpenState()) { + if (view->shouldProcess()) { if (view->handleShortcut(key, mods)) break; }