From b730b803bb64d406bbf7d0623715f2234aeb98fb Mon Sep 17 00:00:00 2001 From: Jakub Jankiewicz Date: Sat, 18 Mar 2023 18:09:47 +0100 Subject: [PATCH] readline: add paste bracket mode The paste bracket mode allows REPL to have auto-indentation that is handled differently when the user copy-pastes the code from the clipboard and the code already has an indentation. PR-URL: https://github.com/nodejs/node/pull/47150 Fixes: https://github.com/nodejs/node/issues/45213 Reviewed-By: Ben Noordhuis Reviewed-By: Kohei Ueno --- lib/internal/readline/utils.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/internal/readline/utils.js b/lib/internal/readline/utils.js index a546516d76b66c..124a5382a0ddae 100644 --- a/lib/internal/readline/utils.js +++ b/lib/internal/readline/utils.js @@ -148,8 +148,10 @@ function* emitKeys(stream) { * * - `;5` part is optional, e.g. it could be `\x1b[24~` * - first part can contain one or two digits + * - there is also special case when there can be 3 digits + * but without modifier. They are the case of paste bracket mode * - * So the generic regexp is like /^\d\d?(;\d)?[~^$]$/ + * So the generic regexp is like /^(?:\d\d?(;\d)?[~^$]|\d{3}~)$/ * * * 2. `\x1b[1;5H` should be parsed as { code: '[H', modifier: 5 } @@ -170,6 +172,10 @@ function* emitKeys(stream) { if (ch >= '0' && ch <= '9') { s += (ch = yield); + + if (ch >= '0' && ch <= '9') { + s += (ch = yield); + } } } @@ -189,9 +195,13 @@ function* emitKeys(stream) { const cmd = StringPrototypeSlice(s, cmdStart); let match; - if ((match = RegExpPrototypeExec(/^(\d\d?)(;(\d))?([~^$])$/, cmd))) { - code += match[1] + match[4]; - modifier = (match[3] || 1) - 1; + if ((match = RegExpPrototypeExec(/^(?:(\d\d?)(?:;(\d))?([~^$])|(\d{3}~))$/, cmd))) { + if (match[4]) { + code += match[4]; + } else { + code += match[1] + match[3]; + modifier = (match[2] || 1) - 1; + } } else if ( (match = RegExpPrototypeExec(/^((\d;)?(\d))?([A-Za-z])$/, cmd)) ) { @@ -228,6 +238,10 @@ function* emitKeys(stream) { case '[13~': key.name = 'f3'; break; case '[14~': key.name = 'f4'; break; + /* paste bracket mode */ + case '[200~': key.name = 'paste-start'; break; + case '[201~': key.name = 'paste-end'; break; + /* from Cygwin and used in libuv */ case '[[A': key.name = 'f1'; break; case '[[B': key.name = 'f2'; break;