Pārlūkot izejas kodu

feat: limited window manipulation support

Only setting the size of the terminal in characters
and reporting this size is supported.
Georg Wechslberger 3 gadi atpakaļ
vecāks
revīzija
355c761cdd

+ 4 - 0
lib/src/core/escape/emitter.dart

@@ -26,4 +26,8 @@ class EscapeEmitter {
   String bracketedPaste(String text) {
     return '\x1b[200~$text\x1b[201~';
   }
+
+  String size(int rows, int cols) {
+    return '\x1b[8;$rows;${cols}t';
+  }
 }

+ 4 - 0
lib/src/core/escape/handler.dart

@@ -147,6 +147,10 @@ abstract class EscapeHandler {
 
   void setUnknownDecMode(int mode, bool enabled);
 
+  void resize(int cols, int rows);
+
+  void sendSize();
+
   /* Select Graphic Rendition (SGR) */
 
   void resetCursorStyle();

+ 50 - 1
lib/src/core/escape/parser.dart

@@ -655,7 +655,56 @@ class EscapeParser {
   ///
   /// https://terminalguide.namepad.de/seq/csi_st/
   void _csiWindowManipulation() {
-    // Not supported.
+    // The sequence needs at least one parameter.
+    if (_csi.params.isEmpty) {
+      return;
+    }
+    // Most the commands in this group are either of the scope of this package,
+    // or should be disabled for security risks.
+    switch (_csi.params.first) {
+      // Window handling is currently not in the scope of the package.
+      case 1: // Restore Terminal Window (show window if minimized)
+      case 2: // Minimize Terminal Window
+      case 3: // Set Terminal Window Position
+      case 4: // Set Terminal Window Size in Pixels
+      case 5: // Raise Terminal Window
+      case 6: // Lower Terminal Window
+      case 7: // Refresh/Redraw Terminal Window
+        return;
+      case 8: // Set Terminal Window Size (in characters)
+        // This CSI contains 2 more parameters: width and height.
+        if (_csi.params.length != 3) {
+          return;
+        }
+        final rows = _csi.params[1];
+        final cols = _csi.params[2];
+        handler.resize(cols, rows);
+        return;
+      // Window handling is currently no in the scope of the package.
+      case 9: // Maximize Terminal Window
+      case 10: // Alias: Maximize Terminal Window
+      case 11: // Report Terminal Window State
+      case 13: // Report Terminal Window Position
+      case 14: // Report Terminal Window Size in Pixels
+      case 15: // Report Screen Size in Pixels
+      case 16: // Report Cell Size in Pixels
+        return;
+      case 18: // Report Terminal Size (in characters)
+        handler.sendSize();
+        return;
+      // Screen handling is currently no in the scope of the package.
+      case 19: // Report Screen Size (in characters)
+      // Disabled as these can a security risk.
+      case 20: // Get Icon Title
+      case 21: // Get Terminal Title
+      // Not implemented.
+      case 22: // Push Terminal Title
+      case 23: // Pop Terminal Title
+        return;
+      // Unknown CSI.
+      default:
+        return;
+    }
   }
 
   /// `ESC [ Ps A` Cursor Up (CUU)

+ 6 - 0
lib/src/terminal.dart

@@ -237,6 +237,7 @@ class Terminal with Observable implements TerminalState, EscapeHandler {
   /// Resize the terminal screen. [newWidth] and [newHeight] should be greater
   /// than 0. Text reflow is currently not implemented and will be avaliable in
   /// the future.
+  @override
   void resize(
     int newWidth,
     int newHeight, [
@@ -528,6 +529,11 @@ class Terminal with Observable implements TerminalState, EscapeHandler {
     _buffer.insertBlankChars(amount);
   }
 
+  @override
+  void sendSize() {
+    onOutput?.call(_emitter.size(viewHeight, viewWidth));
+  }
+
   @override
   void unknownCSI(int finalByte) {
     // no-op

+ 10 - 0
lib/src/utils/debugger.dart

@@ -330,6 +330,16 @@ class _TerminalDebuggerHandler implements EscapeHandler {
     onCommand('insertBlankChars($amount)');
   }
 
+  @override
+  void resize(int cols, int rows) {
+    onCommand('resize($cols, $rows)');
+  }
+
+  @override
+  void sendSize() {
+    onCommand('sendSize');
+  }
+
   /* Modes */
 
   @override