Step 355: Shortcuts Panel Integration (8/8 tests)

This commit is contained in:
Bill
2026-02-16 09:09:37 -07:00
parent b089fa0cd0
commit 1470417c60
6 changed files with 294 additions and 2 deletions

View File

@@ -12,6 +12,7 @@ struct CommandEntry {
std::string id;
std::string label;
std::string shortcut;
std::string symbols;
std::string icon;
std::string category;
std::string inputHint;
@@ -64,7 +65,8 @@ public:
const std::string& inputHint = "",
bool inlineInput = false,
const std::vector<std::string>& aliases = {},
const std::string& icon = "") {
const std::string& icon = "",
const std::string& symbols = "") {
auto& entry = commands_[id];
entry.id = id;
entry.label = label;
@@ -75,6 +77,7 @@ public:
entry.inlineInput = inlineInput;
entry.aliases = aliases;
entry.icon = icon;
entry.symbols = symbols;
}
void registerFromKeybindings(const KeybindingRegistry& registry) {
@@ -89,7 +92,8 @@ public:
"",
false,
{action.id},
WhetstoneIcons::Search
WhetstoneIcons::Search,
binding.toSymbolsAuto()
);
}
}

View File

@@ -205,6 +205,7 @@ public:
// View actions
registerAction("command-palette", "Command Palette", "View");
registerAction("keyboard-shortcuts", "Keyboard Shortcuts", "Help");
registerAction("toggle-file-tree", "Toggle File Tree", "View");
registerAction("toggle-ast-view", "Toggle AST View", "View");
registerAction("toggle-diagnostics", "Toggle Diagnostics", "View");
@@ -234,6 +235,7 @@ public:
bind("find-in-file", KeyCombo::ctrl("F"));
bind("find-in-project", KeyCombo::ctrlShift("F"));
bind("command-palette", KeyCombo::ctrl("P"));
bind("keyboard-shortcuts", KeyCombo::ctrlShift("?"));
bind("toggle-file-tree", KeyCombo::ctrl("B"));
bind("toggle-diagnostics", KeyCombo::ctrlShift("D"));
bind("run-pipeline", KeyCombo::fkey("F5"));

View File

@@ -0,0 +1,85 @@
#pragma once
// Step 355: Keyboard shortcuts panel model.
// Headless grouping/filtering/customize behavior for shortcut display.
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include "KeybindingRegistry.h"
struct ShortcutRow {
std::string actionId;
std::string label;
std::string category;
std::string symbols;
std::string description;
};
class KeyboardShortcutsPanel {
public:
void open() { visible_ = true; }
void close() { visible_ = false; }
bool isVisible() const { return visible_; }
void setFilter(const std::string& text) { filter_ = text; }
const std::string& filter() const { return filter_; }
void loadFromRegistry(const KeybindingRegistry& registry, bool macOS = false) {
rows_.clear();
for (const auto& action : registry.getActions()) {
ShortcutRow row;
row.actionId = action.id;
row.label = action.label;
row.category = action.category;
row.description = action.description;
row.symbols = registry.getSymbols(action.id, macOS);
rows_.push_back(row);
}
std::sort(rows_.begin(), rows_.end(), [](const ShortcutRow& a, const ShortcutRow& b) {
if (a.category != b.category) return a.category < b.category;
return a.label < b.label;
});
}
const std::vector<ShortcutRow>& rows() const { return rows_; }
std::vector<ShortcutRow> filteredRows() const {
if (filter_.empty()) return rows_;
std::string needle = toLower(filter_);
std::vector<ShortcutRow> out;
for (const auto& row : rows_) {
std::string hay = toLower(row.label + " " + row.category + " " + row.actionId);
if (hay.find(needle) != std::string::npos) out.push_back(row);
}
return out;
}
std::map<std::string, std::vector<ShortcutRow>> groupedRows() const {
std::map<std::string, std::vector<ShortcutRow>> groups;
for (const auto& row : filteredRows()) {
groups[row.category].push_back(row);
}
return groups;
}
void requestCustomize() { customizeRequested_ = true; }
bool consumeCustomizeRequest() {
bool value = customizeRequested_;
customizeRequested_ = false;
return value;
}
private:
static std::string toLower(const std::string& s) {
std::string out = s;
std::transform(out.begin(), out.end(), out.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
return out;
}
bool visible_ = false;
bool customizeRequested_ = false;
std::string filter_;
std::vector<ShortcutRow> rows_;
};