Repository: alacritty/alacritty
File: alacritty_terminal/src/term/mod.rs (Rust)

Code before:
        };

        let terminator = terminator.to_owned();

        self.event_proxy.send_event(Event::ClipboardLoad(
            clipboard_type,
            Arc::new(move |text| {
                let base64 = base64::encode(&text);
                format!("\x1b]52;{};{}{}", clipboard as char, base64, terminator)
            }),
        ));
    }

    #[inline]
    fn clear_screen(&mut self, mode: ansi::ClearMode) {
        trace!("Clearing screen: {:?}", mode);

        let template = self.grid.cursor.template;
        let num_cols = self.grid.num_cols();
        let num_lines = self.grid.num_lines();
        let cursor = self.grid.cursor.point;
        let buffer_cursor = self.grid.buffer_cursor();

        match mode {
            ansi::ClearMode::Above => {
                let selection_range = self.selection.as_ref().and_then(|s| s.to_range(&self));

                // If clearing more than one line.
                if cursor.line > Line(1) {
                    // Fully clear all lines before the current line.
                    self.grid.region_mut(..cursor.line).each(|cell| cell.reset(&template));

                    if let Some(true) = selection_range
                        .as_ref()
                        .map(|range| range.is_above_buffer_line(buffer_cursor.line, num_lines.0))
                    {
                        self.selection = None;
                    }
                }

                // Clear up to the current column in the current line.
                let end = min(cursor.col + 1, num_cols);
                let cols = Column(0)..end;
                for cell in &mut self.grid[cursor.line][cols.clone()] {
                    cell.reset(&template);
                }

                if let Some(true) = selection_range
                    .as_ref()
                    .map(|range| range.contains_cols_on_buffer_line(buffer_cursor.line, cols))
                {

Review comment (bug):
If we accept to only do line-based granularity instead of cell-based, I think we should be fine with just using the selection without expansion to range?

Since the expansion is done on rendering anyways, it will just expand to the newly written/cleared content which doesn't seem that incorrect to me compared to what we currently do.

Code after:
    #[inline]
    fn clear_screen(&mut self, mode: ansi::ClearMode) {
        trace!("Clearing screen: {:?}", mode);
        let template = self.grid.cursor.template;

        let num_lines = self.grid.num_lines().0;
        let cursor_buffer_line = self.grid.cursor_buffer_point().line;

        match mode {
            ansi::ClearMode::Above => {
                let cursor = self.grid.cursor.point;

                // If clearing more than one line.
                if cursor.line > Line(1) {
                    // Fully clear all lines before the current line.
                    self.grid.region_mut(..cursor.line).each(|cell| cell.reset(&template));
                }

                // Clear up to the current column in the current line.
                let end = min(cursor.col + 1, self.grid.num_cols());
                for cell in &mut self.grid[cursor.line][..end] {
                    cell.reset(&template);
                }

                self.selection = self
                    .selection
                    .take()
                    .filter(|s| !s.intersects_range(cursor_buffer_line..num_lines));
            },
            ansi::ClearMode::Below => {
                let cursor = self.grid.cursor.point;
                for cell in &mut self.grid[cursor.line][cursor.col..] {
                    cell.reset(&template);
                }

                if cursor.line.0 < num_lines - 1 {
                    self.grid.region_mut((cursor.line + 1)..).each(|cell| cell.reset(&template));
                }

                self.selection =
                    self.selection.take().filter(|s| !s.intersects_range(..=cursor_buffer_line));
            },
            ansi::ClearMode::All => {
                if self.mode.contains(TermMode::ALT_SCREEN) {
                    self.grid.region_mut(..).each(|c| c.reset(&template));
                } else {
                    let template = Cell { bg: template.bg, ..Cell::default() };
                    self.grid.clear_viewport(template);
                }

                self.selection = self.selection.take().filter(|s| !s.intersects_range(..num_lines));