diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1eb2f37bb..b3934610d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -27,6 +27,7 @@ Interactive improvements - Fish now automatically creates ``config.fish`` and the configuration directories in ``$XDG_CONFIG_HOME/fish`` (by default ``~/.config/fish``) if they do not already exist. - ``__fish_prepend_sudo`` now toggles sudo even when it took the commandline from history instead of only adding it. - Fish now defaults job-control to "full" meaning it more sensibly handles assigning the terminal and process groups (:issue:`5036`, :issue:`5832`, :issue:`7721`) +- ``backward-kill-path-component`` (Control+W) no longer erases parts of two tokens when the cursor is positioned immediately after `` /``. (:issue:`6258`). - ``math`` learned two new functions, ``max`` and ``min``. - ``$SHLVL`` is no longer incremented in non-interactive shells. This means it won't be set to values larger than 1 just because your environment happens to run some scripts in $SHELL in its startup path (:issue:`7864`). - Fish no longer rings the bell when flashing. The flashing should already be enough notification and the bell can be annoying (:issue:`7875`). diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 5f143cd51..fcef48a1f 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -2716,10 +2716,15 @@ static void test_word_motion() { test_1_word_motion(word_motion_left, move_word_style_path_components, L"^/^foo/^bar/^baz/^"); test_1_word_motion(word_motion_left, move_word_style_path_components, L"^echo ^--foo ^--bar^"); test_1_word_motion(word_motion_left, move_word_style_path_components, - L"^echo ^hi ^> /^dev/^null^"); + L"^echo ^hi ^> ^/^dev/^null^"); test_1_word_motion(word_motion_left, move_word_style_path_components, - L"^echo /^foo/^bar{^aaa,^bbb,^ccc}^bak/^"); + L"^echo ^/^foo/^bar{^aaa,^bbb,^ccc}^bak/^"); + test_1_word_motion(word_motion_left, move_word_style_path_components, L"^echo ^bak ^///^"); + test_1_word_motion(word_motion_left, move_word_style_path_components, L"^aaa ^@ ^@^aaa^"); + test_1_word_motion(word_motion_left, move_word_style_path_components, L"^aaa ^a ^@^aaa^"); + test_1_word_motion(word_motion_left, move_word_style_path_components, L"^aaa ^@@@ ^@@^aa^"); + test_1_word_motion(word_motion_left, move_word_style_path_components, L"^aa^@@ ^aa@@^a^"); test_1_word_motion(word_motion_right, move_word_style_punctuation, L"^a^ bcd^"); test_1_word_motion(word_motion_right, move_word_style_punctuation, L"a^b^ cde^"); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index b95a5d523..13fb81584 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -752,18 +752,22 @@ bool move_word_state_machine_t::consume_char_path_components(wchar_t c) { s_separator, s_slash, s_path_component_characters, + s_initial_separator, s_end }; - // std::fwprintf(stdout, L"state %d, consume '%lc'\n", state, c); bool consumed = false; while (state != s_end && !consumed) { switch (state) { case s_initial_punctuation: { - if (!is_path_component_character(c)) { - consumed = true; + if (!is_path_component_character(c) && !iswspace(c)) { + state = s_initial_separator; + } else { + if (!is_path_component_character(c)) { + consumed = true; + } + state = s_whitespace; } - state = s_whitespace; break; } case s_whitespace: { @@ -800,6 +804,17 @@ bool move_word_state_machine_t::consume_char_path_components(wchar_t c) { } break; } + case s_initial_separator: { + if (is_path_component_character(c)) { + consumed = true; + state = s_path_component_characters; + } else if (iswspace(c)) { + state = s_end; + } else { + consumed = true; + } + break; + } case s_end: default: { break;