1
0
mirror of synced 2024-11-12 02:00:52 +01:00

feat: Added Experiments

This commit is contained in:
WerWolv 2023-11-10 14:48:26 +01:00
parent 4fc2fb7a6f
commit 3aacf0f1fb
4 changed files with 150 additions and 79 deletions

View File

@ -65,4 +65,5 @@ readability-*,
-readability-redundant-access-specifiers, -readability-redundant-access-specifiers,
-readability-function-cognitive-complexity, -readability-function-cognitive-complexity,
-readability-identifier-naming, -readability-identifier-naming,
-readability-qualified-auto' *-include-cleaner,
-readability-qualified-auto'

View File

@ -11,9 +11,7 @@
#include <map> #include <map>
#include <span> #include <span>
#include <string> #include <string>
#include <string_view>
#include <thread> #include <thread>
#include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -184,7 +182,7 @@ namespace hex {
[[nodiscard]] ImColor getColor() const; [[nodiscard]] ImColor getColor() const;
private: private:
std::array<float, 4> m_value; std::array<float, 4> m_value{};
}; };
class DropDown : public Widget { class DropDown : public Widget {
public: public:
@ -316,8 +314,8 @@ namespace hex {
DisplayCallback displayCallback; DisplayCallback displayCallback;
}; };
std::vector<impl::Entry> &getEntries(); std::vector<Entry> &getEntries();
std::vector<impl::Handler> &getHandlers(); std::vector<Handler> &getHandlers();
} }
@ -340,7 +338,6 @@ namespace hex {
* @brief Adds a new command handler to the command palette * @brief Adds a new command handler to the command palette
* @param type The type of the command * @param type The type of the command
* @param command The command to add * @param command The command to add
* @param unlocalizedDescription The description of the command
* @param queryCallback The callback that will be called when the command palette wants to load the name and callback items * @param queryCallback The callback that will be called when the command palette wants to load the name and callback items
* @param displayCallback The callback that will be called when the command is displayed in the command palette * @param displayCallback The callback that will be called when the command is displayed in the command palette
*/ */
@ -376,7 +373,7 @@ namespace hex {
std::map<std::string, Visualizer> &getVisualizers(); std::map<std::string, Visualizer> &getVisualizers();
std::map<std::string, Visualizer> &getInlineVisualizers(); std::map<std::string, Visualizer> &getInlineVisualizers();
std::map<std::string, pl::api::PragmaHandler> &getPragmas(); std::map<std::string, pl::api::PragmaHandler> &getPragmas();
std::vector<impl::FunctionDefinition> &getFunctions(); std::vector<FunctionDefinition> &getFunctions();
} }
@ -429,19 +426,19 @@ namespace hex {
* @brief Adds a new visualizer to the pattern language * @brief Adds a new visualizer to the pattern language
* @note Visualizers are extensions to the [[hex::visualize]] attribute, used to visualize data * @note Visualizers are extensions to the [[hex::visualize]] attribute, used to visualize data
* @param name The name of the visualizer * @param name The name of the visualizer
* @param func The function callback * @param function The function callback
* @param parameterCount The amount of parameters the function takes * @param parameterCount The amount of parameters the function takes
*/ */
void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &func, pl::api::FunctionParameterCount parameterCount); void addVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount);
/** /**
* @brief Adds a new inline visualizer to the pattern language * @brief Adds a new inline visualizer to the pattern language
* @note Inline visualizers are extensions to the [[hex::inline_visualize]] attribute, used to visualize data * @note Inline visualizers are extensions to the [[hex::inline_visualize]] attribute, used to visualize data
* @param name The name of the visualizer * @param name The name of the visualizer
* @param func The function callback * @param function The function callback
* @param parameterCount The amount of parameters the function takes * @param parameterCount The amount of parameters the function takes
*/ */
void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &func, pl::api::FunctionParameterCount parameterCount); void addInlineVisualizer(const std::string &name, const impl::VisualizerFunctionCallback &function, pl::api::FunctionParameterCount parameterCount);
} }
@ -487,7 +484,7 @@ namespace hex {
bool detached; bool detached;
}; };
std::vector<impl::Entry> &getEntries(); std::vector<Entry> &getEntries();
} }
@ -519,11 +516,11 @@ namespace hex {
std::string unlocalizedName; std::string unlocalizedName;
size_t requiredSize; size_t requiredSize;
size_t maxSize; size_t maxSize;
impl::GeneratorFunction generatorFunction; GeneratorFunction generatorFunction;
std::optional<impl::EditingFunction> editingFunction; std::optional<EditingFunction> editingFunction;
}; };
std::vector<impl::Entry> &getEntries(); std::vector<Entry> &getEntries();
} }
@ -562,7 +559,7 @@ namespace hex {
void add(const Entry &entry); void add(const Entry &entry);
std::vector<impl::Entry> &getEntries(); std::vector<Entry> &getEntries();
} }
@ -647,14 +644,14 @@ namespace hex {
constexpr static auto SeparatorValue = "$SEPARATOR$"; constexpr static auto SeparatorValue = "$SEPARATOR$";
constexpr static auto SubMenuValue = "$SUBMENU$"; constexpr static auto SubMenuValue = "$SUBMENU$";
std::multimap<u32, impl::MainMenuItem> &getMainMenuItems(); std::multimap<u32, MainMenuItem> &getMainMenuItems();
std::multimap<u32, impl::MenuItem> &getMenuItems(); std::multimap<u32, MenuItem> &getMenuItems();
std::vector<impl::DrawCallback> &getWelcomeScreenEntries(); std::vector<DrawCallback> &getWelcomeScreenEntries();
std::vector<impl::DrawCallback> &getFooterItems(); std::vector<DrawCallback> &getFooterItems();
std::vector<impl::DrawCallback> &getToolbarItems(); std::vector<DrawCallback> &getToolbarItems();
std::vector<impl::SidebarItem> &getSidebarItems(); std::vector<SidebarItem> &getSidebarItems();
std::vector<impl::TitleBarButton> &getTitleBarButtons(); std::vector<TitleBarButton> &getTitleBarButtons();
} }
@ -682,7 +679,6 @@ namespace hex {
* @param priority The priority of the entry. Lower values are displayed first * @param priority The priority of the entry. Lower values are displayed first
* @param function The function to call when the entry is clicked * @param function The function to call when the entry is clicked
* @param enabledCallback The function to call to determine if the entry is enabled * @param enabledCallback The function to call to determine if the entry is enabled
* @param view The view to use for the entry. If nullptr, the shortcut will work globally
*/ */
void addMenuItemSubMenu(std::vector<std::string> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback = []{ return true; }); void addMenuItemSubMenu(std::vector<std::string> unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback = []{ return true; });
@ -745,16 +741,16 @@ namespace hex {
* @tparam T The provider type that extends hex::prv::Provider * @tparam T The provider type that extends hex::prv::Provider
* @param addToList Whether to display the provider in the Other Providers list in the welcome screen and File menu * @param addToList Whether to display the provider in the Other Providers list in the welcome screen and File menu
*/ */
template<std::derived_from<hex::prv::Provider> T> template<std::derived_from<prv::Provider> T>
void add(bool addToList = true) { void add(bool addToList = true) {
auto typeName = T().getTypeName(); auto typeName = T().getTypeName();
(void)EventManager::subscribe<RequestCreateProvider>([expectedName = typeName](const std::string &name, bool skipLoadInterface, bool selectProvider, hex::prv::Provider **provider) { (void)EventManager::subscribe<RequestCreateProvider>([expectedName = typeName](const std::string &name, bool skipLoadInterface, bool selectProvider, prv::Provider **provider) {
if (name != expectedName) return; if (name != expectedName) return;
prv::Provider *newProvider = new T(); prv::Provider *newProvider = new T();
hex::ImHexApi::Provider::add(newProvider, skipLoadInterface, selectProvider); ImHexApi::Provider::add(newProvider, skipLoadInterface, selectProvider);
if (provider != nullptr) if (provider != nullptr)
*provider = newProvider; *provider = newProvider;
@ -777,7 +773,7 @@ namespace hex {
Callback callback; Callback callback;
}; };
std::vector<impl::Entry> &getEntries(); std::vector<Entry> &getEntries();
} }
@ -802,7 +798,7 @@ namespace hex {
Callback callback; Callback callback;
}; };
std::vector<impl::Entry> &getEntries(); std::vector<Entry> &getEntries();
} }
@ -858,7 +854,6 @@ namespace hex {
/** /**
* @brief Adds a new cell data visualizer * @brief Adds a new cell data visualizer
* @tparam T The data visualizer type that extends hex::DataVisualizer * @tparam T The data visualizer type that extends hex::DataVisualizer
* @param unlocalizedName The unlocalized name of the data visualizer
* @param args The arguments to pass to the constructor of the data visualizer * @param args The arguments to pass to the constructor of the data visualizer
*/ */
template<std::derived_from<DataVisualizer> T, typename... Args> template<std::derived_from<DataVisualizer> T, typename... Args>
@ -955,6 +950,7 @@ namespace hex {
} }
/* Background Service Registry. Allows adding new background services */
namespace BackgroundServices { namespace BackgroundServices {
namespace impl { namespace impl {
@ -972,6 +968,7 @@ namespace hex {
void registerService(const std::string &unlocalizedName, const impl::Callback &callback); void registerService(const std::string &unlocalizedName, const impl::Callback &callback);
} }
/* Network Communication Interface Registry. Allows adding new communication interface endpoints */
namespace CommunicationInterface { namespace CommunicationInterface {
namespace impl { namespace impl {
@ -983,6 +980,25 @@ namespace hex {
void registerNetworkEndpoint(const std::string &endpoint, const impl::NetworkCallback &callback); void registerNetworkEndpoint(const std::string &endpoint, const impl::NetworkCallback &callback);
} }
/* Experiments Registry. Allows adding new experiments */
namespace Experiments {
namespace impl {
struct Experiment {
std::string unlocalizedName, unlocalizedDescription;
bool enabled;
};
std::map<std::string, Experiment> &getExperiments();
}
void addExperiment(const std::string &experimentName, const std::string &unlocalizedName, const std::string &unlocalizedDescription = "");
void enableExperiement(const std::string &experimentName, bool enabled);
[[nodiscard]] bool isExperimentEnabled(const std::string &experimentName);
}
} }
} }

View File

@ -132,18 +132,19 @@ namespace hex {
} }
std::vector<Category> &getSettings() { std::vector<Category> &getSettings() {
static std::vector<impl::Category> categories; static std::vector<Category> categories;
return categories; return categories;
} }
Widgets::Widget* add(const std::string &unlocalizedCategory, const std::string &unlocalizedSubCategory, const std::string &unlocalizedName, std::unique_ptr<Widgets::Widget> &&widget) { Widgets::Widget* add(const std::string &unlocalizedCategory, const std::string &unlocalizedSubCategory, const std::string &unlocalizedName, std::unique_ptr<Widgets::Widget> &&widget) {
auto category = impl::insertOrGetEntry(impl::getSettings(), unlocalizedCategory); const auto category = insertOrGetEntry(getSettings(), unlocalizedCategory);
auto subCategory = impl::insertOrGetEntry(category->subCategories, unlocalizedSubCategory); const auto subCategory = insertOrGetEntry(category->subCategories, unlocalizedSubCategory);
auto entry = impl::insertOrGetEntry(subCategory->entries, unlocalizedName); const auto entry = insertOrGetEntry(subCategory->entries, unlocalizedName);
entry->widget = std::move(widget); entry->widget = std::move(widget);
entry->widget->load(getSetting(unlocalizedCategory, unlocalizedName, entry->widget->store())); entry->widget->load(getSetting(unlocalizedCategory, unlocalizedName, entry->widget->store()));
entry->widget->onChanged();
return entry->widget.get(); return entry->widget.get();
} }
@ -151,7 +152,7 @@ namespace hex {
} }
void setCategoryDescription(const std::string &unlocalizedCategory, const std::string &unlocalizedDescription) { void setCategoryDescription(const std::string &unlocalizedCategory, const std::string &unlocalizedDescription) {
auto category = impl::insertOrGetEntry(impl::getSettings(), unlocalizedCategory); const auto category = insertOrGetEntry(impl::getSettings(), unlocalizedCategory);
category->unlocalizedDescription = unlocalizedDescription; category->unlocalizedDescription = unlocalizedDescription;
} }
@ -247,9 +248,9 @@ namespace hex {
} }
nlohmann::json ColorPicker::store() { nlohmann::json ColorPicker::store() {
ImColor color(this->m_value[0], this->m_value[1], this->m_value[2], this->m_value[3]); const ImColor color(this->m_value[0], this->m_value[1], this->m_value[2], this->m_value[3]);
return ImU32(color); return static_cast<ImU32>(color);
} }
ImColor ColorPicker::getColor() const { ImColor ColorPicker::getColor() const {
@ -259,7 +260,7 @@ namespace hex {
bool DropDown::draw(const std::string &name) { bool DropDown::draw(const std::string &name) {
const char *preview = ""; const char *preview = "";
if (size_t(this->m_value) < this->m_items.size()) if (static_cast<size_t>(this->m_value) < this->m_items.size())
preview = this->m_items[this->m_value].c_str(); preview = this->m_items[this->m_value].c_str();
bool changed = false; bool changed = false;
@ -267,7 +268,7 @@ namespace hex {
int index = 0; int index = 0;
for (const auto &item : this->m_items) { for (const auto &item : this->m_items) {
bool selected = (index == this->m_value); const bool selected = index == this->m_value;
if (ImGui::Selectable(LangEntry(item), selected)) { if (ImGui::Selectable(LangEntry(item), selected)) {
this->m_value = index; this->m_value = index;
@ -310,7 +311,7 @@ namespace hex {
nlohmann::json DropDown::store() { nlohmann::json DropDown::store() {
if (this->m_value == -1) if (this->m_value == -1)
return this->m_defaultItem; return this->m_defaultItem;
if (size_t(this->m_value) >= this->m_items.size()) if (static_cast<size_t>(this->m_value) >= this->m_items.size())
return this->m_defaultItem; return this->m_defaultItem;
return this->m_settingsValues[this->m_value]; return this->m_settingsValues[this->m_value];
@ -382,13 +383,13 @@ namespace hex {
void add(Type type, const std::string &command, const std::string &unlocalizedDescription, const impl::DisplayCallback &displayCallback, const impl::ExecuteCallback &executeCallback) { void add(Type type, const std::string &command, const std::string &unlocalizedDescription, const impl::DisplayCallback &displayCallback, const impl::ExecuteCallback &executeCallback) {
log::debug("Registered new command palette command: {}", command); log::debug("Registered new command palette command: {}", command);
impl::getEntries().push_back(ContentRegistry::CommandPaletteCommands::impl::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback }); impl::getEntries().push_back(impl::Entry { type, command, unlocalizedDescription, displayCallback, executeCallback });
} }
void addHandler(Type type, const std::string &command, const impl::QueryCallback &queryCallback, const impl::DisplayCallback &displayCallback) { void addHandler(Type type, const std::string &command, const impl::QueryCallback &queryCallback, const impl::DisplayCallback &displayCallback) {
log::debug("Registered new command palette command handler: {}", command); log::debug("Registered new command palette command handler: {}", command);
impl::getHandlers().push_back(ContentRegistry::CommandPaletteCommands::impl::Handler { type, command, queryCallback, displayCallback }); impl::getHandlers().push_back(impl::Handler { type, command, queryCallback, displayCallback });
} }
namespace impl { namespace impl {
@ -451,11 +452,11 @@ namespace hex {
runtime.setIncludePaths(fs::getDefaultPaths(fs::ImHexPath::PatternsInclude) | fs::getDefaultPaths(fs::ImHexPath::Patterns)); runtime.setIncludePaths(fs::getDefaultPaths(fs::ImHexPath::PatternsInclude) | fs::getDefaultPaths(fs::ImHexPath::Patterns));
for (const auto &func : impl::getFunctions()) { for (const auto &[ns, name, paramCount, callback, dangerous] : impl::getFunctions()) {
if (func.dangerous) if (dangerous)
runtime.addDangerousFunction(func.ns, func.name, func.parameterCount, func.callback); runtime.addDangerousFunction(ns, name, paramCount, callback);
else else
runtime.addFunction(func.ns, func.name, func.parameterCount, func.callback); runtime.addFunction(ns, name, paramCount, callback);
} }
for (const auto &[name, callback] : impl::getPragmas()) { for (const auto &[name, callback] : impl::getPragmas()) {
@ -506,14 +507,14 @@ namespace hex {
namespace impl { namespace impl {
std::map<std::string, impl::Visualizer> &getVisualizers() { std::map<std::string, Visualizer> &getVisualizers() {
static std::map<std::string, impl::Visualizer> visualizers; static std::map<std::string, Visualizer> visualizers;
return visualizers; return visualizers;
} }
std::map<std::string, impl::Visualizer> &getInlineVisualizers() { std::map<std::string, Visualizer> &getInlineVisualizers() {
static std::map<std::string, impl::Visualizer> visualizers; static std::map<std::string, Visualizer> visualizers;
return visualizers; return visualizers;
} }
@ -524,8 +525,8 @@ namespace hex {
return pragmas; return pragmas;
} }
std::vector<impl::FunctionDefinition> &getFunctions() { std::vector<FunctionDefinition> &getFunctions() {
static std::vector<impl::FunctionDefinition> functions; static std::vector<FunctionDefinition> functions;
return functions; return functions;
} }
@ -551,7 +552,7 @@ namespace hex {
void impl::add(std::unique_ptr<View> &&view) { void impl::add(std::unique_ptr<View> &&view) {
log::debug("Registered new view: {}", view->getUnlocalizedName()); log::debug("Registered new view: {}", view->getUnlocalizedName());
impl::getEntries().insert({ view->getUnlocalizedName(), std::move(view) }); getEntries().insert({ view->getUnlocalizedName(), std::move(view) });
} }
View* getViewByName(const std::string &unlocalizedName) { View* getViewByName(const std::string &unlocalizedName) {
@ -601,8 +602,8 @@ namespace hex {
namespace impl { namespace impl {
std::vector<impl::Entry> &getEntries() { std::vector<Entry> &getEntries() {
static std::vector<impl::Entry> entries; static std::vector<Entry> entries;
return entries; return entries;
} }
@ -614,7 +615,7 @@ namespace hex {
namespace ContentRegistry::DataProcessorNode { namespace ContentRegistry::DataProcessorNode {
void impl::add(const impl::Entry &entry) { void impl::add(const Entry &entry) {
log::debug("Registered new data processor node type: [{}]: {}", entry.category, entry.name); log::debug("Registered new data processor node type: [{}]: {}", entry.category, entry.name);
getEntries().push_back(entry); getEntries().push_back(entry);
@ -626,8 +627,8 @@ namespace hex {
namespace impl { namespace impl {
std::vector<impl::Entry> &getEntries() { std::vector<Entry> &getEntries() {
static std::vector<impl::Entry> nodes; static std::vector<Entry> nodes;
return nodes; return nodes;
} }
@ -757,39 +758,39 @@ namespace hex {
namespace impl { namespace impl {
std::multimap<u32, impl::MainMenuItem> &getMainMenuItems() { std::multimap<u32, MainMenuItem> &getMainMenuItems() {
static std::multimap<u32, impl::MainMenuItem> items; static std::multimap<u32, MainMenuItem> items;
return items; return items;
} }
std::multimap<u32, impl::MenuItem> &getMenuItems() { std::multimap<u32, MenuItem> &getMenuItems() {
static std::multimap<u32, impl::MenuItem> items; static std::multimap<u32, MenuItem> items;
return items; return items;
} }
std::vector<impl::DrawCallback> &getWelcomeScreenEntries() { std::vector<DrawCallback> &getWelcomeScreenEntries() {
static std::vector<impl::DrawCallback> entries; static std::vector<DrawCallback> entries;
return entries; return entries;
} }
std::vector<impl::DrawCallback> &getFooterItems() { std::vector<DrawCallback> &getFooterItems() {
static std::vector<impl::DrawCallback> items; static std::vector<DrawCallback> items;
return items; return items;
} }
std::vector<impl::DrawCallback> &getToolbarItems() { std::vector<DrawCallback> &getToolbarItems() {
static std::vector<impl::DrawCallback> items; static std::vector<DrawCallback> items;
return items; return items;
} }
std::vector<impl::SidebarItem> &getSidebarItems() { std::vector<SidebarItem> &getSidebarItems() {
static std::vector<impl::SidebarItem> items; static std::vector<SidebarItem> items;
return items; return items;
} }
std::vector<impl::TitleBarButton> &getTitleBarButtons() { std::vector<TitleBarButton> &getTitleBarButtons() {
static std::vector<impl::TitleBarButton> buttons; static std::vector<TitleBarButton> buttons;
return buttons; return buttons;
} }
@ -830,8 +831,8 @@ namespace hex {
namespace impl { namespace impl {
std::vector<impl::Entry> &getEntries() { std::vector<Entry> &getEntries() {
static std::vector<impl::Entry> entries; static std::vector<Entry> entries;
return entries; return entries;
} }
@ -851,8 +852,8 @@ namespace hex {
namespace impl { namespace impl {
std::vector<impl::Entry> &getEntries() { std::vector<Entry> &getEntries() {
static std::vector<impl::Entry> entries; static std::vector<Entry> entries;
return entries; return entries;
} }
@ -882,7 +883,7 @@ namespace hex {
ImGui::PushID(reinterpret_cast<void*>(address)); ImGui::PushID(reinterpret_cast<void*>(address));
ImGui::InputScalarCallback("##editing_input", dataType, data, format, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int { ImGui::InputScalarCallback("##editing_input", dataType, data, format, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
auto &userData = *reinterpret_cast<UserData*>(data->UserData); auto &userData = *static_cast<UserData*>(data->UserData);
if (data->BufTextLen >= userData.maxChars) if (data->BufTextLen >= userData.maxChars)
userData.editingDone = true; userData.editingDone = true;
@ -911,7 +912,7 @@ namespace hex {
ImGui::PushID(reinterpret_cast<void*>(address)); ImGui::PushID(reinterpret_cast<void*>(address));
ImGui::InputText("##editing_input", data.data(), data.size() + 1, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int { ImGui::InputText("##editing_input", data.data(), data.size() + 1, flags | TextInputFlags | ImGuiInputTextFlags_CallbackEdit, [](ImGuiInputTextCallbackData *data) -> int {
auto &userData = *reinterpret_cast<UserData*>(data->UserData); auto &userData = *static_cast<UserData*>(data->UserData);
userData.data->resize(data->BufSize); userData.data->resize(data->BufSize);
@ -1029,4 +1030,55 @@ namespace hex {
} }
namespace ContentRegistry::Experiments {
namespace impl {
std::map<std::string, Experiment> &getExperiments() {
static std::map<std::string, Experiment> experiments;
return experiments;
}
}
void addExperiment(const std::string &experimentName, const std::string &unlocalizedName, const std::string &unlocalizedDescription) {
auto &experiments = impl::getExperiments();
if (experiments.contains(experimentName)) {
log::error("Experiment with name '{}' already exists!", experimentName);
return;
}
experiments[experimentName] = impl::Experiment {
.unlocalizedName = unlocalizedName,
.unlocalizedDescription = unlocalizedDescription,
.enabled = false
};
}
void enableExperiement(const std::string &experimentName, bool enabled) {
auto &experiments = impl::getExperiments();
if (!experiments.contains(experimentName)) {
log::error("Experiment with name '{}' does not exist!", experimentName);
return;
}
experiments[experimentName].enabled = enabled;
}
[[nodiscard]] bool isExperimentEnabled(const std::string &experimentName) {
auto &experiments = impl::getExperiments();
if (!experiments.contains(experimentName)) {
log::error("Experiment with name '{}' does not exist!", experimentName);
return false;
}
return experiments[experimentName].enabled;
}
}
} }

View File

@ -516,6 +516,8 @@
"hex.builtin.provider.motorola_srec": "Motorola SREC Provider", "hex.builtin.provider.motorola_srec": "Motorola SREC Provider",
"hex.builtin.provider.motorola_srec.name": "Motorola SREC {0}", "hex.builtin.provider.motorola_srec.name": "Motorola SREC {0}",
"hex.builtin.provider.view": "View", "hex.builtin.provider.view": "View",
"hex.builtin.setting.experiments": "Experiments",
"hex.builtin.setting.experiments.description": "Experiments are features that are still in development and may not work correctly yet.\n\nFeel free to try them out and report any issues you encounter!",
"hex.builtin.setting.folders": "Folders", "hex.builtin.setting.folders": "Folders",
"hex.builtin.setting.folders.add_folder": "Add new folder", "hex.builtin.setting.folders.add_folder": "Add new folder",
"hex.builtin.setting.folders.description": "Specify additional search paths for patterns, scripts, Yara rules and more", "hex.builtin.setting.folders.description": "Specify additional search paths for patterns, scripts, Yara rules and more",