mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 21:32:13 +03:00
term: extract configuration to a trait
This isn't complete but begins the process of extracting the embedding application configuration into a trait provided by the application rather than passing the values in at construction. This allows the application to change configuration at runtime. The first option to handle this is the scrollback size.
This commit is contained in:
parent
e56dfa9875
commit
7c7825c070
@ -26,6 +26,7 @@ mod daemon;
|
||||
mod font;
|
||||
mod keys;
|
||||
mod ssh;
|
||||
mod terminal;
|
||||
mod tls;
|
||||
mod unix;
|
||||
pub use color::*;
|
||||
@ -33,6 +34,7 @@ pub use daemon::*;
|
||||
pub use font::*;
|
||||
pub use keys::*;
|
||||
pub use ssh::*;
|
||||
pub use terminal::*;
|
||||
pub use tls::*;
|
||||
pub use unix::*;
|
||||
|
||||
@ -214,7 +216,8 @@ pub struct Config {
|
||||
pub colors: Option<Palette>,
|
||||
|
||||
/// How many lines of scrollback you want to retain
|
||||
pub scrollback_lines: Option<usize>,
|
||||
#[serde(default = "default_scrollback_lines")]
|
||||
pub scrollback_lines: usize,
|
||||
|
||||
/// If no `prog` is specified on the command line, use this
|
||||
/// instead of running the user's shell.
|
||||
@ -459,6 +462,10 @@ fn default_swap_backspace_and_delete() -> bool {
|
||||
cfg!(target_os = "macos")
|
||||
}
|
||||
|
||||
fn default_scrollback_lines() -> usize {
|
||||
3500
|
||||
}
|
||||
|
||||
fn default_hyperlink_rules() -> Vec<hyperlink::Rule> {
|
||||
vec![
|
||||
// URL with a protocol
|
||||
|
12
src/config/terminal.rs
Normal file
12
src/config/terminal.rs
Normal file
@ -0,0 +1,12 @@
|
||||
//! Bridge our gui config into the terminal crate configuration
|
||||
|
||||
use crate::config::configuration;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TermConfig;
|
||||
|
||||
impl term::TerminalConfiguration for TermConfig {
|
||||
fn scrollback_size(&self) -> usize {
|
||||
configuration().scrollback_lines
|
||||
}
|
||||
}
|
@ -100,8 +100,8 @@ impl Domain for LocalDomain {
|
||||
size.cols as usize,
|
||||
size.pixel_width as usize,
|
||||
size.pixel_height as usize,
|
||||
config.scrollback_lines.unwrap_or(3500),
|
||||
config.hyperlink_rules.clone(),
|
||||
std::sync::Arc::new(crate::config::TermConfig {}),
|
||||
);
|
||||
|
||||
let mux = Mux::get().unwrap();
|
||||
|
@ -352,8 +352,8 @@ impl Domain for RemoteSshDomain {
|
||||
size.cols as usize,
|
||||
size.pixel_width as usize,
|
||||
size.pixel_height as usize,
|
||||
config.scrollback_lines.unwrap_or(3500),
|
||||
config.hyperlink_rules.clone(),
|
||||
std::sync::Arc::new(crate::config::TermConfig {}),
|
||||
);
|
||||
|
||||
let mux = Mux::get().unwrap();
|
||||
|
26
term/src/config.rs
Normal file
26
term/src/config.rs
Normal file
@ -0,0 +1,26 @@
|
||||
pub trait TerminalConfiguration: std::fmt::Debug {
|
||||
fn scrollback_size(&self) -> usize {
|
||||
3500
|
||||
}
|
||||
|
||||
// TODO: expose is_double_click_word in config file
|
||||
fn is_double_click_word(&self, s: &str) -> bool {
|
||||
if s.len() > 1 {
|
||||
true
|
||||
} else if s.len() == 1 {
|
||||
match s.chars().nth(0).unwrap() {
|
||||
' ' | '\t' | '\n' | '{' | '[' | '}' | ']' | '(' | ')' | '"' | '\'' => false,
|
||||
_ => true,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: expose scroll_to_bottom_on_key_input in config file
|
||||
fn scroll_to_bottom_on_key_input(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
// fn hyperlink_rules(&self) -> &Vec<HyperlinkRule>;
|
||||
}
|
@ -5,6 +5,9 @@ use failure::Error;
|
||||
use std::ops::{Deref, DerefMut, Range};
|
||||
use std::str;
|
||||
|
||||
pub mod config;
|
||||
pub use config::TerminalConfiguration;
|
||||
|
||||
pub mod input;
|
||||
pub use crate::input::*;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::*;
|
||||
use log::debug;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Holds the model of a screen. This can either be the primary screen
|
||||
/// which includes lines of scrollback text, or the alternate screen
|
||||
@ -18,8 +19,9 @@ pub struct Screen {
|
||||
/// would otherwise have exceeded the line capacity
|
||||
pub lines: VecDeque<Line>,
|
||||
|
||||
/// Maximum number of lines of scrollback
|
||||
pub scrollback_size: usize,
|
||||
/// config so we can access Maximum number of lines of scrollback
|
||||
config: Arc<dyn TerminalConfiguration>,
|
||||
allow_scrollback: bool,
|
||||
|
||||
/// Physical, visible height of the screen (not including scrollback)
|
||||
pub physical_rows: usize,
|
||||
@ -27,33 +29,52 @@ pub struct Screen {
|
||||
pub physical_cols: usize,
|
||||
}
|
||||
|
||||
fn scrollback_size(config: &Arc<dyn TerminalConfiguration>, allow_scrollback: bool) -> usize {
|
||||
if allow_scrollback {
|
||||
config.scrollback_size()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl Screen {
|
||||
/// Create a new Screen with the specified dimensions.
|
||||
/// The Cells in the viewable portion of the screen are set to the
|
||||
/// default cell attributes.
|
||||
pub fn new(physical_rows: usize, physical_cols: usize, scrollback_size: usize) -> Screen {
|
||||
pub fn new(
|
||||
physical_rows: usize,
|
||||
physical_cols: usize,
|
||||
config: &Arc<dyn TerminalConfiguration>,
|
||||
allow_scrollback: bool,
|
||||
) -> Screen {
|
||||
let physical_rows = physical_rows.max(1);
|
||||
let physical_cols = physical_cols.max(1);
|
||||
|
||||
let mut lines = VecDeque::with_capacity(physical_rows + scrollback_size);
|
||||
let mut lines =
|
||||
VecDeque::with_capacity(physical_rows + scrollback_size(config, allow_scrollback));
|
||||
for _ in 0..physical_rows {
|
||||
lines.push_back(Line::with_width(physical_cols));
|
||||
}
|
||||
|
||||
Screen {
|
||||
lines,
|
||||
scrollback_size,
|
||||
config: Arc::clone(config),
|
||||
allow_scrollback,
|
||||
physical_rows,
|
||||
physical_cols,
|
||||
}
|
||||
}
|
||||
|
||||
fn scrollback_size(&self) -> usize {
|
||||
scrollback_size(&self.config, self.allow_scrollback)
|
||||
}
|
||||
|
||||
/// Resize the physical, viewable portion of the screen
|
||||
pub fn resize(&mut self, physical_rows: usize, physical_cols: usize) {
|
||||
let physical_rows = physical_rows.max(1);
|
||||
let physical_cols = physical_cols.max(1);
|
||||
|
||||
let capacity = physical_rows + self.scrollback_size;
|
||||
let capacity = physical_rows + self.scrollback_size();
|
||||
let current_capacity = self.lines.capacity();
|
||||
if capacity > current_capacity {
|
||||
self.lines.reserve(capacity - current_capacity);
|
||||
@ -209,7 +230,7 @@ impl Screen {
|
||||
// Remove the scrolled lines
|
||||
num_rows
|
||||
} else {
|
||||
let max_allowed = self.physical_rows + self.scrollback_size;
|
||||
let max_allowed = self.physical_rows + self.scrollback_size();
|
||||
if self.lines.len() + num_rows >= max_allowed {
|
||||
(self.lines.len() + num_rows) - max_allowed
|
||||
} else {
|
||||
|
@ -72,8 +72,8 @@ impl Terminal {
|
||||
physical_cols: usize,
|
||||
pixel_width: usize,
|
||||
pixel_height: usize,
|
||||
scrollback_size: usize,
|
||||
hyperlink_rules: Vec<HyperlinkRule>,
|
||||
config: Arc<dyn TerminalConfiguration>,
|
||||
) -> Terminal {
|
||||
Terminal {
|
||||
state: TerminalState::new(
|
||||
@ -81,8 +81,8 @@ impl Terminal {
|
||||
physical_cols,
|
||||
pixel_height,
|
||||
pixel_width,
|
||||
scrollback_size,
|
||||
hyperlink_rules,
|
||||
config,
|
||||
),
|
||||
parser: Parser::new(),
|
||||
}
|
||||
|
@ -100,9 +100,13 @@ impl DerefMut for ScreenOrAlt {
|
||||
}
|
||||
|
||||
impl ScreenOrAlt {
|
||||
pub fn new(physical_rows: usize, physical_cols: usize, scrollback_size: usize) -> Self {
|
||||
let screen = Screen::new(physical_rows, physical_cols, scrollback_size);
|
||||
let alt_screen = Screen::new(physical_rows, physical_cols, 0);
|
||||
pub fn new(
|
||||
physical_rows: usize,
|
||||
physical_cols: usize,
|
||||
config: &Arc<dyn TerminalConfiguration>,
|
||||
) -> Self {
|
||||
let screen = Screen::new(physical_rows, physical_cols, config, true);
|
||||
let alt_screen = Screen::new(physical_rows, physical_cols, config, false);
|
||||
|
||||
Self {
|
||||
screen,
|
||||
@ -140,6 +144,8 @@ impl ScreenOrAlt {
|
||||
}
|
||||
|
||||
pub struct TerminalState {
|
||||
config: Arc<dyn TerminalConfiguration>,
|
||||
|
||||
screen: ScreenOrAlt,
|
||||
/// The current set of attributes in effect for the next
|
||||
/// attempt to print to the display
|
||||
@ -203,6 +209,7 @@ pub struct TerminalState {
|
||||
|
||||
tabs: TabStop,
|
||||
|
||||
/// FIXME: replace hyperlink_rules with config access
|
||||
hyperlink_rules: Vec<HyperlinkRule>,
|
||||
|
||||
/// The terminal title string
|
||||
@ -213,20 +220,6 @@ pub struct TerminalState {
|
||||
pixel_height: usize,
|
||||
}
|
||||
|
||||
fn is_double_click_word(s: &str) -> bool {
|
||||
// TODO: add configuration for this
|
||||
if s.len() > 1 {
|
||||
true
|
||||
} else if s.len() == 1 {
|
||||
match s.chars().nth(0).unwrap() {
|
||||
' ' | '\t' | '\n' | '{' | '[' | '}' | ']' | '(' | ')' | '"' | '\'' => false,
|
||||
_ => true,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_modifiers(mods: KeyModifiers) -> u8 {
|
||||
let mut number = 0;
|
||||
if mods.contains(KeyModifiers::SHIFT) {
|
||||
@ -267,12 +260,13 @@ impl TerminalState {
|
||||
physical_cols: usize,
|
||||
pixel_width: usize,
|
||||
pixel_height: usize,
|
||||
scrollback_size: usize,
|
||||
hyperlink_rules: Vec<HyperlinkRule>,
|
||||
config: Arc<dyn TerminalConfiguration>,
|
||||
) -> TerminalState {
|
||||
let screen = ScreenOrAlt::new(physical_rows, physical_cols, scrollback_size);
|
||||
let screen = ScreenOrAlt::new(physical_rows, physical_cols, &config);
|
||||
|
||||
TerminalState {
|
||||
config,
|
||||
screen,
|
||||
pen: CellAttributes::default(),
|
||||
cursor: CursorPosition::default(),
|
||||
@ -483,7 +477,7 @@ impl TerminalState {
|
||||
- self.viewport_offset as ScrollbackOrVisibleRowIndex;
|
||||
let idx = self.screen().scrollback_or_visible_row(y);
|
||||
let selection_range = match self.screen().lines[idx]
|
||||
.compute_double_click_range(event.x, is_double_click_word)
|
||||
.compute_double_click_range(event.x, |s| self.config.is_double_click_word(s))
|
||||
{
|
||||
DoubleClickRange::Range(click_range) => SelectionRange {
|
||||
start: SelectionCoordinate {
|
||||
@ -508,7 +502,7 @@ impl TerminalState {
|
||||
|
||||
for y_cont in idx + 1..self.screen().lines.len() {
|
||||
match self.screen().lines[y_cont]
|
||||
.compute_double_click_range(0, is_double_click_word)
|
||||
.compute_double_click_range(0, |s| self.config.is_double_click_word(s))
|
||||
{
|
||||
DoubleClickRange::Range(range_end) => {
|
||||
if range_end.end > range_end.start {
|
||||
@ -1089,8 +1083,10 @@ impl TerminalState {
|
||||
writer.write_all(to_send.as_bytes())?;
|
||||
|
||||
// Reset the viewport if we sent data to the parser
|
||||
if !to_send.is_empty() && self.viewport_offset != 0 {
|
||||
// TODO: some folks like to configure this behavior.
|
||||
if !to_send.is_empty()
|
||||
&& self.viewport_offset != 0
|
||||
&& self.config.scroll_to_bottom_on_key_input()
|
||||
{
|
||||
self.set_scroll_viewport(0);
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,16 @@ struct TestTerm {
|
||||
host: TestHost,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TestTermConfig {
|
||||
scrollback: usize,
|
||||
}
|
||||
impl TerminalConfiguration for TestTermConfig {
|
||||
fn scrollback_size(&self) -> usize {
|
||||
self.scrollback
|
||||
}
|
||||
}
|
||||
|
||||
impl TestTerm {
|
||||
fn new(height: usize, width: usize, scrollback: usize) -> Self {
|
||||
Self {
|
||||
@ -94,8 +104,8 @@ impl TestTerm {
|
||||
width,
|
||||
height * 16,
|
||||
width * 8,
|
||||
scrollback,
|
||||
Vec::new(),
|
||||
Arc::new(TestTermConfig { scrollback }),
|
||||
),
|
||||
host: TestHost::new(),
|
||||
}
|
||||
|
@ -195,10 +195,10 @@ impl Line {
|
||||
s
|
||||
}
|
||||
|
||||
pub fn compute_double_click_range(
|
||||
pub fn compute_double_click_range<F: Fn(&str) -> bool>(
|
||||
&self,
|
||||
click_col: usize,
|
||||
is_word: fn(s: &str) -> bool,
|
||||
is_word: F,
|
||||
) -> DoubleClickRange {
|
||||
let mut lower = click_col;
|
||||
let mut upper = click_col;
|
||||
|
Loading…
Reference in New Issue
Block a user