diff --git a/alacritty_macos.yml b/alacritty_macos.yml index 663647dc..05173e6a 100644 --- a/alacritty_macos.yml +++ b/alacritty_macos.yml @@ -315,6 +315,8 @@ key_bindings: - { key: Key0, mods: Command, action: ResetFontSize } - { key: Equals, mods: Command, action: IncreaseFontSize } - { key: Minus, mods: Command, action: DecreaseFontSize } + - { key: K, mods: Command, action: ClearHistory } + - { key: K, mods: Command, chars: "\x0c" } - { key: PageUp, mods: Shift, chars: "\x1b[5;2~" } - { key: PageUp, mods: Control, chars: "\x1b[5;5~" } - { key: PageUp, chars: "\x1b[5~" } diff --git a/src/config.rs b/src/config.rs index 00c3a933..f4da671c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -598,7 +598,7 @@ impl<'a> de::Deserialize<'a> for ActionWrapper { fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("Paste, Copy, PasteSelection, IncreaseFontSize, DecreaseFontSize, \ ResetFontSize, ScrollPageUp, ScrollPageDown, ScrollToTop, \ - ScrollToBottom, Hide, or Quit") + ScrollToBottom, ClearHistory, Hide, or Quit") } fn visit_str(self, value: &str) -> ::std::result::Result @@ -615,6 +615,7 @@ impl<'a> de::Deserialize<'a> for ActionWrapper { "ScrollPageDown" => Action::ScrollPageDown, "ScrollToTop" => Action::ScrollToTop, "ScrollToBottom" => Action::ScrollToBottom, + "ClearHistory" => Action::ClearHistory, "Hide" => Action::Hide, "Quit" => Action::Quit, _ => return Err(E::invalid_value(Unexpected::Str(value), &self)), diff --git a/src/event.rs b/src/event.rs index ea3d1d74..589f1a42 100644 --- a/src/event.rs +++ b/src/event.rs @@ -10,6 +10,7 @@ use parking_lot::MutexGuard; use glutin::{self, ModifiersState, Event, ElementState}; use copypasta::{Clipboard, Load, Store}; +use ansi::{Handler, ClearMode}; use grid::Scroll; use config::{self, Config}; use cli::Options; @@ -59,6 +60,10 @@ impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> { self.terminal.scroll_display(scroll); } + fn clear_history(&mut self) { + self.terminal.clear_screen(ClearMode::Saved); + } + fn copy_selection(&self, buffer: ::copypasta::Buffer) { if let Some(selected) = self.terminal.selection_to_string() { if !selected.is_empty() { diff --git a/src/grid/mod.rs b/src/grid/mod.rs index 6359a4ee..680aa7bd 100644 --- a/src/grid/mod.rs +++ b/src/grid/mod.rs @@ -219,14 +219,9 @@ impl Grid { /// Add lines to the visible area /// - /// The behavior in Terminal.app and iTerm.app is to keep the cursor at the - /// bottom of the screen as long as there is scrollback available. Once - /// scrollback is exhausted, new lines are simply added to the bottom of the - /// screen. - /// - /// Alacritty takes a different approach. Rather than trying to move with - /// the scrollback, we simply pull additional lines from the back of the - /// buffer in order to populate the new area. + /// Alacritty keeps the cursor at the bottom of the terminal as long as there + /// is scrollback available. Once scrollback is exhausted, new lines are + /// simply added to the bottom of the screen. fn grow_lines( &mut self, new_line_count: index::Line, diff --git a/src/input.rs b/src/input.rs index cccb3bb4..3c20fe36 100644 --- a/src/input.rs +++ b/src/input.rs @@ -69,6 +69,7 @@ pub trait ActionContext { fn change_font_size(&mut self, delta: f32); fn reset_font_size(&mut self); fn scroll(&mut self, scroll: Scroll); + fn clear_history(&mut self); fn hide_window(&mut self); } @@ -183,6 +184,9 @@ pub enum Action { /// Scroll all the way to the bottom ScrollToBottom, + /// Clear the display buffer(s) to remove history + ClearHistory, + /// Run given command Command(String, Vec), @@ -272,6 +276,9 @@ impl Action { Action::ScrollToBottom => { ctx.scroll(Scroll::Bottom); }, + Action::ClearHistory => { + ctx.clear_history(); + }, } } @@ -634,15 +641,16 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { /// /// Returns true if an action is executed. fn process_key_bindings(&mut self, mods: ModifiersState, key: VirtualKeyCode) -> bool { + let mut has_binding = false; for binding in self.key_bindings { if binding.is_triggered_by(self.ctx.terminal_mode(), mods, &key) { // binding was triggered; run the action binding.execute(&mut self.ctx); - return true; + has_binding = true; } } - false + has_binding } /// Attempts to find a binding and execute its action @@ -652,15 +660,16 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> { /// /// Returns true if an action is executed. fn process_mouse_bindings(&mut self, mods: ModifiersState, button: MouseButton) -> bool { + let mut has_binding = false; for binding in self.mouse_bindings { if binding.is_triggered_by(self.ctx.terminal_mode(), mods, &button) { // binding was triggered; run the action binding.execute(&mut self.ctx); - return true; + has_binding = true; } } - false + has_binding } } @@ -756,6 +765,8 @@ mod tests { } fn reset_font_size(&mut self) { } + fn clear_history(&mut self) { + } fn hide_window(&mut self) { } } diff --git a/src/term/mod.rs b/src/term/mod.rs index ff7a53e9..21c97671 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -1797,7 +1797,9 @@ impl ansi::Handler for Term { } }, // If scrollback is implemented, this should clear it - ansi::ClearMode::Saved => return + ansi::ClearMode::Saved => { + self.grid.clear_history(); + } } } @@ -2006,9 +2008,9 @@ mod tests { use super::{Cell, Term, SizeInfo}; use term::cell; - use grid::Grid; + use grid::{Grid, Scroll}; use index::{Point, Line, Column}; - use ansi::{Handler, CharsetIndex, StandardCharset}; + use ansi::{self, Handler, CharsetIndex, StandardCharset}; use selection::Selection; use std::mem; use input::FONT_SIZE_STEP; @@ -2183,6 +2185,31 @@ mod tests { let expected_font_size: Size = config.font().size(); assert_eq!(term.font_size, expected_font_size); } + + #[test] + fn clear_saved_lines() { + let size = SizeInfo { + width: 21.0, + height: 51.0, + cell_width: 3.0, + cell_height: 3.0, + padding_x: 0.0, + padding_y: 0.0, + }; + let config: Config = Default::default(); + let mut term: Term = Term::new(&config, size); + + // Add one line of scrollback + term.grid.scroll_up(&(Line(0)..Line(1)), Line(1), &Cell::default()); + + // Clear the history + term.clear_screen(ansi::ClearMode::Saved); + + // Make sure that scrolling does not change the grid + let mut scrolled_grid = term.grid.clone(); + scrolled_grid.scroll_display(Scroll::Top); + assert_eq!(term.grid, scrolled_grid); + } } #[cfg(all(test, feature = "bench"))]