Эх сурвалжийг харах

Add Termianl.onPrivateOSC callback

xuty 2 жил өмнө
parent
commit
fb9cc308f5

+ 1 - 1
lib/src/core/escape/handler.dart

@@ -211,5 +211,5 @@ abstract class EscapeHandler {
 
   void setIconName(String name);
 
-  void unknownOSC(String ps);
+  void unknownOSC(String code, List<String> args);
 }

+ 26 - 18
lib/src/core/escape/parser.dart

@@ -1044,32 +1044,40 @@ class EscapeParser {
     }
   }
 
+  /// Parse a OSC sequence from the queue. Returns true if a sequence was
+  /// found and handled.
   bool _escHandleOSC() {
     final consumed = _consumeOsc();
-    if (!consumed) return false;
+    if (!consumed) {
+      return false;
+    }
 
-    if (_osc.length < 2) {
+    if (_osc.isEmpty) {
       return true;
     }
 
-    final ps = _osc[0];
-    final pt = _osc[1];
-
-    switch (ps) {
-      case '0':
-        handler.setTitle(pt);
-        handler.setIconName(pt);
-        break;
-      case '1':
-        handler.setIconName(pt);
-        break;
-      case '2':
-        handler.setTitle(pt);
-        break;
-      default:
-        handler.unknownOSC(ps);
+    // Common OSCs
+    if (_osc.length >= 2) {
+      final ps = _osc[0];
+      final pt = _osc[1];
+
+      switch (ps) {
+        case '0':
+          handler.setTitle(pt);
+          handler.setIconName(pt);
+          return true;
+        case '1':
+          handler.setIconName(pt);
+          return true;
+        case '2':
+          handler.setTitle(pt);
+          return true;
+      }
     }
 
+    // Private extensions
+    handler.unknownOSC(_osc[0], _osc.sublist(1));
+
     return true;
   }
 

+ 7 - 2
lib/src/terminal.dart

@@ -59,6 +59,10 @@ class Terminal with Observable implements TerminalState, EscapeHandler {
 
   TerminalMouseHandler? mouseHandler;
 
+  /// The callback that is called when the terminal receives a unrecognized
+  /// escape sequence.
+  void Function(String code, List<String> args)? onPrivateOSC;
+
   /// Flag to toggle os specific behaviors.
   final TerminalTargetPlatform platform;
 
@@ -76,6 +80,7 @@ class Terminal with Observable implements TerminalState, EscapeHandler {
     this.platform = TerminalTargetPlatform.unknown,
     this.inputHandler = defaultInputHandler,
     this.mouseHandler = defaultMouseHandler,
+    this.onPrivateOSC,
     this.reflowEnabled = true,
     this.wordSeparators,
   });
@@ -895,7 +900,7 @@ class Terminal with Observable implements TerminalState, EscapeHandler {
   }
 
   @override
-  void unknownOSC(String ps) {
-    // no-op
+  void unknownOSC(String ps, List<String> pt) {
+    onPrivateOSC?.call(ps, pt);
   }
 }

+ 2 - 2
lib/src/utils/debugger.dart

@@ -589,7 +589,7 @@ class _TerminalDebuggerHandler implements EscapeHandler {
   }
 
   @override
-  void unknownOSC(String ps) {
-    onCommand('unknownOSC($ps)', error: true);
+  void unknownOSC(String code, List<String> args) {
+    onCommand('unknownOSC($code, $args)', error: true);
   }
 }

+ 2 - 2
test/src/core/escape/parser_test.mocks.dart

@@ -860,10 +860,10 @@ class MockEscapeHandler extends _i1.Mock implements _i2.EscapeHandler {
         returnValueForMissingStub: null,
       );
   @override
-  void unknownOSC(String? ps) => super.noSuchMethod(
+  void unknownOSC(String? code, List<String>? args) => super.noSuchMethod(
         Invocation.method(
           #unknownOSC,
-          [ps],
+          [code],
         ),
         returnValueForMissingStub: null,
       );

+ 83 - 0
test/src/terminal_test.dart

@@ -113,6 +113,89 @@ void main() {
       );
     });
   });
+
+  group('Terminal.onPrivateOSC', () {
+    test(r'works with \a end', () {
+      String? lastCode;
+      List<String>? lastData;
+
+      final terminal = Terminal(
+        onPrivateOSC: (String code, List<String> data) {
+          lastCode = code;
+          lastData = data;
+        },
+      );
+
+      terminal.write('\x1b]6\x07');
+
+      expect(lastCode, '6');
+      expect(lastData, []);
+
+      terminal.write('\x1b]66;hello world\x07');
+
+      expect(lastCode, '66');
+      expect(lastData, ['hello world']);
+
+      terminal.write('\x1b]666;hello;world\x07');
+
+      expect(lastCode, '666');
+      expect(lastData, ['hello', 'world']);
+
+      terminal.write('\x1b]hello;world\x07');
+
+      expect(lastCode, 'hello');
+      expect(lastData, ['world']);
+    });
+
+    test(r'works with \x1b\ end', () {
+      String? lastCode;
+      List<String>? lastData;
+
+      final terminal = Terminal(
+        onPrivateOSC: (String code, List<String> data) {
+          lastCode = code;
+          lastData = data;
+        },
+      );
+
+      terminal.write('\x1b]6\x1b\\');
+
+      expect(lastCode, '6');
+      expect(lastData, []);
+
+      terminal.write('\x1b]66;hello world\x1b\\');
+
+      expect(lastCode, '66');
+      expect(lastData, ['hello world']);
+
+      terminal.write('\x1b]666;hello;world\x1b\\');
+
+      expect(lastCode, '666');
+      expect(lastData, ['hello', 'world']);
+
+      terminal.write('\x1b]hello;world\x1b\\');
+
+      expect(lastCode, 'hello');
+      expect(lastData, ['world']);
+    });
+
+    test('do not receive common osc', () {
+      String? lastCode;
+      List<String>? lastData;
+
+      final terminal = Terminal(
+        onPrivateOSC: (String code, List<String> data) {
+          lastCode = code;
+          lastData = data;
+        },
+      );
+
+      terminal.write('\x1b]0;hello world\x07');
+
+      expect(lastCode, isNull);
+      expect(lastData, isNull);
+    });
+  });
 }
 
 class _TestInputHandler implements TerminalInputHandler {