11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst PassThrough = require('stream').PassThrough;
41cb0ef41Sopenharmony_ciconst assert = require('assert');
51cb0ef41Sopenharmony_ciconst Interface = require('readline').Interface;
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciclass FakeInput extends PassThrough {}
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cifunction extend(k) {
101cb0ef41Sopenharmony_ci  return Object.assign({ ctrl: false, meta: false, shift: false }, k);
111cb0ef41Sopenharmony_ci}
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciconst fi = new FakeInput();
151cb0ef41Sopenharmony_ciconst fo = new FakeInput();
161cb0ef41Sopenharmony_cinew Interface({ input: fi, output: fo, terminal: true });
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cilet keys = [];
191cb0ef41Sopenharmony_cifi.on('keypress', (s, k) => {
201cb0ef41Sopenharmony_ci  keys.push(k);
211cb0ef41Sopenharmony_ci});
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cifunction addTest(sequences, expectedKeys) {
251cb0ef41Sopenharmony_ci  if (!Array.isArray(sequences)) {
261cb0ef41Sopenharmony_ci    sequences = [ sequences ];
271cb0ef41Sopenharmony_ci  }
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  if (!Array.isArray(expectedKeys)) {
301cb0ef41Sopenharmony_ci    expectedKeys = [ expectedKeys ];
311cb0ef41Sopenharmony_ci  }
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  expectedKeys = expectedKeys.map(extend);
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  keys = [];
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  sequences.forEach((sequence) => {
381cb0ef41Sopenharmony_ci    fi.write(sequence);
391cb0ef41Sopenharmony_ci  });
401cb0ef41Sopenharmony_ci  assert.deepStrictEqual(keys, expectedKeys);
411cb0ef41Sopenharmony_ci}
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci// Simulate key interval test cases
441cb0ef41Sopenharmony_ci// Returns a function that takes `next` test case and returns a thunk
451cb0ef41Sopenharmony_ci// that can be called to run tests in sequence
461cb0ef41Sopenharmony_ci// e.g.
471cb0ef41Sopenharmony_ci// addKeyIntervalTest(..)
481cb0ef41Sopenharmony_ci//   (addKeyIntervalTest(..)
491cb0ef41Sopenharmony_ci//      (addKeyIntervalTest(..)(noop)))()
501cb0ef41Sopenharmony_ci// where noop is a terminal function(() => {}).
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ciconst addKeyIntervalTest = (sequences, expectedKeys, interval = 550,
531cb0ef41Sopenharmony_ci                            assertDelay = 550) => {
541cb0ef41Sopenharmony_ci  const fn = common.mustCall((next) => () => {
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci    if (!Array.isArray(sequences)) {
571cb0ef41Sopenharmony_ci      sequences = [ sequences ];
581cb0ef41Sopenharmony_ci    }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci    if (!Array.isArray(expectedKeys)) {
611cb0ef41Sopenharmony_ci      expectedKeys = [ expectedKeys ];
621cb0ef41Sopenharmony_ci    }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci    expectedKeys = expectedKeys.map(extend);
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci    const keys = [];
671cb0ef41Sopenharmony_ci    fi.on('keypress', (s, k) => keys.push(k));
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci    const emitKeys = ([head, ...tail]) => {
701cb0ef41Sopenharmony_ci      if (head) {
711cb0ef41Sopenharmony_ci        fi.write(head);
721cb0ef41Sopenharmony_ci        setTimeout(() => emitKeys(tail), interval);
731cb0ef41Sopenharmony_ci      } else {
741cb0ef41Sopenharmony_ci        setTimeout(() => {
751cb0ef41Sopenharmony_ci          next();
761cb0ef41Sopenharmony_ci          assert.deepStrictEqual(keys, expectedKeys);
771cb0ef41Sopenharmony_ci        }, assertDelay);
781cb0ef41Sopenharmony_ci      }
791cb0ef41Sopenharmony_ci    };
801cb0ef41Sopenharmony_ci    emitKeys(sequences);
811cb0ef41Sopenharmony_ci  });
821cb0ef41Sopenharmony_ci  return fn;
831cb0ef41Sopenharmony_ci};
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci// Regular alphanumerics
861cb0ef41Sopenharmony_ciaddTest('io.JS', [
871cb0ef41Sopenharmony_ci  { name: 'i', sequence: 'i' },
881cb0ef41Sopenharmony_ci  { name: 'o', sequence: 'o' },
891cb0ef41Sopenharmony_ci  { name: undefined, sequence: '.' },
901cb0ef41Sopenharmony_ci  { name: 'j', sequence: 'J', shift: true },
911cb0ef41Sopenharmony_ci  { name: 's', sequence: 'S', shift: true },
921cb0ef41Sopenharmony_ci]);
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci// Named characters
951cb0ef41Sopenharmony_ciaddTest('\n\r\t\x1b\n\x1b\r\x1b\t', [
961cb0ef41Sopenharmony_ci  { name: 'enter', sequence: '\n' },
971cb0ef41Sopenharmony_ci  { name: 'return', sequence: '\r' },
981cb0ef41Sopenharmony_ci  { name: 'tab', sequence: '\t' },
991cb0ef41Sopenharmony_ci  { name: 'enter', sequence: '\x1b\n', meta: true },
1001cb0ef41Sopenharmony_ci  { name: 'return', sequence: '\x1b\r', meta: true },
1011cb0ef41Sopenharmony_ci  { name: 'tab', sequence: '\x1b\t', meta: true },
1021cb0ef41Sopenharmony_ci]);
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci// Space and backspace
1051cb0ef41Sopenharmony_ciaddTest('\b\x7f\x1b\b\x1b\x7f\x1b\x1b  \x1b ', [
1061cb0ef41Sopenharmony_ci  { name: 'backspace', sequence: '\b' },
1071cb0ef41Sopenharmony_ci  { name: 'backspace', sequence: '\x7f' },
1081cb0ef41Sopenharmony_ci  { name: 'backspace', sequence: '\x1b\b', meta: true },
1091cb0ef41Sopenharmony_ci  { name: 'backspace', sequence: '\x1b\x7f', meta: true },
1101cb0ef41Sopenharmony_ci  { name: 'space', sequence: '\x1b\x1b ', meta: true },
1111cb0ef41Sopenharmony_ci  { name: 'space', sequence: ' ' },
1121cb0ef41Sopenharmony_ci  { name: 'space', sequence: '\x1b ', meta: true },
1131cb0ef41Sopenharmony_ci]);
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci// Escape key
1161cb0ef41Sopenharmony_ciaddTest('\x1b\x1b\x1b', [
1171cb0ef41Sopenharmony_ci  { name: 'escape', sequence: '\x1b\x1b\x1b', meta: true },
1181cb0ef41Sopenharmony_ci]);
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci// Escape sequence
1211cb0ef41Sopenharmony_ciaddTest('\x1b]', [{ name: undefined, sequence: '\x1B]', meta: true }]);
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci// Control keys
1241cb0ef41Sopenharmony_ciaddTest('\x01\x0b\x10', [
1251cb0ef41Sopenharmony_ci  { name: 'a', sequence: '\x01', ctrl: true },
1261cb0ef41Sopenharmony_ci  { name: 'k', sequence: '\x0b', ctrl: true },
1271cb0ef41Sopenharmony_ci  { name: 'p', sequence: '\x10', ctrl: true },
1281cb0ef41Sopenharmony_ci]);
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci// Alt keys
1311cb0ef41Sopenharmony_ciaddTest('a\x1baA\x1bA', [
1321cb0ef41Sopenharmony_ci  { name: 'a', sequence: 'a' },
1331cb0ef41Sopenharmony_ci  { name: 'a', sequence: '\x1ba', meta: true },
1341cb0ef41Sopenharmony_ci  { name: 'a', sequence: 'A', shift: true },
1351cb0ef41Sopenharmony_ci  { name: 'a', sequence: '\x1bA', meta: true, shift: true },
1361cb0ef41Sopenharmony_ci]);
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci// xterm/gnome ESC [ letter (with modifiers)
1391cb0ef41Sopenharmony_ciaddTest('\x1b[2P\x1b[3P\x1b[4P\x1b[5P\x1b[6P\x1b[7P\x1b[8P\x1b[3Q\x1b[8Q\x1b[3R\x1b[8R\x1b[3S\x1b[8S', [
1401cb0ef41Sopenharmony_ci  { name: 'f1', sequence: '\x1b[2P', code: '[P', shift: true, meta: false, ctrl: false },
1411cb0ef41Sopenharmony_ci  { name: 'f1', sequence: '\x1b[3P', code: '[P', shift: false, meta: true, ctrl: false },
1421cb0ef41Sopenharmony_ci  { name: 'f1', sequence: '\x1b[4P', code: '[P', shift: true, meta: true, ctrl: false },
1431cb0ef41Sopenharmony_ci  { name: 'f1', sequence: '\x1b[5P', code: '[P', shift: false, meta: false, ctrl: true },
1441cb0ef41Sopenharmony_ci  { name: 'f1', sequence: '\x1b[6P', code: '[P', shift: true, meta: false, ctrl: true },
1451cb0ef41Sopenharmony_ci  { name: 'f1', sequence: '\x1b[7P', code: '[P', shift: false, meta: true, ctrl: true },
1461cb0ef41Sopenharmony_ci  { name: 'f1', sequence: '\x1b[8P', code: '[P', shift: true, meta: true, ctrl: true },
1471cb0ef41Sopenharmony_ci  { name: 'f2', sequence: '\x1b[3Q', code: '[Q', meta: true },
1481cb0ef41Sopenharmony_ci  { name: 'f2', sequence: '\x1b[8Q', code: '[Q', shift: true, meta: true, ctrl: true },
1491cb0ef41Sopenharmony_ci  { name: 'f3', sequence: '\x1b[3R', code: '[R', meta: true },
1501cb0ef41Sopenharmony_ci  { name: 'f3', sequence: '\x1b[8R', code: '[R', shift: true, meta: true, ctrl: true },
1511cb0ef41Sopenharmony_ci  { name: 'f4', sequence: '\x1b[3S', code: '[S', meta: true },
1521cb0ef41Sopenharmony_ci  { name: 'f4', sequence: '\x1b[8S', code: '[S', shift: true, meta: true, ctrl: true },
1531cb0ef41Sopenharmony_ci]);
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci// xterm/gnome ESC O letter
1561cb0ef41Sopenharmony_ciaddTest('\x1bOP\x1bOQ\x1bOR\x1bOS', [
1571cb0ef41Sopenharmony_ci  { name: 'f1', sequence: '\x1bOP', code: 'OP' },
1581cb0ef41Sopenharmony_ci  { name: 'f2', sequence: '\x1bOQ', code: 'OQ' },
1591cb0ef41Sopenharmony_ci  { name: 'f3', sequence: '\x1bOR', code: 'OR' },
1601cb0ef41Sopenharmony_ci  { name: 'f4', sequence: '\x1bOS', code: 'OS' },
1611cb0ef41Sopenharmony_ci]);
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci// xterm/rxvt ESC [ number ~ */
1641cb0ef41Sopenharmony_ciaddTest('\x1b[11~\x1b[12~\x1b[13~\x1b[14~', [
1651cb0ef41Sopenharmony_ci  { name: 'f1', sequence: '\x1b[11~', code: '[11~' },
1661cb0ef41Sopenharmony_ci  { name: 'f2', sequence: '\x1b[12~', code: '[12~' },
1671cb0ef41Sopenharmony_ci  { name: 'f3', sequence: '\x1b[13~', code: '[13~' },
1681cb0ef41Sopenharmony_ci  { name: 'f4', sequence: '\x1b[14~', code: '[14~' },
1691cb0ef41Sopenharmony_ci]);
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci// From Cygwin and used in libuv
1721cb0ef41Sopenharmony_ciaddTest('\x1b[[A\x1b[[B\x1b[[C\x1b[[D\x1b[[E', [
1731cb0ef41Sopenharmony_ci  { name: 'f1', sequence: '\x1b[[A', code: '[[A' },
1741cb0ef41Sopenharmony_ci  { name: 'f2', sequence: '\x1b[[B', code: '[[B' },
1751cb0ef41Sopenharmony_ci  { name: 'f3', sequence: '\x1b[[C', code: '[[C' },
1761cb0ef41Sopenharmony_ci  { name: 'f4', sequence: '\x1b[[D', code: '[[D' },
1771cb0ef41Sopenharmony_ci  { name: 'f5', sequence: '\x1b[[E', code: '[[E' },
1781cb0ef41Sopenharmony_ci]);
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci// Common
1811cb0ef41Sopenharmony_ciaddTest('\x1b[15~\x1b[17~\x1b[18~\x1b[19~\x1b[20~\x1b[21~\x1b[23~\x1b[24~', [
1821cb0ef41Sopenharmony_ci  { name: 'f5', sequence: '\x1b[15~', code: '[15~' },
1831cb0ef41Sopenharmony_ci  { name: 'f6', sequence: '\x1b[17~', code: '[17~' },
1841cb0ef41Sopenharmony_ci  { name: 'f7', sequence: '\x1b[18~', code: '[18~' },
1851cb0ef41Sopenharmony_ci  { name: 'f8', sequence: '\x1b[19~', code: '[19~' },
1861cb0ef41Sopenharmony_ci  { name: 'f9', sequence: '\x1b[20~', code: '[20~' },
1871cb0ef41Sopenharmony_ci  { name: 'f10', sequence: '\x1b[21~', code: '[21~' },
1881cb0ef41Sopenharmony_ci  { name: 'f11', sequence: '\x1b[23~', code: '[23~' },
1891cb0ef41Sopenharmony_ci  { name: 'f12', sequence: '\x1b[24~', code: '[24~' },
1901cb0ef41Sopenharmony_ci]);
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci// xterm ESC [ letter
1931cb0ef41Sopenharmony_ciaddTest('\x1b[A\x1b[B\x1b[C\x1b[D\x1b[E\x1b[F\x1b[H', [
1941cb0ef41Sopenharmony_ci  { name: 'up', sequence: '\x1b[A', code: '[A' },
1951cb0ef41Sopenharmony_ci  { name: 'down', sequence: '\x1b[B', code: '[B' },
1961cb0ef41Sopenharmony_ci  { name: 'right', sequence: '\x1b[C', code: '[C' },
1971cb0ef41Sopenharmony_ci  { name: 'left', sequence: '\x1b[D', code: '[D' },
1981cb0ef41Sopenharmony_ci  { name: 'clear', sequence: '\x1b[E', code: '[E' },
1991cb0ef41Sopenharmony_ci  { name: 'end', sequence: '\x1b[F', code: '[F' },
2001cb0ef41Sopenharmony_ci  { name: 'home', sequence: '\x1b[H', code: '[H' },
2011cb0ef41Sopenharmony_ci]);
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci// xterm/gnome ESC O letter
2041cb0ef41Sopenharmony_ciaddTest('\x1bOA\x1bOB\x1bOC\x1bOD\x1bOE\x1bOF\x1bOH', [
2051cb0ef41Sopenharmony_ci  { name: 'up', sequence: '\x1bOA', code: 'OA' },
2061cb0ef41Sopenharmony_ci  { name: 'down', sequence: '\x1bOB', code: 'OB' },
2071cb0ef41Sopenharmony_ci  { name: 'right', sequence: '\x1bOC', code: 'OC' },
2081cb0ef41Sopenharmony_ci  { name: 'left', sequence: '\x1bOD', code: 'OD' },
2091cb0ef41Sopenharmony_ci  { name: 'clear', sequence: '\x1bOE', code: 'OE' },
2101cb0ef41Sopenharmony_ci  { name: 'end', sequence: '\x1bOF', code: 'OF' },
2111cb0ef41Sopenharmony_ci  { name: 'home', sequence: '\x1bOH', code: 'OH' },
2121cb0ef41Sopenharmony_ci]);
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci// Old xterm shift-arrows
2151cb0ef41Sopenharmony_ciaddTest('\x1bO2A\x1bO2B', [
2161cb0ef41Sopenharmony_ci  { name: 'up', sequence: '\x1bO2A', code: 'OA', shift: true },
2171cb0ef41Sopenharmony_ci  { name: 'down', sequence: '\x1bO2B', code: 'OB', shift: true },
2181cb0ef41Sopenharmony_ci]);
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci// xterm/rxvt ESC [ number ~
2211cb0ef41Sopenharmony_ciaddTest('\x1b[1~\x1b[2~\x1b[3~\x1b[4~\x1b[5~\x1b[6~', [
2221cb0ef41Sopenharmony_ci  { name: 'home', sequence: '\x1b[1~', code: '[1~' },
2231cb0ef41Sopenharmony_ci  { name: 'insert', sequence: '\x1b[2~', code: '[2~' },
2241cb0ef41Sopenharmony_ci  { name: 'delete', sequence: '\x1b[3~', code: '[3~' },
2251cb0ef41Sopenharmony_ci  { name: 'end', sequence: '\x1b[4~', code: '[4~' },
2261cb0ef41Sopenharmony_ci  { name: 'pageup', sequence: '\x1b[5~', code: '[5~' },
2271cb0ef41Sopenharmony_ci  { name: 'pagedown', sequence: '\x1b[6~', code: '[6~' },
2281cb0ef41Sopenharmony_ci]);
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci// putty
2311cb0ef41Sopenharmony_ciaddTest('\x1b[[5~\x1b[[6~', [
2321cb0ef41Sopenharmony_ci  { name: 'pageup', sequence: '\x1b[[5~', code: '[[5~' },
2331cb0ef41Sopenharmony_ci  { name: 'pagedown', sequence: '\x1b[[6~', code: '[[6~' },
2341cb0ef41Sopenharmony_ci]);
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci// rxvt
2371cb0ef41Sopenharmony_ciaddTest('\x1b[7~\x1b[8~', [
2381cb0ef41Sopenharmony_ci  { name: 'home', sequence: '\x1b[7~', code: '[7~' },
2391cb0ef41Sopenharmony_ci  { name: 'end', sequence: '\x1b[8~', code: '[8~' },
2401cb0ef41Sopenharmony_ci]);
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci// gnome terminal
2431cb0ef41Sopenharmony_ciaddTest('\x1b[A\x1b[B\x1b[2A\x1b[2B', [
2441cb0ef41Sopenharmony_ci  { name: 'up', sequence: '\x1b[A', code: '[A' },
2451cb0ef41Sopenharmony_ci  { name: 'down', sequence: '\x1b[B', code: '[B' },
2461cb0ef41Sopenharmony_ci  { name: 'up', sequence: '\x1b[2A', code: '[A', shift: true },
2471cb0ef41Sopenharmony_ci  { name: 'down', sequence: '\x1b[2B', code: '[B', shift: true },
2481cb0ef41Sopenharmony_ci]);
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci// `rxvt` keys with modifiers.
2511cb0ef41Sopenharmony_ciaddTest('\x1b[20~\x1b[2$\x1b[2^\x1b[3$\x1b[3^\x1b[5$\x1b[5^\x1b[6$\x1b[6^\x1b[7$\x1b[7^\x1b[8$\x1b[8^', [
2521cb0ef41Sopenharmony_ci  { name: 'f9', sequence: '\x1b[20~', code: '[20~' },
2531cb0ef41Sopenharmony_ci  { name: 'insert', sequence: '\x1b[2$', code: '[2$', shift: true },
2541cb0ef41Sopenharmony_ci  { name: 'insert', sequence: '\x1b[2^', code: '[2^', ctrl: true },
2551cb0ef41Sopenharmony_ci  { name: 'delete', sequence: '\x1b[3$', code: '[3$', shift: true },
2561cb0ef41Sopenharmony_ci  { name: 'delete', sequence: '\x1b[3^', code: '[3^', ctrl: true },
2571cb0ef41Sopenharmony_ci  { name: 'pageup', sequence: '\x1b[5$', code: '[5$', shift: true },
2581cb0ef41Sopenharmony_ci  { name: 'pageup', sequence: '\x1b[5^', code: '[5^', ctrl: true },
2591cb0ef41Sopenharmony_ci  { name: 'pagedown', sequence: '\x1b[6$', code: '[6$', shift: true },
2601cb0ef41Sopenharmony_ci  { name: 'pagedown', sequence: '\x1b[6^', code: '[6^', ctrl: true },
2611cb0ef41Sopenharmony_ci  { name: 'home', sequence: '\x1b[7$', code: '[7$', shift: true },
2621cb0ef41Sopenharmony_ci  { name: 'home', sequence: '\x1b[7^', code: '[7^', ctrl: true },
2631cb0ef41Sopenharmony_ci  { name: 'end', sequence: '\x1b[8$', code: '[8$', shift: true },
2641cb0ef41Sopenharmony_ci  { name: 'end', sequence: '\x1b[8^', code: '[8^', ctrl: true },
2651cb0ef41Sopenharmony_ci]);
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci// Misc
2681cb0ef41Sopenharmony_ciaddTest('\x1b[Z', [
2691cb0ef41Sopenharmony_ci  { name: 'tab', sequence: '\x1b[Z', code: '[Z', shift: true },
2701cb0ef41Sopenharmony_ci]);
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci// xterm + modifiers
2731cb0ef41Sopenharmony_ciaddTest('\x1b[20;5~\x1b[6;5^', [
2741cb0ef41Sopenharmony_ci  { name: 'f9', sequence: '\x1b[20;5~', code: '[20~', ctrl: true },
2751cb0ef41Sopenharmony_ci  { name: 'pagedown', sequence: '\x1b[6;5^', code: '[6^', ctrl: true },
2761cb0ef41Sopenharmony_ci]);
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ciaddTest('\x1b[H\x1b[5H\x1b[1;5H', [
2791cb0ef41Sopenharmony_ci  { name: 'home', sequence: '\x1b[H', code: '[H' },
2801cb0ef41Sopenharmony_ci  { name: 'home', sequence: '\x1b[5H', code: '[H', ctrl: true },
2811cb0ef41Sopenharmony_ci  { name: 'home', sequence: '\x1b[1;5H', code: '[H', ctrl: true },
2821cb0ef41Sopenharmony_ci]);
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci// Escape sequences broken into multiple data chunks
2851cb0ef41Sopenharmony_ciaddTest('\x1b[D\x1b[C\x1b[D\x1b[C'.split(''), [
2861cb0ef41Sopenharmony_ci  { name: 'left', sequence: '\x1b[D', code: '[D' },
2871cb0ef41Sopenharmony_ci  { name: 'right', sequence: '\x1b[C', code: '[C' },
2881cb0ef41Sopenharmony_ci  { name: 'left', sequence: '\x1b[D', code: '[D' },
2891cb0ef41Sopenharmony_ci  { name: 'right', sequence: '\x1b[C', code: '[C' },
2901cb0ef41Sopenharmony_ci]);
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci// Escape sequences mixed with regular ones
2931cb0ef41Sopenharmony_ciaddTest('\x1b[DD\x1b[2DD\x1b[2^D', [
2941cb0ef41Sopenharmony_ci  { name: 'left', sequence: '\x1b[D', code: '[D' },
2951cb0ef41Sopenharmony_ci  { name: 'd', sequence: 'D', shift: true },
2961cb0ef41Sopenharmony_ci  { name: 'left', sequence: '\x1b[2D', code: '[D', shift: true },
2971cb0ef41Sopenharmony_ci  { name: 'd', sequence: 'D', shift: true },
2981cb0ef41Sopenharmony_ci  { name: 'insert', sequence: '\x1b[2^', code: '[2^', ctrl: true },
2991cb0ef41Sopenharmony_ci  { name: 'd', sequence: 'D', shift: true },
3001cb0ef41Sopenharmony_ci]);
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci// Color sequences
3031cb0ef41Sopenharmony_ciaddTest('\x1b[31ma\x1b[39ma', [
3041cb0ef41Sopenharmony_ci  { name: 'undefined', sequence: '\x1b[31m', code: '[31m' },
3051cb0ef41Sopenharmony_ci  { name: 'a', sequence: 'a' },
3061cb0ef41Sopenharmony_ci  { name: 'undefined', sequence: '\x1b[39m', code: '[39m' },
3071cb0ef41Sopenharmony_ci  { name: 'a', sequence: 'a' },
3081cb0ef41Sopenharmony_ci]);
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci// `rxvt` keys with modifiers.
3111cb0ef41Sopenharmony_ciaddTest('\x1b[a\x1b[b\x1b[c\x1b[d\x1b[e', [
3121cb0ef41Sopenharmony_ci  { name: 'up', sequence: '\x1b[a', code: '[a', shift: true },
3131cb0ef41Sopenharmony_ci  { name: 'down', sequence: '\x1b[b', code: '[b', shift: true },
3141cb0ef41Sopenharmony_ci  { name: 'right', sequence: '\x1b[c', code: '[c', shift: true },
3151cb0ef41Sopenharmony_ci  { name: 'left', sequence: '\x1b[d', code: '[d', shift: true },
3161cb0ef41Sopenharmony_ci  { name: 'clear', sequence: '\x1b[e', code: '[e', shift: true },
3171cb0ef41Sopenharmony_ci]);
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ciaddTest('\x1bOa\x1bOb\x1bOc\x1bOd\x1bOe', [
3201cb0ef41Sopenharmony_ci  { name: 'up', sequence: '\x1bOa', code: 'Oa', ctrl: true },
3211cb0ef41Sopenharmony_ci  { name: 'down', sequence: '\x1bOb', code: 'Ob', ctrl: true },
3221cb0ef41Sopenharmony_ci  { name: 'right', sequence: '\x1bOc', code: 'Oc', ctrl: true },
3231cb0ef41Sopenharmony_ci  { name: 'left', sequence: '\x1bOd', code: 'Od', ctrl: true },
3241cb0ef41Sopenharmony_ci  { name: 'clear', sequence: '\x1bOe', code: 'Oe', ctrl: true },
3251cb0ef41Sopenharmony_ci]);
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci// Reduce array of addKeyIntervalTest(..) right to left
3281cb0ef41Sopenharmony_ci// with () => {} as initial function.
3291cb0ef41Sopenharmony_ciconst runKeyIntervalTests = [
3301cb0ef41Sopenharmony_ci  // Escape character
3311cb0ef41Sopenharmony_ci  addKeyIntervalTest('\x1b', [
3321cb0ef41Sopenharmony_ci    { name: 'escape', sequence: '\x1b', meta: true },
3331cb0ef41Sopenharmony_ci  ]),
3341cb0ef41Sopenharmony_ci  // Chain of escape characters.
3351cb0ef41Sopenharmony_ci  addKeyIntervalTest('\x1b\x1b\x1b\x1b'.split(''), [
3361cb0ef41Sopenharmony_ci    { name: 'escape', sequence: '\x1b', meta: true },
3371cb0ef41Sopenharmony_ci    { name: 'escape', sequence: '\x1b', meta: true },
3381cb0ef41Sopenharmony_ci    { name: 'escape', sequence: '\x1b', meta: true },
3391cb0ef41Sopenharmony_ci    { name: 'escape', sequence: '\x1b', meta: true },
3401cb0ef41Sopenharmony_ci  ]),
3411cb0ef41Sopenharmony_ci].reverse().reduce((acc, fn) => fn(acc), () => {});
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci// Run key interval tests one after another.
3441cb0ef41Sopenharmony_cirunKeyIntervalTests();
345