port clide runtime to Windows (ConPTY, AF_UNIX, PATHEXT)
Bring the runtime up on Windows without disturbing the POSIX paths. PTY: introduce a platform-neutral PtySession contract with a factory that picks NativePty (posix_openpt/posix_spawn) or the new WindowsPty (ConPTY via CreatePseudoConsole). The pane registry programs against the interface; NativePty now implements it. IPC: the per-workspace AF_UNIX socket lives under %LOCALAPPDATA% and is hashed from a canonical workspace key (backslash + ASCII-folded case) so the Dart server and the C client agree despite NTFS case- insensitivity. The C client grows a Win32 shim (winsock afunix); chmod is a no-op on Windows where the per-user ACL is the gate. Toolchain: PATH probing splits on ';' and tries PATHEXT extensions; the shell defaults to PowerShell (pwsh, then powershell); tmux is treated as optional since it has no Windows build; dugite falls back to PATH git for now. Build: add `make build-windows`, a clide-cli MSVC build wrapped by ci/build_cli_windows.sh, and a ConPTY smoke-test suite that self- skips off-platform. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/// Platform-neutral PTY session contract + factory.
|
||||
///
|
||||
/// The pane registry (and anything else that spawns PTY children)
|
||||
/// programs against [PtySession]; [startPtySession] picks the
|
||||
/// platform backend — `posix_openpt` + `posix_spawn` on Linux/macOS
|
||||
/// ([NativePty]), ConPTY on Windows ([WindowsPty]). Both backends
|
||||
/// share the same lifecycle: spawn → byte stream out → write/resize
|
||||
/// in → EOF on child exit → close() reaps.
|
||||
library;
|
||||
|
||||
import 'dart:io' show Platform;
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'native_pty.dart';
|
||||
import 'windows_pty.dart';
|
||||
|
||||
abstract interface class PtySession {
|
||||
/// OS process id of the spawned child.
|
||||
int get pid;
|
||||
|
||||
/// Byte stream of data produced by the child.
|
||||
Stream<Uint8List> get output;
|
||||
|
||||
bool get isClosed;
|
||||
|
||||
/// Write bytes to the child's stdin. Returns the bytes written.
|
||||
int write(List<int> bytes);
|
||||
|
||||
/// Resize the terminal.
|
||||
void resize({required int cols, required int rows});
|
||||
|
||||
/// Signal the child. [signal] is a POSIX signal number; backends
|
||||
/// without signals (Windows) treat any value as terminate. Null
|
||||
/// means the backend's default hang-up behaviour.
|
||||
bool kill([int? signal]);
|
||||
|
||||
/// Kill the child and release resources.
|
||||
Future<void> close();
|
||||
}
|
||||
|
||||
/// Spawn a child under a PTY using the platform backend.
|
||||
///
|
||||
/// [environment] must be the complete environment — it goes straight
|
||||
/// to the child. Merge `Platform.environment` before calling.
|
||||
PtySession startPtySession({
|
||||
required String executable,
|
||||
List<String> arguments = const [],
|
||||
required int columns,
|
||||
required int rows,
|
||||
String? workingDirectory,
|
||||
Map<String, String> environment = const {},
|
||||
}) {
|
||||
if (Platform.isWindows) {
|
||||
return WindowsPty.start(
|
||||
executable: executable,
|
||||
arguments: arguments,
|
||||
columns: columns,
|
||||
rows: rows,
|
||||
workingDirectory: workingDirectory,
|
||||
environment: environment,
|
||||
);
|
||||
}
|
||||
return NativePty.start(
|
||||
executable: executable,
|
||||
arguments: arguments,
|
||||
columns: columns,
|
||||
rows: rows,
|
||||
workingDirectory: workingDirectory,
|
||||
environment: environment,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user