From 02c04550fd3fa87e7fce98c439c52c29cc000caa Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Thu, 12 Feb 2026 13:45:34 +1100 Subject: [PATCH] Fix Vi mode cw deleting trailing whitespace Fixes 38e633d49b1 (fish_vi_key_bindings: add support for count, 2025-12-16). Fixes #12443 --- CHANGELOG.rst | 1 + share/functions/fish_vi_key_bindings.fish | 22 ++++++++++++++++------ tests/pexpects/bind.py | 6 +++--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5d63b457e..a9c871dde 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,6 +12,7 @@ Deprecations and removed features Regression fixes: ----------------- - (from 4.4.0) Vi mode ``d,f`` key binding did not work (:issue:`12417`). +- (from 4.4.0) Vi mode ``c,w`` key binding wrongly deleted trailing spaces (:issue:`12443`). - (from 4.4.0) Vi mode crash on ``c,i,w`` after accepting autosuggestion (:issue:`12430`). - (from 4.4.0) ``fish_vi_key_bindings`` called with a mode argument produced an error (:issue:`12413`). - (from 4.0.0) Build on Illumos (:issue:`12410`). diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish index a56436424..b5abb85f9 100644 --- a/share/functions/fish_vi_key_bindings.fish +++ b/share/functions/fish_vi_key_bindings.fish @@ -93,10 +93,12 @@ function fish_vi_exec_motion set motion (string replace -- forward kill $motion) end end + set -l motion_cmd switch $motion[1] case commandline + set motion_cmd $motion case '*' - set motion commandline -f $motion + set motion_cmd commandline -f $motion end if $use_selection commandline -f begin-selection @@ -107,14 +109,22 @@ function fish_vi_exec_motion switch $__fish_vi_operator case delete for i in (seq $total) - $motion || { set ok false; break } + $motion_cmd || { set ok false; break } end if $ok && $use_selection commandline -f kill-selection end case change - for i in (seq $total) - $motion || { set ok false; break } + switch $motion[1] + case kill-word-vi + for i in (seq (math $total - 1)) + $motion_cmd + end + commandline -f kill-word + case '*' + for i in (seq $total) + $motion_cmd || { set ok false; break } + end end if $ok if $use_selection @@ -124,7 +134,7 @@ function fish_vi_exec_motion end case yank for i in (seq $total) - $motion || { set ok false; break } + $motion_cmd || { set ok false; break } end if $ok if $use_selection @@ -135,7 +145,7 @@ function fish_vi_exec_motion end case swap-case for i in (seq $total) - $motion || { set ok false; break } + $motion_cmd || { set ok false; break } end if $ok if set -q swap_case_hack[1] diff --git a/tests/pexpects/bind.py b/tests/pexpects/bind.py index 2317e3f3f..6b9aebe35 100644 --- a/tests/pexpects/bind.py +++ b/tests/pexpects/bind.py @@ -304,7 +304,7 @@ sleep(0.200) send("0w") send("c2wREPLACED") sendline("") -expect_prompt("echo REPLACEDthree") +expect_prompt("echo REPLACED three") # Test escape cancelling count send("echo one two three") @@ -460,9 +460,9 @@ expect_prompt( send("echo abc def") send("\033") sleep(0.200) -send("0wcwXXX\r") # Move to 'abc', 'cw' deletes 'abc ' (including space), type 'XXX' +send("0wcwXXX\r") # Move to 'abc', 'cw' deletes 'abc', type 'XXX' expect_prompt( - "\r\n.*XXXdef\r\n", unmatched="vi mode 'cw' should delete to start of next word" + "\r\n.*XXX def\r\n", unmatched="vi mode 'cw' should delete to start of next word" ) # Test 'ce' - change to end of word (like vim's 'de')