mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 13:23:09 +00:00
Also handle overflown screens if editing pager search field
As mentioned in 04c913427
(Limit command line rendering to $LINES
lines, 2024-10-25) our rendering breaks when the command line overflows
the screen and we have a pager search field.
Let's also apply the overflow logic in this case.
Note that the search field still works, it's just not visible.
In future we should maybe show a small search field (~4 lines) in
this case (removing 4 screen lines worth of command line). But again,
this is not really important.
This commit is contained in:
parent
adfa87d141
commit
f89909ae31
3 changed files with 43 additions and 38 deletions
|
@ -71,7 +71,7 @@ const PAGER_UNDISCLOSED_MAX_ROWS: usize = 4;
|
|||
const PAGER_MIN_WIDTH: usize = 16;
|
||||
|
||||
/// Minimum height to show completions
|
||||
const PAGER_MIN_HEIGHT: usize = 4;
|
||||
pub const PAGER_MIN_HEIGHT: usize = 4;
|
||||
|
||||
/// The maximum number of columns of completion to attempt to fit onto the screen.
|
||||
const PAGER_MAX_COLS: usize = 6;
|
||||
|
|
|
@ -427,8 +427,8 @@ struct LayoutData {
|
|||
/// Position of the cursor in the command line.
|
||||
position: usize,
|
||||
|
||||
/// Whether the cursor is focused on the pager or not.
|
||||
focused_on_pager: bool,
|
||||
/// The cursor position in the pager search field.
|
||||
pager_search_field_position: Option<usize>,
|
||||
|
||||
/// Visual selection of the command line, or none if none.
|
||||
selection: Option<SelectionData>,
|
||||
|
@ -1386,6 +1386,7 @@ impl<'a> Reader<'a> {
|
|||
};
|
||||
|
||||
let focused_on_pager = self.active_edit_line_tag() == EditableLineTag::SearchField;
|
||||
let pager_search_field_position = focused_on_pager.then_some(self.pager.cursor_position());
|
||||
let last = &self.rendered_layout;
|
||||
check(self.force_exec_prompt_and_repaint, "forced")
|
||||
|| check(self.command_line.text() != last.text, "text")
|
||||
|
@ -1394,8 +1395,11 @@ impl<'a> Reader<'a> {
|
|||
"highlight",
|
||||
)
|
||||
|| check(self.selection != last.selection, "selection")
|
||||
|| check(focused_on_pager != last.focused_on_pager, "focus")
|
||||
|| check(self.command_line.position() != last.position, "position")
|
||||
|| check(
|
||||
pager_search_field_position != last.pager_search_field_position,
|
||||
"pager_search_field_position",
|
||||
)
|
||||
|| check(
|
||||
self.history_search.search_range_if_active() != last.history_search_range,
|
||||
"history search",
|
||||
|
@ -1431,13 +1435,10 @@ impl<'a> Reader<'a> {
|
|||
result.text = self.command_line.text().to_owned();
|
||||
result.colors = self.command_line.colors().to_vec();
|
||||
assert!(result.text.len() == result.colors.len());
|
||||
result.position = if focused_on_pager {
|
||||
self.pager.cursor_position()
|
||||
} else {
|
||||
self.command_line.position()
|
||||
};
|
||||
result.position = self.command_line.position();
|
||||
result.pager_search_field_position =
|
||||
focused_on_pager.then_some(self.pager.cursor_position());
|
||||
result.selection = self.selection;
|
||||
result.focused_on_pager = focused_on_pager;
|
||||
result.history_search_range = self.history_search.search_range_if_active();
|
||||
result.autosuggestion = self.autosuggestion.text.clone();
|
||||
result.left_prompt_buff = self.left_prompt_buff.clone();
|
||||
|
@ -1516,10 +1517,10 @@ impl<'a> Reader<'a> {
|
|||
&colors,
|
||||
&indents,
|
||||
data.position,
|
||||
data.pager_search_field_position,
|
||||
self.parser.vars(),
|
||||
pager,
|
||||
current_page_rendering,
|
||||
data.focused_on_pager,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//! The current implementation is less smart than ncurses allows and can not for example move blocks
|
||||
//! of text around to handle text insertion.
|
||||
|
||||
use crate::pager::{PageRendering, Pager};
|
||||
use crate::pager::{PageRendering, Pager, PAGER_MIN_HEIGHT};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::LinkedList;
|
||||
use std::ffi::{CStr, CString};
|
||||
|
@ -237,7 +237,6 @@ impl Screen {
|
|||
/// of the command line \param colors the colors to use for the commanad line \param indent the
|
||||
/// indent to use for the command line \param cursor_pos where the cursor is \param pager the
|
||||
/// pager to render below the command line \param page_rendering to cache the current pager view
|
||||
/// \param cursor_is_within_pager whether the position is within the pager line (first line)
|
||||
pub fn write(
|
||||
&mut self,
|
||||
left_prompt: &wstr,
|
||||
|
@ -247,10 +246,10 @@ impl Screen {
|
|||
colors: &[HighlightSpec],
|
||||
indent: &[i32],
|
||||
cursor_pos: usize,
|
||||
pager_search_field_position: Option<usize>,
|
||||
vars: &dyn Environment,
|
||||
pager: &mut Pager,
|
||||
page_rendering: &mut PageRendering,
|
||||
cursor_is_within_pager: bool,
|
||||
) {
|
||||
let curr_termsize = termsize_last();
|
||||
let screen_width = curr_termsize.width;
|
||||
|
@ -337,7 +336,7 @@ impl Screen {
|
|||
let mut i = 0;
|
||||
loop {
|
||||
// Grab the current cursor's x,y position if this character matches the cursor's offset.
|
||||
if !cursor_is_within_pager && i == cursor_pos {
|
||||
if i == cursor_pos {
|
||||
cursor_arr = Some(ScrolledCursor {
|
||||
cursor: self.desired.cursor,
|
||||
scroll_amount: (self.desired.line_count()
|
||||
|
@ -379,39 +378,44 @@ impl Screen {
|
|||
}
|
||||
i += 1;
|
||||
}
|
||||
cursor_arr.as_mut().map(
|
||||
|ScrolledCursor {
|
||||
ref mut cursor,
|
||||
scroll_amount,
|
||||
}| {
|
||||
if *scroll_amount != 0 {
|
||||
self.desired.line_datas = self.desired.line_datas.split_off(*scroll_amount);
|
||||
cursor.y -= *scroll_amount;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let full_line_count = self.desired.cursor.y + 1;
|
||||
let pager_available_height = std::cmp::max(
|
||||
1,
|
||||
curr_termsize
|
||||
.height
|
||||
.saturating_sub_unsigned(full_line_count),
|
||||
);
|
||||
|
||||
// Now that we've output everything, set the cursor to the position that we saved in the loop
|
||||
// above.
|
||||
self.desired.cursor = cursor_arr.as_ref().map(|sc| sc.cursor).unwrap_or_default();
|
||||
|
||||
if cursor_is_within_pager {
|
||||
self.desired.cursor.x = cursor_pos;
|
||||
self.desired.cursor.y = self.desired.line_count();
|
||||
}
|
||||
self.desired.cursor = match pager_search_field_position {
|
||||
Some(pager_cursor_pos)
|
||||
if pager_available_height >= isize::try_from(PAGER_MIN_HEIGHT).unwrap() =>
|
||||
{
|
||||
Cursor {
|
||||
x: pager_cursor_pos,
|
||||
y: self.desired.line_count(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let ScrolledCursor {
|
||||
mut cursor,
|
||||
scroll_amount,
|
||||
} = cursor_arr.unwrap();
|
||||
if scroll_amount != 0 {
|
||||
self.desired.line_datas = self.desired.line_datas.split_off(scroll_amount);
|
||||
cursor.y -= scroll_amount;
|
||||
}
|
||||
cursor
|
||||
}
|
||||
};
|
||||
|
||||
// Re-render our completions page if necessary. Limit the term size of the pager to the true
|
||||
// term size, minus the number of lines consumed by our string.
|
||||
pager.set_term_size(&Termsize::new(
|
||||
std::cmp::max(1, curr_termsize.width),
|
||||
std::cmp::max(
|
||||
1,
|
||||
curr_termsize
|
||||
.height
|
||||
.saturating_sub_unsigned(full_line_count),
|
||||
),
|
||||
pager_available_height,
|
||||
));
|
||||
|
||||
pager.update_rendering(page_rendering);
|
||||
|
|
Loading…
Reference in a new issue