]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.2048: MS-Windows: backspace behavior wrong with ConPTY v9.1.2048
authorMuraoka Taro <koron.kaoriya@gmail.com>
Sat, 3 Jan 2026 17:06:03 +0000 (17:06 +0000)
committerChristian Brabandt <cb@256bit.org>
Sat, 3 Jan 2026 17:06:03 +0000 (17:06 +0000)
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 <koron.kaoriya@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/terminal.c
src/testdir/test_terminal3.vim
src/version.c

index d2e20e251b825acc314fe59fb61bfb6422e93b2e..138579ab337037013cd79af82e7b3dd47a2dd069 100644 (file)
@@ -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;
index b332ff4e6dbcde3507e8593f7e089a7cda9e90aa..ff8f8c206bcad5489056365c6f224290ad7fd5ac 100644 (file)
@@ -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, "\<BS>")
+  call WaitForAssert({-> assert_equal('>foo ba', s:get_cmd_prompt(buf))}, 100)
+  " Ctrl+H behaves like Backspace
+  call term_sendkeys(buf, "\<C-H>")
+  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, "\<BS>\<BS>\<C-H>\<C-H>")
+  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
index 163f4fb72ea90d6ad3e448e6f0e778bf011e1d2c..7375bfbb26b38ce989eac9d11eb4efe6907aca0b 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2048,
 /**/
     2047,
 /**/