Phase 3c: Classical editing mode (Steps 50-53)
Implement TextASTSync and TextEditor — the core text editing layer that bridges raw text and the structured AST. TextASTSync provides bidirectional text-AST sync with debounce via TreeSitterParser and generators. TextEditor wraps a text buffer with edit operations, undo/redo that tracks AST state, find/replace, and selection. New files: TextASTSync.h, TextEditor.h, step50_test.cpp Updated: step51/53 tests (replaced stubs with real includes), CMakeLists.txt (tree-sitter linking), PROGRESS.md Fixed: step53 find-position off-by-one, canRedo assert logic 19/19 tests pass (step50: 8, step51: 5, step53: 6) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,54 +4,21 @@
|
||||
// 1. Undo in text mode undoes both text and AST changes
|
||||
// 2. Redo restores both text and AST
|
||||
// 3. Find text in the text buffer
|
||||
// 4. Replace text → AST updates accordingly
|
||||
// 4. Replace text -> AST updates accordingly
|
||||
// 5. Copy/paste operations work in text mode
|
||||
// 6. Text undo/redo integrates with orchestrator's operation journal
|
||||
//
|
||||
// Will fail until classical editing operations are implemented.
|
||||
// Depends on: TextEditor, TreeSitterParser, PythonGenerator
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include "ast/ASTNode.h"
|
||||
#include "ast/Module.h"
|
||||
#include "ast/Function.h"
|
||||
#include "TextEditor.h"
|
||||
|
||||
static bool contains(const std::string& haystack, const std::string& needle) {
|
||||
return haystack.find(needle) != std::string::npos;
|
||||
}
|
||||
|
||||
// Forward declaration — TextEditor class that wraps text ops + AST sync
|
||||
class TextEditor {
|
||||
public:
|
||||
// Set initial content
|
||||
void setContent(const std::string& text, const std::string& language);
|
||||
|
||||
// Get current text
|
||||
std::string getContent() const;
|
||||
|
||||
// Get current AST
|
||||
Module* getAST() const;
|
||||
|
||||
// Edit operations
|
||||
void insertText(int position, const std::string& text);
|
||||
void deleteText(int position, int length);
|
||||
void replaceText(int position, int length, const std::string& replacement);
|
||||
|
||||
// Undo/redo (must also undo/redo AST changes)
|
||||
void undo();
|
||||
void redo();
|
||||
bool canUndo() const;
|
||||
bool canRedo() const;
|
||||
|
||||
// Find/replace
|
||||
int find(const std::string& query, int startPos = 0) const;
|
||||
int replaceAll(const std::string& query, const std::string& replacement);
|
||||
|
||||
// Clipboard
|
||||
std::string getSelection(int start, int length) const;
|
||||
};
|
||||
|
||||
int main() {
|
||||
int passed = 0;
|
||||
int failed = 0;
|
||||
@@ -112,7 +79,7 @@ int main() {
|
||||
|
||||
editor.replaceText(4, 5, "world");
|
||||
editor.undo();
|
||||
assert(!editor.canRedo() == false && "Should be able to redo after undo");
|
||||
assert(editor.canRedo() && "Should be able to redo after undo");
|
||||
|
||||
editor.redo();
|
||||
std::string text = editor.getContent();
|
||||
@@ -134,7 +101,9 @@ int main() {
|
||||
|
||||
int pos = editor.find("return");
|
||||
assert(pos >= 0 && "Should find 'return' in text");
|
||||
assert(pos == 18 && "Position of 'return' should be at column after indent");
|
||||
// "def hello():\n return 42\n"
|
||||
// 0123456789012 34567... -> 'r' of "return" is at index 17
|
||||
assert(pos == 17 && "Position of 'return' should be at index 17");
|
||||
|
||||
int notFound = editor.find("nonexistent");
|
||||
assert(notFound == -1 && "Should return -1 for not found");
|
||||
|
||||
Reference in New Issue
Block a user