add editor subsystem — daemon state + editor.* IPC

EditorBuffer + Selection + EditorRegistry hold the daemon-side
active-file model (D-006 subsystem 'editor'). Active buffer
tracking means `clide insert "…"` and `clide replace-selection
"…"` target the UI's focused file without the caller supplying an
id. Mutations mark buffers dirty; editor.save writes back to disk
through the workspace root; events fire on every state change so
subscribers can mirror.

IPC surface matches CLAUDE.md's tier-2 list + the natural extras
(list, read, activate, set-selection, set-content, close). Tests
cover open-idempotence, insert at caret, replace-selection range
swap, dirty→save→clean round-trip, close picks a new active
buffer, out-of-range selection clamping.

69 core tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-04-22 10:10:42 +02:00
co-authored by Claude
parent 37108230f2
commit d32e8fdc17
8 changed files with 705 additions and 0 deletions
+6
View File
@@ -16,8 +16,10 @@ import 'package:clide/clide.dart';
// Daemon-only deep imports — these pull in dart:ffi (PTY) and
// daemon-subsystem wiring that the Flutter app doesn't need and
// can't compile for web. See lib/clide.dart for the barrel split.
import 'package:clide/src/daemon/editor_commands.dart';
import 'package:clide/src/daemon/files_commands.dart';
import 'package:clide/src/daemon/pane_commands.dart';
import 'package:clide/src/editor/registry.dart' show EditorRegistry;
import 'package:clide/src/panes/registry.dart';
Future<void> main(List<String> argv) async {
@@ -85,6 +87,9 @@ Future<void> _runDaemon(List<String> args) async {
final files = FilesService.atCwd(events: events);
registerFilesCommands(dispatcher, files);
final editor = EditorRegistry(events: events, workspaceRoot: files.root);
registerEditorCommands(dispatcher, editor);
final stopping = Completer<void>();
void shutdown(ProcessSignal sig) {
if (!stopping.isCompleted) {
@@ -99,6 +104,7 @@ Future<void> _runDaemon(List<String> args) async {
await server.start();
await stopping.future;
await registry.shutdown();
await editor.shutdown();
await files.shutdown();
await server.stop();
exit(0);