mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-28 17:51:15 -03:00
Fix spurious blank lines when executing scrolled commandline
The result of
commandline -i ": '$(seq $LINES)"\n"first scrolled line'"
is a commandline that is scrolled by one line.
Before executing that commandline, we move the cursor down by one
too many line. This is a regression from 610338cc70 (On undo after
execute, restore the cursor position, 2024-12-21). Fix that.
The test also demonstrates an unrelated problem, probably specific
to tmux.
This commit is contained in:
@@ -2134,7 +2134,9 @@ fn readline(&mut self, nchars: Option<NonZeroUsize>) -> Option<WString> {
|
||||
|
||||
// Redraw the command line. This is what ensures the autosuggestion is hidden, etc. after the
|
||||
// user presses enter.
|
||||
if zelf.is_repaint_needed(None) || zelf.screen.scrolled || zelf.conf.inputfd != STDIN_FILENO
|
||||
if zelf.is_repaint_needed(None)
|
||||
|| zelf.screen.scrolled()
|
||||
|| zelf.conf.inputfd != STDIN_FILENO
|
||||
{
|
||||
zelf.layout_and_repaint_before_execution();
|
||||
}
|
||||
|
||||
@@ -189,8 +189,9 @@ pub fn is_empty(&self) -> bool {
|
||||
pub struct Screen {
|
||||
/// Whether the last-drawn autosuggestion (if any) is truncated, or hidden entirely.
|
||||
pub autosuggestion_is_truncated: bool,
|
||||
/// True if the last rendering was so large we could only display part of the command line.
|
||||
pub scrolled: bool,
|
||||
/// If the last rendering was so large we could only display part of the command line,
|
||||
/// this is the number of lines that were pushed to scrollback.
|
||||
pub scroll_amount: usize,
|
||||
|
||||
/// Receiver for our output.
|
||||
outp: &'static RefCell<Outputter>,
|
||||
@@ -227,7 +228,7 @@ pub fn new() -> Self {
|
||||
Self {
|
||||
outp: Outputter::stdoutput(),
|
||||
autosuggestion_is_truncated: Default::default(),
|
||||
scrolled: Default::default(),
|
||||
scroll_amount: Default::default(),
|
||||
desired: Default::default(),
|
||||
actual: Default::default(),
|
||||
actual_left_prompt: Default::default(),
|
||||
@@ -241,6 +242,10 @@ pub fn new() -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scrolled(&self) -> bool {
|
||||
self.scroll_amount != 0
|
||||
}
|
||||
|
||||
/// This is the main function for the screen output library. It is used to define the desired
|
||||
/// contents of the screen. The screen command will use its knowledge of the current contents of
|
||||
/// the screen in order to render the desired output using as few terminal commands as possible.
|
||||
@@ -459,7 +464,7 @@ struct ScrolledCursor {
|
||||
// Append pager_data (none if empty).
|
||||
self.desired.append_lines(&page_rendering.screen_data);
|
||||
|
||||
self.scrolled = scrolled_cursor.scroll_amount != 0;
|
||||
self.scroll_amount = scrolled_cursor.scroll_amount;
|
||||
|
||||
self.update(
|
||||
vars,
|
||||
@@ -500,7 +505,7 @@ pub fn reset_line(&mut self, repaint_prompt: bool /* = false */) {
|
||||
}
|
||||
|
||||
pub fn move_to_end(&mut self) {
|
||||
self.r#move(0, self.actual.line_count());
|
||||
self.r#move(0, self.actual.line_count() - self.scroll_amount);
|
||||
}
|
||||
|
||||
pub fn push_to_scrollback(&mut self, cursor_y: usize) {
|
||||
@@ -1035,14 +1040,15 @@ fn update(
|
||||
let term = term.as_ref();
|
||||
|
||||
// Output the left prompt if it has changed.
|
||||
if zelf.scrolled && !is_final_rendering {
|
||||
if zelf.scrolled() && !is_final_rendering {
|
||||
zelf.r#move(0, 0);
|
||||
zelf.outp
|
||||
.borrow_mut()
|
||||
.tputs_if_some(&term.and_then(|term| term.clr_eol.as_ref()));
|
||||
zelf.actual_left_prompt.clear();
|
||||
zelf.actual.cursor.x = 0;
|
||||
} else if left_prompt != zelf.actual_left_prompt || (zelf.scrolled && is_final_rendering) {
|
||||
} else if left_prompt != zelf.actual_left_prompt || (zelf.scrolled() && is_final_rendering)
|
||||
{
|
||||
zelf.r#move(0, 0);
|
||||
let mut start = 0;
|
||||
let osc_133_prompt_start =
|
||||
@@ -1092,7 +1098,7 @@ fn s_line(zelf: &Screen, i: usize) -> &Line {
|
||||
// Note that skip_remaining is a width, not a character count.
|
||||
let mut skip_remaining = start_pos;
|
||||
|
||||
let shared_prefix = if zelf.scrolled {
|
||||
let shared_prefix = if zelf.scrolled() {
|
||||
0
|
||||
} else {
|
||||
line_shared_prefix(o_line(&zelf, i), s_line(&zelf, i))
|
||||
|
||||
@@ -32,6 +32,23 @@ isolated-tmux capture-pane -p
|
||||
# CHECK: 10
|
||||
# CHECK: scroll_here
|
||||
|
||||
# The output is broken here (seems tmux specific).
|
||||
isolated-tmux send-keys C-c
|
||||
tmux-sleep
|
||||
isolated-tmux send-keys C-l 'commandline -i ": \'$(seq $LINES)" A B "C\'"' Enter Enter
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p
|
||||
# CHECK: 4
|
||||
# CHECK: 5
|
||||
# CHECK: 6
|
||||
# CHECK: 7
|
||||
# CHECK: 8
|
||||
# CHECK: 9
|
||||
# CHECK: 10
|
||||
# CHECK: prompt 5>
|
||||
# CHECK: B
|
||||
# CHECK: C'
|
||||
|
||||
# Soft-wrapped commandline with omitted right prompt.
|
||||
isolated-tmux send-keys C-c
|
||||
tmux-sleep
|
||||
@@ -43,7 +60,7 @@ isolated-tmux send-keys C-l '
|
||||
' Enter
|
||||
tmux-sleep
|
||||
isolated-tmux capture-pane -p | sed 1,5d
|
||||
# CHECK: prompt 5> echo 00000000000000000000000000000000000000000000000000000000000000000
|
||||
# CHECK: prompt {{\d+}}> echo 00000000000000000000000000000000000000000000000000000000000000000
|
||||
# CHECK: 000000000000000
|
||||
# CHECK: 00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
# CHECK: prompt 6> right-prompt
|
||||
# CHECK: prompt {{\d+}}> right-prompt
|
||||
|
||||
Reference in New Issue
Block a user