From: Muraoka Taro Date: Sat, 3 Jan 2026 17:06:03 +0000 (+0000) Subject: patch 9.1.2048: MS-Windows: backspace behavior wrong with ConPTY X-Git-Tag: v9.1.2048^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=997952a512e077e719011862ce67807e771b129e;p=thirdparty%2Fvim.git patch 9.1.2048: MS-Windows: backspace behavior wrong with ConPTY Problem: Pressing backspace in ConPTY on Windows deletes an entire word, not just a single character. This is the same as pressing Alt + backspace in cmd.exe. Solution: When using ConPTY on Windows, the `VTERM_KEY_BACKSPACE` key is now sent when the Backspace key or Ctrl+H is detected. (Muraoka Taro) Historically, Windows has assigned the code 0x7F (DEL) to backspace, and it seems necessary to follow that behavior when using ConPTY. closes: #19065 Signed-off-by: Muraoka Taro Signed-off-by: Christian Brabandt --- diff --git a/src/terminal.c b/src/terminal.c index d2e20e251b..138579ab33 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -1584,9 +1584,26 @@ term_convert_key(term_T *term, int c, int modmask, char *buf) { // don't use VTERM_KEY_ENTER, it may do an unwanted conversion - // don't use VTERM_KEY_BACKSPACE, it always - // becomes 0x7f DEL - case K_BS: c = term_backspace_char; break; + case K_BS: +#ifdef MSWIN + // In ConPTY, we must use VTERM_KEY_BACKSPACE, otherwise it will + // delete one word, equivalent to Alt+Backspace. + if (term->tl_conpty) + key = VTERM_KEY_BACKSPACE; + else +#endif + // don't use VTERM_KEY_BACKSPACE, it always becomes 0x7f DEL + c = term_backspace_char; + break; + +#ifdef MSWIN + case BS: + // In ConPTY, we must use VTERM_KEY_BACKSPACE, otherwise it will + // delete one word, equivalent to Alt+Backspace. + if (term->tl_conpty) + key = VTERM_KEY_BACKSPACE; + break; +#endif case ESC: key = VTERM_KEY_ESCAPE; break; case K_DEL: key = VTERM_KEY_DEL; break; diff --git a/src/testdir/test_terminal3.vim b/src/testdir/test_terminal3.vim index b332ff4e6d..ff8f8c206b 100644 --- a/src/testdir/test_terminal3.vim +++ b/src/testdir/test_terminal3.vim @@ -1090,4 +1090,38 @@ func Test_terminal_ansi_color_windows_cui() call assert_equal(expected_colors, term_scrape(buf, 1)[:len_to_check-1]->map({_, v -> v['bg']})) endfunc +func Test_terminal_backspace_on_windows() + if !has('win32') + throw 'Skipped: only for the Windows CUI' + endif + " Specify a simple prompt for easy comparison + let save_prompt = $PROMPT + let $PROMPT = '>' + + " Return the prompt line before the cursor + func s:get_cmd_prompt(buf) + let cur = term_getcursor(a:buf) + return term_getline(a:buf, cur[0])[:cur[1]-2] + endfunc + + let buf = term_start('cmd.exe') + call WaitForAssert({-> assert_equal('>', s:get_cmd_prompt(buf))}, 100) + + " Verify sent characters are echoed back + call term_sendkeys(buf, 'foo bar') + call WaitForAssert({-> assert_equal('>foo bar', s:get_cmd_prompt(buf))}, 100) + " Backspace should delete a character in front of the cursor + call term_sendkeys(buf, "\") + call WaitForAssert({-> assert_equal('>foo ba', s:get_cmd_prompt(buf))}, 100) + " Ctrl+H behaves like Backspace + call term_sendkeys(buf, "\") + call WaitForAssert({-> assert_equal('>foo b', s:get_cmd_prompt(buf))}, 100) + " Send a total of four BS and Ctrl+H to erase four characters. + call term_sendkeys(buf, "\\\\") + call WaitForAssert({-> assert_equal('>f', s:get_cmd_prompt(buf))}, 100) + + delfunc s:get_cmd_prompt + let $PROMPT = save_prompt +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 163f4fb72e..7375bfbb26 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2048, /**/ 2047, /**/