소스 검색

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
7개의 변경된 파일53개의 추가작업 그리고 61개의 파일을 삭제
  1. 0 5
      lib/frontend/terminal_view.dart
  2. 1 1
      lib/mouse/mouse_mode.dart
  3. 4 3
      lib/terminal/csi.dart
  4. 10 6
      lib/terminal/terminal.dart
  5. 9 0
      lib/terminal/terminal_backend.dart
  6. 28 46
      lib/terminal/terminal_isolate.dart
  7. 1 0
      lib/xterm.dart

+ 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';