Fix editor build break and improve startup usability
This commit is contained in:
@@ -19,11 +19,11 @@ enum KeyMod : int {
|
||||
WMOD_SUPER = 1 << 3 // Cmd on Mac, Win on Windows
|
||||
};
|
||||
|
||||
struct KeyCombo {
|
||||
struct LegacyKeyCombo {
|
||||
int key; // virtual key or character code (e.g. 'S', 'Z', 'F')
|
||||
int modifiers; // bitmask of KeyMod
|
||||
|
||||
bool operator==(const KeyCombo& other) const {
|
||||
bool operator==(const LegacyKeyCombo& other) const {
|
||||
return key == other.key && modifiers == other.modifiers;
|
||||
}
|
||||
|
||||
@@ -85,14 +85,14 @@ public:
|
||||
}
|
||||
|
||||
// Look up the key combo for an action (returns empty combo if not bound)
|
||||
KeyCombo getBinding(const std::string& action) const {
|
||||
LegacyKeyCombo getBinding(const std::string& action) const {
|
||||
auto it = bindings_.find(action);
|
||||
if (it != bindings_.end()) return it->second;
|
||||
return {0, WMOD_NONE};
|
||||
}
|
||||
|
||||
// Look up the action for a key combo (returns "" if not bound)
|
||||
std::string getAction(const KeyCombo& combo) const {
|
||||
std::string getAction(const LegacyKeyCombo& combo) const {
|
||||
for (const auto& [action, binding] : bindings_) {
|
||||
if (binding == combo) return action;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
}
|
||||
|
||||
// Override a single binding
|
||||
void setBinding(const std::string& action, KeyCombo combo) {
|
||||
void setBinding(const std::string& action, LegacyKeyCombo combo) {
|
||||
bindings_[action] = combo;
|
||||
}
|
||||
|
||||
@@ -272,5 +272,5 @@ private:
|
||||
}
|
||||
|
||||
KeybindingProfile profile_;
|
||||
std::map<std::string, KeyCombo> bindings_;
|
||||
std::map<std::string, LegacyKeyCombo> bindings_;
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ static void renderShortcutReference(EditorState& state, ShortcutReferenceState&
|
||||
std::transform(lower.begin(), lower.end(), lower.begin(),
|
||||
[](unsigned char c) { return (char)std::tolower(c); });
|
||||
if (!filterText.empty() && lower.find(filterText) == std::string::npos) continue;
|
||||
KeyCombo combo = state.keys.getBinding(action);
|
||||
LegacyKeyCombo combo = state.keys.getBinding(action);
|
||||
ImGui::Text("%s", action.c_str());
|
||||
ImGui::SameLine(260.0f);
|
||||
ImGui::TextDisabled("%s", combo.toString().c_str());
|
||||
|
||||
@@ -317,6 +317,11 @@ int main(int, char**) {
|
||||
} else {
|
||||
state.ui.showFirstRunWizard = true;
|
||||
}
|
||||
if (state.buffers.bufferCount() == 0) {
|
||||
state.createBuffer(state.makeUntitledName(), "", "python",
|
||||
BufferManager::BufferMode::Text);
|
||||
state.ui.focusTarget = FocusRegion::Editor;
|
||||
}
|
||||
state.lspTransport = std::make_shared<NullLSPTransport>();
|
||||
state.lsp = std::make_shared<LSPClient>(state.lspTransport);
|
||||
|
||||
@@ -399,7 +404,7 @@ int main(int, char**) {
|
||||
}
|
||||
|
||||
if (key != 0 && mods != WMOD_NONE) {
|
||||
KeyCombo combo{key, mods};
|
||||
LegacyKeyCombo combo{key, mods};
|
||||
std::string action = state.keys.getAction(combo);
|
||||
if (action == "edit.undo") state.doUndo();
|
||||
else if (action == "edit.redo") state.doRedo();
|
||||
|
||||
@@ -97,6 +97,7 @@ static void renderMenuBar(EditorState& state) {
|
||||
ImGui::MenuItem("Dependencies", nullptr, &state.library.showDependencyPanel);
|
||||
ImGui::MenuItem("Libraries", nullptr, &state.library.showLibraryBrowserPanel);
|
||||
ImGui::MenuItem("Compose", nullptr, &state.library.showCompositionPanel);
|
||||
ImGui::MenuItem("Memory Strategies", nullptr, &state.ui.showMemoryStrategies);
|
||||
ImGui::MenuItem("Emacs Packages", nullptr, &state.emacsState.showEmacsPackagesPanel);
|
||||
ImGui::MenuItem("Emacs Bridge", nullptr, &state.emacsState.showEmacsBridgePanel);
|
||||
ImGui::MenuItem("Settings", nullptr, &state.ui.showSettingsPanel);
|
||||
|
||||
@@ -249,11 +249,12 @@ static void renderMinibuffer(EditorState& state) {
|
||||
}
|
||||
|
||||
static void renderMemoryStrategiesPanel(EditorState& state) {
|
||||
if (!state.ui.showMemoryStrategies) return;
|
||||
if (state.ui.focusTarget == FocusRegion::Side) {
|
||||
ImGui::SetNextWindowFocus();
|
||||
state.ui.focusTarget = FocusRegion::None;
|
||||
}
|
||||
ImGui::Begin("Memory Strategies");
|
||||
ImGui::Begin("Memory Strategies", &state.ui.showMemoryStrategies);
|
||||
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)) {
|
||||
state.ui.focusedRegion = FocusRegion::Side;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ struct UIFlags {
|
||||
bool showFirstRunWizard = false;
|
||||
bool showShortcutReference = false;
|
||||
bool showHelpPanel = false;
|
||||
bool showMemoryStrategies = false;
|
||||
bool showAnnotateWizard = false;
|
||||
bool showProjectWizard = false;
|
||||
bool showAgentWizard = false;
|
||||
|
||||
@@ -32,15 +32,15 @@ int main() {
|
||||
// --- Test 2: VSCode bindings are correct ---
|
||||
{
|
||||
KeybindingManager mgr;
|
||||
KeyCombo save = mgr.getBinding("file.save");
|
||||
LegacyKeyCombo save = mgr.getBinding("file.save");
|
||||
assert(save.key == 'S' && save.modifiers == WMOD_CTRL &&
|
||||
"VSCode: file.save should be Ctrl+S");
|
||||
|
||||
KeyCombo undo = mgr.getBinding("edit.undo");
|
||||
LegacyKeyCombo undo = mgr.getBinding("edit.undo");
|
||||
assert(undo.key == 'Z' && undo.modifiers == WMOD_CTRL &&
|
||||
"VSCode: edit.undo should be Ctrl+Z");
|
||||
|
||||
KeyCombo redo = mgr.getBinding("edit.redo");
|
||||
LegacyKeyCombo redo = mgr.getBinding("edit.redo");
|
||||
assert(redo.key == 'Y' && redo.modifiers == WMOD_CTRL &&
|
||||
"VSCode: edit.redo should be Ctrl+Y");
|
||||
|
||||
@@ -54,12 +54,12 @@ int main() {
|
||||
mgr.setProfile(KeybindingProfile::JetBrains);
|
||||
assert(mgr.getProfile() == KeybindingProfile::JetBrains);
|
||||
|
||||
KeyCombo redo = mgr.getBinding("edit.redo");
|
||||
LegacyKeyCombo redo = mgr.getBinding("edit.redo");
|
||||
assert(redo.key == 'Z' && redo.modifiers == (WMOD_CTRL | WMOD_SHIFT) &&
|
||||
"JetBrains: edit.redo should be Ctrl+Shift+Z");
|
||||
|
||||
// But save is still Ctrl+S
|
||||
KeyCombo save = mgr.getBinding("file.save");
|
||||
LegacyKeyCombo save = mgr.getBinding("file.save");
|
||||
assert(save.key == 'S' && save.modifiers == WMOD_CTRL &&
|
||||
"JetBrains: file.save should still be Ctrl+S");
|
||||
|
||||
@@ -74,7 +74,7 @@ int main() {
|
||||
assert(mgr.getProfile() == KeybindingProfile::Emacs);
|
||||
|
||||
// Emacs uses Ctrl+Y for paste
|
||||
KeyCombo paste = mgr.getBinding("edit.paste");
|
||||
LegacyKeyCombo paste = mgr.getBinding("edit.paste");
|
||||
assert(paste.key == 'Y' && paste.modifiers == WMOD_CTRL &&
|
||||
"Emacs: edit.paste should be Ctrl+Y");
|
||||
|
||||
@@ -85,11 +85,11 @@ int main() {
|
||||
// --- Test 5: Reverse lookup (combo -> action) ---
|
||||
{
|
||||
KeybindingManager mgr; // VSCode
|
||||
KeyCombo ctrlS = {'S', WMOD_CTRL};
|
||||
LegacyKeyCombo ctrlS = {'S', WMOD_CTRL};
|
||||
std::string action = mgr.getAction(ctrlS);
|
||||
assert(action == "file.save" && "Ctrl+S should map to file.save");
|
||||
|
||||
KeyCombo unknown = {'Q', WMOD_CTRL | WMOD_ALT | WMOD_SHIFT};
|
||||
LegacyKeyCombo unknown = {'Q', WMOD_CTRL | WMOD_ALT | WMOD_SHIFT};
|
||||
std::string none = mgr.getAction(unknown);
|
||||
assert(none.empty() && "Unknown combo should return empty string");
|
||||
|
||||
@@ -102,7 +102,7 @@ int main() {
|
||||
KeybindingManager mgr;
|
||||
mgr.setBinding("file.save", {'S', WMOD_CTRL | WMOD_ALT});
|
||||
|
||||
KeyCombo save = mgr.getBinding("file.save");
|
||||
LegacyKeyCombo save = mgr.getBinding("file.save");
|
||||
assert(save.key == 'S' && save.modifiers == (WMOD_CTRL | WMOD_ALT) &&
|
||||
"Custom override should change binding");
|
||||
|
||||
@@ -121,7 +121,7 @@ int main() {
|
||||
KeybindingManager mgr;
|
||||
mgr.setProfile(profile);
|
||||
for (const auto& action : coreActions) {
|
||||
KeyCombo combo = mgr.getBinding(action);
|
||||
LegacyKeyCombo combo = mgr.getBinding(action);
|
||||
assert(combo.key != 0 &&
|
||||
(std::string("Profile ") +
|
||||
KeybindingManager::profileName(profile) +
|
||||
@@ -149,15 +149,15 @@ int main() {
|
||||
++passed;
|
||||
}
|
||||
|
||||
// --- Test 9: KeyCombo toString ---
|
||||
// --- Test 9: LegacyKeyCombo toString ---
|
||||
{
|
||||
KeyCombo ctrlS = {'S', WMOD_CTRL};
|
||||
LegacyKeyCombo ctrlS = {'S', WMOD_CTRL};
|
||||
assert(ctrlS.toString() == "Ctrl+S" && "Ctrl+S toString");
|
||||
|
||||
KeyCombo ctrlShiftZ = {'Z', WMOD_CTRL | WMOD_SHIFT};
|
||||
LegacyKeyCombo ctrlShiftZ = {'Z', WMOD_CTRL | WMOD_SHIFT};
|
||||
assert(ctrlShiftZ.toString() == "Ctrl+Shift+Z" && "Ctrl+Shift+Z toString");
|
||||
|
||||
std::cout << "Test 9 PASS: KeyCombo toString" << std::endl;
|
||||
std::cout << "Test 9 PASS: LegacyKeyCombo toString" << std::endl;
|
||||
++passed;
|
||||
}
|
||||
|
||||
|
||||
47
progress.md
47
progress.md
@@ -5232,6 +5232,53 @@ visual workflow path.
|
||||
- `editor/src/MCPServer.h` (`1940` > `600`)
|
||||
- `editor/src/HeadlessAgentRPCHandler.h` (`2768` > `600`)
|
||||
|
||||
## Post-Sprint Stabilization: Build + Startup Usability
|
||||
|
||||
### Hotfix A: Keybinding type collision blocking editor build
|
||||
**Status:** PASS (build restored)
|
||||
|
||||
Resolved a compile-breaking global type collision between legacy keybinding code
|
||||
and the newer registry by namespacing the legacy combo type.
|
||||
|
||||
**Files modified:**
|
||||
- `editor/src/KeybindingManager.h` — renamed legacy `KeyCombo` to `LegacyKeyCombo`
|
||||
- `editor/src/main.cpp` — updated shortcut dispatch type usage
|
||||
- `editor/src/ShortcutReference.h` — updated shortcut panel type usage
|
||||
- `editor/tests/step54_test.cpp` — updated test references
|
||||
|
||||
**Verification run:**
|
||||
- `cmake --build editor/build-native --target whetstone_editor` — PASS
|
||||
- `step54_test` — PASS (10/10) regression coverage
|
||||
|
||||
### Hotfix B: startup usability (editable buffer + dismissible side panel)
|
||||
**Status:** PASS (build restored, UX defaults improved)
|
||||
|
||||
Adjusted startup defaults so users can type immediately and hide optional side
|
||||
panels cleanly.
|
||||
|
||||
**Files modified:**
|
||||
- `editor/src/state/UIFlags.h` — added `showMemoryStrategies` flag (default `false`)
|
||||
- `editor/src/panels/SidePanels.h` — made Memory Strategies panel conditional and closable
|
||||
- `editor/src/panels/MenuBarPanel.h` — added View menu toggle for Memory Strategies panel
|
||||
- `editor/src/main.cpp` — auto-create untitled text buffer when startup/session has no buffers; set editor focus
|
||||
|
||||
**Verification run:**
|
||||
- `cmake --build editor/build-native --target whetstone_editor` — PASS
|
||||
- `step54_test` — PASS (10/10) regression coverage
|
||||
- `step437_test` — PASS (8/8) regression coverage
|
||||
|
||||
**Build health check cadence (to run after each sprint step cluster):**
|
||||
- `cmake --build editor/build-native --target whetstone_editor -j4`
|
||||
- `./editor/build-native/step54_test`
|
||||
- `./editor/build-native/step437_test`
|
||||
|
||||
**Architecture gate check:**
|
||||
- `editor/src/main.cpp` within main-file limit (`587` <= `1500`)
|
||||
- `editor/src/KeybindingManager.h` within header-size limit (`276` <= `600`)
|
||||
- `editor/src/panels/SidePanels.h` within header-size limit (`308` <= `600`)
|
||||
- `editor/src/panels/MenuBarPanel.h` within header-size limit (`268` <= `600`)
|
||||
- `editor/src/state/UIFlags.h` within header-size limit (`33` <= `600`)
|
||||
|
||||
# Roadmap Planning — Sprints 12-25+
|
||||
|
||||
## Status: Planning Complete (Sprints 12-19 detailed, 20-25 in roadmap.md)
|
||||
|
||||
Reference in New Issue
Block a user