فهرست منبع

TerminalBackend interface

Out, ExitCode, write and resize are now routed via the Terminal
Terminal triggers initialization of the backend (so that the initialization can happen in the Terminal Isolate)
devmil 4 سال پیش
والد
کامیت
df9c4cb671

+ 0 - 5
lib/frontend/terminal_view.dart

@@ -21,13 +21,10 @@ import 'package:xterm/theme/terminal_style.dart';
 import 'package:xterm/util/bit_flags.dart';
 import 'package:xterm/util/hash_values.dart';
 
-typedef TerminalResizeHandler = void Function(int width, int height);
-
 class TerminalView extends StatefulWidget {
   TerminalView({
     Key? key,
     required this.terminal,
-    this.onResize,
     this.style = const TerminalStyle(),
     this.opacity = 1.0,
     FocusNode? focusNode,
@@ -40,7 +37,6 @@ class TerminalView extends StatefulWidget {
         super(key: key ?? ValueKey(terminal));
 
   final TerminalUiInteraction terminal;
-  final TerminalResizeHandler? onResize;
   final FocusNode focusNode;
   final bool autofocus;
   final ScrollController scrollController;
@@ -288,7 +284,6 @@ class _TerminalViewState extends State<TerminalView> {
     _lastTerminalWidth = termWidth;
     _lastTerminalHeight = termHeight;
 
-    widget.onResize?.call(termWidth, termHeight);
     widget.terminal.resize(termWidth, termHeight);
   }
 

+ 1 - 1
lib/mouse/mouse_mode.dart

@@ -49,6 +49,6 @@ class MouseModeX10 extends MouseMode {
     buffer.writeCharCode(btn + 32);
     buffer.writeCharCode(px + 32);
     buffer.writeCharCode(py + 32);
-    terminal.onInput(buffer.toString());
+    terminal.backend?.write(buffer.toString());
   }
 }

+ 4 - 3
lib/terminal/csi.dart

@@ -306,10 +306,11 @@ void csiDeviceStatusReportHandler(CSI csi, Terminal terminal) {
 
   switch (csi.params[0]) {
     case 5:
-      terminal.onInput("\x1b[0n");
+      terminal.backend?.write("\x1b[0n");
       break;
     case 6: // report cursor position
-      terminal.onInput("\x1b[${terminal.cursorX + 1};${terminal.cursorY + 1}R");
+      terminal.backend
+          ?.write("\x1b[${terminal.cursorX + 1};${terminal.cursorY + 1}R");
       break;
     default:
       terminal.debug
@@ -325,7 +326,7 @@ void csiSendDeviceAttributesHandler(CSI csi, Terminal terminal) {
     response = '>0;0;0';
   }
 
-  terminal.onInput('\x1b[${response}c');
+  terminal.backend?.write('\x1b[${response}c');
 }
 
 void csiCursorUpHandler(CSI csi, Terminal terminal) {

+ 10 - 6
lib/terminal/terminal.dart

@@ -14,6 +14,7 @@ import 'package:xterm/terminal/cursor.dart';
 import 'package:xterm/terminal/platform.dart';
 import 'package:xterm/terminal/sbc.dart';
 import 'package:xterm/terminal/tabs.dart';
+import 'package:xterm/terminal/terminal_backend.dart';
 import 'package:xterm/theme/terminal_color.dart';
 import 'package:xterm/theme/terminal_theme.dart';
 import 'package:xterm/theme/terminal_themes.dart';
@@ -32,7 +33,7 @@ void _defaultIconHandler(String _) {}
 
 class Terminal with Observable {
   Terminal({
-    this.onInput = _defaultInputHandler,
+    this.backend,
     this.onBell = _defaultBellHandler,
     this.onTitleChange = _defaultTitleHandler,
     this.onIconChange = _defaultIconHandler,
@@ -40,6 +41,8 @@ class Terminal with Observable {
     this.theme = TerminalThemes.defaultTheme,
     required int maxLines,
   }) : _maxLines = maxLines {
+    backend?.init();
+    backend?.out.listen(write);
     _mainBuffer = Buffer(this);
     _altBuffer = Buffer(this);
     _buffer = _mainBuffer;
@@ -182,7 +185,7 @@ class Terminal with Observable {
   final tabs = Tabs();
   final debug = DebugHandler();
 
-  final TerminalInputHandler onInput;
+  final TerminalBackend? backend;
   final BellHandler onBell;
   final TitleChangeHandler onTitleChange;
   final IconChangeHandler onIconChange;
@@ -349,6 +352,7 @@ class Terminal with Observable {
   /// than 0. Text reflow is currently not implemented and will be avaliable in
   /// the future.
   void resize(int newWidth, int newHeight) {
+    backend?.resize(newWidth, newHeight);
     newWidth = max(newWidth, 1);
     newHeight = max(newHeight, 1);
 
@@ -429,7 +433,7 @@ class Terminal with Observable {
       if (record.action.type == KeytabActionType.input) {
         debug.onMsg('input: ${record.action.value}');
         final input = keytabUnescape(record.action.value);
-        onInput(input);
+        backend?.write(input);
         return;
       }
     }
@@ -438,7 +442,7 @@ class Terminal with Observable {
       if (key.index >= TerminalKey.keyA.index &&
           key.index <= TerminalKey.keyZ.index) {
         final input = key.index - TerminalKey.keyA.index + 1;
-        onInput(String.fromCharCode(input));
+        backend?.write(String.fromCharCode(input));
         return;
       }
     }
@@ -447,7 +451,7 @@ class Terminal with Observable {
       if (key.index >= TerminalKey.keyA.index &&
           key.index <= TerminalKey.keyZ.index) {
         final input = [0x1b, key.index - TerminalKey.keyA.index + 65];
-        onInput(String.fromCharCodes(input));
+        backend?.write(String.fromCharCodes(input));
         return;
       }
     }
@@ -508,7 +512,7 @@ class Terminal with Observable {
       data = '\x1b[200~$data\x1b[201~';
     }
 
-    onInput(data);
+    backend?.write(data);
   }
 
   void selectWord(int x, int y) {}

+ 9 - 0
lib/terminal/terminal_backend.dart

@@ -0,0 +1,9 @@
+abstract class TerminalBackend {
+  void init();
+
+  Stream<String> get out;
+  Future<int> get exitCode;
+
+  void write(String input);
+  void resize(int width, int height);
+}

+ 28 - 46
lib/terminal/terminal_isolate.dart

@@ -7,6 +7,7 @@ import 'package:xterm/mouse/position.dart';
 import 'package:xterm/mouse/selection.dart';
 import 'package:xterm/terminal/platform.dart';
 import 'package:xterm/terminal/terminal.dart';
+import 'package:xterm/terminal/terminal_backend.dart';
 import 'package:xterm/terminal/terminal_ui_interaction.dart';
 import 'package:xterm/theme/terminal_theme.dart';
 import 'package:xterm/theme/terminal_themes.dart';
@@ -27,9 +28,7 @@ void terminalMain(SendPort port) async {
       case 'init':
         final TerminalInitData initData = msg[1];
         _terminal = Terminal(
-            onInput: (String input) {
-              port.send(['onInput', input]);
-            },
+            backend: initData.backend,
             onTitleChange: (String title) {
               port.send(['onTitleChange', title]);
             },
@@ -45,56 +44,35 @@ void terminalMain(SendPort port) async {
         _terminal.addListener(() {
           port.send(['notify']);
         });
+        initData.backend?.exitCode.then((value) => port.send(['exit', value]));
         port.send(['notify']);
         break;
       case 'write':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.write(msg[1]);
+        _terminal?.write(msg[1]);
         break;
       case 'refresh':
-        if (_terminal == null) {
-          break;
-        }
-
-        _terminal.refresh();
+        _terminal?.refresh();
         break;
       case 'selection.clear':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.selection.clear();
+        _terminal?.selection.clear();
         break;
       case 'mouseMode.onTap':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.mouseMode.onTap(_terminal, msg[1]);
+        _terminal?.mouseMode.onTap(_terminal, msg[1]);
         break;
       case 'mouseMode.onPanStart':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.mouseMode.onPanStart(_terminal, msg[1]);
+        _terminal?.mouseMode.onPanStart(_terminal, msg[1]);
         break;
       case 'mouseMode.onPanUpdate':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.mouseMode.onPanUpdate(_terminal, msg[1]);
+        _terminal?.mouseMode.onPanUpdate(_terminal, msg[1]);
         break;
       case 'setScrollOffsetFromBottom':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.setScrollOffsetFromBottom(msg[1]);
+        _terminal?.setScrollOffsetFromBottom(msg[1]);
         break;
       case 'resize':
-        if (_terminal == null) {
-          break;
-        }
-        _terminal.resize(msg[1], msg[2]);
+        _terminal?.resize(msg[1], msg[2]);
+        break;
+      case 'onInput':
+        _terminal?.backend?.write(msg[1]);
         break;
       case 'keyInput':
         if (_terminal == null) {
@@ -141,8 +119,8 @@ class TerminalInitData {
   PlatformBehavior platform;
   TerminalTheme theme;
   int maxLines;
-
-  TerminalInitData(this.platform, this.theme, this.maxLines);
+  TerminalBackend? backend;
+  TerminalInitData(this.backend, this.platform, this.theme, this.maxLines);
 }
 
 class TerminalState {
@@ -199,7 +177,7 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
   SendPort? _sendPort;
   late Isolate _isolate;
 
-  final TerminalInputHandler onInput;
+  final TerminalBackend? backend;
   final BellHandler onBell;
   final TitleChangeHandler onTitleChange;
   final IconChangeHandler onIconChange;
@@ -209,13 +187,15 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
   final int maxLines;
 
   TerminalState? _lastState;
+  final _backendExited = Completer<int>();
+  Future<int> get backendExited => _backendExited.future;
 
   TerminalState? get lastState {
     return _lastState;
   }
 
   TerminalIsolate(
-      {this.onInput = _defaultInputHandler,
+      {this.backend,
       this.onBell = _defaultBellHandler,
       this.onTitleChange = _defaultTitleHandler,
       this.onIconChange = _defaultIconHandler,
@@ -312,9 +292,6 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
     _receivePort.listen((message) {
       String action = message[0];
       switch (action) {
-        case 'onInput':
-          this.onInput(message[1]);
-          break;
         case 'onBell':
           this.onBell();
           break;
@@ -334,10 +311,15 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
           }
           this.notifyListeners();
           break;
+        case 'exit':
+          _backendExited.complete(message[1]);
+          break;
       }
     });
-    _sendPort!.send(
-        ['init', TerminalInitData(this.platform, this.theme, this.maxLines)]);
+    _sendPort!.send([
+      'init',
+      TerminalInitData(this.backend, this.platform, this.theme, this.maxLines)
+    ]);
     await initialRefreshCompleted.future;
   }
 
@@ -427,7 +409,7 @@ class TerminalIsolate with Observable implements TerminalUiInteraction {
   }
 
   void raiseOnInput(String text) {
-    onInput(text);
+    _sendPort!.send(['onInput', text]);
   }
 
   void keyInput(

+ 1 - 0
lib/xterm.dart

@@ -1,5 +1,6 @@
 library xterm;
 
 export 'terminal/terminal_isolate.dart';
+export 'terminal/terminal_backend.dart';
 export 'terminal/terminal_ui_interaction.dart';
 export 'terminal/platform.dart';