Rework auto-scrolling options

This changes two things, the first thing it does is that now whenever a
keybinding sends an escape sequence, the viewport is automatically
scrolled to the bottom.
This is enabled by default and fixes #1187.

The second thing is automatic scrolling when a command writes to the
terminal. So when running a command like `sleep 3; ls -lah`, alacritty
will scroll to the bottom once the output is sent, even if the viewport
is currently not at the bottom of the scrollback.
Because this can have an impact on performance, and is not enabled by
default in terminals like iTerm or Termite (VTE), it is an opt-in
setting in the config.
This commit is contained in:
Christian Duerr 2018-03-23 01:01:55 +01:00 committed by Joe Wilm
parent 4333b2fb19
commit 688cabefc0
6 changed files with 33 additions and 4 deletions

View File

@ -52,6 +52,10 @@ scrolling:
# To disable this completely, set `faux_multiplier` to 0.
faux_multiplier: 3
# Automatically scroll to the bottom when new text is written
# to the terminal.
auto_scroll: false
# Display tabs using this many cells (changes require restart)
tabspaces: 8

View File

@ -50,6 +50,10 @@ scrolling:
# To disable this completely, set `faux_multiplier` to 0.
faux_multiplier: 3
# Automatically scroll to the bottom when new text is written
# to the terminal.
auto_scroll: false
# Display tabs using this many cells (changes require restart)
tabspaces: 8

View File

@ -478,6 +478,8 @@ pub struct Scrolling {
#[serde(deserialize_with="deserialize_scrolling_multiplier")]
#[serde(default="default_scrolling_multiplier")]
pub faux_multiplier: u8,
#[serde(default, deserialize_with="failure_default")]
pub auto_scroll: bool,
}
fn default_scrolling_history() -> u32 {
@ -495,6 +497,7 @@ impl Default for Scrolling {
history: default_scrolling_history(),
multiplier: default_scrolling_multiplier(),
faux_multiplier: default_scrolling_multiplier(),
auto_scroll: false,
}
}
}

View File

@ -255,6 +255,9 @@ impl<Io> EventLoop<Io>
let mut processed = 0;
let mut terminal = None;
// Flag to keep track if wakeup has already been sent
let mut send_wakeup = false;
loop {
match self.pty.read(&mut buf[..]) {
Ok(0) => break,
@ -272,10 +275,14 @@ impl<Io> EventLoop<Io>
// Get reference to terminal. Lock is acquired on initial
// iteration and held until there's no bytes left to parse
// or we've reached MAX_READ.
if terminal.is_none() {
let terminal = if terminal.is_none() {
terminal = Some(self.terminal.lock());
}
let terminal = terminal.as_mut().unwrap();
let terminal = terminal.as_mut().unwrap();
send_wakeup = !terminal.dirty;
terminal
} else {
terminal.as_mut().unwrap()
};
// Run the parser
for byte in &buf[..got] {
@ -301,7 +308,7 @@ impl<Io> EventLoop<Io>
// Only request a draw if one hasn't already been requested.
if let Some(mut terminal) = terminal {
if !terminal.dirty {
if send_wakeup {
self.display.notify();
terminal.dirty = true;
}

View File

@ -192,6 +192,7 @@ impl Action {
fn execute<A: ActionContext>(&self, ctx: &mut A) {
match *self {
Action::Esc(ref s) => {
ctx.scroll(Scroll::Bottom);
ctx.write_to_pty(s.clone().into_bytes())
},
Action::Copy => {

View File

@ -756,6 +756,9 @@ pub struct Term {
/// Number of spaces in one tab
tabspaces: usize,
/// Automatically scroll to bottom when new lines are added
auto_scroll: bool,
}
/// Terminal size info
@ -879,6 +882,7 @@ impl Term {
default_cursor_style: config.cursor_style(),
dynamic_title: config.dynamic_title(),
tabspaces,
auto_scroll: config.scrolling().auto_scroll,
}
}
@ -905,6 +909,7 @@ impl Term {
self.visual_bell.update_config(config);
self.default_cursor_style = config.cursor_style();
self.dynamic_title = config.dynamic_title();
self.auto_scroll = config.scrolling().auto_scroll;
}
#[inline]
@ -1255,6 +1260,11 @@ impl ansi::Handler for Term {
/// A character to be displayed
#[inline]
fn input(&mut self, c: char) {
// If enabled, scroll to bottom when character is received
if self.auto_scroll {
self.scroll_display(Scroll::Bottom);
}
if self.input_needs_wrap {
if !self.mode.contains(mode::TermMode::LINE_WRAP) {
return;