From 4f4faa8e3c4bae5a499e69fb177ec23ef3566f71 Mon Sep 17 00:00:00 2001 From: DrunkenPoney Date: Sat, 19 Sep 2020 05:33:49 -0400 Subject: [PATCH] readline: fix key name for function keys with modifiers Fixes: https://github.com/nodejs/node/issues/35251 PR-URL: https://github.com/nodejs/node/pull/35268 Reviewed-By: Anna Henningsen Reviewed-By: Joyee Cheung Reviewed-By: Rich Trott --- lib/internal/readline/utils.js | 11 ++++++++++- test/parallel/test-readline-keys.js | 24 +++++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/internal/readline/utils.js b/lib/internal/readline/utils.js index 0b9fe8cde4f5ce..d75b64dd46beac 100644 --- a/lib/internal/readline/utils.js +++ b/lib/internal/readline/utils.js @@ -199,7 +199,13 @@ function* emitKeys(stream) { // Parse the key itself switch (code) { - /* xterm/gnome ESC O letter */ + /* xterm/gnome ESC [ letter (with modifier) */ + case '[P': key.name = 'f1'; break; + case '[Q': key.name = 'f2'; break; + case '[R': key.name = 'f3'; break; + case '[S': key.name = 'f4'; break; + + /* xterm/gnome ESC O letter (without modifier) */ case 'OP': key.name = 'f1'; break; case 'OQ': key.name = 'f2'; break; case 'OR': key.name = 'f3'; break; @@ -296,12 +302,15 @@ function* emitKeys(stream) { } else if (ch === '\r') { // carriage return key.name = 'return'; + key.meta = escaped; } else if (ch === '\n') { // Enter, should have been called linefeed key.name = 'enter'; + key.meta = escaped; } else if (ch === '\t') { // tab key.name = 'tab'; + key.meta = escaped; } else if (ch === '\b' || ch === '\x7f') { // backspace or ctrl+h key.name = 'backspace'; diff --git a/test/parallel/test-readline-keys.js b/test/parallel/test-readline-keys.js index f0162ab06b8f38..bdc93c148edbfe 100644 --- a/test/parallel/test-readline-keys.js +++ b/test/parallel/test-readline-keys.js @@ -92,10 +92,13 @@ addTest('io.JS', [ ]); // Named characters -addTest('\n\r\t', [ +addTest('\n\r\t\x1b\n\x1b\r\x1b\t', [ { name: 'enter', sequence: '\n' }, { name: 'return', sequence: '\r' }, { name: 'tab', sequence: '\t' }, + { name: 'enter', sequence: '\x1b\n', meta: true }, + { name: 'return', sequence: '\x1b\r', meta: true }, + { name: 'tab', sequence: '\x1b\t', meta: true }, ]); // Space and backspace @@ -132,6 +135,25 @@ addTest('a\x1baA\x1bA', [ { name: 'a', sequence: '\x1bA', meta: true, shift: true }, ]); +// xterm/gnome ESC [ letter (with modifiers) +/* eslint-disable max-len */ +addTest('\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', [ + { name: 'f1', sequence: '\x1b[2P', code: '[P', shift: true, meta: false, ctrl: false }, + { name: 'f1', sequence: '\x1b[3P', code: '[P', shift: false, meta: true, ctrl: false }, + { name: 'f1', sequence: '\x1b[4P', code: '[P', shift: true, meta: true, ctrl: false }, + { name: 'f1', sequence: '\x1b[5P', code: '[P', shift: false, meta: false, ctrl: true }, + { name: 'f1', sequence: '\x1b[6P', code: '[P', shift: true, meta: false, ctrl: true }, + { name: 'f1', sequence: '\x1b[7P', code: '[P', shift: false, meta: true, ctrl: true }, + { name: 'f1', sequence: '\x1b[8P', code: '[P', shift: true, meta: true, ctrl: true }, + { name: 'f2', sequence: '\x1b[3Q', code: '[Q', meta: true }, + { name: 'f2', sequence: '\x1b[8Q', code: '[Q', shift: true, meta: true, ctrl: true }, + { name: 'f3', sequence: '\x1b[3R', code: '[R', meta: true }, + { name: 'f3', sequence: '\x1b[8R', code: '[R', shift: true, meta: true, ctrl: true }, + { name: 'f4', sequence: '\x1b[3S', code: '[S', meta: true }, + { name: 'f4', sequence: '\x1b[8S', code: '[S', shift: true, meta: true, ctrl: true }, +]); +/* eslint-enable max-len */ + // xterm/gnome ESC O letter addTest('\x1bOP\x1bOQ\x1bOR\x1bOS', [ { name: 'f1', sequence: '\x1bOP', code: 'OP' },