Преглед изворни кода

Merge pull request #169 from nuc134r/master

Added support for Ctrl+Home, Ctrl+End etc
xuty пре 2 година
родитељ
комит
29bf33bb47

+ 3 - 0
CHANGELOG.md

@@ -1,6 +1,7 @@
 # [upcoming]
 * Support customizing word separators for selection [#160]. Thanks [@itzhoujun].
 * Fix incorrect tab stop handling [#161]. Thanks [@itzhoujun].
+* Added support for Ctrl+Home, Ctrl+End etc [#169]. Thanks [@nuc134r].
 
 ## [3.4.1] - 2023-01-27
 * Fix Flutter 3.7 incompatibilities [#151], thanks [@jpnurmi].
@@ -209,6 +210,7 @@
 [@LucasAschenbach]: https://github.com/LucasAschenbach
 [@tauu]: https://github.com/tauu
 [@itzhoujun]: https://github.com/itzhoujun
+[@nuc134r]: https://github.com/nuc134r
 
 
 [#40]: https://github.com/TerminalStudio/xterm.dart/pull/40
@@ -255,4 +257,5 @@
 
 [#160]: https://github.com/TerminalStudio/xterm.dart/pull/160
 [#161]: https://github.com/TerminalStudio/xterm.dart/pull/161
+[#169]: https://github.com/TerminalStudio/xterm.dart/pull/169
 

+ 38 - 8
lib/src/core/input/handler.dart

@@ -1,7 +1,7 @@
 import 'package:xterm/src/core/input/keys.dart';
 import 'package:xterm/src/core/input/keytab/keytab.dart';
-import 'package:xterm/src/utils/platform.dart';
 import 'package:xterm/src/core/state.dart';
+import 'package:xterm/src/utils/platform.dart';
 
 /// The key event received from the keyboard, along with the state of the
 /// modifier keys and state of the terminal. Typically consumed by the
@@ -99,16 +99,18 @@ const defaultInputHandler = CascadeInputHandler([
   AltInputHandler(),
 ]);
 
-final _keytab = Keytab.defaultKeytab();
-
 /// A [TerminalInputHandler] that translates key events according to a keytab
-/// file.
+/// file. If no keytab is provided, [Keytab.defaultKeytab] is used.
 class KeytabInputHandler implements TerminalInputHandler {
-  const KeytabInputHandler();
+  const KeytabInputHandler([this.keytab]);
+
+  final Keytab? keytab;
 
   @override
   String? call(TerminalKeyboardEvent event) {
-    final action = _keytab.find(
+    final keytab = this.keytab ?? Keytab.defaultKeytab;
+
+    final record = keytab.find(
       event.key,
       ctrl: event.ctrl,
       alt: event.alt,
@@ -120,11 +122,39 @@ class KeytabInputHandler implements TerminalInputHandler {
       macos: event.platform == TerminalTargetPlatform.macos,
     );
 
-    if (action == null) {
+    if (record == null) {
       return null;
     }
 
-    return action.action.unescapedValue();
+    var result = record.action.unescapedValue();
+    result = insertModifiers(event, result);
+    return result;
+  }
+
+  String insertModifiers(TerminalKeyboardEvent event, String action) {
+    String? code;
+
+    if (event.shift && event.alt && event.ctrl) {
+      code = '8';
+    } else if (event.ctrl && event.alt) {
+      code = '7';
+    } else if (event.shift && event.ctrl) {
+      code = '6';
+    } else if (event.ctrl) {
+      code = '5';
+    } else if (event.shift && event.alt) {
+      code = '4';
+    } else if (event.alt) {
+      code = '3';
+    } else if (event.shift) {
+      code = '2';
+    }
+
+    if (code != null) {
+      return action.replaceAll('*', code);
+    }
+
+    return action;
   }
 }
 

+ 6 - 3
lib/src/core/input/keytab/keytab.dart

@@ -16,9 +16,7 @@ class Keytab {
     return parser.result;
   }
 
-  factory Keytab.defaultKeytab() {
-    return Keytab.parse(kDefaultKeytab);
-  }
+  static final defaultKeytab = Keytab.parse(kDefaultKeytab);
 
   final String? name;
 
@@ -32,6 +30,7 @@ class Keytab {
     bool newLineMode = false,
     bool appCursorKeys = false,
     bool appKeyPad = false,
+    bool keyPad = false,
     bool appScreen = false,
     bool macos = false,
     // bool meta,
@@ -76,6 +75,10 @@ class Keytab {
         continue;
       }
 
+      if (record.keyPad != null && record.keyPad != keyPad) {
+        continue;
+      }
+
       if (record.appScreen != null && record.appScreen != appScreen) {
         continue;
       }

+ 26 - 2
test/src/core/input/handler_test.dart

@@ -1,6 +1,6 @@
 import 'package:test/test.dart';
-import 'package:xterm/src/core/input/keys.dart';
-import 'package:xterm/src/terminal.dart';
+import 'package:xterm/src/core/input/keytab/keytab.dart';
+import 'package:xterm/xterm.dart';
 
 void main() {
   group('defaultInputHandler', () {
@@ -11,4 +11,28 @@ void main() {
       expect(output, ['\r']);
     });
   });
+
+  group('KeytabInputHandler', () {
+    test('can insert modifier code', () {
+      final handler = KeytabInputHandler(
+        Keytab.parse(r'key Home +AnyMod : "\E[1;*H"'),
+      );
+
+      final terminal = Terminal(inputHandler: handler);
+
+      late String output;
+
+      terminal.onOutput = (data) {
+        output = data;
+      };
+
+      terminal.keyInput(TerminalKey.home, ctrl: true);
+
+      expect(output, '\x1b[1;5H');
+
+      terminal.keyInput(TerminalKey.home, shift: true);
+
+      expect(output, '\x1b[1;2H');
+    });
+  });
 }

+ 16 - 0
test/src/core/input/keytab/keytab_test.dart

@@ -0,0 +1,16 @@
+import 'package:test/test.dart';
+import 'package:xterm/src/core/input/keys.dart';
+import 'package:xterm/src/core/input/keytab/keytab.dart';
+
+void main() {
+  group('Keytab.find()', () {
+    test('can match keyPad', () {
+      final keytab = Keytab.parse(r'key Home +KeyPad : "TEST"');
+      final record = keytab.find(TerminalKey.home, keyPad: true);
+      expect(record!.action.unescapedValue(), 'TEST');
+
+      final record1 = keytab.find(TerminalKey.home);
+      expect(record1, isNull);
+    });
+  });
+}