Skip to content

Commit

Permalink
readline: add paste bracket mode
Browse files Browse the repository at this point in the history
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: #47150
Fixes: #45213
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Kohei Ueno <kohei.ueno119@gmail.com>
  • Loading branch information
jcubic authored and targos committed Nov 26, 2023
1 parent 7ee26fb commit a625f22
Showing 1 changed file with 18 additions and 4 deletions.
22 changes: 18 additions & 4 deletions lib/internal/readline/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -170,6 +172,10 @@ function* emitKeys(stream) {

if (ch >= '0' && ch <= '9') {
s += (ch = yield);

if (ch >= '0' && ch <= '9') {
s += (ch = yield);
}
}
}

Expand All @@ -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))
) {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit a625f22

Please sign in to comment.