From eb535322d0856474fd2b06d402c4e3f1151761b4 Mon Sep 17 00:00:00 2001 From: Sean Reifschneider Date: Fri, 29 May 2026 09:24:50 -0600 Subject: [PATCH] Fix cW Vi mode regression deleting trailing space Missed in 02c0455 (Fix Vi mode cw deleting trailing whitespace, 2026-02-12), Closes #12790 Closes #12791 --- CHANGELOG.rst | 3 ++- doc_src/cmds/fish_vi_key_bindings.rst | 5 ----- share/functions/fish_vi_key_bindings.fish | 5 +++-- tests/pexpects/bind.py | 6 +++--- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 98cd6ebe9..52c8af529 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -28,7 +28,8 @@ For distributors and developers Regression fixes: ----------------- -- (from 4.4) Vi mode ``x`` in :doc:`builtin read ` (:issue:`12724`). +- (from 4.4.0) Vi mode ``c,W`` key binding wrongly deleted trailing spaces (:issue:`12790`). +- (from 4.4.0) Vi mode ``x`` in :doc:`builtin read ` (:issue:`12724`). - (from 4.3.3) Repeated tab would sometimes insert smartcase completions redundantly. fish 4.7.1 (released May 08, 2026) diff --git a/doc_src/cmds/fish_vi_key_bindings.rst b/doc_src/cmds/fish_vi_key_bindings.rst index 743c8599d..b1f89e34f 100644 --- a/doc_src/cmds/fish_vi_key_bindings.rst +++ b/doc_src/cmds/fish_vi_key_bindings.rst @@ -32,11 +32,6 @@ Fish's vi mode aims to be familiar to vim users, but there are some differences: **Word character handling** In vim, underscore (``_``) is treated as a keyword character by default, so word motions like ``w``, ``b``, and ``e`` treat ``foo_bar`` as a single word. In fish, underscore is treated as punctuation, so word motions stop at underscores. For example, pressing ``w`` on ``foo_bar`` in fish stops at the ``_``, while in vim it would jump past the entire identifier. -**The** ``cw`` **command** - In vim, ``cw`` has special behavior: when the cursor is on a non-space character, it behaves like ``ce`` (change to end of word), but when the cursor is on a space, it behaves like ``dwi`` (delete word then insert). - - In fish, ``cw`` always behaves like ``dwi`` - it deletes to the start of the next word (including trailing whitespace), then enters insert mode. To get vim's ``cw`` behavior in fish, use ``ce`` instead. - Examples -------- diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish index 9fc5ba662..83703ae46 100644 --- a/share/functions/fish_vi_key_bindings.fish +++ b/share/functions/fish_vi_key_bindings.fish @@ -151,10 +151,11 @@ function fish_vi_exec_motion end case change switch $motion[1] - case kill-word-vi + case kill-word-vi kill-bigword-vi + set -l end_kill (string replace -- -vi '' $motion[1]) for i in $seq_total if test $i -eq $total - commandline -f kill-word + commandline -f $end_kill else $motion_cmd end diff --git a/tests/pexpects/bind.py b/tests/pexpects/bind.py index 3863b160a..5512f9975 100644 --- a/tests/pexpects/bind.py +++ b/tests/pexpects/bind.py @@ -474,15 +474,15 @@ expect_prompt( "\r\n.*XXX def\r\n", unmatched="vi mode 'ce' should change to end of word" ) -# Test 'cW' - change WORD, deletes to start of next WORD (like vim's 'dW') +# Test 'cW' - change WORD, changes to end of WORD keeping trailing space (like 'cE') send("echo abc-def ghi") send("\033") sleep(0.200) send( "0wcWXXX\r" -) # Move to 'abc-def', 'cW' deletes 'abc-def ' (including space), type 'XXX' +) # Move to 'abc-def', 'cW' changes 'abc-def' (not the space), type 'XXX' expect_prompt( - "\r\n.*XXXghi\r\n", unmatched="vi mode 'cW' should delete to start of next WORD" + "\r\n.*XXX ghi\r\n", unmatched="vi mode 'cW' should change to end of WORD" ) # Test 'cE' - change to end of WORD (like vim's 'dE')