Fix regression causing glitches when prompt has control character

Since commit 0627c9d9af (Render control characters as Unicode Control Pictures,
2020-08-29), we render control character in the commandline as "␇" etc.
They can be inserted via either history search, or bindings such as

	bind ctrl-g "commandline -i \a"

That commit incorrectly assumes that the prompt is rendered the same way as
the command line (which goes through "ScreenData" etc).
This is wrong -- prompt text is written to stdout as-is, and a prompt that
outputs \t (tab) or \a (BEL) is valid.  The wrong assumption means that we
overestimate the width of prompts containing control characters.

(For some reason, after switching from Vi insert to Vi normal mode, we seem
to get the width right which means the command line jumps around)

Let's revert to the old width computation for any prompt text.

Closes #11252

(cherry picked from commit 4d81cf8af4)
This commit is contained in:
Johannes Altmanninger
2025-03-10 23:34:10 +01:00
parent 5d31be1c3e
commit e37e1b8f78

View File

@@ -35,7 +35,7 @@
use crate::output::Outputter;
use crate::termsize::{termsize_last, Termsize};
use crate::wchar::prelude::*;
use crate::wcstringutil::string_prefixes_string;
use crate::wcstringutil::{fish_wcwidth_visible, string_prefixes_string};
use crate::wutil::fstat;
#[derive(Clone, Default)]
@@ -1636,7 +1636,7 @@ fn measure_run_from(
width = next_tab_stop(width);
} else {
// Ordinary char. Add its width with care to ignore control chars which have width -1.
width += wcwidth_rendered_min_0(input.char_at(idx));
width += usize::try_from(fish_wcwidth_visible(input.char_at(idx))).unwrap();
}
idx += 1;
}
@@ -1682,7 +1682,7 @@ fn truncate_run(
curr_width = measure_run_from(run, 0, None, cache);
idx = 0;
} else {
let char_width = wcwidth_rendered_min_0(c);
let char_width = usize::try_from(fish_wcwidth_visible(c)).unwrap();
curr_width -= std::cmp::min(curr_width, char_width);
run.remove(idx);
}