mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
Also use control pictures for pager prefix
The test case shows that the pager rendering is not quite right. It renders '{\', leaving out the newline. This rendering is ambiguous. Let's fix it by rendering \n as control picture, like we do for other control characters in the pager.
This commit is contained in:
parent
f5c6829670
commit
c41dbe4551
3 changed files with 37 additions and 21 deletions
19
src/pager.rs
19
src/pager.rs
|
@ -8,13 +8,12 @@ use crate::common::{
|
||||||
};
|
};
|
||||||
use crate::complete::Completion;
|
use crate::complete::Completion;
|
||||||
use crate::editable_line::EditableLine;
|
use crate::editable_line::EditableLine;
|
||||||
use crate::fallback::{fish_wcswidth, fish_wcwidth};
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::future::IsSomeAnd;
|
use crate::future::IsSomeAnd;
|
||||||
use crate::highlight::{highlight_shell, HighlightRole, HighlightSpec};
|
use crate::highlight::{highlight_shell, HighlightRole, HighlightSpec};
|
||||||
use crate::libc::MB_CUR_MAX;
|
use crate::libc::MB_CUR_MAX;
|
||||||
use crate::operation_context::OperationContext;
|
use crate::operation_context::OperationContext;
|
||||||
use crate::screen::{Line, ScreenData};
|
use crate::screen::{wcswidth_rendered, wcwidth_rendered, Line, ScreenData};
|
||||||
use crate::termsize::Termsize;
|
use crate::termsize::Termsize;
|
||||||
use crate::wchar::prelude::*;
|
use crate::wchar::prelude::*;
|
||||||
use crate::wcstringutil::string_fuzzy_match_string;
|
use crate::wcstringutil::string_fuzzy_match_string;
|
||||||
|
@ -344,7 +343,7 @@ impl Pager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn measure_completion_infos(&mut self) {
|
fn measure_completion_infos(&mut self) {
|
||||||
let prefix_len = usize::try_from(fish_wcswidth(&self.prefix));
|
let prefix_len = wcswidth_rendered(&self.prefix);
|
||||||
for comp in &mut self.unfiltered_completion_infos {
|
for comp in &mut self.unfiltered_completion_infos {
|
||||||
let comp_strings = &mut comp.comp;
|
let comp_strings = &mut comp.comp;
|
||||||
|
|
||||||
|
@ -354,14 +353,14 @@ impl Pager {
|
||||||
comp.comp_width += 2;
|
comp.comp_width += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fish_wcswidth() can return -1 if it can't calculate the width. So be cautious.
|
// This can return -1 if it can't calculate the width. So be cautious.
|
||||||
let comp_width = fish_wcswidth(comp_string);
|
let comp_width = wcswidth_rendered(comp_string);
|
||||||
comp.comp_width += prefix_len.unwrap_or_default();
|
comp.comp_width += usize::try_from(prefix_len).unwrap_or_default();
|
||||||
comp.comp_width += usize::try_from(comp_width).unwrap_or_default();
|
comp.comp_width += usize::try_from(comp_width).unwrap_or_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
// fish_wcswidth() can return -1 if it can't calculate the width. So be cautious.
|
// This can return -1 if it can't calculate the width. So be cautious.
|
||||||
let desc_width = fish_wcswidth(&comp.desc);
|
let desc_width = wcswidth_rendered(&comp.desc);
|
||||||
comp.desc_width = usize::try_from(desc_width).unwrap_or_default();
|
comp.desc_width = usize::try_from(desc_width).unwrap_or_default();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1071,7 +1070,7 @@ fn print_max_impl(
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let mut remaining = max;
|
let mut remaining = max;
|
||||||
for (i, c) in s.chars().enumerate() {
|
for (i, c) in s.chars().enumerate() {
|
||||||
let iwidth_c = fish_wcwidth(c);
|
let iwidth_c = wcwidth_rendered(c);
|
||||||
let Ok(width_c) = usize::try_from(iwidth_c) else {
|
let Ok(width_c) = usize::try_from(iwidth_c) else {
|
||||||
// skip non-printable characters
|
// skip non-printable characters
|
||||||
continue;
|
continue;
|
||||||
|
@ -1084,7 +1083,7 @@ fn print_max_impl(
|
||||||
let ellipsis = get_ellipsis_char();
|
let ellipsis = get_ellipsis_char();
|
||||||
if (width_c == remaining) && (has_more || i + 1 < s.len()) {
|
if (width_c == remaining) && (has_more || i + 1 < s.len()) {
|
||||||
line.append(ellipsis, color(i));
|
line.append(ellipsis, color(i));
|
||||||
let ellipsis_width = fish_wcwidth(ellipsis);
|
let ellipsis_width = wcwidth_rendered(ellipsis);
|
||||||
remaining = remaining.saturating_sub(usize::try_from(ellipsis_width).unwrap());
|
remaining = remaining.saturating_sub(usize::try_from(ellipsis_width).unwrap());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ impl Line {
|
||||||
pub fn wcswidth_min_0(&self, max: usize /* = usize::MAX */) -> usize {
|
pub fn wcswidth_min_0(&self, max: usize /* = usize::MAX */) -> usize {
|
||||||
let mut result: usize = 0;
|
let mut result: usize = 0;
|
||||||
for c in &self.text[..max.min(self.text.len())] {
|
for c in &self.text[..max.min(self.text.len())] {
|
||||||
result += wcwidth_rendered(c.character);
|
result += wcwidth_rendered_min_0(c.character);
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -327,7 +327,7 @@ impl Screen {
|
||||||
colors[i],
|
colors[i],
|
||||||
usize::try_from(indent[i]).unwrap(),
|
usize::try_from(indent[i]).unwrap(),
|
||||||
first_line_prompt_space,
|
first_line_prompt_space,
|
||||||
wcwidth_rendered(effective_commandline.as_char_slice()[i]),
|
wcwidth_rendered_min_0(effective_commandline.as_char_slice()[i]),
|
||||||
);
|
);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
@ -925,7 +925,7 @@ impl Screen {
|
||||||
// Skip over skip_remaining width worth of characters.
|
// Skip over skip_remaining width worth of characters.
|
||||||
let mut j = 0;
|
let mut j = 0;
|
||||||
while j < o_line(&zelf, i).len() {
|
while j < o_line(&zelf, i).len() {
|
||||||
let width = wcwidth_rendered(o_line(&zelf, i).char_at(j));
|
let width = wcwidth_rendered_min_0(o_line(&zelf, i).char_at(j));
|
||||||
if skip_remaining < width {
|
if skip_remaining < width {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -936,7 +936,7 @@ impl Screen {
|
||||||
|
|
||||||
// Skip over zero-width characters (e.g. combining marks at the end of the prompt).
|
// Skip over zero-width characters (e.g. combining marks at the end of the prompt).
|
||||||
while j < o_line(&zelf, i).len() {
|
while j < o_line(&zelf, i).len() {
|
||||||
let width = wcwidth_rendered(o_line(&zelf, i).char_at(j));
|
let width = wcwidth_rendered_min_0(o_line(&zelf, i).char_at(j));
|
||||||
if width > 0 {
|
if width > 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -969,7 +969,7 @@ impl Screen {
|
||||||
let color = o_line(&zelf, i).color_at(j);
|
let color = o_line(&zelf, i).color_at(j);
|
||||||
set_color(&mut zelf, color);
|
set_color(&mut zelf, color);
|
||||||
let ch = o_line(&zelf, i).char_at(j);
|
let ch = o_line(&zelf, i).char_at(j);
|
||||||
let width = wcwidth_rendered(ch);
|
let width = wcwidth_rendered_min_0(ch);
|
||||||
zelf.write_char(ch, isize::try_from(width).unwrap());
|
zelf.write_char(ch, isize::try_from(width).unwrap());
|
||||||
current_width += width;
|
current_width += width;
|
||||||
j += 1;
|
j += 1;
|
||||||
|
@ -1524,7 +1524,7 @@ fn measure_run_from(
|
||||||
width = next_tab_stop(width);
|
width = next_tab_stop(width);
|
||||||
} else {
|
} else {
|
||||||
// Ordinary char. Add its width with care to ignore control chars which have width -1.
|
// Ordinary char. Add its width with care to ignore control chars which have width -1.
|
||||||
width += wcwidth_rendered(input.char_at(idx));
|
width += wcwidth_rendered_min_0(input.char_at(idx));
|
||||||
}
|
}
|
||||||
idx += 1;
|
idx += 1;
|
||||||
}
|
}
|
||||||
|
@ -1570,7 +1570,7 @@ fn truncate_run(
|
||||||
curr_width = measure_run_from(run, 0, None, cache);
|
curr_width = measure_run_from(run, 0, None, cache);
|
||||||
idx = 0;
|
idx = 0;
|
||||||
} else {
|
} else {
|
||||||
let char_width = wcwidth_rendered(c);
|
let char_width = wcwidth_rendered_min_0(c);
|
||||||
curr_width -= std::cmp::min(curr_width, char_width);
|
curr_width -= std::cmp::min(curr_width, char_width);
|
||||||
run.remove(idx);
|
run.remove(idx);
|
||||||
}
|
}
|
||||||
|
@ -1719,7 +1719,7 @@ fn compute_layout(
|
||||||
multiline = true;
|
multiline = true;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
first_line_width += wcwidth_rendered(c);
|
first_line_width += wcwidth_rendered_min_0(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let first_command_line_width = first_line_width;
|
let first_command_line_width = first_line_width;
|
||||||
|
@ -1734,7 +1734,7 @@ fn compute_layout(
|
||||||
autosuggest_truncated_widths.reserve(1 + autosuggestion_str.len());
|
autosuggest_truncated_widths.reserve(1 + autosuggestion_str.len());
|
||||||
for c in autosuggestion.chars() {
|
for c in autosuggestion.chars() {
|
||||||
autosuggest_truncated_widths.push(autosuggest_total_width);
|
autosuggest_truncated_widths.push(autosuggest_total_width);
|
||||||
autosuggest_total_width += wcwidth_rendered(c);
|
autosuggest_total_width += wcwidth_rendered_min_0(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1839,6 +1839,12 @@ fn rendered_character(c: char) -> char {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wcwidth_rendered(c: char) -> usize {
|
fn wcwidth_rendered_min_0(c: char) -> usize {
|
||||||
usize::try_from(fish_wcwidth(rendered_character(c))).unwrap_or_default()
|
usize::try_from(wcwidth_rendered(c)).unwrap()
|
||||||
|
}
|
||||||
|
pub fn wcwidth_rendered(c: char) -> isize {
|
||||||
|
fish_wcwidth(rendered_character(c))
|
||||||
|
}
|
||||||
|
pub fn wcswidth_rendered(s: &wstr) -> isize {
|
||||||
|
s.chars().map(|c| fish_wcwidth(rendered_character(c))).sum()
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,4 +194,15 @@ fn test_pager_layout() {
|
||||||
validate!(&mut pager, 18, L!("abcdefghijklmnopq…"));
|
validate!(&mut pager, 18, L!("abcdefghijklmnopq…"));
|
||||||
validate!(&mut pager, 17, L!("abcdefghijklmnop…"));
|
validate!(&mut pager, 17, L!("abcdefghijklmnop…"));
|
||||||
validate!(&mut pager, 16, L!("abcdefghijklmno…"));
|
validate!(&mut pager, 16, L!("abcdefghijklmno…"));
|
||||||
|
|
||||||
|
// Newlines in prefix
|
||||||
|
let c4s = vec![Completion::new(
|
||||||
|
L!("Hello").to_owned(),
|
||||||
|
L!("").to_owned(),
|
||||||
|
StringFuzzyMatch::exact_match(),
|
||||||
|
CompleteFlags::default(),
|
||||||
|
)];
|
||||||
|
pager.set_prefix(L!("{\\\n"), false); // }
|
||||||
|
pager.set_completions(&c4s, true);
|
||||||
|
validate!(&mut pager, 30, L!("{\\␊Hello")); // }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue