Step 107a: add text mode toggle

This commit is contained in:
Bill
2026-02-09 11:46:57 -07:00
parent bd05b8a68f
commit a8c7b2adfc
5 changed files with 81 additions and 4 deletions

View File

@@ -207,8 +207,9 @@ All 38 steps implemented and passing. Each step has a corresponding test (`step1
- [x] Step 104: **IMPLEMENTED** — Cross-language projection button with read-only projected tabs and annotation summary (2/2 tests pass)
- [x] Step 105: **IMPLEMENTED** — Optimization controls panel with constraint-aware buttons and summaries (2/2 tests pass)
- [x] Step 106: **IMPLEMENTED** — Transform history panel with undo controls and provenance coloring (1/1 tests pass)
- [ ] Step 107a107c: **PLANNED** — Text-Editor Mode toggle, UI behavior by mode, and per-buffer persistence (not started)
- [x] Step 107: **IMPLEMENTED** — Before/after diff view with preview and accept/reject (1/1 tests pass)
- [x] Step 107a: **IMPLEMENTED** — Text-Editor Mode toggle and per-buffer mode tracking (2/2 tests pass)
- [ ] Step 107b107c: **PLANNED** — Mode-specific UI behavior and per-buffer persistence (not started)
---
@@ -296,6 +297,7 @@ vcpkg's imgui 1.91.9 removed the `sdl2-binding` feature (only `sdl3-binding` exi
**Step 105:** Compile and pass (2/2)
**Step 106:** Compile and pass (1/1)
**Step 107:** Compile and pass (1/1)
**Step 107a:** Compile and pass (2/2)
---
@@ -413,3 +415,4 @@ Sprint 4 in progress. Step 76 (LayoutManager) done. Next: Step 77 (custom code e
| 2026-02-09 | Codex | Step 106: Transform history panel with undo controls and provenance coloring. 1/1 tests pass. |
| 2026-02-09 | Codex | Planned Step 107a107c: add Text-Editor Mode toggle, mode-specific UI behavior, and per-buffer persistence. |
| 2026-02-09 | Codex | Step 107: Before/after diff view with preview and accept/reject. 1/1 tests pass. |
| 2026-02-09 | Codex | Step 107a: Text-Editor Mode toggle and per-buffer mode tracking. 2/2 tests pass. |

View File

@@ -578,6 +578,10 @@ add_executable(step107_test tests/step107_test.cpp)
target_include_directories(step107_test PRIVATE src)
target_link_libraries(step107_test PRIVATE nlohmann_json::nlohmann_json)
add_executable(step107a_test tests/step107a_test.cpp)
target_include_directories(step107a_test PRIVATE src)
target_link_libraries(step107a_test PRIVATE nlohmann_json::nlohmann_json)
find_package(SDL2 CONFIG REQUIRED)
find_package(OpenGL REQUIRED)
find_package(glad CONFIG REQUIRED)

View File

@@ -11,20 +11,27 @@
class BufferManager {
public:
enum class BufferMode {
Structured,
Text
};
struct BufferInfo {
std::string path;
std::string content;
std::string language;
bool modified = false;
BufferMode mode = BufferMode::Structured;
};
BufferManager() = default;
// Open a file into a buffer (makes it active)
bool openBuffer(const std::string& path, const std::string& content,
const std::string& language) {
const std::string& language,
BufferMode mode = BufferMode::Structured) {
if (hasBuffer(path)) return false; // already open
BufferInfo info{path, content, language, false};
BufferInfo info{path, content, language, false, mode};
buffers_[path] = info;
activeBuffer_ = path;
return true;
@@ -70,6 +77,19 @@ public:
}
}
void setBufferMode(const std::string& path, BufferMode mode) {
auto it = buffers_.find(path);
if (it != buffers_.end()) {
it->second.mode = mode;
}
}
BufferMode getBufferMode(const std::string& path) const {
auto it = buffers_.find(path);
if (it != buffers_.end()) return it->second.mode;
return BufferMode::Structured;
}
// Get list of all open buffer paths
std::vector<std::string> getOpenBuffers() const {
std::vector<std::string> result;

View File

@@ -17,6 +17,7 @@
#include "TextASTSync.h"
#include "SyntaxHighlighter.h"
#include "KeybindingManager.h"
#include "BufferManager.h"
#include "CodeEditorWidget.h"
#include "EditorMode.h"
#include "FileDialog.h"
@@ -70,6 +71,7 @@ struct BufferState {
std::string generatedLanguage = "python";
std::string path = "(untitled)";
bool readOnly = false;
BufferManager::BufferMode mode = BufferManager::BufferMode::Structured;
bool modified = false;
int cursorLine = 1;
int cursorCol = 1;
@@ -251,7 +253,8 @@ struct EditorState {
state->generatedHighlightsDirty = true;
state->modified = false;
state->lspVersion = 1;
buffers.openBuffer(path, content, language);
buffers.openBuffer(path, content, language, BufferManager::BufferMode::Structured);
state->mode = BufferManager::BufferMode::Structured;
activeBuffer = state.get();
bufferStates[path] = std::move(state);
if (path.rfind("(untitled", 0) != 0) watcher.watch(path);
@@ -1328,6 +1331,15 @@ int main(int, char**) {
ImGui::MenuItem("Show Minimap", nullptr, &state.showMinimap);
ImGui::MenuItem("Show Annotations", nullptr, &state.showAnnotations);
ImGui::MenuItem("LSP Servers...", nullptr, &state.showLspSettings);
if (state.active()) {
bool textMode = state.active()->mode == BufferManager::BufferMode::Text;
if (ImGui::MenuItem("Text-Editor Mode", nullptr, textMode)) {
state.active()->mode = textMode ?
BufferManager::BufferMode::Structured :
BufferManager::BufferMode::Text;
state.buffers.setBufferMode(state.active()->path, state.active()->mode);
}
}
if (ImGui::BeginMenu("Layout")) {
if (ImGui::MenuItem("VSCode", nullptr, state.layoutPreset == LayoutPreset::VSCode))
state.layoutPreset = LayoutPreset::VSCode;
@@ -2575,6 +2587,16 @@ int main(int, char**) {
ImGui::Text("-");
ImGui::SameLine(0, 30);
// Mode
if (state.active()) {
const char* modeLabel =
state.active()->mode == BufferManager::BufferMode::Text ? "Text" : "Structured";
ImGui::Text("Mode: %s", modeLabel);
} else {
ImGui::Text("Mode: -");
}
ImGui::SameLine(0, 30);
// Keybinding profile
ImGui::Text("Keys: %s", KeybindingManager::profileName(state.keys.getProfile()));
ImGui::SameLine(0, 30);

View File

@@ -0,0 +1,28 @@
// Step 107a TDD Test: Text editor mode toggle persistence in BufferManager
//
// Tests:
// 1. Default mode is Structured
// 2. setBufferMode updates mode
#include <cassert>
#include <iostream>
#include "BufferManager.h"
int main() {
int passed = 0;
int failed = 0;
BufferManager bm;
bm.openBuffer("file1", "", "python");
assert(bm.getBufferMode("file1") == BufferManager::BufferMode::Structured);
std::cout << "Test 1 PASS: default mode structured" << std::endl;
++passed;
bm.setBufferMode("file1", BufferManager::BufferMode::Text);
assert(bm.getBufferMode("file1") == BufferManager::BufferMode::Text);
std::cout << "Test 2 PASS: mode updated" << std::endl;
++passed;
std::cout << "\n=== Step 107a Results: " << passed << " passed, " << failed << " failed ===" << std::endl;
return failed > 0 ? 1 : 0;
}