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
This commit is contained in:
Kunal Mohan 2022-01-04 23:24:05 +05:30 committed by GitHub
parent 3e0ac752cc
commit e23d06b70d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 7 deletions

View file

@ -37,6 +37,7 @@ use route::route_thread_main;
use zellij_utils::{ use zellij_utils::{
channels::{self, ChannelWithContext, SenderWithContext}, channels::{self, ChannelWithContext, SenderWithContext},
cli::CliArgs, cli::CliArgs,
consts::{DEFAULT_SCROLL_BUFFER_SIZE, SCROLL_BUFFER_SIZE},
errors::{ContextType, ErrorInstruction, ServerContext}, errors::{ContextType, ErrorInstruction, ServerContext},
input::{ input::{
command::{RunCommand, TerminalAction}, command::{RunCommand, TerminalAction},
@ -541,6 +542,15 @@ fn init_session(
layout, layout,
plugins, plugins,
} = options; } = options;
SCROLL_BUFFER_SIZE
.set(
config_options
.scroll_buffer_size
.unwrap_or(DEFAULT_SCROLL_BUFFER_SIZE),
)
.unwrap();
let (to_screen, screen_receiver): ChannelWithContext<ScreenInstruction> = channels::unbounded(); let (to_screen, screen_receiver): ChannelWithContext<ScreenInstruction> = channels::unbounded();
let to_screen = SenderWithContext::new(to_screen); let to_screen = SenderWithContext::new(to_screen);

View file

@ -7,10 +7,13 @@ use std::{
str, 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? 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; pub const MAX_TITLE_STACK_SIZE: usize = 1000;
use vte::{Params, Perform}; use vte::{Params, Perform};
@ -226,7 +229,7 @@ fn transfer_rows_from_lines_below_to_viewport(
fn bounded_push(vec: &mut VecDeque<Row>, value: Row) -> Option<usize> { fn bounded_push(vec: &mut VecDeque<Row>, value: Row) -> Option<usize> {
let mut dropped_line_width = None; let mut dropped_line_width = None;
if vec.len() >= SCROLL_BACK { if vec.len() >= *SCROLL_BUFFER_SIZE.get().unwrap() {
let line = vec.pop_front(); let line = vec.pop_front();
if let Some(line) = line { if let Some(line) = line {
dropped_line_width = Some(line.width()); dropped_line_width = Some(line.width());
@ -419,7 +422,11 @@ impl Debug for Grid {
impl Grid { impl Grid {
pub fn new(rows: usize, columns: usize, colors: Palette) -> Self { pub fn new(rows: usize, columns: usize, colors: Palette) -> Self {
Grid { 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()], viewport: vec![Row::new(columns).canonical()],
lines_below: vec![], lines_below: vec![],
horizontal_tabstops: create_horizontal_tabstops(columns), horizontal_tabstops: create_horizontal_tabstops(columns),
@ -1350,7 +1357,7 @@ impl Grid {
self.should_render = true; self.should_render = true;
} }
fn reset_terminal_state(&mut self) { 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.lines_below = vec![];
self.viewport = vec![Row::new(self.width).canonical()]; self.viewport = vec![Row::new(self.width).canonical()];
self.alternative_lines_above_viewport_and_cursor = None; self.alternative_lines_above_viewport_and_cursor = None;
@ -1849,7 +1856,7 @@ impl Perform for Grid {
Some(1049) => { Some(1049) => {
let current_lines_above = std::mem::replace( let current_lines_above = std::mem::replace(
&mut self.lines_above, &mut self.lines_above,
VecDeque::with_capacity(SCROLL_BACK), VecDeque::with_capacity(*SCROLL_BUFFER_SIZE.get().unwrap()),
); );
let current_viewport = std::mem::replace( let current_viewport = std::mem::replace(
&mut self.viewport, &mut self.viewport,

View file

@ -20,7 +20,7 @@ interprocess = "1.1.1"
lazy_static = "1.4.0" lazy_static = "1.4.0"
libc = "0.2" libc = "0.2"
nix = "0.19.1" nix = "0.19.1"
once_cell = "1.7.2" once_cell = "1.8.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8" serde_yaml = "0.8"
serde_json = "1.0" serde_json = "1.0"

View file

@ -461,3 +461,10 @@ plugins:
# - true (default) # - true (default)
# - false # - false
#mouse_mode: 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

View file

@ -5,6 +5,7 @@ use crate::shared::set_permissions;
use directories_next::ProjectDirs; use directories_next::ProjectDirs;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use nix::unistd::Uid; use nix::unistd::Uid;
use once_cell::sync::OnceCell;
use std::path::PathBuf; use std::path::PathBuf;
use std::{env, fs}; 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_CONFIG_DIR_ENV: &str = "ZELLIJ_CONFIG_DIR";
pub const ZELLIJ_LAYOUT_DIR_ENV: &str = "ZELLIJ_LAYOUT_DIR"; pub const ZELLIJ_LAYOUT_DIR_ENV: &str = "ZELLIJ_LAYOUT_DIR";
pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const DEFAULT_SCROLL_BUFFER_SIZE: usize = 10_000;
pub static SCROLL_BUFFER_SIZE: OnceCell<usize> = OnceCell::new();
pub const SYSTEM_DEFAULT_CONFIG_DIR: &str = "/etc/zellij"; pub const SYSTEM_DEFAULT_CONFIG_DIR: &str = "/etc/zellij";
pub const SYSTEM_DEFAULT_DATA_DIR_PREFIX: &str = system_default_data_dir(); pub const SYSTEM_DEFAULT_DATA_DIR_PREFIX: &str = system_default_data_dir();

View file

@ -72,6 +72,8 @@ pub struct Options {
/// Set behaviour on force close (quit or detach) /// Set behaviour on force close (quit or detach)
#[structopt(long)] #[structopt(long)]
pub on_force_close: Option<OnForceClose>, pub on_force_close: Option<OnForceClose>,
#[structopt(long)]
pub scroll_buffer_size: Option<usize>,
} }
impl Options { impl Options {
@ -96,6 +98,7 @@ impl Options {
let layout_dir = other.layout_dir.or_else(|| self.layout_dir.clone()); let layout_dir = other.layout_dir.or_else(|| self.layout_dir.clone());
let theme = other.theme.or_else(|| self.theme.clone()); let theme = other.theme.or_else(|| self.theme.clone());
let on_force_close = other.on_force_close.or(self.on_force_close); 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 { Options {
simplified_ui, simplified_ui,
@ -107,6 +110,7 @@ impl Options {
pane_frames, pane_frames,
mirror_session, mirror_session,
on_force_close, 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 layout_dir = other.layout_dir.or_else(|| self.layout_dir.clone());
let theme = other.theme.or_else(|| self.theme.clone()); let theme = other.theme.or_else(|| self.theme.clone());
let on_force_close = other.on_force_close.or(self.on_force_close); 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 { Options {
simplified_ui, simplified_ui,
@ -146,6 +151,7 @@ impl Options {
pane_frames, pane_frames,
mirror_session, mirror_session,
on_force_close, on_force_close,
scroll_buffer_size,
} }
} }
@ -193,6 +199,7 @@ impl From<CliOptions> for Options {
pane_frames: opts.pane_frames, pane_frames: opts.pane_frames,
mirror_session: opts.mirror_session, mirror_session: opts.mirror_session,
on_force_close: opts.on_force_close, on_force_close: opts.on_force_close,
scroll_buffer_size: opts.scroll_buffer_size,
} }
} }
} }