From e23d06b70d827bd2a4d1c674019a0321a9f67e2d Mon Sep 17 00:00:00 2001 From: Kunal Mohan <44079328+kunalmohan@users.noreply.github.com> Date: Tue, 4 Jan 2022 23:24:05 +0530 Subject: [PATCH] Feature: Configurable scroll buffer (#936) * Configurable scroll buffer * Fix unit test failures * Add scroll_buffer_size description in the default config file * Fix config file --- zellij-server/src/lib.rs | 10 ++++++++++ zellij-server/src/panes/grid.rs | 19 +++++++++++++------ zellij-utils/Cargo.toml | 2 +- zellij-utils/assets/config/default.yaml | 7 +++++++ zellij-utils/src/consts.rs | 3 +++ zellij-utils/src/input/options.rs | 7 +++++++ 6 files changed, 41 insertions(+), 7 deletions(-) diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs index 4a242715..96b7e7fa 100644 --- a/zellij-server/src/lib.rs +++ b/zellij-server/src/lib.rs @@ -37,6 +37,7 @@ use route::route_thread_main; use zellij_utils::{ channels::{self, ChannelWithContext, SenderWithContext}, cli::CliArgs, + consts::{DEFAULT_SCROLL_BUFFER_SIZE, SCROLL_BUFFER_SIZE}, errors::{ContextType, ErrorInstruction, ServerContext}, input::{ command::{RunCommand, TerminalAction}, @@ -541,6 +542,15 @@ fn init_session( layout, plugins, } = options; + + SCROLL_BUFFER_SIZE + .set( + config_options + .scroll_buffer_size + .unwrap_or(DEFAULT_SCROLL_BUFFER_SIZE), + ) + .unwrap(); + let (to_screen, screen_receiver): ChannelWithContext = channels::unbounded(); let to_screen = SenderWithContext::new(to_screen); diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs index c1b40b14..5db11671 100644 --- a/zellij-server/src/panes/grid.rs +++ b/zellij-server/src/panes/grid.rs @@ -7,10 +7,13 @@ use std::{ str, }; -use zellij_utils::{position::Position, vte, zellij_tile}; +use zellij_utils::{ + consts::{DEFAULT_SCROLL_BUFFER_SIZE, SCROLL_BUFFER_SIZE}, + position::Position, + vte, zellij_tile, +}; const TABSTOP_WIDTH: usize = 8; // TODO: is this always right? -pub const SCROLL_BACK: usize = 10_000; pub const MAX_TITLE_STACK_SIZE: usize = 1000; use vte::{Params, Perform}; @@ -226,7 +229,7 @@ fn transfer_rows_from_lines_below_to_viewport( fn bounded_push(vec: &mut VecDeque, value: Row) -> Option { let mut dropped_line_width = None; - if vec.len() >= SCROLL_BACK { + if vec.len() >= *SCROLL_BUFFER_SIZE.get().unwrap() { let line = vec.pop_front(); if let Some(line) = line { dropped_line_width = Some(line.width()); @@ -419,7 +422,11 @@ impl Debug for Grid { impl Grid { pub fn new(rows: usize, columns: usize, colors: Palette) -> Self { Grid { - lines_above: VecDeque::with_capacity(SCROLL_BACK), + lines_above: VecDeque::with_capacity( + // .get_or_init() is used instead of .get().unwrap() to prevent + // unit tests from panicking where SCROLL_BUFFER_SIZE is uninitialized. + *SCROLL_BUFFER_SIZE.get_or_init(|| DEFAULT_SCROLL_BUFFER_SIZE), + ), viewport: vec![Row::new(columns).canonical()], lines_below: vec![], horizontal_tabstops: create_horizontal_tabstops(columns), @@ -1350,7 +1357,7 @@ impl Grid { self.should_render = true; } fn reset_terminal_state(&mut self) { - self.lines_above = VecDeque::with_capacity(SCROLL_BACK); + self.lines_above = VecDeque::with_capacity(*SCROLL_BUFFER_SIZE.get().unwrap()); self.lines_below = vec![]; self.viewport = vec![Row::new(self.width).canonical()]; self.alternative_lines_above_viewport_and_cursor = None; @@ -1849,7 +1856,7 @@ impl Perform for Grid { Some(1049) => { let current_lines_above = std::mem::replace( &mut self.lines_above, - VecDeque::with_capacity(SCROLL_BACK), + VecDeque::with_capacity(*SCROLL_BUFFER_SIZE.get().unwrap()), ); let current_viewport = std::mem::replace( &mut self.viewport, diff --git a/zellij-utils/Cargo.toml b/zellij-utils/Cargo.toml index 2825a721..e6f7ddb6 100644 --- a/zellij-utils/Cargo.toml +++ b/zellij-utils/Cargo.toml @@ -20,7 +20,7 @@ interprocess = "1.1.1" lazy_static = "1.4.0" libc = "0.2" nix = "0.19.1" -once_cell = "1.7.2" +once_cell = "1.8.0" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" serde_json = "1.0" diff --git a/zellij-utils/assets/config/default.yaml b/zellij-utils/assets/config/default.yaml index dd67fe1f..13176973 100644 --- a/zellij-utils/assets/config/default.yaml +++ b/zellij-utils/assets/config/default.yaml @@ -461,3 +461,10 @@ plugins: # - true (default) # - false #mouse_mode: false + +# Configure the scroll back buffer size +# This is the number of lines zellij stores for each pane in the scroll back +# buffer. Excess number of lines are discarded in a FIFO fashion. +# Valid values: positive integers +# Default value: 10000 +#scroll_buffer_size: 10000 diff --git a/zellij-utils/src/consts.rs b/zellij-utils/src/consts.rs index 416153f2..494d12a2 100644 --- a/zellij-utils/src/consts.rs +++ b/zellij-utils/src/consts.rs @@ -5,6 +5,7 @@ use crate::shared::set_permissions; use directories_next::ProjectDirs; use lazy_static::lazy_static; use nix::unistd::Uid; +use once_cell::sync::OnceCell; use std::path::PathBuf; use std::{env, fs}; @@ -12,6 +13,8 @@ pub const ZELLIJ_CONFIG_FILE_ENV: &str = "ZELLIJ_CONFIG_FILE"; pub const ZELLIJ_CONFIG_DIR_ENV: &str = "ZELLIJ_CONFIG_DIR"; pub const ZELLIJ_LAYOUT_DIR_ENV: &str = "ZELLIJ_LAYOUT_DIR"; pub const VERSION: &str = env!("CARGO_PKG_VERSION"); +pub const DEFAULT_SCROLL_BUFFER_SIZE: usize = 10_000; +pub static SCROLL_BUFFER_SIZE: OnceCell = OnceCell::new(); pub const SYSTEM_DEFAULT_CONFIG_DIR: &str = "/etc/zellij"; pub const SYSTEM_DEFAULT_DATA_DIR_PREFIX: &str = system_default_data_dir(); diff --git a/zellij-utils/src/input/options.rs b/zellij-utils/src/input/options.rs index e0a38946..dcaad306 100644 --- a/zellij-utils/src/input/options.rs +++ b/zellij-utils/src/input/options.rs @@ -72,6 +72,8 @@ pub struct Options { /// Set behaviour on force close (quit or detach) #[structopt(long)] pub on_force_close: Option, + #[structopt(long)] + pub scroll_buffer_size: Option, } impl Options { @@ -96,6 +98,7 @@ impl Options { let layout_dir = other.layout_dir.or_else(|| self.layout_dir.clone()); let theme = other.theme.or_else(|| self.theme.clone()); let on_force_close = other.on_force_close.or(self.on_force_close); + let scroll_buffer_size = other.scroll_buffer_size.or(self.scroll_buffer_size); Options { simplified_ui, @@ -107,6 +110,7 @@ impl Options { pane_frames, mirror_session, on_force_close, + scroll_buffer_size, } } @@ -135,6 +139,7 @@ impl Options { let layout_dir = other.layout_dir.or_else(|| self.layout_dir.clone()); let theme = other.theme.or_else(|| self.theme.clone()); let on_force_close = other.on_force_close.or(self.on_force_close); + let scroll_buffer_size = other.scroll_buffer_size.or(self.scroll_buffer_size); Options { simplified_ui, @@ -146,6 +151,7 @@ impl Options { pane_frames, mirror_session, on_force_close, + scroll_buffer_size, } } @@ -193,6 +199,7 @@ impl From for Options { pane_frames: opts.pane_frames, mirror_session: opts.mirror_session, on_force_close: opts.on_force_close, + scroll_buffer_size: opts.scroll_buffer_size, } } }