diff --git a/crates/terminal/src/alacritty.rs b/crates/terminal/src/alacritty.rs index 4cf8fe1d58..1e1acb798d 100644 --- a/crates/terminal/src/alacritty.rs +++ b/crates/terminal/src/alacritty.rs @@ -806,6 +806,19 @@ pub(super) fn shrink_to_used(term: &mut Term) { term.grid_mut().truncate(); } +pub(super) fn used_lines(term: &Term) -> usize { + if term.mode().contains(TermMode::ALT_SCREEN) { + return term.total_lines(); + } + let grid = term.grid(); + let cursor_line = grid.cursor.point.line.0.max(0) as usize; + let last_occupied_line = (cursor_line + 1..term.screen_lines()) + .rev() + .find(|&line| !grid[Line(line as i32)].is_clear()) + .unwrap_or(cursor_line); + term.history_size() + last_occupied_line + 1 +} + pub(super) fn make_content(term: &Term, last_content: &Content) -> Content { let content = term.renderable_content(); diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 310c191305..170dba9d98 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -70,7 +70,8 @@ use crate::alacritty::{ scroll_display, scroll_to_point, search_matches, selection_text, set_default_cursor_style, set_selection as set_term_selection, shrink_to_used, spawn_event_loop, toggle_vi_mode as toggle_term_vi_mode, total_lines, update_selection as update_term_selection, - update_selection_to_vi_cursor, update_vi_cursor_for_scroll, vi_goto_point, vi_motion, + update_selection_to_vi_cursor, update_vi_cursor_for_scroll, used_lines, vi_goto_point, + vi_motion, }; use crate::mappings::colors::to_vte_rgb; use crate::mappings::keys::to_esc_str; @@ -1891,6 +1892,10 @@ impl Terminal { screen_lines(&self.term.lock_unfair()) } + pub fn used_lines(&self) -> usize { + used_lines(&self.term.lock_unfair()) + } + //To test: //- Activate match on terminal (scrolling and selection) //- Editor search snapping behavior diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 1f380c8aac..6ef5121136 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -346,12 +346,13 @@ impl TerminalView { TerminalMode::Embedded { max_lines_when_unfocused, } => { - let total_lines = self.terminal.read(cx).total_lines(); + let terminal = self.terminal.read(cx); + let total_lines = terminal.total_lines(); if total_lines > Self::MAX_EMBEDDED_LINES { ContentMode::Scrollable } else { - let mut displayed_lines = total_lines; + let mut displayed_lines = terminal.used_lines().min(total_lines); if !self.focus_handle.is_focused(window) && let Some(max_lines) = max_lines_when_unfocused @@ -3168,6 +3169,61 @@ mod tests { } } + #[gpui::test] + async fn test_inline_terminal_shrinks_after_clear(cx: &mut TestAppContext) { + let (project, workspace) = init_test(cx).await; + let terminal = cx.new(|cx| { + terminal::TerminalBuilder::new_display_only( + CursorShape::default(), + terminal::terminal_settings::AlternateScroll::On, + None, + 0, + cx.background_executor(), + PathStyle::local(), + ) + .subscribe(cx) + }); + let (terminal_view, cx) = cx.add_window_view(|window, cx| { + let mut terminal_view = TerminalView::new( + terminal.clone(), + workspace.downgrade(), + None, + project.downgrade(), + window, + cx, + ); + terminal_view.set_embedded_mode(None, cx); + terminal_view + }); + + for _ in 1..=20 { + terminal.update(cx, |terminal, cx| { + terminal.write_output(b"line\n", cx); + }); + cx.draw( + gpui::Point::default(), + gpui::size(px(400.), px(100.)), + |_, _| terminal_view.clone().into_any_element(), + ); + } + terminal.read_with(cx, |terminal, _| { + assert_eq!(terminal.total_lines(), 21); + }); + + terminal.update(cx, |terminal, _| terminal.clear()); + for _ in 1..=2 { + cx.draw( + gpui::Point::default(), + gpui::size(px(400.), px(100.)), + |_, _| terminal_view.clone().into_any_element(), + ); + } + terminal.read_with(cx, |terminal, _| { + assert_eq!(terminal.total_lines(), 1); + assert_eq!(terminal.viewport_lines(), 1); + }); + } + #[gpui::test] async fn test_tab_content_shows_terminal_title_when_custom_title_directly_set_empty( cx: &mut TestAppContext,