Fixed command palette and added /web command

This commit is contained in:
WerWolv 2021-02-08 19:56:04 +01:00
parent 1b98afe37d
commit 179e222919
8 changed files with 87 additions and 42 deletions

View file

@ -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<void(std::string)> executeCallback;
};
bool m_commandPaletteOpen = false;
bool m_justOpened = false;
bool m_focusInputTextBox = false;
std::vector<char> m_commandBuffer;
std::vector<std::string> m_lastResults;
std::vector<CommandResult> m_lastResults;
std::string m_exactResult;
std::vector<std::string> getCommandResults(std::string_view command);
void focusInputTextBox() {
this->m_focusInputTextBox = true;
}
std::vector<CommandResult> getCommandResults(std::string_view command);
};
}

View file

@ -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);
});
}
}

View file

@ -74,10 +74,11 @@ namespace hex {
Type type;
std::string command;
std::string description;
std::function<std::string(std::string)> callback;
std::function<std::string(std::string)> displayCallback;
std::function<void(std::string)> executeCallback;
};
static void add(Type type, std::string_view command, std::string_view description, const std::function<std::string(std::string)> &callback);
static void add(Type type, std::string_view command, std::string_view description, const std::function<std::string(std::string)> &displayCallback, const std::function<void(std::string)> &executeCallback = [](auto){});
static std::vector<Entry>& getEntries();
};

View file

@ -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<void(std::string)> &callback);
static void doLater(std::function<void()> &&function);

View file

@ -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<std::string(std::string)> &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<std::string(std::string)> &displayCallback, const std::function<void(std::string)> &executeCallback) {
getEntries().push_back(ContentRegistry::CommandPaletteCommands::Entry{ type, command.data(), description.data(), displayCallback, executeCallback });
}
std::vector<ContentRegistry::CommandPaletteCommands::Entry>& ContentRegistry::CommandPaletteCommands::getEntries() {

View file

@ -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<uint32_t, 256> table = {0};
for (uint32_t i = 0; i < 256; i++) {

View file

@ -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<ViewCommandPalette*>(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<std::string> ViewCommandPalette::getCommandResults(std::string_view input) {
constexpr auto matchCommand = [](std::string_view currCommand, std::string_view commandToMatch) -> std::pair<MatchType, std::string_view> {
std::vector<ViewCommandPalette::CommandResult> ViewCommandPalette::getCommandResults(std::string_view input) {
constexpr auto MatchCommand = [](std::string_view currCommand, std::string_view commandToMatch) -> std::pair<MatchType, std::string_view> {
if (currCommand.empty()) {
return { MatchType::InfoMatch, "" };
}
@ -98,23 +99,33 @@ namespace hex {
}
};
std::vector<std::string> results;
std::vector<CommandResult> 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 });
}
}
}

View file

@ -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;
}