fix: strip leftover suffix when completing with cursor not at end

When the input cursor is not at the end of the text and a completion
is submitted (e.g. via `cmp:close --submit`), the `Input::complete()`
method would preserve the text after the cursor (`after`), appending
it to the completed path. For example, typing `/home/user/Doc` and
moving the cursor back to after `D`, then completing `Documents/`,
would produce `/home/user/Documents/oc` instead of `/home/user/Documents/`.

Fix this by stripping the remainder of the current path component from
the `after` slice before building the new value. Any text beyond the
next path separator is preserved so that multi-component paths are not
truncated.

Resolves #2943

Co-Authored-By: Claude (claude-opus-4-6) <noreply@anthropic.com>
This commit is contained in:
easonysliu 2026-03-16 16:06:01 +08:00
parent de01a56ac5
commit 99e5484f93

View file

@ -15,6 +15,17 @@ const SEPARATOR: char = std::path::MAIN_SEPARATOR;
impl Input {
pub fn complete(&mut self, opt: CompleteOpt) -> Result<Data> {
let (before, after) = self.partition();
// Strip the remainder of the current path component from `after`, so that
// completing when the cursor is in the middle of a word replaces the entire
// word instead of appending the completion before the leftover suffix.
// e.g. input "/home/user/D|oc" (cursor at |) completing "Documents/" should
// yield "/home/user/Documents/", not "/home/user/Documents/oc".
let after = match after.find(SEPARATOR) {
Some(i) => &after[i..],
None => "",
};
let new = if let Some((prefix, _)) = before.rsplit_once(SEPARATOR) {
format!("{prefix}/{}{after}", opt.completable()).replace(SEPARATOR, MAIN_SEPARATOR_STR)
} else {