Re: nano appends a tilde when pasting five characters over ssh
Benno Schulenberg <[email protected]>
| Newsgroups | gmane.editors.nano.devel |
|---|---|
| Message-ID | <[email protected]> |
Op 24-02-2025 om 07:00 schreef Doug Smythies:
> I have been having an issue where nano will freeze after a paste of some characters.
> The only way out was to close the terminal and start again. [...]
> is sort of fixed with
> commit 4a915b1ed581967350591c67965374f90e673030
> input: avoid hanging after a 39-character paste on a VSCode terminal
> As mentioned in the commit, there is an undesired ~ character
> pasted where previously the session would have frozen.
Finally, the issue was mostly fixed by commit bf12c90b:
https://git.savannah.gnu.org/cgit/nano.git/commit/?id=bf12c90b
(The patch is also attached.)
Benno
0001-input-implement-bracketed-pastes-in-a-different-mann.patch
(text/x-patch, 9.4 KB)
From bf12c90b076a424d2a399c543de24dac906f0a21 Mon Sep 17 00:00:00 2001 From: Benno Schulenberg <[email protected]> Date: Sun, 9 Mar 2025 12:04:41 +0100 Subject: [PATCH] input: implement bracketed pastes in a different manner Ask ncurses to recognize the escape sequences that mark the start and end of a bracketed paste, and thus benefit from the waiting that ncurses does for an escape sequence to complete. This helps prevent nano from failing to recognize an end-of-paste sequence (resulting in hanging or inserting some sequence characters into the buffer). This addresses https://savannah.gnu.org/bugs/?66858 in a better way. Reported-by: Doug Smythies <[email protected]> --- src/browser.c | 10 +++++----- src/definitions.h | 7 ++++--- src/global.c | 12 +++--------- src/help.c | 8 ++++---- src/nano.c | 17 ++++++++--------- src/prompt.c | 18 +++++++++++++++--- src/prototypes.h | 2 +- src/winio.c | 3 +-- 8 files changed, 41 insertions(+), 36 deletions(-) diff --git a/src/browser.c b/src/browser.c index 56aa0410..3b2ddb45 100644 --- a/src/browser.c +++ b/src/browser.c @@ -483,11 +483,7 @@ char *browse(char *path) continue; } #endif /* ENABLE_MOUSE */ -#ifndef NANO_TINY - while (bracketed_paste && kbinput != FOREIGN_SEQUENCE) - kbinput = get_kbinput(midwin, BLIND); - bracketed_paste = FALSE; -#endif + function = interpret(kbinput); if (function == do_help || function == full_refresh) { @@ -638,6 +634,10 @@ char *browse(char *path) implant(first_sc_for(MBROWSER, function)->expansion); #endif #ifndef NANO_TINY + } else if (kbinput == START_OF_PASTE) { + while (get_kbinput(midwin, BLIND) != END_OF_PASTE) + ; + statusline(AHEM, _("Paste is ignored")); } else if (kbinput == THE_WINDOW_RESIZED) { ; /* Gets handled below. */ #endif diff --git a/src/definitions.h b/src/definitions.h index 97d5e203..c27a8a2c 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -217,6 +217,10 @@ #define FOCUS_IN 0x491 #define FOCUS_OUT 0x499 +/* Custom keycodes for signaling the start and end of a bracketed paste. */ +#define START_OF_PASTE 0x4B5 +#define END_OF_PASTE 0x4BE + /* Special keycodes for when a string bind has been partially implanted * or has an unpaired opening brace, or when a function in a string bind * needs execution or a specified function name is invalid. */ @@ -233,9 +237,6 @@ #define THE_WINDOW_RESIZED 0x4F7 #endif -/* A special keycode to signal the beginning and end of a bracketed paste. */ -#define BRACKETED_PASTE_MARKER 0x4FB - /* A special keycode for when a key produces an unknown escape sequence. */ #define FOREIGN_SEQUENCE 0x4FC diff --git a/src/global.c b/src/global.c index 1e133ea4..5f2a9c9f 100644 --- a/src/global.c +++ b/src/global.c @@ -43,8 +43,6 @@ bool shift_held; /* Whether Shift was being held together with a movement key. */ bool mute_modifiers = FALSE; /* Whether to ignore modifier keys while running a macro or string bind. */ -bool bracketed_paste = FALSE; - /* Whether text is being pasted into nano from outside. */ bool we_are_running = FALSE; /* Becomes TRUE as soon as all options and files have been read. */ @@ -480,11 +478,6 @@ const keystruct *get_shortcut(const int keycode) if (meta_key && keycode < 0x20) return NULL; -#ifndef NANO_TINY - /* During a paste at a prompt, ignore all command keycodes. */ - if (bracketed_paste && keycode != BRACKETED_PASTE_MARKER) - return NULL; -#endif #ifdef ENABLE_NANORC if (keycode == PLANTED_A_COMMAND) return planted_shortcut; @@ -1583,8 +1576,9 @@ void shortcut_init(void) add_to_sclist((MMOST & ~MMAIN) | MYESNO, "", KEY_CANCEL, do_cancel, 0); add_to_sclist(MMAIN, "", KEY_CENTER, do_center, 0); add_to_sclist(MMAIN, "", KEY_SIC, do_insertfile, 0); - /* Catch and ignore bracketed paste marker keys. */ - add_to_sclist(MMOST|MBROWSER|MHELP|MYESNO, "", BRACKETED_PASTE_MARKER, do_nothing, 0); + add_to_sclist(MMAIN, "", START_OF_PASTE, suck_up_input_and_paste_it, 0); + add_to_sclist(MMOST, "", START_OF_PASTE, do_nothing, 0); + add_to_sclist(MMOST, "", END_OF_PASTE, do_nothing, 0); #else add_to_sclist(MMOST|MBROWSER|MHELP|MYESNO, "", KEY_FRESH, full_refresh, 0); #endif diff --git a/src/help.c b/src/help.c index 65958e53..2888807e 100644 --- a/src/help.c +++ b/src/help.c @@ -476,10 +476,6 @@ void show_help(void) #ifndef NANO_TINY spotlighted = FALSE; - - while (bracketed_paste && kbinput != FOREIGN_SEQUENCE) - kbinput = get_kbinput(midwin, BLIND); - bracketed_paste = FALSE; #endif function = interpret(kbinput); @@ -508,6 +504,10 @@ void show_help(void) get_mouseinput(&dummy_row, &dummy_col, TRUE); #endif #ifndef NANO_TINY + } else if (kbinput == START_OF_PASTE) { + while (get_kbinput(midwin, BLIND) != END_OF_PASTE) + ; + statusline(AHEM, _("Paste is ignored")); } else if (kbinput == THE_WINDOW_RESIZED) { ; /* Nothing to do. */ #endif diff --git a/src/nano.c b/src/nano.c index 58bdc2d1..7bd06326 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1307,8 +1307,6 @@ void unbound_key(int code) statusline(AHEM, _("Missing }")); #endif #ifndef NANO_TINY - else if (code == BRACKETED_PASTE_MARKER) - statusline(AHEM, _("Paste is ignored")); else if (code > KEY_F0 && code < KEY_F0 + 25) /* TRANSLATORS: This refers to an unbound function key. */ statusline(AHEM, _("Unbound key: F%i"), code - KEY_F0); @@ -1446,7 +1444,7 @@ void suck_up_input_and_paste_it(void) line->data = copy_of(""); cutbuffer = line; - while (bracketed_paste) { + while (TRUE) { input = get_kbinput(midwin, BLIND); if ((0x20 <= input && input <= 0xFF && input != DEL_CODE) || input == '\t') { @@ -1458,8 +1456,8 @@ void suck_up_input_and_paste_it(void) line = line->next; line->data = copy_of(""); index = 0; - } else if (input != BRACKETED_PASTE_MARKER) - bracketed_paste = FALSE; + } else + break; } if (ISSET(VIEW_MODE)) @@ -1467,7 +1465,7 @@ void suck_up_input_and_paste_it(void) else paste_text(); - if (input == FOREIGN_SEQUENCE) + if (input != END_OF_PASTE) statusline(ALERT, _("Flawed paste")); free_lines(cutbuffer); @@ -1725,9 +1723,6 @@ void process_a_keystroke(void) } else if (openfile->current != was_current) also_the_last = FALSE; - if (bracketed_paste) - suck_up_input_and_paste_it(); - if (ISSET(STATEFLAGS) && openfile->mark != was_mark) titlebar(NULL); #endif @@ -2483,6 +2478,10 @@ int main(int argc, char **argv) shiftaltright = get_keycode("kRIT4", SHIFT_ALT_RIGHT); shiftaltup = get_keycode("kUP4", SHIFT_ALT_UP); shiftaltdown = get_keycode("kDN4", SHIFT_ALT_DOWN); + + /* Tell ncurses to transform bracketed-paste sequences into keycodes. */ + define_key("\e[200~", START_OF_PASTE); + define_key("\e[201~", END_OF_PASTE); #endif mousefocusin = get_keycode("kxIN", FOCUS_IN); mousefocusout = get_keycode("kxOUT", FOCUS_OUT); diff --git a/src/prompt.c b/src/prompt.c index e47f24ab..d5d7a043 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -426,6 +426,9 @@ functionptrtype acquire_an_answer(int *actual, bool *listed, size_t fragment_length = 0; /* The length of the fragment that the user tries to tab complete. */ #endif +#endif +#ifndef NANO_TINY + bool bracketed_paste = FALSE; #endif const keystruct *shortcut; functionptrtype function; @@ -450,6 +453,8 @@ functionptrtype acquire_an_answer(int *actual, bool *listed, #endif return NULL; } + if (input == START_OF_PASTE || input == END_OF_PASTE) + bracketed_paste = (input == START_OF_PASTE); #endif #ifdef ENABLE_MOUSE /* For a click on a shortcut, read in the resulting keycode. */ @@ -466,6 +471,12 @@ functionptrtype acquire_an_answer(int *actual, bool *listed, /* When it's a normal character, add it to the answer. */ absorb_character(input, function); +#ifndef NANO_TINY + /* Ignore any commands inside an external paste. */ + if (bracketed_paste) + continue; +#endif + if (function == do_cancel || function == do_enter) break; @@ -711,10 +722,11 @@ int ask_user(bool withall, const char *question) continue; /* Accept first character of an external paste and ignore the rest. */ - if (bracketed_paste) + if (kbinput == START_OF_PASTE) { kbinput = get_kbinput(footwin, BLIND); - while (bracketed_paste) - get_kbinput(footwin, BLIND); + while (get_kbinput(footwin, BLIND) != END_OF_PASTE) + ; + } #endif #ifdef ENABLE_NLS diff --git a/src/prototypes.h b/src/prototypes.h index f857365e..ceca2c23 100644 --- a/src/prototypes.h +++ b/src/prototypes.h @@ -32,7 +32,6 @@ extern bool shifted_metas; extern bool meta_key; extern bool shift_held; extern bool mute_modifiers; -extern bool bracketed_paste; extern bool we_are_running; extern bool more_than_one; @@ -441,6 +440,7 @@ void confirm_margin(void); #endif void unbound_key(int code); bool changes_something(functionptrtype f); +void suck_up_input_and_paste_it(void); void inject(char *burst, size_t count); /* Most functions in prompt.c. */ diff --git a/src/winio.c b/src/winio.c index 1095c292..bb56e771 100644 --- a/src/winio.c +++ b/src/winio.c @@ -728,8 +728,7 @@ int convert_CSI_sequence(const int *seq, size_t length, int *consumed) /* Esc [ 2 0 0 ~ == start of a bracketed paste, * Esc [ 2 0 1 ~ == end of a bracketed paste. */ *consumed = 4; - bracketed_paste = (seq[2] == '0'); - return BRACKETED_PASTE_MARKER; + return (seq[2] == '0') ? START_OF_PASTE : END_OF_PASTE; } else { *consumed = length; return FOREIGN_SEQUENCE; -- 2.48.1
OpenPGP_signature.asc
(application/pgp-signature, 840 B)
-----BEGIN PGP SIGNATURE----- wsF5BAABCAAjFiEEFo5vQpe/16ea/USWUUu+Lrjhlh8FAmfRkWAFAwAAAAAACgkQUUu+Lrjhlh+C Nw//f4r4aJt8yhiKTUDXb/yQESeAclHReQaPGHqqSaT3G7e32zYAJOyURjNxhZJphAG3zCZxo5Cm NYYTP8blKwspmPoYUY9BrIgyVsoPa40H9GIx/TIfX+1DSqmNI8/YxSlpiv4Z46Wo0Sin81racFIX LcExH1HCrGsZsiAzSQOhC4WYwqlu9ZbcMwvum9i7To4K8vcR6RDHM32l949jyrkeD5WwYWFKokZD m6Vx2WZfqlzRQTpD3I8jP93pV1cMLKjUYIdpb2nH6aT2oDtW7hT9tNGpmxbH++98HCewCBoaNDe+ PnZP148Tfg3zzgyMdng0aJsIPc225DBVh+g83jnHPa2pIl53329IdCI6DhxgLlwmP2Iu5qJ2JvWf xe6rDYbxRon22c+j7pGiCzRgHn5cX0++oasZ/1YKZ934Ufxm9sLtSdRmkUnHpPv1hTpXe9bSo2b1 hSfExMlE1GV3OTsfgt51LfNJEOiFR7E4nJGPvjFvep8Tx0e6lWjK3IOXwbBaOO6tPwVqD9Tyj4ma fqjmg9obledFEiMpDlOwv8gQR81EyHg2+GmIh6xDwXQWfPPM20MtqEMTx5wKlMw7nqk6IXb5kuVE hAQI5+ItgGzhsd89Glv7uKSqYMyHSJ0GSKgMye0LfWIGnogTvS/65+Dx6G5OUynhhIwuLgq0r525 GYk= =KP6/ -----END PGP SIGNATURE-----