diff --git a/Cargo.lock b/Cargo.lock index f3533409..12545181 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,11 +4,11 @@ version = 3 [[package]] name = "addr2line" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a" +checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" dependencies = [ - "gimli 0.24.0", + "gimli 0.25.0", ] [[package]] @@ -227,16 +227,16 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7815ea54e4d821e791162e078acbebfd6d8c8939cd559c9335dceb1c8ca7282" +checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", - "object 0.25.3", + "object 0.26.0", "rustc-demangle", ] @@ -715,9 +715,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b705829d1e87f762c2df6da140b26af5839e1033aa84aa5f56bb688e4e1bdb" +checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e" dependencies = [ "instant", ] @@ -736,9 +736,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" +checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" dependencies = [ "futures-channel", "futures-core", @@ -751,9 +751,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" +checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9" dependencies = [ "futures-core", "futures-sink", @@ -761,15 +761,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" +checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" [[package]] name = "futures-executor" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" +checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" dependencies = [ "futures-core", "futures-task", @@ -778,9 +778,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" +checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" [[package]] name = "futures-lite" @@ -799,9 +799,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" +checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" dependencies = [ "autocfg", "proc-macro-hack", @@ -812,21 +812,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" +checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" [[package]] name = "futures-task" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" +checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" [[package]] name = "futures-util" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" +checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" dependencies = [ "autocfg", "futures-channel", @@ -897,9 +897,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" +checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" [[package]] name = "gloo-timers" @@ -1325,9 +1325,9 @@ dependencies = [ [[package]] name = "object" -version = "0.25.3" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" +checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" dependencies = [ "memchr", ] @@ -1500,9 +1500,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" dependencies = [ "unicode-xid", ] @@ -1966,9 +1966,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.73" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" +checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 5ccd8e48..d41cf02b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,4 +57,3 @@ assets = [ [features] disable_automatic_asset_installation = [] -parametric_resize_beta = [] diff --git a/Makefile.toml b/Makefile.toml index e0043ab7..041b82ea 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -70,7 +70,7 @@ args = ["clippy", "--", "@@split(CARGO_MAKE_TASK_ARGS,;)"] # Release building and installing Zellij [tasks.install] workspace = false -dependencies = ["build-plugins-release", "wasm-opt-plugins", "build-release", "manpage"] +dependencies = ["wasm-opt-plugins", "build-release", "manpage"] script_runner = "@duckscript" script = ''' if is_dir ${CARGO_MAKE_TASK_ARGS} @@ -89,6 +89,7 @@ env = { "CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS" = ["default-plugins/status-bar", run_task = { name = "build", fork = true } [tasks.wasm-opt-plugins] +dependencies = ["build-plugins-release"] script_runner = "@duckscript" script = ''' plugins = glob_array ${CARGO_TARGET_DIR}/wasm32-wasi/release/*.wasm @@ -134,6 +135,7 @@ args = ["build", "--verbose", "--target", "x86_64-unknown-linux-musl"] # Run e2e tests - we mark the e2e tests as "ignored" so they will not be run with the normal ones [tasks.e2e-test] workspace = false +dependencies = ["build-e2e"] command = "cargo" args = ["test", "--", "--ignored", "--nocapture", "--test-threads", "1", "@@split(CARGO_MAKE_TASK_ARGS,;)"] diff --git a/assets/plugins/status-bar.wasm b/assets/plugins/status-bar.wasm index 677e8727..0523679c 100644 Binary files a/assets/plugins/status-bar.wasm and b/assets/plugins/status-bar.wasm differ diff --git a/assets/plugins/strider.wasm b/assets/plugins/strider.wasm index b4fe4a7c..1f01a123 100644 Binary files a/assets/plugins/strider.wasm and b/assets/plugins/strider.wasm differ diff --git a/assets/plugins/tab-bar.wasm b/assets/plugins/tab-bar.wasm index 221d1baa..b2e1599b 100644 Binary files a/assets/plugins/tab-bar.wasm and b/assets/plugins/tab-bar.wasm differ diff --git a/default-plugins/status-bar/src/main.rs b/default-plugins/status-bar/src/main.rs index d2c6d82b..9f8e9eaa 100644 --- a/default-plugins/status-bar/src/main.rs +++ b/default-plugins/status-bar/src/main.rs @@ -135,8 +135,6 @@ fn color_elements(palette: Palette) -> ColoredElements { impl ZellijPlugin for State { fn load(&mut self) { set_selectable(false); - set_invisible_borders(true); - set_fixed_height(2); subscribe(&[ EventType::ModeUpdate, EventType::CopyToClipboard, diff --git a/default-plugins/tab-bar/src/line.rs b/default-plugins/tab-bar/src/line.rs index fc18abfd..b92f7573 100644 --- a/default-plugins/tab-bar/src/line.rs +++ b/default-plugins/tab-bar/src/line.rs @@ -5,9 +5,7 @@ use zellij_tile::prelude::*; use zellij_tile_utils::style; fn get_current_title_len(current_title: &[LinePart]) -> usize { - current_title - .iter() - .fold(0, |acc, title_part| acc + title_part.len) + current_title.iter().map(|p| p.len).sum() } fn populate_tabs_in_tab_line( @@ -144,20 +142,29 @@ fn add_next_tabs_msg( title_bar.push(right_more_message); } -fn tab_line_prefix(session_name: Option<&str>, palette: Palette) -> LinePart { - let mut prefix_text = " Zellij ".to_string(); - if let Some(name) = session_name { - prefix_text.push_str(&format!("({}) ", name)); - } +fn tab_line_prefix(session_name: Option<&str>, palette: Palette, cols: usize) -> Vec { + let prefix_text = " Zellij ".to_string(); let prefix_text_len = prefix_text.chars().count(); let prefix_styled_text = style!(palette.white, palette.cyan) .bold() .paint(prefix_text); - LinePart { + let mut parts = vec![LinePart { part: format!("{}", prefix_styled_text), len: prefix_text_len, + }]; + if let Some(name) = session_name { + let name_part = format!("({}) ", name); + let name_part_len = name_part.chars().count(); + let name_part_styled_text = style!(palette.white, palette.cyan).bold().paint(name_part); + if cols.saturating_sub(prefix_text_len) >= name_part_len { + parts.push(LinePart { + part: format!("{}", name_part_styled_text), + len: name_part_len, + }) + } } + parts } pub fn tab_separator(capabilities: PluginCapabilities) -> &'static str { @@ -176,7 +183,7 @@ pub fn tab_line( palette: Palette, capabilities: PluginCapabilities, ) -> Vec { - let mut tabs_to_render: Vec = vec![]; + let mut tabs_to_render = Vec::new(); let mut tabs_after_active = all_tabs.split_off(active_tab_index); let mut tabs_before_active = all_tabs; let active_tab = if !tabs_after_active.is_empty() { @@ -184,14 +191,17 @@ pub fn tab_line( } else { tabs_before_active.pop().unwrap() }; - tabs_to_render.push(active_tab); + let mut prefix = tab_line_prefix(session_name, palette, cols); + let prefix_len = get_current_title_len(&prefix); + if prefix_len + active_tab.len <= cols { + tabs_to_render.push(active_tab); + } - let prefix = tab_line_prefix(session_name, palette); populate_tabs_in_tab_line( &mut tabs_before_active, &mut tabs_after_active, &mut tabs_to_render, - cols.saturating_sub(prefix.len), + cols.saturating_sub(prefix_len), ); let mut tab_line: Vec = vec![]; @@ -200,7 +210,7 @@ pub fn tab_line( &mut tabs_before_active, &mut tabs_to_render, &mut tab_line, - cols.saturating_sub(prefix.len), + cols.saturating_sub(prefix_len), palette, tab_separator(capabilities), ); @@ -210,11 +220,11 @@ pub fn tab_line( add_next_tabs_msg( &mut tabs_after_active, &mut tab_line, - cols.saturating_sub(prefix.len), + cols.saturating_sub(prefix_len), palette, tab_separator(capabilities), ); } - tab_line.insert(0, prefix); - tab_line + prefix.append(&mut tab_line); + prefix } diff --git a/default-plugins/tab-bar/src/main.rs b/default-plugins/tab-bar/src/main.rs index a185ccc3..3256c13c 100644 --- a/default-plugins/tab-bar/src/main.rs +++ b/default-plugins/tab-bar/src/main.rs @@ -25,8 +25,6 @@ register_plugin!(State); impl ZellijPlugin for State { fn load(&mut self) { set_selectable(false); - set_invisible_borders(true); - set_fixed_height(1); subscribe(&[EventType::TabUpdate, EventType::ModeUpdate]); } diff --git a/rust-toolchain b/rust-toolchain index 078d01ce..2e6fad37 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "beta" +channel = "stable" components = ["rustfmt", "clippy", "rust-analysis"] targets = ["wasm32-wasi"] diff --git a/src/tests/e2e/cases.rs b/src/tests/e2e/cases.rs index d28ae2f7..2e09b53f 100644 --- a/src/tests/e2e/cases.rs +++ b/src/tests/e2e/cases.rs @@ -1,7 +1,7 @@ #![allow(unused)] use ::insta::assert_snapshot; -use zellij_utils::{pane_size::PositionAndSize, position::Position}; +use zellij_utils::{pane_size::Size, position::Position}; use rand::Rng; @@ -71,19 +71,16 @@ pub fn normal_mouse_report(position: Position, button: u8) -> Vec { #[test] #[ignore] pub fn starts_with_one_terminal() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("starts_with_one_terminal", fake_win_size, None) + let last_snapshot = RemoteRunner::new("starts_with_one_terminal", fake_win_size) .add_step(Step { name: "Wait for app to load", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { step_is_complete = true; } @@ -97,20 +94,17 @@ pub fn starts_with_one_terminal() { #[test] #[ignore] pub fn split_terminals_vertically() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("split_terminals_vertically", fake_win_size, None) + let last_snapshot = RemoteRunner::new("split_terminals_vertically", fake_win_size) .add_step(Step { name: "Split pane to the right", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); @@ -139,23 +133,16 @@ pub fn split_terminals_vertically() { #[test] #[ignore] pub fn cannot_split_terminals_vertically_when_active_terminal_is_too_small() { - let fake_win_size = PositionAndSize { - cols: 8, - rows: 20, - x: 0, - y: 0, - ..Default::default() - }; + let fake_win_size = Size { cols: 8, rows: 20 }; let last_snapshot = RemoteRunner::new( "cannot_split_terminals_vertically_when_active_terminal_is_too_small", fake_win_size, - None, ) .add_step(Step { name: "Split pane to the right", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) { + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); // back to normal mode after split @@ -178,7 +165,7 @@ pub fn cannot_split_terminals_vertically_when_active_terminal_is_too_small() { name: "Wait for text to appear", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(5, 2) && remote_terminal.snapshot_contains("Hi!") + if remote_terminal.cursor_position_is(6, 2) && remote_terminal.snapshot_contains("Hi!") { step_is_complete = true; } @@ -192,19 +179,16 @@ pub fn cannot_split_terminals_vertically_when_active_terminal_is_too_small() { #[test] #[ignore] pub fn scrolling_inside_a_pane() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("scrolling_inside_a_pane", fake_win_size, None) + let last_snapshot = RemoteRunner::new("scrolling_inside_a_pane", fake_win_size) .add_step(Step { name: "Split pane to the right", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); @@ -279,19 +263,16 @@ pub fn scrolling_inside_a_pane() { #[test] #[ignore] pub fn toggle_pane_fullscreen() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("toggle_pane_fullscreen", fake_win_size, None) + let last_snapshot = RemoteRunner::new("toggle_pane_fullscreen", fake_win_size) .add_step(Step { name: "Split pane to the right", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); @@ -321,7 +302,7 @@ pub fn toggle_pane_fullscreen() { name: "Wait for pane to become fullscreen", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(2, 2) { + if remote_terminal.cursor_position_is(3, 2) { // cursor is in full screen pane now step_is_complete = true; } @@ -335,19 +316,16 @@ pub fn toggle_pane_fullscreen() { #[test] #[ignore] pub fn open_new_tab() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("open_new_tab", fake_win_size, None) + let last_snapshot = RemoteRunner::new("open_new_tab", fake_win_size) .add_step(Step { name: "Split pane to the right", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); @@ -377,7 +355,7 @@ pub fn open_new_tab() { name: "Wait for new tab to open", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(2, 2) + if remote_terminal.cursor_position_is(3, 2) && remote_terminal.tip_appears() && remote_terminal.snapshot_contains("Tab #2") && remote_terminal.status_bar_appears() @@ -395,19 +373,16 @@ pub fn open_new_tab() { #[test] #[ignore] pub fn close_pane() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("close_pane", fake_win_size, None) + let last_snapshot = RemoteRunner::new("close_pane", fake_win_size) .add_step(Step { name: "Split pane to the right", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); @@ -437,7 +412,7 @@ pub fn close_pane() { name: "Wait for pane to close", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(2, 2) && remote_terminal.tip_appears() { + if remote_terminal.cursor_position_is(3, 2) && remote_terminal.tip_appears() { // cursor is in the original pane step_is_complete = true; } @@ -451,19 +426,16 @@ pub fn close_pane() { #[test] #[ignore] pub fn exit_zellij() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("exit_zellij", fake_win_size, None) + let last_snapshot = RemoteRunner::new("exit_zellij", fake_win_size) .add_step(Step { name: "Wait for app to load", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&QUIT); step_is_complete = true; @@ -490,19 +462,16 @@ pub fn exit_zellij() { #[test] #[ignore] pub fn closing_last_pane_exits_zellij() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("closing_last_pane_exits_zellij", fake_win_size, None) + let last_snapshot = RemoteRunner::new("closing_last_pane_exits_zellij", fake_win_size) .add_step(Step { name: "Close pane", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&CLOSE_PANE_IN_PANE_MODE); @@ -528,19 +497,16 @@ pub fn closing_last_pane_exits_zellij() { #[test] #[ignore] pub fn resize_pane() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("resize_pane", fake_win_size, None) + let last_snapshot = RemoteRunner::new("resize_pane", fake_win_size) .add_step(Step { name: "Split pane to the right", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); @@ -570,7 +536,7 @@ pub fn resize_pane() { name: "Wait for pane to be resized", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(53, 2) && remote_terminal.tip_appears() { + if remote_terminal.cursor_position_is(57, 2) && remote_terminal.tip_appears() { // pane has been resized step_is_complete = true; } @@ -584,19 +550,16 @@ pub fn resize_pane() { #[test] #[ignore] pub fn lock_mode() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("lock_mode", fake_win_size, None) + let last_snapshot = RemoteRunner::new("lock_mode", fake_win_size) .add_step(Step { name: "Enter lock mode", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&LOCK_MODE); step_is_complete = true; @@ -621,7 +584,7 @@ pub fn lock_mode() { name: "Wait for terminal to render sent keys", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(6, 2) { + if remote_terminal.cursor_position_is(7, 2) { // text has been entered into the only terminal pane step_is_complete = true; } @@ -636,19 +599,16 @@ pub fn lock_mode() { #[ignore] pub fn resize_terminal_window() { // this checks the resizing of the whole terminal window (reaction to SIGWINCH) and not just one pane - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("resize_terminal_window", fake_win_size, None) + let last_snapshot = RemoteRunner::new("resize_terminal_window", fake_win_size) .add_step(Step { name: "Split pane to the right", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); @@ -675,7 +635,7 @@ pub fn resize_terminal_window() { name: "wait for terminal to be resized and app to be re-rendered", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(43, 2) && remote_terminal.tip_appears() { + if remote_terminal.cursor_position_is(53, 2) && remote_terminal.tip_appears() { // size has been changed step_is_complete = true; } @@ -689,98 +649,87 @@ pub fn resize_terminal_window() { #[test] #[ignore] pub fn detach_and_attach_session() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let session_id = rand::thread_rng().gen_range(0..10000); - let session_name = format!("session_{}", session_id); - let last_snapshot = RemoteRunner::new( - "detach_and_attach_session", - fake_win_size, - Some(session_name), - ) - .add_step(Step { - name: "Split pane to the right", - instruction: |mut remote_terminal: RemoteTerminal| -> bool { - let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) { - remote_terminal.send_key(&PANE_MODE); - remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); - // back to normal mode after split - remote_terminal.send_key(&ENTER); - step_is_complete = true; - } - step_is_complete - }, - }) - .add_step(Step { - name: "Send some text to the active pane", - instruction: |mut remote_terminal: RemoteTerminal| -> bool { - let mut step_is_complete = false; - if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { - // new pane has been opened and focused - remote_terminal.send_key(&"I am some text".as_bytes()); - step_is_complete = true; - } - step_is_complete - }, - }) - .add_step(Step { - name: "Detach session", - instruction: |mut remote_terminal: RemoteTerminal| -> bool { - let mut step_is_complete = false; - if remote_terminal.cursor_position_is(77, 2) { - remote_terminal.send_key(&SESSION_MODE); - remote_terminal.send_key(&DETACH_IN_SESSION_MODE); - // text has been entered - step_is_complete = true; - } - step_is_complete - }, - }) - .add_step(Step { - name: "Reattach session", - instruction: |mut remote_terminal: RemoteTerminal| -> bool { - let mut step_is_complete = false; - if !remote_terminal.status_bar_appears() { - // we don't see the toolbar, so we can assume we've already detached - remote_terminal.attach_to_original_session(); - step_is_complete = true; - } - step_is_complete - }, - }) - .add_step(Step { - name: "Wait for session to be attached", - instruction: |remote_terminal: RemoteTerminal| -> bool { - let mut step_is_complete = false; - if remote_terminal.cursor_position_is(77, 2) { - // we're back inside the session - step_is_complete = true; - } - step_is_complete - }, - }) - .run_all_steps(); + let last_snapshot = RemoteRunner::new("detach_and_attach_session", fake_win_size) + .add_step(Step { + name: "Split pane to the right", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) + { + remote_terminal.send_key(&PANE_MODE); + remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); + // back to normal mode after split + remote_terminal.send_key(&ENTER); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Send some text to the active pane", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { + // new pane has been opened and focused + remote_terminal.send_key(&"I am some text".as_bytes()); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Detach session", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(77, 2) { + remote_terminal.send_key(&SESSION_MODE); + remote_terminal.send_key(&DETACH_IN_SESSION_MODE); + // text has been entered + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Reattach session", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if !remote_terminal.status_bar_appears() { + // we don't see the toolbar, so we can assume we've already detached + remote_terminal.attach_to_original_session(); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Wait for session to be attached", + instruction: |remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(77, 2) { + // we're back inside the session + step_is_complete = true; + } + step_is_complete + }, + }) + .run_all_steps(); assert_snapshot!(last_snapshot); } #[test] #[ignore] pub fn accepts_basic_layout() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; let layout_file_name = "three-panes-with-nesting.yaml"; - let last_snapshot = RemoteRunner::new_with_layout("accepts_basic_layout", fake_win_size, layout_file_name, None) + let last_snapshot = RemoteRunner::new_with_layout("accepts_basic_layout", fake_win_size, layout_file_name) .add_step(Step { name: "Wait for app to load", instruction: |remote_terminal: RemoteTerminal| -> bool { @@ -800,20 +749,17 @@ pub fn accepts_basic_layout() { #[test] #[ignore] fn focus_pane_with_mouse() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new("split_terminals_vertically", fake_win_size, None) + let last_snapshot = RemoteRunner::new("split_terminals_vertically", fake_win_size) .add_step(Step { name: "Split pane to the right", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) { remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); @@ -853,103 +799,95 @@ fn focus_pane_with_mouse() { #[test] #[ignore] pub fn scrolling_inside_a_pane_with_mouse() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = - RemoteRunner::new("scrolling_inside_a_pane_with_mouse", fake_win_size, None) - .add_step(Step { - name: "Split pane to the right", - instruction: |mut remote_terminal: RemoteTerminal| -> bool { - let mut step_is_complete = false; - if remote_terminal.status_bar_appears() - && remote_terminal.cursor_position_is(2, 2) - { - remote_terminal.send_key(&PANE_MODE); - remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); - // back to normal mode after split - remote_terminal.send_key(&ENTER); - step_is_complete = true; - } - step_is_complete - }, - }) - .add_step(Step { - name: "Fill terminal with text", - instruction: |mut remote_terminal: RemoteTerminal| -> bool { - let mut step_is_complete = false; - if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { - // cursor is in the newly opened second pane - remote_terminal.send_key(&format!("{:0<56}", "line1 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line2 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line3 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line4 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line5 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line6 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line7 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line8 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line9 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line10 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line11 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line12 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line13 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line14 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line15 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line16 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line17 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line18 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<58}", "line19 ").as_bytes()); - remote_terminal.send_key(&format!("{:0<57}", "line20 ").as_bytes()); - step_is_complete = true; - } - step_is_complete - }, - }) - .add_step(Step { - name: "Scroll up inside pane", - instruction: |mut remote_terminal: RemoteTerminal| -> bool { - let mut step_is_complete = false; - if remote_terminal.cursor_position_is(118, 20) { - // all lines have been written to the pane - remote_terminal.send_key(&normal_mouse_report(Position::new(2, 64), 64)); - step_is_complete = true; - } - step_is_complete - }, - }) - .add_step(Step { - name: "Wait for scroll to finish", - instruction: |remote_terminal: RemoteTerminal| -> bool { - let mut step_is_complete = false; - if remote_terminal.cursor_position_is(118, 20) - && remote_terminal.snapshot_contains("line1 ") - { - // scrolled up one line - step_is_complete = true; - } - step_is_complete - }, - }) - .run_all_steps(); + let last_snapshot = RemoteRunner::new("scrolling_inside_a_pane_with_mouse", fake_win_size) + .add_step(Step { + name: "Split pane to the right", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) + { + remote_terminal.send_key(&PANE_MODE); + remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); + // back to normal mode after split + remote_terminal.send_key(&ENTER); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Fill terminal with text", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { + // cursor is in the newly opened second pane + remote_terminal.send_key(&format!("{:0<56}", "line1 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line2 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line3 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line4 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line5 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line6 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line7 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line8 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line9 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line10 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line11 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line12 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line13 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line14 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line15 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line16 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line17 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line18 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line19 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<57}", "line20 ").as_bytes()); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Scroll up inside pane", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(118, 20) { + // all lines have been written to the pane + remote_terminal.send_key(&normal_mouse_report(Position::new(2, 64), 64)); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Wait for scroll to finish", + instruction: |remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(118, 20) + && remote_terminal.snapshot_contains("line1 ") + { + // scrolled up one line + step_is_complete = true; + } + step_is_complete + }, + }) + .run_all_steps(); assert_snapshot!(last_snapshot); } #[test] #[ignore] pub fn start_without_pane_frames() { - let fake_win_size = PositionAndSize { + let fake_win_size = Size { cols: 120, rows: 24, - x: 0, - y: 0, - ..Default::default() }; - let last_snapshot = RemoteRunner::new_without_frames("no_pane_frames", fake_win_size, None) + let last_snapshot = RemoteRunner::new_without_frames("no_pane_frames", fake_win_size) .add_step(Step { name: "Split pane to the right", instruction: |mut remote_terminal: RemoteTerminal| -> bool { diff --git a/src/tests/e2e/remote_runner.rs b/src/tests/e2e/remote_runner.rs index 819bee86..de9c35ed 100644 --- a/src/tests/e2e/remote_runner.rs +++ b/src/tests/e2e/remote_runner.rs @@ -1,7 +1,7 @@ use zellij_tile::data::Palette; -use zellij_utils::pane_size::PositionAndSize; use zellij_server::panes::TerminalPane; +use zellij_utils::pane_size::{Dimension, PaneGeom, Size}; use zellij_utils::{vte, zellij_tile}; use ssh2::Session; @@ -15,6 +15,7 @@ const ZELLIJ_LAYOUT_PATH: &str = "/usr/src/zellij/fixtures/layouts"; const CONNECTION_STRING: &str = "127.0.0.1:2222"; const CONNECTION_USERNAME: &str = "test"; const CONNECTION_PASSWORD: &str = "test"; +const SESSION_NAME: &str = "e2e-test"; fn ssh_connect() -> ssh2::Session { let tcp = TcpStream::connect(CONNECTION_STRING).unwrap(); @@ -27,7 +28,7 @@ fn ssh_connect() -> ssh2::Session { sess } -fn setup_remote_environment(channel: &mut ssh2::Channel, win_size: PositionAndSize) { +fn setup_remote_environment(channel: &mut ssh2::Channel, win_size: Size) { let (columns, rows) = (win_size.cols as u32, win_size.rows as u32); channel .request_pty("xterm", None, Some((columns, rows, 0, 0))) @@ -39,60 +40,51 @@ fn setup_remote_environment(channel: &mut ssh2::Channel, win_size: PositionAndSi channel.flush().unwrap(); } -fn start_zellij(channel: &mut ssh2::Channel, session_name: Option<&String>) { - match session_name.as_ref() { - Some(name) => { - channel - .write_all( - format!("{} --session {}\n", ZELLIJ_EXECUTABLE_LOCATION, name).as_bytes(), - ) - .unwrap(); - } - None => { - channel - .write_all(format!("{}\n", ZELLIJ_EXECUTABLE_LOCATION).as_bytes()) - .unwrap(); - } - }; - channel.flush().unwrap(); +fn stop_zellij(channel: &mut ssh2::Channel) { + channel + .write_all("killall -KILL zellij\n".as_bytes()) + .unwrap(); } -fn start_zellij_without_frames(channel: &mut ssh2::Channel) { +fn start_zellij(channel: &mut ssh2::Channel) { + stop_zellij(channel); channel - .write_all(format!("{} options --no-pane-frames\n", ZELLIJ_EXECUTABLE_LOCATION).as_bytes()) + .write_all( + format!( + "{} --session {}\n", + ZELLIJ_EXECUTABLE_LOCATION, SESSION_NAME + ) + .as_bytes(), + ) .unwrap(); channel.flush().unwrap(); } -fn start_zellij_with_layout( - channel: &mut ssh2::Channel, - layout_path: &str, - session_name: Option<&String>, -) { - match session_name.as_ref() { - Some(name) => { - channel - .write_all( - format!( - "{} --layout-path {} --session {}\n", - ZELLIJ_EXECUTABLE_LOCATION, layout_path, name - ) - .as_bytes(), - ) - .unwrap(); - } - None => { - channel - .write_all( - format!( - "{} --layout-path {}\n", - ZELLIJ_EXECUTABLE_LOCATION, layout_path - ) - .as_bytes(), - ) - .unwrap(); - } - }; +fn start_zellij_without_frames(channel: &mut ssh2::Channel) { + stop_zellij(channel); + channel + .write_all( + format!( + "{} --session {} options --no-pane-frames\n", + ZELLIJ_EXECUTABLE_LOCATION, SESSION_NAME + ) + .as_bytes(), + ) + .unwrap(); + channel.flush().unwrap(); +} + +fn start_zellij_with_layout(channel: &mut ssh2::Channel, layout_path: &str) { + stop_zellij(channel); + channel + .write_all( + format!( + "{} --layout-path {} --session {}\n", + ZELLIJ_EXECUTABLE_LOCATION, layout_path, SESSION_NAME + ) + .as_bytes(), + ) + .unwrap(); channel.flush().unwrap(); } @@ -119,7 +111,6 @@ pub fn take_snapshot(terminal_output: &mut TerminalPane) -> String { pub struct RemoteTerminal<'a> { channel: &'a mut ssh2::Channel, - session_name: Option<&'a String>, cursor_x: usize, cursor_y: usize, current_snapshot: String, @@ -174,12 +165,7 @@ impl<'a> RemoteTerminal<'a> { pub fn attach_to_original_session(&mut self) { self.channel .write_all( - format!( - "{} attach {}\n", - ZELLIJ_EXECUTABLE_LOCATION, - self.session_name.unwrap() - ) - .as_bytes(), + format!("{} attach {}\n", ZELLIJ_EXECUTABLE_LOCATION, SESSION_NAME).as_bytes(), ) .unwrap(); self.channel.flush().unwrap(); @@ -198,33 +184,37 @@ pub struct RemoteRunner { vte_parser: vte::Parser, terminal_output: TerminalPane, channel: ssh2::Channel, - session_name: Option, test_name: &'static str, currently_running_step: Option, retries_left: usize, - win_size: PositionAndSize, + win_size: Size, layout_file_name: Option<&'static str>, without_frames: bool, } impl RemoteRunner { - pub fn new( - test_name: &'static str, - win_size: PositionAndSize, - session_name: Option, - ) -> Self { + pub fn new(test_name: &'static str, win_size: Size) -> Self { let sess = ssh_connect(); let mut channel = sess.channel_session().unwrap(); let vte_parser = vte::Parser::new(); - let terminal_output = TerminalPane::new(0, win_size, Palette::default(), 0); // 0 is the pane index + let mut rows = Dimension::fixed(win_size.rows); + let mut cols = Dimension::fixed(win_size.cols); + rows.set_inner(win_size.rows); + cols.set_inner(win_size.cols); + let pane_geom = PaneGeom { + x: 0, + y: 0, + rows, + cols, + }; + let terminal_output = TerminalPane::new(0, pane_geom, Palette::default(), 0); // 0 is the pane index setup_remote_environment(&mut channel, win_size); - start_zellij(&mut channel, session_name.as_ref()); + start_zellij(&mut channel); RemoteRunner { steps: vec![], channel, terminal_output, vte_parser, - session_name, test_name, currently_running_step: None, current_step_index: 0, @@ -234,15 +224,21 @@ impl RemoteRunner { without_frames: false, } } - pub fn new_without_frames( - test_name: &'static str, - win_size: PositionAndSize, - session_name: Option, - ) -> Self { + pub fn new_without_frames(test_name: &'static str, win_size: Size) -> Self { let sess = ssh_connect(); let mut channel = sess.channel_session().unwrap(); let vte_parser = vte::Parser::new(); - let terminal_output = TerminalPane::new(0, win_size, Palette::default(), 0); // 0 is the pane index + let mut rows = Dimension::fixed(win_size.rows); + let mut cols = Dimension::fixed(win_size.cols); + rows.set_inner(win_size.rows); + cols.set_inner(win_size.cols); + let pane_geom = PaneGeom { + x: 0, + y: 0, + rows, + cols, + }; + let terminal_output = TerminalPane::new(0, pane_geom, Palette::default(), 0); // 0 is the pane index setup_remote_environment(&mut channel, win_size); start_zellij_without_frames(&mut channel); RemoteRunner { @@ -250,7 +246,6 @@ impl RemoteRunner { channel, terminal_output, vte_parser, - session_name, test_name, currently_running_step: None, current_step_index: 0, @@ -262,27 +257,31 @@ impl RemoteRunner { } pub fn new_with_layout( test_name: &'static str, - win_size: PositionAndSize, + win_size: Size, layout_file_name: &'static str, - session_name: Option, ) -> Self { let remote_path = Path::new(ZELLIJ_LAYOUT_PATH).join(layout_file_name); let sess = ssh_connect(); let mut channel = sess.channel_session().unwrap(); let vte_parser = vte::Parser::new(); - let terminal_output = TerminalPane::new(0, win_size, Palette::default(), 0); // 0 is the pane index + let mut rows = Dimension::fixed(win_size.rows); + let mut cols = Dimension::fixed(win_size.cols); + rows.set_inner(win_size.rows); + cols.set_inner(win_size.cols); + let pane_geom = PaneGeom { + x: 0, + y: 0, + rows, + cols, + }; + let terminal_output = TerminalPane::new(0, pane_geom, Palette::default(), 0); // 0 is the pane index setup_remote_environment(&mut channel, win_size); - start_zellij_with_layout( - &mut channel, - &remote_path.to_string_lossy(), - session_name.as_ref(), - ); + start_zellij_with_layout(&mut channel, &remote_path.to_string_lossy()); RemoteRunner { steps: vec![], channel, terminal_output, vte_parser, - session_name, test_name, currently_running_step: None, current_step_index: 0, @@ -307,7 +306,6 @@ impl RemoteRunner { cursor_y, current_snapshot, channel: &mut self.channel, - session_name: self.session_name.as_ref(), } } pub fn run_next_step(&mut self) { @@ -319,7 +317,6 @@ impl RemoteRunner { cursor_y, current_snapshot, channel: &mut self.channel, - session_name: self.session_name.as_ref(), }; let instruction = next_step.instruction; self.currently_running_step = Some(String::from(next_step.name)); @@ -332,32 +329,22 @@ impl RemoteRunner { self.steps.get(self.current_step_index).is_some() } fn restart_test(&mut self) -> String { - let session_name = self.session_name.as_ref().map(|name| { - // this is so that we don't try to connect to the previous session if it's still stuck - // inside the container - format!("{}_{}", name, self.retries_left) - }); if let Some(layout_file_name) = self.layout_file_name.as_ref() { // let mut new_runner = RemoteRunner::new_with_layout(self.test_name, self.win_size, Path::new(&local_layout_path), session_name); - let mut new_runner = RemoteRunner::new_with_layout( - self.test_name, - self.win_size, - layout_file_name, - session_name, - ); + let mut new_runner = + RemoteRunner::new_with_layout(self.test_name, self.win_size, layout_file_name); new_runner.retries_left = self.retries_left - 1; new_runner.replace_steps(self.steps.clone()); drop(std::mem::replace(self, new_runner)); self.run_all_steps() } else if self.without_frames { - let mut new_runner = - RemoteRunner::new_without_frames(self.test_name, self.win_size, session_name); + let mut new_runner = RemoteRunner::new_without_frames(self.test_name, self.win_size); new_runner.retries_left = self.retries_left - 1; new_runner.replace_steps(self.steps.clone()); drop(std::mem::replace(self, new_runner)); self.run_all_steps() } else { - let mut new_runner = RemoteRunner::new(self.test_name, self.win_size, session_name); + let mut new_runner = RemoteRunner::new(self.test_name, self.win_size); new_runner.retries_left = self.retries_left - 1; new_runner.replace_steps(self.steps.clone()); drop(std::mem::replace(self, new_runner)); diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap index 91c83a44..d37f23e3 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap @@ -3,23 +3,23 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - -──────── -$ Hi!█ - - - - - - - - - - - - - - - + Zellij +┌──────┐ +│$ Hi!█│ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────┘ Ctrl + diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__close_pane.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__close_pane.snap index e7487028..af676286 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__close_pane.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__close_pane.snap @@ -3,27 +3,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  -─ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────────────────────── -$ █ - - - - - - - - - - - - - - - - - - - + Zellij (e2e-test)  Tab #1  +┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│$ █ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ Ctrl + LOCK 

PANE  TAB  RESIZE  SCROLL  SESSION  QUIT  Tip: Alt + n => open new pane. Alt + [] or hjkl => navigate between panes. diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__detach_and_attach_session.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__detach_and_attach_session.snap index 92484dd6..65ebb338 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__detach_and_attach_session.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__detach_and_attach_session.snap @@ -3,7 +3,7 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  + Zellij (e2e-test)  Tab #1  ┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ │$ ││$ I am some text█ │ │ ││ │ diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__focus_pane_with_mouse.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__focus_pane_with_mouse.snap index 5a409760..3578cf5e 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__focus_pane_with_mouse.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__focus_pane_with_mouse.snap @@ -3,7 +3,7 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  + Zellij (e2e-test)  Tab #1  ┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ │$ █ ││$ │ │ ││ │ diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__lock_mode.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__lock_mode.snap index 0796484c..cf59dc66 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__lock_mode.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__lock_mode.snap @@ -3,27 +3,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  -─ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────────────────────── -$ nabc█ - - - - - - - - - - - - - - - - - - - + Zellij (e2e-test)  Tab #1  +┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│$ nabc█ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ Ctrl + LOCK 

PANE  TAB  RESIZE  SCROLL  SESSION  QUIT  -- INTERFACE LOCKED -- diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__open_new_tab.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__open_new_tab.snap index f9b84f68..ca19eb01 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__open_new_tab.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__open_new_tab.snap @@ -3,27 +3,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  Tab #2  -─ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────────────────────── -$ █ - - - - - - - - - - - - - - - - - - - + Zellij (e2e-test)  Tab #1  Tab #2  +┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│$ █ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ Ctrl + LOCK 

PANE  TAB  RESIZE  SCROLL  SESSION  QUIT  Tip: Alt + n => open new pane. Alt + [] or hjkl => navigate between panes. diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_pane.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_pane.snap index ae130ab5..4220c0c8 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_pane.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_pane.snap @@ -3,27 +3,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  -┌ Pane #1 ───────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└────────────────────────────────────────────────┘└────────────────────────────────────────────────────────────────────┘ + Zellij (e2e-test)  Tab #1  +┌ Pane #1 ───────────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────────────────────┐ +│$ ││$ █ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +└────────────────────────────────────────────────────┘└────────────────────────────────────────────────────────────────┘ Ctrl + LOCK 

PANE  TAB  RESIZE  SCROLL  SESSION  QUIT  Tip: Alt + n => open new pane. Alt + [] or hjkl => navigate between panes. diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap index b329e8c6..6eea2929 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap @@ -3,27 +3,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  -┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (e2e-test)  Tab #1  +┌ Pane #1 ───────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────┐ +│$ ││$ █ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +│ ││ │ +└────────────────────────────────────────────────┘└────────────────────────────────────────────────┘ Ctrl + LOCK 

PANE  TAB  RESIZE  SCROLL  SESSION  QUIT  Tip: Alt + n => open new pane. Alt + [] or hjkl => navigate between panes. diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane.snap index a33ab400..f9f23c1c 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane.snap @@ -3,7 +3,7 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  + Zellij (e2e-test)  Tab #1  ┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────── SCROLL: 1/1 ┐ │$ ││$ line1 00000000000000000000000000000000000000000000000000│ │ ││line2 0000000000000000000000000000000000000000000000000000│ diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane_with_mouse.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane_with_mouse.snap index dfed0611..5ad40ae7 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane_with_mouse.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane_with_mouse.snap @@ -3,7 +3,7 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  + Zellij (e2e-test)  Tab #1  ┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────── SCROLL: 1/1 ┐ │$ ││$ line1 00000000000000000000000000000000000000000000000000│ │ ││line2 0000000000000000000000000000000000000000000000000000│ diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__split_terminals_vertically.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__split_terminals_vertically.snap index 36f0e6d8..b1f54404 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__split_terminals_vertically.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__split_terminals_vertically.snap @@ -3,7 +3,7 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  + Zellij (e2e-test)  Tab #1  ┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ │$ ││$ █ │ │ ││ │ diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__start_without_pane_frames.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__start_without_pane_frames.snap index 85c6db54..21f47e56 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__start_without_pane_frames.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__start_without_pane_frames.snap @@ -3,7 +3,7 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  + Zellij (e2e-test)  Tab #1  $ │$ █ │ │ diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap index e7487028..af676286 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap @@ -3,27 +3,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  -─ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────────────────────── -$ █ - - - - - - - - - - - - - - - - - - - + Zellij (e2e-test)  Tab #1  +┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│$ █ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ Ctrl + LOCK 

PANE  TAB  RESIZE  SCROLL  SESSION  QUIT  Tip: Alt + n => open new pane. Alt + [] or hjkl => navigate between panes. diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__toggle_pane_fullscreen.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__toggle_pane_fullscreen.snap index 9108099d..347b0a70 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__toggle_pane_fullscreen.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__toggle_pane_fullscreen.snap @@ -3,27 +3,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij  Tab #1  -─ Pane #2 ────────────────────────────────────────────────────────────────────────────────────────────────────────────── -$ █ - - - - - - - - - - - - - - - - - - - + Zellij (e2e-test)  Tab #1  +┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│$ █ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ Ctrl + LOCK 

PANE  TAB  RESIZE  SCROLL  SESSION  QUIT  Tip: Alt + n => open new pane. Alt + [] or hjkl => navigate between panes. diff --git a/zellij-client/src/lib.rs b/zellij-client/src/lib.rs index e806ec3b..7d67a01a 100644 --- a/zellij-client/src/lib.rs +++ b/zellij-client/src/lib.rs @@ -116,7 +116,7 @@ pub fn start_client( let full_screen_ws = os_input.get_terminal_size_using_fd(0); let client_attributes = ClientAttributes { - position_and_size: full_screen_ws, + size: full_screen_ws, palette, }; @@ -137,7 +137,7 @@ pub fn start_client( client_attributes, Box::new(opts), Box::new(config_options.clone()), - layout, + layout.unwrap(), ) } }; diff --git a/zellij-client/src/os_input_output.rs b/zellij-client/src/os_input_output.rs index 7242bf7a..b5018c29 100644 --- a/zellij-client/src/os_input_output.rs +++ b/zellij-client/src/os_input_output.rs @@ -1,4 +1,5 @@ use zellij_utils::input::actions::Action; +use zellij_utils::pane_size::Size; use zellij_utils::{interprocess, libc, nix, signal_hook, termion, zellij_tile}; use interprocess::local_socket::LocalSocketStream; @@ -15,7 +16,6 @@ use zellij_tile::data::Palette; use zellij_utils::{ errors::ErrorContext, ipc::{ClientToServerMsg, IpcReceiverWithContext, IpcSenderWithContext, ServerToClientMsg}, - pane_size::PositionAndSize, shared::default_palette, }; @@ -35,7 +35,7 @@ fn unset_raw_mode(pid: RawFd, orig_termios: termios::Termios) { }; } -pub(crate) fn get_terminal_size_using_fd(fd: RawFd) -> PositionAndSize { +pub(crate) fn get_terminal_size_using_fd(fd: RawFd) -> Size { // TODO: do this with the nix ioctl use libc::ioctl; use libc::TIOCGWINSZ; @@ -54,7 +54,10 @@ pub(crate) fn get_terminal_size_using_fd(fd: RawFd) -> PositionAndSize { unsafe { ioctl(fd, TIOCGWINSZ.into(), &mut winsize) }; - PositionAndSize::from(winsize) + Size { + rows: winsize.ws_row as usize, + cols: winsize.ws_col as usize, + } } #[derive(Clone)] @@ -69,7 +72,7 @@ pub struct ClientOsInputOutput { /// Zellij client requires. pub trait ClientOsApi: Send + Sync { /// Returns the size of the terminal associated to file descriptor `fd`. - fn get_terminal_size_using_fd(&self, fd: RawFd) -> PositionAndSize; + fn get_terminal_size_using_fd(&self, fd: RawFd) -> Size; /// Set the terminal associated to file descriptor `fd` to /// [raw mode](https://en.wikipedia.org/wiki/Terminal_mode). fn set_raw_mode(&mut self, fd: RawFd); @@ -98,7 +101,7 @@ pub trait ClientOsApi: Send + Sync { } impl ClientOsApi for ClientOsInputOutput { - fn get_terminal_size_using_fd(&self, fd: RawFd) -> PositionAndSize { + fn get_terminal_size_using_fd(&self, fd: RawFd) -> Size { get_terminal_size_using_fd(fd) } fn set_raw_mode(&mut self, fd: RawFd) { diff --git a/zellij-client/src/unit/input_handler_tests.rs b/zellij-client/src/unit/input_handler_tests.rs index 9b0bc71c..a9b86a75 100644 --- a/zellij-client/src/unit/input_handler_tests.rs +++ b/zellij-client/src/unit/input_handler_tests.rs @@ -2,7 +2,7 @@ use super::input_loop; use zellij_utils::input::actions::{Action, Direction}; use zellij_utils::input::config::Config; use zellij_utils::input::options::Options; -use zellij_utils::pane_size::PositionAndSize; +use zellij_utils::pane_size::Size; use zellij_utils::zellij_tile::data::Palette; use crate::{os_input_output::ClientOsApi, ClientInstruction, CommandIsExecuting}; @@ -93,7 +93,7 @@ impl FakeClientOsApi { } impl ClientOsApi for FakeClientOsApi { - fn get_terminal_size_using_fd(&self, _fd: RawFd) -> PositionAndSize { + fn get_terminal_size_using_fd(&self, _fd: RawFd) -> Size { unimplemented!() } fn set_raw_mode(&mut self, _fd: RawFd) { diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs index 57c68f9f..9073ed3a 100644 --- a/zellij-server/src/lib.rs +++ b/zellij-server/src/lib.rs @@ -46,12 +46,7 @@ use zellij_utils::{ /// Instructions related to server-side application #[derive(Debug, Clone)] pub(crate) enum ServerInstruction { - NewClient( - ClientAttributes, - Box, - Box, - Option, - ), + NewClient(ClientAttributes, Box, Box, LayoutFromYaml), Render(Option), UnblockInputThread, ClientExit, @@ -127,8 +122,6 @@ pub fn start_server(os_input: Box, socket_path: PathBuf) { daemonize::Daemonize::new() .working_directory(std::env::current_dir().unwrap()) .umask(0o077) - // FIXME: My cherished `dbg!` was broken, so this is a hack to bring it back - //.stderr(std::fs::File::create("dbg.log").unwrap()) .start() .expect("could not daemonize the server process"); @@ -237,19 +230,12 @@ pub fn start_server(os_input: Box, socket_path: PathBuf) { .unwrap() }; - match layout { - None => { - spawn_tabs(None); - } - Some(layout) => { - if !&layout.tabs.is_empty() { - for tab_layout in layout.tabs { - spawn_tabs(Some(tab_layout.clone())); - } - } else { - spawn_tabs(None); - } + if !&layout.tabs.is_empty() { + for tab_layout in layout.tabs { + spawn_tabs(Some(tab_layout.clone())); } + } else { + spawn_tabs(None); } } ServerInstruction::AttachClient(attrs, _, options) => { @@ -258,7 +244,7 @@ pub fn start_server(os_input: Box, socket_path: PathBuf) { let session_data = rlock.as_ref().unwrap(); session_data .senders - .send_to_screen(ScreenInstruction::TerminalResize(attrs.position_and_size)) + .send_to_screen(ScreenInstruction::TerminalResize(attrs.size)) .unwrap(); let default_mode = options.default_mode.unwrap_or_default(); let mode_info = @@ -326,7 +312,7 @@ fn init_session( to_server: SenderWithContext, client_attributes: ClientAttributes, session_state: Arc>, - layout: Option, + layout: LayoutFromYaml, ) -> SessionMetaData { let (to_screen, screen_receiver): ChannelWithContext = channels::unbounded(); let to_screen = SenderWithContext::new(to_screen); diff --git a/zellij-server/src/os_input_output.rs b/zellij-server/src/os_input_output.rs index 198a1487..05980805 100644 --- a/zellij-server/src/os_input_output.rs +++ b/zellij-server/src/os_input_output.rs @@ -251,7 +251,9 @@ pub trait ServerOsApi: Send + Sync { impl ServerOsApi for ServerOsInputOutput { fn set_terminal_size_using_fd(&self, fd: RawFd, cols: u16, rows: u16) { - set_terminal_size_using_fd(fd, cols, rows); + if cols > 0 && rows > 0 { + set_terminal_size_using_fd(fd, cols, rows); + } } fn spawn_terminal(&self, terminal_action: Option) -> (RawFd, Pid) { let orig_termios = self.orig_termios.lock().unwrap(); diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs index cb03eb6a..5e3479ee 100644 --- a/zellij-server/src/panes/grid.rs +++ b/zellij-server/src/panes/grid.rs @@ -592,8 +592,13 @@ impl Grid { self.change_size(new_rows, new_columns); } pub fn change_size(&mut self, new_rows: usize, new_columns: usize) { + // Do nothing if this pane hasn't been given a proper size yet + if new_columns == 0 || new_rows == 0 { + return; + } self.selection.reset(); if new_columns != self.width { + self.horizontal_tabstops = create_horizontal_tabstops(new_columns); let mut cursor_canonical_line_index = self.cursor_canonical_line_index(); let cursor_index_in_canonical_line = self.cursor_index_in_canonical_line(); let mut viewport_canonical_lines = vec![]; @@ -635,6 +640,11 @@ impl Grid { } else { canonical_line.columns.drain(..).collect() }; + // If the next character is wider than the grid (i.e. there is nothing in + // `next_wrap`, then just abort the resizing + if next_wrap.is_empty() { + break; + } let row = Row::from_columns(next_wrap); // if there are no more parts, this row is canonical as long as it originally // was canonical (it might not have been for example if it's the first row in @@ -956,10 +966,9 @@ impl Grid { self.cursor.x += count_to_move; } pub fn replace_characters_in_line_after_cursor(&mut self, replace_with: TerminalCharacter) { - self.viewport - .get_mut(self.cursor.y) - .unwrap() - .replace_and_pad_end(self.cursor.x, self.width, replace_with); + if let Some(row) = self.viewport.get_mut(self.cursor.y) { + row.replace_and_pad_end(self.cursor.x, self.width, replace_with); + } self.output_buffer.update_line(self.cursor.y); } pub fn replace_characters_in_line_before_cursor(&mut self, replace_with: TerminalCharacter) { @@ -1109,7 +1118,7 @@ impl Grid { self.scroll_region = None; } pub fn set_scroll_region_to_viewport_size(&mut self) { - self.scroll_region = Some((0, self.height - 1)); + self.scroll_region = Some((0, self.height.saturating_sub(1))); } pub fn delete_lines_in_scroll_region( &mut self, diff --git a/zellij-server/src/panes/plugin_pane.rs b/zellij-server/src/panes/plugin_pane.rs index 3bac21eb..c4de9398 100644 --- a/zellij-server/src/panes/plugin_pane.rs +++ b/zellij-server/src/panes/plugin_pane.rs @@ -2,33 +2,37 @@ use std::sync::mpsc::channel; use std::time::Instant; use std::unimplemented; -use crate::panes::{PaneDecoration, PaneId}; +use crate::panes::PaneId; use crate::pty::VteBytes; use crate::tab::Pane; -use crate::ui::pane_boundaries_frame::PaneBoundariesFrame; +use crate::ui::pane_boundaries_frame::PaneFrame; use crate::wasm_vm::PluginInstruction; +use zellij_utils::pane_size::Offset; use zellij_utils::shared::ansi_len; use zellij_utils::zellij_tile::prelude::PaletteColor; -use zellij_utils::{channels::SenderWithContext, pane_size::PositionAndSize}; +use zellij_utils::{ + channels::SenderWithContext, + pane_size::{Dimension, PaneGeom}, +}; pub(crate) struct PluginPane { pub pid: u32, pub should_render: bool, pub selectable: bool, - pub invisible_borders: bool, - pub position_and_size: PositionAndSize, - pub position_and_size_override: Option, - pub content_position_and_size: PositionAndSize, + pub geom: PaneGeom, + pub geom_override: Option, + pub content_offset: Offset, pub send_plugin_instructions: SenderWithContext, pub active_at: Instant, pub pane_title: String, - pane_decoration: PaneDecoration, + frame: bool, + frame_color: Option, } impl PluginPane { pub fn new( pid: u32, - position_and_size: PositionAndSize, + position_and_size: PaneGeom, send_plugin_instructions: SenderWithContext, title: String, ) -> Self { @@ -36,53 +40,16 @@ impl PluginPane { pid, should_render: true, selectable: true, - invisible_borders: false, - position_and_size, - position_and_size_override: None, + geom: position_and_size, + geom_override: None, send_plugin_instructions, active_at: Instant::now(), - pane_decoration: PaneDecoration::ContentOffset((0, 0)), - content_position_and_size: position_and_size, + frame: false, + frame_color: None, + content_offset: Offset::default(), pane_title: title, } } - pub fn get_content_x(&self) -> usize { - self.get_content_posision_and_size().x - } - pub fn get_content_y(&self) -> usize { - self.get_content_posision_and_size().y - } - pub fn get_content_columns(&self) -> usize { - // content columns might differ from the pane's columns if the pane has a frame - // in that case they would be 2 less - self.get_content_posision_and_size().cols - } - pub fn get_content_rows(&self) -> usize { - // content rows might differ from the pane's rows if the pane has a frame - // in that case they would be 2 less - self.get_content_posision_and_size().rows - } - pub fn get_content_posision_and_size(&self) -> PositionAndSize { - self.content_position_and_size - } - fn redistribute_space(&mut self) { - let position_and_size = self - .position_and_size_override - .unwrap_or_else(|| self.position_and_size()); - match &mut self.pane_decoration { - PaneDecoration::BoundariesFrame(boundaries_frame) => { - boundaries_frame.change_pos_and_size(position_and_size); - self.content_position_and_size = boundaries_frame.content_position_and_size(); - } - PaneDecoration::ContentOffset((content_columns_offset, content_rows_offset)) => { - self.content_position_and_size = position_and_size; - self.content_position_and_size.cols = - position_and_size.cols - *content_columns_offset; - self.content_position_and_size.rows = position_and_size.rows - *content_rows_offset; - } - }; - self.set_should_render(true); - } } impl Pane for PluginPane { @@ -90,51 +57,46 @@ impl Pane for PluginPane { // with something like a get_pos_and_sz() method underpinning all of them. Alternatively and // preferably, just use an enum and not a trait object fn x(&self) -> usize { - self.position_and_size_override - .unwrap_or(self.position_and_size) - .x + self.geom_override.unwrap_or(self.geom).x } fn y(&self) -> usize { - self.position_and_size_override - .unwrap_or(self.position_and_size) - .y + self.geom_override.unwrap_or(self.geom).y } fn rows(&self) -> usize { - self.position_and_size_override - .unwrap_or(self.position_and_size) - .rows + self.geom_override.unwrap_or(self.geom).rows.as_usize() } - fn columns(&self) -> usize { - self.position_and_size_override - .unwrap_or(self.position_and_size) - .cols + fn cols(&self) -> usize { + self.geom_override.unwrap_or(self.geom).cols.as_usize() + } + fn get_content_x(&self) -> usize { + self.x() + self.content_offset.left + } + fn get_content_y(&self) -> usize { + self.y() + self.content_offset.top } fn get_content_columns(&self) -> usize { - self.get_content_columns() + // content columns might differ from the pane's columns if the pane has a frame + // in that case they would be 2 less + self.cols() + .saturating_sub(self.content_offset.left + self.content_offset.right) } fn get_content_rows(&self) -> usize { - self.get_content_rows() + // content rows might differ from the pane's rows if the pane has a frame + // in that case they would be 2 less + self.rows() + .saturating_sub(self.content_offset.top + self.content_offset.bottom) } fn reset_size_and_position_override(&mut self) { - self.position_and_size_override = None; - self.redistribute_space(); + self.geom_override = None; self.should_render = true; } - fn change_pos_and_size(&mut self, position_and_size: &PositionAndSize) { - self.position_and_size = *position_and_size; - self.redistribute_space(); + fn set_geom(&mut self, position_and_size: PaneGeom) { + self.geom = position_and_size; + self.should_render = true; } - // FIXME: This is obviously a bit outdated and needs the x and y moved into `size` - fn override_size_and_position(&mut self, x: usize, y: usize, size: &PositionAndSize) { - let position_and_size_override = PositionAndSize { - x, - y, - rows: size.rows, - cols: size.cols, - ..Default::default() - }; - self.position_and_size_override = Some(position_and_size_override); - self.redistribute_space(); + fn get_geom_override(&mut self, pane_geom: PaneGeom) { + self.geom_override = Some(pane_geom); + self.should_render = true; } fn handle_pty_bytes(&mut self, _event: VteBytes) { unimplemented!() @@ -143,13 +105,16 @@ impl Pane for PluginPane { None } fn adjust_input_to_terminal(&self, _input_bytes: Vec) -> Vec { - unimplemented!() // FIXME: Shouldn't need this implmented? + unimplemented!() } - fn position_and_size(&self) -> PositionAndSize { - self.position_and_size + fn position_and_size(&self) -> PaneGeom { + self.geom } - fn position_and_size_override(&self) -> Option { - self.position_and_size_override + fn current_geom(&self) -> PaneGeom { + self.geom_override.unwrap_or(self.geom) + } + fn geom_override(&self) -> Option { + self.geom_override } fn should_render(&self) -> bool { self.should_render @@ -157,28 +122,12 @@ impl Pane for PluginPane { fn set_should_render(&mut self, should_render: bool) { self.should_render = should_render; } - fn set_should_render_boundaries(&mut self, should_render: bool) { - if let PaneDecoration::BoundariesFrame(boundaries_frame) = &mut self.pane_decoration { - boundaries_frame.set_should_render(should_render); - } - } fn selectable(&self) -> bool { self.selectable } fn set_selectable(&mut self, selectable: bool) { self.selectable = selectable; } - fn set_invisible_borders(&mut self, invisible_borders: bool) { - self.invisible_borders = invisible_borders; - } - fn set_fixed_height(&mut self, fixed_height: usize) { - self.position_and_size.rows = fixed_height; - self.position_and_size.rows_fixed = true; - } - fn set_fixed_width(&mut self, fixed_width: usize) { - self.position_and_size.cols = fixed_width; - self.position_and_size.cols_fixed = true; - } fn render(&mut self) -> Option { // if self.should_render { if true { @@ -200,10 +149,16 @@ impl Pane for PluginPane { self.should_render = false; let contents = buf_rx.recv().unwrap(); - if let PaneDecoration::BoundariesFrame(boundaries_frame) = &mut self.pane_decoration { - if let Some(boundaries_frame_vte) = boundaries_frame.render() { - vte_output.push_str(&boundaries_frame_vte); - } + // FIXME: This is a hack that assumes all fixed-size panes are borderless. This + // will eventually need fixing! + if self.frame && !(self.geom.rows.is_fixed() || self.geom.cols.is_fixed()) { + let frame = PaneFrame { + geom: self.current_geom().into(), + title: self.pane_title.clone(), + color: self.frame_color, + ..Default::default() + }; + vte_output.push_str(&frame.render()); } for (index, line) in contents.lines().enumerate() { let actual_len = ansi_len(line); @@ -257,68 +212,44 @@ impl Pane for PluginPane { fn pid(&self) -> PaneId { PaneId::Plugin(self.pid) } - fn reduce_height_down(&mut self, count: usize) { - self.position_and_size.y += count; - self.position_and_size.rows -= count; - self.redistribute_space(); - self.should_render = true; + fn reduce_height(&mut self, percent: f64) { + if let Some(p) = self.geom.rows.as_percent() { + self.geom.rows = Dimension::percent(p - percent); + self.should_render = true; + } } - fn increase_height_down(&mut self, count: usize) { - self.position_and_size.rows += count; - self.redistribute_space(); - self.should_render = true; + fn increase_height(&mut self, percent: f64) { + if let Some(p) = self.geom.rows.as_percent() { + self.geom.rows = Dimension::percent(p + percent); + self.should_render = true; + } } - fn increase_height_up(&mut self, count: usize) { - self.position_and_size.y -= count; - self.position_and_size.rows += count; - self.redistribute_space(); - self.should_render = true; + fn reduce_width(&mut self, percent: f64) { + if let Some(p) = self.geom.cols.as_percent() { + self.geom.cols = Dimension::percent(p - percent); + self.should_render = true; + } } - fn reduce_height_up(&mut self, count: usize) { - self.position_and_size.rows -= count; - self.redistribute_space(); - self.should_render = true; - } - fn reduce_width_right(&mut self, count: usize) { - self.position_and_size.x += count; - self.position_and_size.cols -= count; - self.redistribute_space(); - self.should_render = true; - } - fn reduce_width_left(&mut self, count: usize) { - self.position_and_size.cols -= count; - self.redistribute_space(); - self.should_render = true; - } - fn increase_width_left(&mut self, count: usize) { - self.position_and_size.x -= count; - self.position_and_size.cols += count; - self.redistribute_space(); - self.should_render = true; - } - fn increase_width_right(&mut self, count: usize) { - self.position_and_size.cols += count; - self.redistribute_space(); - self.should_render = true; + fn increase_width(&mut self, percent: f64) { + if let Some(p) = self.geom.cols.as_percent() { + self.geom.cols = Dimension::percent(p + percent); + self.should_render = true; + } } fn push_down(&mut self, count: usize) { - self.position_and_size.y += count; - self.redistribute_space(); + self.geom.y += count; self.should_render = true; } fn push_right(&mut self, count: usize) { - self.position_and_size.x += count; - self.redistribute_space(); + self.geom.x += count; self.should_render = true; } fn pull_left(&mut self, count: usize) { - self.position_and_size.x -= count; - self.redistribute_space(); + self.geom.x -= count; self.should_render = true; } fn pull_up(&mut self, count: usize) { - self.position_and_size.y -= count; - self.redistribute_space(); + self.geom.y -= count; self.should_render = true; } fn scroll_up(&mut self, _count: usize) { @@ -330,25 +261,6 @@ impl Pane for PluginPane { fn clear_scroll(&mut self) { //unimplemented!() } - // FIXME: This need to be reevaluated and deleted if possible. - // `max` doesn't make sense when things are fixed... - fn max_height(&self) -> Option { - if self.position_and_size.rows_fixed { - Some(self.position_and_size.rows) - } else { - None - } - } - fn max_width(&self) -> Option { - if self.position_and_size.cols_fixed { - Some(self.position_and_size.cols) - } else { - None - } - } - fn invisible_borders(&self) -> bool { - self.invisible_borders - } fn active_at(&self) -> Instant { self.active_at @@ -357,61 +269,14 @@ impl Pane for PluginPane { fn set_active_at(&mut self, time: Instant) { self.active_at = time; } + fn set_frame(&mut self, frame: bool) { + self.frame = frame; + } + fn set_content_offset(&mut self, offset: Offset) { + self.content_offset = offset; + } fn set_boundary_color(&mut self, color: Option) { - if let PaneDecoration::BoundariesFrame(boundaries_frame) = &mut self.pane_decoration { - boundaries_frame.set_color(color); - } - } - fn offset_content_columns(&mut self, by: usize) { - if !self.selectable { - return; - } - if let PaneDecoration::ContentOffset(content_offset) = &mut self.pane_decoration { - content_offset.0 = by; - } else { - self.pane_decoration = PaneDecoration::ContentOffset((by, 0)); - } - self.redistribute_space(); - self.set_should_render(true); - } - fn offset_content_rows(&mut self, by: usize) { - if !self.selectable { - return; - } - if let PaneDecoration::ContentOffset(content_offset) = &mut self.pane_decoration { - content_offset.1 = by; - } else { - self.pane_decoration = PaneDecoration::ContentOffset((0, by)); - } - self.redistribute_space(); - self.set_should_render(true); - } - fn show_boundaries_frame(&mut self, should_render_only_title: bool) { - if !self.selectable { - return; - } - let position_and_size = self - .position_and_size_override - .unwrap_or(self.position_and_size); - if let PaneDecoration::BoundariesFrame(boundaries_frame) = &mut self.pane_decoration { - boundaries_frame.render_only_title(should_render_only_title); - self.content_position_and_size = boundaries_frame.content_position_and_size(); - } else { - let mut boundaries_frame = - PaneBoundariesFrame::new(position_and_size, self.pane_title.clone()); - boundaries_frame.render_only_title(should_render_only_title); - self.content_position_and_size = boundaries_frame.content_position_and_size(); - self.pane_decoration = PaneDecoration::BoundariesFrame(boundaries_frame); - } - self.redistribute_space(); - self.set_should_render(true); - } - fn remove_boundaries_frame(&mut self) { - if !self.selectable { - return; - } - self.pane_decoration = PaneDecoration::ContentOffset((0, 0)); - self.redistribute_space(); + self.frame_color = color; self.set_should_render(true); } } diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs index d3405023..38b092a9 100644 --- a/zellij-server/src/panes/terminal_pane.rs +++ b/zellij-server/src/panes/terminal_pane.rs @@ -1,14 +1,3 @@ -use zellij_utils::position::Position; -use zellij_utils::zellij_tile::prelude::PaletteColor; -use zellij_utils::{vte, zellij_tile}; - -use std::fmt::Debug; -use std::os::unix::io::RawFd; -use std::time::{self, Instant}; -use zellij_tile::data::Palette; - -use zellij_utils::pane_size::PositionAndSize; - use crate::panes::AnsiCode; use crate::panes::{ grid::Grid, @@ -18,10 +7,20 @@ use crate::panes::{ }; use crate::pty::VteBytes; use crate::tab::Pane; +use std::fmt::Debug; +use std::os::unix::io::RawFd; +use std::time::{self, Instant}; +use zellij_utils::pane_size::Offset; +use zellij_utils::{ + pane_size::{Dimension, PaneGeom}, + position::Position, + vte, + zellij_tile::data::{Palette, PaletteColor}, +}; pub const SELECTION_SCROLL_INTERVAL_MS: u64 = 10; -use crate::ui::pane_boundaries_frame::PaneBoundariesFrame; +use crate::ui::pane_boundaries_frame::PaneFrame; #[derive(PartialEq, Eq, Ord, PartialOrd, Hash, Clone, Copy, Debug)] pub enum PaneId { @@ -29,24 +28,22 @@ pub enum PaneId { Plugin(u32), // FIXME: Drop the trait object, make this a wrapper for the struct? } -pub enum PaneDecoration { - BoundariesFrame(PaneBoundariesFrame), - ContentOffset((usize, usize)), // (columns, rows) -} - +// FIXME: This should hold an os_api handle so that terminal panes can set their own size via FD in +// their `reflow_lines()` method. Drop a Box in here somewhere. pub struct TerminalPane { pub grid: Grid, pub pid: RawFd, pub selectable: bool, - position_and_size: PositionAndSize, - position_and_size_override: Option, + pub geom: PaneGeom, + pub geom_override: Option, pub active_at: Instant, pub colors: Palette, vte_parser: vte::Parser, selection_scrolled_at: time::Instant, - content_position_and_size: PositionAndSize, + content_offset: Offset, pane_title: String, - pane_decoration: PaneDecoration, + frame: Option, + frame_color: Option, } impl Pane for TerminalPane { @@ -59,32 +56,38 @@ impl Pane for TerminalPane { fn rows(&self) -> usize { self.get_rows() } - fn columns(&self) -> usize { + fn cols(&self) -> usize { self.get_columns() } + fn get_content_x(&self) -> usize { + self.get_x() + self.content_offset.left + } + fn get_content_y(&self) -> usize { + self.get_y() + self.content_offset.top + } fn get_content_columns(&self) -> usize { - self.get_content_columns() + // content columns might differ from the pane's columns if the pane has a frame + // in that case they would be 2 less + self.get_columns() + .saturating_sub(self.content_offset.left + self.content_offset.right) } fn get_content_rows(&self) -> usize { - self.get_content_rows() + // content rows might differ from the pane's rows if the pane has a frame + // in that case they would be 2 less + self.get_rows() + .saturating_sub(self.content_offset.top + self.content_offset.bottom) } fn reset_size_and_position_override(&mut self) { - self.position_and_size_override = None; - self.redistribute_space(); + self.geom_override = None; + self.reflow_lines(); } - fn change_pos_and_size(&mut self, position_and_size: &PositionAndSize) { - self.position_and_size = *position_and_size; - self.redistribute_space(); + fn set_geom(&mut self, position_and_size: PaneGeom) { + self.geom = position_and_size; + self.reflow_lines(); } - fn override_size_and_position(&mut self, x: usize, y: usize, size: &PositionAndSize) { - self.position_and_size_override = Some(PositionAndSize { - x, - y, - rows: size.rows, - cols: size.cols, - ..Default::default() - }); - self.redistribute_space(); + fn get_geom_override(&mut self, pane_geom: PaneGeom) { + self.geom_override = Some(pane_geom); + self.reflow_lines(); } fn handle_pty_bytes(&mut self, bytes: VteBytes) { for byte in bytes.iter() { @@ -94,17 +97,10 @@ impl Pane for TerminalPane { } fn cursor_coordinates(&self) -> Option<(usize, usize)> { // (x, y) - let (x_offset, y_offset) = match &self.pane_decoration { - PaneDecoration::BoundariesFrame(boundries_frame) => { - let (content_columns_offset, content_rows_offset) = - boundries_frame.content_offset(); - (content_columns_offset, content_rows_offset) - } - PaneDecoration::ContentOffset(_) => (0, 0), - }; + let Offset { top, left, .. } = self.content_offset; self.grid .cursor_coordinates() - .map(|(x, y)| (x + x_offset, y + y_offset)) + .map(|(x, y)| (x + left, y + top)) } fn adjust_input_to_terminal(&self, input_bytes: Vec) -> Vec { // there are some cases in which the terminal state means that input sent to it @@ -157,11 +153,14 @@ impl Pane for TerminalPane { }; input_bytes } - fn position_and_size(&self) -> PositionAndSize { - self.position_and_size + fn position_and_size(&self) -> PaneGeom { + self.geom } - fn position_and_size_override(&self) -> Option { - self.position_and_size_override + fn current_geom(&self) -> PaneGeom { + self.geom_override.unwrap_or(self.geom) + } + fn geom_override(&self) -> Option { + self.geom_override } fn should_render(&self) -> bool { self.grid.should_render @@ -169,14 +168,10 @@ impl Pane for TerminalPane { fn set_should_render(&mut self, should_render: bool) { self.grid.should_render = should_render; } - fn set_should_render_boundaries(&mut self, should_render: bool) { - if let PaneDecoration::BoundariesFrame(boundaries_frame) = &mut self.pane_decoration { - boundaries_frame.set_should_render(should_render); - } - } fn render_full_viewport(&mut self) { // this marks the pane for a full re-render, rather than just rendering the // diff as it usually does with the OutputBuffer + self.frame.replace(PaneFrame::default()); self.grid.render_full_viewport(); } fn selectable(&self) -> bool { @@ -185,17 +180,6 @@ impl Pane for TerminalPane { fn set_selectable(&mut self, selectable: bool) { self.selectable = selectable; } - fn set_fixed_height(&mut self, fixed_height: usize) { - self.position_and_size.rows = fixed_height; - self.position_and_size.rows_fixed = true; - } - fn set_fixed_width(&mut self, fixed_width: usize) { - self.position_and_size.cols = fixed_width; - self.position_and_size.cols_fixed = true; - } - fn set_invisible_borders(&mut self, _invisible_borders: bool) { - unimplemented!(); - } fn render(&mut self) -> Option { if self.should_render() { let mut vte_output = String::new(); @@ -254,11 +238,20 @@ impl Pane for TerminalPane { } character_styles.clear(); } - if let PaneDecoration::BoundariesFrame(boundaries_frame) = &mut self.pane_decoration { - boundaries_frame.update_scroll(self.grid.scrollback_position_and_length()); - boundaries_frame.update_title(self.grid.title.as_ref()); - if let Some(boundaries_frame_vte) = boundaries_frame.render() { - vte_output.push_str(&boundaries_frame_vte); + if let Some(last_frame) = &self.frame { + let frame = PaneFrame { + geom: self.current_geom().into(), + title: self + .grid + .title + .clone() + .unwrap_or_else(|| self.pane_title.clone()), + scroll_position: self.grid.scrollback_position_and_length(), + color: self.frame_color, + }; + if &frame != last_frame { + vte_output.push_str(&frame.render()); + self.frame = Some(frame); } } self.set_should_render(false); @@ -270,57 +263,45 @@ impl Pane for TerminalPane { fn pid(&self) -> PaneId { PaneId::Terminal(self.pid) } - fn reduce_height_down(&mut self, count: usize) { - self.position_and_size.y += count; - self.position_and_size.rows -= count; - self.redistribute_space(); + fn reduce_height(&mut self, percent: f64) { + if let Some(p) = self.geom.rows.as_percent() { + self.geom.rows = Dimension::percent(p - percent); + self.set_should_render(true); + } } - fn increase_height_down(&mut self, count: usize) { - self.position_and_size.rows += count; - self.redistribute_space(); + fn increase_height(&mut self, percent: f64) { + if let Some(p) = self.geom.rows.as_percent() { + self.geom.rows = Dimension::percent(p + percent); + self.set_should_render(true); + } } - fn increase_height_up(&mut self, count: usize) { - self.position_and_size.y -= count; - self.position_and_size.rows += count; - self.redistribute_space(); + fn reduce_width(&mut self, percent: f64) { + if let Some(p) = self.geom.cols.as_percent() { + self.geom.cols = Dimension::percent(p - percent); + self.set_should_render(true); + } } - fn reduce_height_up(&mut self, count: usize) { - self.position_and_size.rows -= count; - self.redistribute_space(); - } - fn reduce_width_right(&mut self, count: usize) { - self.position_and_size.x += count; - self.position_and_size.cols -= count; - self.redistribute_space(); - } - fn reduce_width_left(&mut self, count: usize) { - self.position_and_size.cols -= count; - self.redistribute_space(); - } - fn increase_width_left(&mut self, count: usize) { - self.position_and_size.x -= count; - self.position_and_size.cols += count; - self.redistribute_space(); - } - fn increase_width_right(&mut self, count: usize) { - self.position_and_size.cols += count; - self.redistribute_space(); + fn increase_width(&mut self, percent: f64) { + if let Some(p) = self.geom.cols.as_percent() { + self.geom.cols = Dimension::percent(p + percent); + self.set_should_render(true); + } } fn push_down(&mut self, count: usize) { - self.position_and_size.y += count; - self.redistribute_space(); + self.geom.y += count; + self.reflow_lines(); } fn push_right(&mut self, count: usize) { - self.position_and_size.x += count; - self.redistribute_space(); + self.geom.x += count; + self.reflow_lines(); } fn pull_left(&mut self, count: usize) { - self.position_and_size.x -= count; - self.redistribute_space(); + self.geom.x -= count; + self.reflow_lines(); } fn pull_up(&mut self, count: usize) { - self.position_and_size.y -= count; - self.redistribute_space(); + self.geom.y -= count; + self.reflow_lines(); } fn scroll_up(&mut self, count: usize) { self.grid.move_viewport_up(count); @@ -392,73 +373,47 @@ impl Pane for TerminalPane { self.grid.get_selected_text() } + fn set_frame(&mut self, frame: bool) { + self.frame = if frame { + Some(PaneFrame::default()) + } else { + None + }; + } + + fn set_content_offset(&mut self, offset: Offset) { + self.content_offset = offset; + self.reflow_lines(); + } + fn set_boundary_color(&mut self, color: Option) { - if let PaneDecoration::BoundariesFrame(boundaries_frame) = &mut self.pane_decoration { - if boundaries_frame.color != color { - boundaries_frame.set_color(color); - self.set_should_render(true); - } - } - } - fn relative_position(&self, position_on_screen: &Position) -> Position { - let pane_position_and_size = self.get_content_posision_and_size(); - position_on_screen.relative_to(&pane_position_and_size) - } - fn offset_content_columns(&mut self, by: usize) { - if let PaneDecoration::ContentOffset(content_offset) = &mut self.pane_decoration { - content_offset.0 = by; - } else { - self.pane_decoration = PaneDecoration::ContentOffset((by, 0)); - } - self.redistribute_space(); - } - fn offset_content_rows(&mut self, by: usize) { - if let PaneDecoration::ContentOffset(content_offset) = &mut self.pane_decoration { - content_offset.1 = by; - } else { - self.pane_decoration = PaneDecoration::ContentOffset((0, by)); - } - self.redistribute_space(); - } - fn show_boundaries_frame(&mut self, only_title: bool) { - let position_and_size = self - .position_and_size_override - .unwrap_or(self.position_and_size); - if let PaneDecoration::BoundariesFrame(boundaries_frame) = &mut self.pane_decoration { - boundaries_frame.render_only_title(only_title); - self.content_position_and_size = boundaries_frame.content_position_and_size(); - } else { - let mut boundaries_frame = - PaneBoundariesFrame::new(position_and_size, self.pane_title.clone()); - boundaries_frame.render_only_title(only_title); - self.content_position_and_size = boundaries_frame.content_position_and_size(); - self.pane_decoration = PaneDecoration::BoundariesFrame(boundaries_frame); - } - self.redistribute_space(); - } - fn remove_boundaries_frame(&mut self) { - self.pane_decoration = PaneDecoration::ContentOffset((0, 0)); - self.redistribute_space(); + self.frame_color = color; + self.set_should_render(true); } } impl TerminalPane { pub fn new( pid: RawFd, - position_and_size: PositionAndSize, + position_and_size: PaneGeom, palette: Palette, - pane_position: usize, + pane_index: usize, ) -> TerminalPane { - let initial_pane_title = format!("Pane #{}", pane_position); - let grid = Grid::new(position_and_size.rows, position_and_size.cols, palette); + let initial_pane_title = format!("Pane #{}", pane_index); + let grid = Grid::new( + position_and_size.rows.as_usize(), + position_and_size.cols.as_usize(), + palette, + ); TerminalPane { - pane_decoration: PaneDecoration::ContentOffset((0, 0)), - content_position_and_size: position_and_size, + frame: None, + frame_color: None, + content_offset: Offset::default(), pid, grid, selectable: true, - position_and_size, - position_and_size_override: None, + geom: position_and_size, + geom_override: None, vte_parser: vte::Parser::new(), active_at: Instant::now(), colors: palette, @@ -467,52 +422,33 @@ impl TerminalPane { } } pub fn get_x(&self) -> usize { - match self.position_and_size_override.as_ref() { + match self.geom_override { Some(position_and_size_override) => position_and_size_override.x, - None => self.position_and_size.x, + None => self.geom.x, } } pub fn get_y(&self) -> usize { - match self.position_and_size_override.as_ref() { + match self.geom_override { Some(position_and_size_override) => position_and_size_override.y, - None => self.position_and_size.y, + None => self.geom.y, } } pub fn get_columns(&self) -> usize { - match self.position_and_size_override.as_ref() { - Some(position_and_size_override) => position_and_size_override.cols, - None => self.position_and_size.cols, + match self.geom_override { + Some(position_and_size_override) => position_and_size_override.cols.as_usize(), + None => self.geom.cols.as_usize(), } } pub fn get_rows(&self) -> usize { - match self.position_and_size_override.as_ref() { - Some(position_and_size_override) => position_and_size_override.rows, - None => self.position_and_size.rows, + match self.geom_override { + Some(position_and_size_override) => position_and_size_override.rows.as_usize(), + None => self.geom.rows.as_usize(), } } - pub fn get_content_x(&self) -> usize { - self.get_content_posision_and_size().x - } - pub fn get_content_y(&self) -> usize { - self.get_content_posision_and_size().y - } - pub fn get_content_columns(&self) -> usize { - // content columns might differ from the pane's columns if the pane has a frame - // in that case they would be 2 less - self.get_content_posision_and_size().cols - } - pub fn get_content_rows(&self) -> usize { - // content rows might differ from the pane's rows if the pane has a frame - // in that case they would be 2 less - self.get_content_posision_and_size().rows - } - pub fn get_content_posision_and_size(&self) -> PositionAndSize { - self.content_position_and_size - } fn reflow_lines(&mut self) { let rows = self.get_content_rows(); - let columns = self.get_content_columns(); - self.grid.change_size(rows, columns); + let cols = self.get_content_columns(); + self.grid.change_size(rows, cols); self.set_should_render(true); } pub fn read_buffer_as_lines(&self) -> Vec> { @@ -522,24 +458,6 @@ impl TerminalPane { // (x, y) self.grid.cursor_coordinates() } - fn redistribute_space(&mut self) { - let position_and_size = self - .position_and_size_override - .unwrap_or_else(|| self.position_and_size()); - match &mut self.pane_decoration { - PaneDecoration::BoundariesFrame(boundaries_frame) => { - boundaries_frame.change_pos_and_size(position_and_size); - self.content_position_and_size = boundaries_frame.content_position_and_size(); - } - PaneDecoration::ContentOffset((content_columns_offset, content_rows_offset)) => { - self.content_position_and_size = position_and_size; - self.content_position_and_size.cols = - position_and_size.cols - *content_columns_offset; - self.content_position_and_size.rows = position_and_size.rows - *content_rows_offset; - } - }; - self.reflow_lines(); - } } #[cfg(test)] diff --git a/zellij-server/src/panes/unit/terminal_pane_tests.rs b/zellij-server/src/panes/unit/terminal_pane_tests.rs index 70e4e172..3ca7e8a7 100644 --- a/zellij-server/src/panes/unit/terminal_pane_tests.rs +++ b/zellij-server/src/panes/unit/terminal_pane_tests.rs @@ -1,18 +1,15 @@ use super::super::TerminalPane; use crate::tab::Pane; use ::insta::assert_snapshot; -use zellij_utils::pane_size::PositionAndSize; +use zellij_utils::pane_size::PaneGeom; use zellij_utils::zellij_tile::data::Palette; #[test] pub fn scrolling_inside_a_pane() { - let fake_win_size = PositionAndSize { - cols: 121, - rows: 20, - x: 0, - y: 0, - ..Default::default() - }; + let mut fake_win_size = PaneGeom::default(); + fake_win_size.cols.set_inner(121); + fake_win_size.rows.set_inner(20); + let pid = 1; let palette = Palette::default(); let mut terminal_pane = TerminalPane::new(pid, fake_win_size, palette, 0); // 0 is the pane index diff --git a/zellij-server/src/pty.rs b/zellij-server/src/pty.rs index 011b45ca..e28729b7 100644 --- a/zellij-server/src/pty.rs +++ b/zellij-server/src/pty.rs @@ -60,7 +60,7 @@ pub(crate) struct Pty { task_handles: HashMap>, } -pub(crate) fn pty_thread_main(mut pty: Pty, maybe_layout: Option) { +pub(crate) fn pty_thread_main(mut pty: Pty, layout: LayoutFromYaml) { loop { let (event, mut err_ctx) = pty.bus.recv().expect("failed to receive event on channel"); err_ctx.add_call(ContextType::Pty((&event).into())); @@ -87,16 +87,8 @@ pub(crate) fn pty_thread_main(mut pty: Pty, maybe_layout: Option .unwrap(); } PtyInstruction::NewTab(terminal_action, tab_layout) => { - if let Some(layout) = maybe_layout.clone() { - let merged_layout = layout.template.insert_tab_layout(tab_layout); - pty.spawn_terminals_for_layout(merged_layout.into(), terminal_action.clone()); - } else { - let pid = pty.spawn_terminal(terminal_action.clone()); - pty.bus - .senders - .send_to_screen(ScreenInstruction::NewTab(pid)) - .unwrap(); - } + let merged_layout = layout.template.clone().insert_tab_layout(tab_layout); + pty.spawn_terminals_for_layout(merged_layout.into(), terminal_action.clone()); } PtyInstruction::ClosePane(id) => { pty.close_pane(id); diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index d0e02e80..8d17d529 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -5,6 +5,7 @@ use std::os::unix::io::RawFd; use std::str; use std::sync::{Arc, RwLock}; +use zellij_utils::pane_size::Size; use zellij_utils::{input::layout::Layout, position::Position, zellij_tile}; use crate::{ @@ -20,7 +21,6 @@ use zellij_utils::{ errors::{ContextType, ScreenContext}, input::{get_mode_info, options::Options}, ipc::ClientAttributes, - pane_size::PositionAndSize, }; /// Instructions that can be sent to the [`Screen`]. @@ -58,12 +58,8 @@ pub(crate) enum ScreenInstruction { ToggleActiveTerminalFullscreen, TogglePaneFrames, SetSelectable(PaneId, bool, usize), - SetFixedHeight(PaneId, usize, usize), - SetFixedWidth(PaneId, usize, usize), - SetInvisibleBorders(PaneId, bool, usize), ClosePane(PaneId), ApplyLayout(Layout, Vec), - NewTab(RawFd), SwitchTabNext, SwitchTabPrev, ToggleActiveSyncTab, @@ -71,7 +67,7 @@ pub(crate) enum ScreenInstruction { GoToTab(u32), ToggleTab, UpdateTabName(Vec), - TerminalResize(PositionAndSize), + TerminalResize(Size), ChangeMode(ModeInfo), LeftClick(Position), MouseRelease(Position), @@ -116,12 +112,8 @@ impl From<&ScreenInstruction> for ScreenContext { } ScreenInstruction::TogglePaneFrames => ScreenContext::TogglePaneFrames, ScreenInstruction::SetSelectable(..) => ScreenContext::SetSelectable, - ScreenInstruction::SetInvisibleBorders(..) => ScreenContext::SetInvisibleBorders, - ScreenInstruction::SetFixedHeight(..) => ScreenContext::SetFixedHeight, - ScreenInstruction::SetFixedWidth(..) => ScreenContext::SetFixedWidth, ScreenInstruction::ClosePane(_) => ScreenContext::ClosePane, ScreenInstruction::ApplyLayout(..) => ScreenContext::ApplyLayout, - ScreenInstruction::NewTab(_) => ScreenContext::NewTab, ScreenInstruction::SwitchTabNext => ScreenContext::SwitchTabNext, ScreenInstruction::SwitchTabPrev => ScreenContext::SwitchTabPrev, ScreenInstruction::CloseTab => ScreenContext::CloseTab, @@ -151,7 +143,7 @@ pub(crate) struct Screen { /// A map between this [`Screen`]'s tabs and their ID/key. tabs: BTreeMap, /// The full size of this [`Screen`]. - position_and_size: PositionAndSize, + size: Size, /// The index of this [`Screen`]'s active [`Tab`]. active_tab_index: Option, tab_history: Vec>, @@ -174,7 +166,7 @@ impl Screen { Screen { bus, max_panes, - position_and_size: client_attributes.position_and_size, + size: client_attributes.size, colors: client_attributes.palette, active_tab_index: None, tabs: BTreeMap::new(), @@ -185,32 +177,6 @@ impl Screen { } } - /// Creates a new [`Tab`] in this [`Screen`], containing a single - /// [pane](crate::client::panes) with PTY file descriptor `pane_id`. - pub fn new_tab(&mut self, pane_id: RawFd) { - let tab_index = self.get_new_tab_index(); - let position = self.tabs.len(); - let tab = Tab::new( - tab_index, - position, - String::new(), - &self.position_and_size, - self.bus.os_input.as_ref().unwrap().clone(), - self.bus.senders.clone(), - self.max_panes, - Some(PaneId::Terminal(pane_id)), - self.mode_info.clone(), - self.colors, - self.session_state.clone(), - self.draw_pane_frames, - ); - self.tab_history.push(self.active_tab_index); - self.active_tab_index = Some(tab_index); - self.tabs.insert(tab_index, tab); - self.update_tabs(); - self.render(); - } - /// Returns the index where a new [`Tab`] should be created in this [`Screen`]. /// Currently, this is right after the last currently existing tab, or `0` if /// no tabs exist in this screen yet. @@ -308,8 +274,8 @@ impl Screen { } } - pub fn resize_to_screen(&mut self, new_screen_size: PositionAndSize) { - self.position_and_size = new_screen_size; + pub fn resize_to_screen(&mut self, new_screen_size: Size) { + self.size = new_screen_size; for (_, tab) in self.tabs.iter_mut() { tab.resize_whole_tab(new_screen_size); } @@ -377,11 +343,10 @@ impl Screen { tab_index, position, String::new(), - &self.position_and_size, + self.size, self.bus.os_input.as_ref().unwrap().clone(), self.bus.senders.clone(), self.max_panes, - None, self.mode_info.clone(), self.colors, self.session_state.clone(), @@ -657,43 +622,6 @@ pub(crate) fn screen_thread_main( |tab| tab.set_pane_selectable(id, selectable), ); } - ScreenInstruction::SetFixedHeight(id, fixed_height, tab_index) => { - screen.get_indexed_tab_mut(tab_index).map_or_else( - || { - log::warn!( - "Tab index #{} not found, could not set fixed height for plugin #{:?}.", - tab_index, - id - ) - }, - |tab| tab.set_pane_fixed_height(id, fixed_height), - ); - } - ScreenInstruction::SetFixedWidth(id, fixed_width, tab_index) => { - screen.get_indexed_tab_mut(tab_index).map_or_else( - || { - log::warn!( - "Tab index #{} not found, could not set fixed width for plugin #{:?}.", - tab_index, - id - ) - }, - |tab| tab.set_pane_fixed_width(id, fixed_width), - ); - } - ScreenInstruction::SetInvisibleBorders(id, invisible_borders, tab_index) => { - screen.get_indexed_tab_mut(tab_index).map_or_else( - || { - log::warn!( - r#"Tab index #{} not found, could not set invisible borders for plugin #{:?}."#, - tab_index, - id - ) - }, - |tab| tab.set_pane_invisible_borders(id, invisible_borders), - ); - screen.render(); - } ScreenInstruction::ClosePane(id) => { screen.get_active_tab_mut().unwrap().close_pane(id); screen.render(); @@ -711,14 +639,6 @@ pub(crate) fn screen_thread_main( } screen.render(); } - ScreenInstruction::NewTab(pane_id) => { - screen.new_tab(pane_id); - screen - .bus - .senders - .send_to_server(ServerInstruction::UnblockInputThread) - .unwrap(); - } ScreenInstruction::SwitchTabNext => { screen.switch_tab_next(); screen diff --git a/zellij-server/src/tab.rs b/zellij-server/src/tab.rs index 6ecf33b7..9de19146 100644 --- a/zellij-server/src/tab.rs +++ b/zellij-server/src/tab.rs @@ -1,12 +1,6 @@ //! `Tab`s holds multiple panes. It tracks their coordinates (x/y) and size, //! as well as how they should be resized - -use zellij_utils::{position::Position, serde, zellij_tile}; - -#[cfg(not(feature = "parametric_resize_beta"))] use crate::ui::pane_resizer::PaneResizer; -#[cfg(feature = "parametric_resize_beta")] -use crate::ui::pane_resizer_beta::PaneResizer; use crate::{ os_input_output::ServerOsApi, panes::{PaneId, PluginPane, TerminalPane}, @@ -25,65 +19,74 @@ use std::{ collections::{BTreeMap, HashSet}, }; use zellij_tile::data::{Event, InputMode, ModeInfo, Palette, PaletteColor}; +use zellij_utils::input::layout::Direction; +use zellij_utils::pane_size::{Offset, Size, Viewport}; use zellij_utils::{ input::{ layout::{Layout, Run}, parse_keys, }, - pane_size::PositionAndSize, + pane_size::{Dimension, PaneGeom}, + position::Position, + serde, zellij_tile, }; const CURSOR_HEIGHT_WIDTH_RATIO: usize = 4; // this is not accurate and kind of a magic number, TODO: look into this -// MIN_TERMINAL_HEIGHT here must be larger than the height of any of the status bars -// this is a dirty hack until we implement fixed panes +// FIXME: This should be replaced by `RESIZE_PERCENT` at some point const MIN_TERMINAL_HEIGHT: usize = 5; const MIN_TERMINAL_WIDTH: usize = 5; +const RESIZE_PERCENT: f64 = 5.0; + type BorderAndPaneIds = (usize, Vec); -fn split_vertically(rect: &PositionAndSize) -> (PositionAndSize, PositionAndSize) { - let width_of_each_half = rect.cols / 2; - let mut first_rect = *rect; - let mut second_rect = *rect; - if rect.cols % 2 == 0 { - first_rect.cols = width_of_each_half; +fn split(direction: Direction, rect: &PaneGeom) -> Option<(PaneGeom, PaneGeom)> { + let space = match direction { + Direction::Vertical => rect.cols, + Direction::Horizontal => rect.rows, + }; + if let Some(p) = space.as_percent() { + let first_rect = match direction { + Direction::Vertical => PaneGeom { + cols: Dimension::percent(p / 2.0), + ..*rect + }, + Direction::Horizontal => PaneGeom { + rows: Dimension::percent(p / 2.0), + ..*rect + }, + }; + let second_rect = match direction { + Direction::Vertical => PaneGeom { + x: first_rect.x + 1, + cols: first_rect.cols, + ..*rect + }, + Direction::Horizontal => PaneGeom { + y: first_rect.y + 1, + rows: first_rect.rows, + ..*rect + }, + }; + Some((first_rect, second_rect)) } else { - first_rect.cols = width_of_each_half + 1; + None } - second_rect.x = first_rect.x + first_rect.cols; - second_rect.cols = width_of_each_half; - (first_rect, second_rect) } -fn split_horizontally(rect: &PositionAndSize) -> (PositionAndSize, PositionAndSize) { - let height_of_each_half = rect.rows / 2; - let mut first_rect = *rect; - let mut second_rect = *rect; - if rect.rows % 2 == 0 { - first_rect.rows = height_of_each_half; - } else { - first_rect.rows = height_of_each_half + 1; - } - second_rect.y = first_rect.y + first_rect.rows; - second_rect.rows = height_of_each_half; - (first_rect, second_rect) -} - -fn pane_content_offset( - position_and_size: &PositionAndSize, - viewport: &PositionAndSize, -) -> (usize, usize) { +fn pane_content_offset(position_and_size: &PaneGeom, viewport: &Viewport) -> (usize, usize) { // (columns_offset, rows_offset) // if the pane is not on the bottom or right edge on the screen, we need to reserve one space // from its content to leave room for the boundary between it and the next pane (if it doesn't // draw its own frame) - let columns_offset = if position_and_size.x + position_and_size.cols < viewport.cols { + let columns_offset = if position_and_size.x + position_and_size.cols.as_usize() < viewport.cols + { 1 } else { 0 }; - let rows_offset = if position_and_size.y + position_and_size.rows < viewport.rows { + let rows_offset = if position_and_size.y + position_and_size.rows.as_usize() < viewport.rows { 1 } else { 0 @@ -99,8 +102,8 @@ pub(crate) struct Tab { panes_to_hide: HashSet, active_terminal: Option, max_panes: Option, - viewport: PositionAndSize, // includes all selectable panes - display_area: PositionAndSize, // includes all panes (including eg. the status bar and tab bar in the default layout) + viewport: Viewport, // includes all selectable panes + display_area: Size, // includes all panes (including eg. the status bar and tab bar in the default layout) fullscreen_is_active: bool, os_api: Box, pub senders: ThreadSenders, @@ -115,7 +118,6 @@ pub(crate) struct Tab { #[derive(Clone, Debug, Default, Serialize, Deserialize)] #[serde(crate = "self::serde")] pub(crate) struct TabData { - /* subset of fields to publish to plugins */ pub position: usize, pub name: String, pub active: bool, @@ -128,33 +130,31 @@ pub trait Pane { fn x(&self) -> usize; fn y(&self) -> usize; fn rows(&self) -> usize; - fn columns(&self) -> usize; + fn cols(&self) -> usize; + fn get_content_x(&self) -> usize; + fn get_content_y(&self) -> usize; + fn get_content_columns(&self) -> usize; + fn get_content_rows(&self) -> usize; fn reset_size_and_position_override(&mut self); - fn change_pos_and_size(&mut self, position_and_size: &PositionAndSize); - fn override_size_and_position(&mut self, x: usize, y: usize, size: &PositionAndSize); + fn set_geom(&mut self, position_and_size: PaneGeom); + fn get_geom_override(&mut self, pane_geom: PaneGeom); fn handle_pty_bytes(&mut self, bytes: VteBytes); fn cursor_coordinates(&self) -> Option<(usize, usize)>; fn adjust_input_to_terminal(&self, input_bytes: Vec) -> Vec; - fn position_and_size(&self) -> PositionAndSize; - fn position_and_size_override(&self) -> Option; + fn position_and_size(&self) -> PaneGeom; + fn current_geom(&self) -> PaneGeom; + fn geom_override(&self) -> Option; fn should_render(&self) -> bool; fn set_should_render(&mut self, should_render: bool); fn set_should_render_boundaries(&mut self, _should_render: bool) {} fn selectable(&self) -> bool; fn set_selectable(&mut self, selectable: bool); - fn set_invisible_borders(&mut self, invisible_borders: bool); - fn set_fixed_height(&mut self, fixed_height: usize); - fn set_fixed_width(&mut self, fixed_width: usize); fn render(&mut self) -> Option; fn pid(&self) -> PaneId; - fn reduce_height_down(&mut self, count: usize); - fn increase_height_down(&mut self, count: usize); - fn increase_height_up(&mut self, count: usize); - fn reduce_height_up(&mut self, count: usize); - fn increase_width_right(&mut self, count: usize); - fn reduce_width_right(&mut self, count: usize); - fn reduce_width_left(&mut self, count: usize); - fn increase_width_left(&mut self, count: usize); + fn reduce_height(&mut self, percent: f64); + fn increase_height(&mut self, percent: f64); + fn reduce_width(&mut self, percent: f64); + fn increase_width(&mut self, percent: f64); fn push_down(&mut self, count: usize); fn push_right(&mut self, count: usize); fn pull_left(&mut self, count: usize); @@ -164,11 +164,13 @@ pub trait Pane { fn clear_scroll(&mut self); fn active_at(&self) -> Instant; fn set_active_at(&mut self, instant: Instant); + fn set_frame(&mut self, frame: bool); + fn set_content_offset(&mut self, offset: Offset); fn cursor_shape_csi(&self) -> String { "\u{1b}[0 q".to_string() // default to non blinking block } fn contains(&self, position: &Position) -> bool { - match self.position_and_size_override() { + match self.geom_override() { Some(position_and_size) => position_and_size.contains(position), None => self.position_and_size().contains(position), } @@ -182,16 +184,16 @@ pub trait Pane { } fn right_boundary_x_coords(&self) -> usize { - self.x() + self.columns() + self.x() + self.cols() } fn bottom_boundary_y_coords(&self) -> usize { self.y() + self.rows() } fn is_directly_right_of(&self, other: &dyn Pane) -> bool { - self.x() == other.x() + other.columns() + self.x() == other.x() + other.cols() } fn is_directly_left_of(&self, other: &dyn Pane) -> bool { - self.x() + self.columns() == other.x() + self.x() + self.cols() == other.x() } fn is_directly_below(&self, other: &dyn Pane) -> bool { self.y() == other.y() + other.rows() @@ -211,33 +213,21 @@ pub trait Pane { - std::cmp::max(self.y(), other.y()) } fn vertically_overlaps_with(&self, other: &dyn Pane) -> bool { - (self.x() >= other.x() && self.x() < (other.x() + other.columns())) - || ((self.x() + self.columns()) <= (other.x() + other.columns()) - && (self.x() + self.columns()) > other.x()) - || (self.x() <= other.x() - && (self.x() + self.columns() >= (other.x() + other.columns()))) - || (other.x() <= self.x() - && (other.x() + other.columns() >= (self.x() + self.columns()))) + (self.x() >= other.x() && self.x() < (other.x() + other.cols())) + || ((self.x() + self.cols()) <= (other.x() + other.cols()) + && (self.x() + self.cols()) > other.x()) + || (self.x() <= other.x() && (self.x() + self.cols() >= (other.x() + other.cols()))) + || (other.x() <= self.x() && (other.x() + other.cols() >= (self.x() + self.cols()))) } fn get_vertical_overlap_with(&self, other: &dyn Pane) -> usize { - std::cmp::min(self.x() + self.columns(), other.x() + other.columns()) + std::cmp::min(self.x() + self.cols(), other.x() + other.cols()) - std::cmp::max(self.x(), other.x()) } - fn can_increase_height_by(&self, increase_by: usize) -> bool { - self.max_height() - .map(|max_height| self.rows() + increase_by <= max_height) - .unwrap_or(true) - } - fn can_increase_width_by(&self, increase_by: usize) -> bool { - self.max_width() - .map(|max_width| self.columns() + increase_by <= max_width) - .unwrap_or(true) - } fn can_reduce_height_by(&self, reduce_by: usize) -> bool { self.rows() > reduce_by && self.rows() - reduce_by >= self.min_height() } fn can_reduce_width_by(&self, reduce_by: usize) -> bool { - self.columns() > reduce_by && self.columns() - reduce_by >= self.min_width() + self.cols() > reduce_by && self.cols() - reduce_by >= self.min_width() } fn min_width(&self) -> usize { MIN_TERMINAL_WIDTH @@ -245,42 +235,16 @@ pub trait Pane { fn min_height(&self) -> usize { MIN_TERMINAL_HEIGHT } - fn max_width(&self) -> Option { - None - } - fn max_height(&self) -> Option { - None - } - fn invisible_borders(&self) -> bool { - false - } fn drain_messages_to_pty(&mut self) -> Vec> { // TODO: this is only relevant to terminal panes // we should probably refactor away from this trait at some point vec![] } fn render_full_viewport(&mut self) {} - fn relative_position(&self, position: &Position) -> Position { - match self.position_and_size_override() { - Some(position_and_size) => position.relative_to(&position_and_size), - None => position.relative_to(&self.position_and_size()), - } - } - fn get_content_rows(&self) -> usize { - // content rows might differ from the pane's rows if the pane has a frame - // in that case they would be 2 less - self.rows() - } - fn get_content_columns(&self) -> usize { - // content columns might differ from the pane's columns if the pane has a frame - // in that case they would be 2 less - self.columns() + fn relative_position(&self, position_on_screen: &Position) -> Position { + position_on_screen.relative_to(self.get_content_y(), self.get_content_x()) } fn set_boundary_color(&mut self, _color: Option) {} - fn offset_content_columns(&mut self, _by: usize) {} - fn offset_content_rows(&mut self, _by: usize) {} - fn show_boundaries_frame(&mut self, _render_only_title: bool) {} - fn remove_boundaries_frame(&mut self) {} } impl Tab { @@ -290,33 +254,16 @@ impl Tab { index: usize, position: usize, name: String, - viewport: &PositionAndSize, + display_area: Size, os_api: Box, senders: ThreadSenders, max_panes: Option, - pane_id: Option, mode_info: ModeInfo, colors: Palette, session_state: Arc>, draw_pane_frames: bool, ) -> Self { - let panes = if let Some(PaneId::Terminal(pid)) = pane_id { - let pane_title_only = true; - let mut new_terminal = TerminalPane::new(pid, *viewport, colors, 1); - if draw_pane_frames { - new_terminal.show_boundaries_frame(pane_title_only); - } - os_api.set_terminal_size_using_fd( - new_terminal.pid, - new_terminal.columns() as u16, - new_terminal.rows() as u16, - ); - let mut panes: BTreeMap> = BTreeMap::new(); - panes.insert(PaneId::Terminal(pid), Box::new(new_terminal)); - panes - } else { - BTreeMap::new() - }; + let panes = BTreeMap::new(); let name = if name.is_empty() { format!("Tab #{}", position + 1) @@ -331,9 +278,9 @@ impl Tab { name, max_panes, panes_to_hide: HashSet::new(), - active_terminal: pane_id, - viewport: *viewport, - display_area: *viewport, + active_terminal: None, + viewport: display_area.into(), + display_area, fullscreen_is_active: false, synchronize_is_active: false, os_api, @@ -347,43 +294,19 @@ impl Tab { } pub fn apply_layout(&mut self, layout: Layout, new_pids: Vec, tab_index: usize) { - // TODO: this should be an attribute on Screen instead of viewport - let free_space = PositionAndSize { - x: 0, - y: 0, - rows: self.viewport.rows, - cols: self.viewport.cols, - ..Default::default() - }; + // TODO: this should be an attribute on Screen instead of full_screen_ws + let free_space = PaneGeom::default(); self.panes_to_hide.clear(); let positions_in_layout = layout.position_panes_in_space(&free_space); - for (layout, position_and_size) in &positions_in_layout { - // we need to do this first because it decides the size of the screen - // which we use for other stuff in the main loop below (eg. which type of frames the - // panes should have) - if layout.borderless { - self.offset_viewport(position_and_size); - } - } - let mut positions_and_size = positions_in_layout.iter(); - let total_borderless_panes = layout.total_borderless_panes(); - let total_panes_with_border = positions_in_layout - .len() - .saturating_sub(total_borderless_panes); for (pane_kind, terminal_pane) in self.panes.iter_mut() { // for now the layout only supports terminal panes if let PaneId::Terminal(pid) = pane_kind { match positions_and_size.next() { - Some((_, position_and_size)) => { + Some(&(_, position_and_size)) => { terminal_pane.reset_size_and_position_override(); - terminal_pane.change_pos_and_size(position_and_size); - self.os_api.set_terminal_size_using_fd( - *pid, - position_and_size.cols as u16, - position_and_size.rows as u16, - ); + terminal_pane.set_geom(position_and_size); } None => { // we filled the entire layout, no room for this pane @@ -403,18 +326,13 @@ impl Tab { .send_to_plugin(PluginInstruction::Load(pid_tx, plugin.clone(), tab_index)) .unwrap(); let pid = pid_rx.recv().unwrap(); - let draw_pane_frames = self.draw_pane_frames && !layout.borderless; - let pane_title_only = !layout.borderless && total_panes_with_border == 1; let title = String::from(plugin.as_path().as_os_str().to_string_lossy()); - let mut new_plugin = PluginPane::new( + let new_plugin = PluginPane::new( pid, *position_and_size, self.senders.to_plugin.as_ref().unwrap().clone(), title, ); - if draw_pane_frames && !layout.borderless { - new_plugin.show_boundaries_frame(pane_title_only); - } self.panes.insert(PaneId::Plugin(pid), Box::new(new_plugin)); // Send an initial mode update to the newly loaded plugin only! self.senders @@ -427,30 +345,14 @@ impl Tab { // there are still panes left to fill, use the pids we received in this method let pid = new_pids.next().unwrap(); // if this crashes it means we got less pids than there are panes in this layout let next_selectable_pane_position = self.get_next_selectable_pane_position(); - let pane_title_only = - next_selectable_pane_position == 1 && total_panes_with_border == 1; - let draw_pane_frames = self.draw_pane_frames && !layout.borderless; - let mut new_terminal = TerminalPane::new( + let new_pane = TerminalPane::new( *pid, *position_and_size, self.colors, next_selectable_pane_position, ); - if draw_pane_frames { - new_terminal.show_boundaries_frame(pane_title_only); - } else { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(position_and_size, &self.viewport); - new_terminal.offset_content_columns(pane_columns_offset); - new_terminal.offset_content_rows(pane_rows_offset); - } - self.os_api.set_terminal_size_using_fd( - new_terminal.pid, - new_terminal.get_content_columns() as u16, - new_terminal.get_content_rows() as u16, - ); self.panes - .insert(PaneId::Terminal(*pid), Box::new(new_terminal)); + .insert(PaneId::Terminal(*pid), Box::new(new_pane)); } } for unused_pid in new_pids { @@ -461,6 +363,26 @@ impl Tab { .send_to_pty(PtyInstruction::ClosePane(PaneId::Terminal(*unused_pid))) .unwrap(); } + // FIXME: This is another hack to crop the viewport to fixed-size panes. Once you can have + // non-fixed panes that are part of the viewport, get rid of this! + self.resize_whole_tab(self.display_area); + let boundary_geom: Vec<_> = self + .panes + .values() + .filter_map(|p| { + let geom = p.position_and_size(); + if geom.cols.is_fixed() || geom.rows.is_fixed() { + Some(geom.into()) + } else { + None + } + }) + .collect(); + for geom in boundary_geom { + self.offset_viewport(&geom) + } + // This is the end of the nasty viewport hack... + // FIXME: Active / new / current terminal, should be pane self.active_terminal = self.panes.iter().map(|(id, _)| id.to_owned()).next(); self.render(); } @@ -469,187 +391,81 @@ impl Tab { if self.fullscreen_is_active { self.toggle_active_pane_fullscreen(); } - if !self.has_panes() { - if let PaneId::Terminal(term_pid) = pid { - let next_selectable_pane_position = self.get_next_selectable_pane_position(); - let pane_title_only = next_selectable_pane_position == 1; - let mut new_terminal = TerminalPane::new( - term_pid, - self.viewport, - self.colors, - next_selectable_pane_position, - ); - if self.draw_pane_frames { - new_terminal.show_boundaries_frame(pane_title_only); - } - self.os_api.set_terminal_size_using_fd( - new_terminal.pid, - new_terminal.columns() as u16, - new_terminal.rows() as u16, - ); - self.panes.insert(pid, Box::new(new_terminal)); - self.active_terminal = Some(pid); - } - } else { - // TODO: check minimum size of active terminal + // TODO: check minimum size of active terminal - let (_largest_terminal_size, terminal_id_to_split) = self.get_panes().fold( - (0, None), - |(current_largest_terminal_size, current_terminal_id_to_split), - id_and_terminal_to_check| { - let (id_of_terminal_to_check, terminal_to_check) = id_and_terminal_to_check; - let terminal_size = (terminal_to_check.rows() * CURSOR_HEIGHT_WIDTH_RATIO) - * terminal_to_check.columns(); - let terminal_can_be_split = terminal_to_check.columns() >= MIN_TERMINAL_WIDTH - && terminal_to_check.rows() >= MIN_TERMINAL_HEIGHT - && ((terminal_to_check.columns() > terminal_to_check.min_width() * 2) - || (terminal_to_check.rows() > terminal_to_check.min_height() * 2)); - if terminal_can_be_split && terminal_size > current_largest_terminal_size { - (terminal_size, Some(*id_of_terminal_to_check)) - } else { - (current_largest_terminal_size, current_terminal_id_to_split) - } - }, - ); - if terminal_id_to_split.is_none() { - self.senders - .send_to_pty(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty - .unwrap(); - return; // likely no terminal large enough to split - } - let terminal_id_to_split = terminal_id_to_split.unwrap(); - let next_selectable_pane_position = self.get_next_selectable_pane_position(); - let terminal_to_split = self.panes.get_mut(&terminal_id_to_split).unwrap(); - let terminal_ws = PositionAndSize { - rows: terminal_to_split.rows(), - cols: terminal_to_split.columns(), - x: terminal_to_split.x(), - y: terminal_to_split.y(), - ..Default::default() - }; - if terminal_to_split.rows() * CURSOR_HEIGHT_WIDTH_RATIO > terminal_to_split.columns() - && terminal_to_split.rows() > terminal_to_split.min_height() * 2 - { - if let PaneId::Terminal(term_pid) = pid { - let (top_winsize, bottom_winsize) = split_horizontally(&terminal_ws); - let pane_title_only = next_selectable_pane_position == 1; - let mut new_terminal = TerminalPane::new( + let (_largest_terminal_size, terminal_id_to_split) = self.get_panes().fold( + (0, None), + |(current_largest_terminal_size, current_terminal_id_to_split), + id_and_terminal_to_check| { + let (id_of_terminal_to_check, terminal_to_check) = id_and_terminal_to_check; + let terminal_size = (terminal_to_check.rows() * CURSOR_HEIGHT_WIDTH_RATIO) + * terminal_to_check.cols(); + let terminal_can_be_split = terminal_to_check.cols() >= MIN_TERMINAL_WIDTH + && terminal_to_check.rows() >= MIN_TERMINAL_HEIGHT + && ((terminal_to_check.cols() > terminal_to_check.min_width() * 2) + || (terminal_to_check.rows() > terminal_to_check.min_height() * 2)); + if terminal_can_be_split && terminal_size > current_largest_terminal_size { + (terminal_size, Some(*id_of_terminal_to_check)) + } else { + (current_largest_terminal_size, current_terminal_id_to_split) + } + }, + ); + if terminal_id_to_split.is_none() { + self.senders + .send_to_pty(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty + .unwrap(); + return; // likely no terminal large enough to split + } + let terminal_id_to_split = terminal_id_to_split.unwrap(); + let next_selectable_pane_position = self.get_next_selectable_pane_position(); + let terminal_to_split = self.panes.get_mut(&terminal_id_to_split).unwrap(); + let terminal_ws = terminal_to_split.position_and_size(); + if terminal_to_split.rows() * CURSOR_HEIGHT_WIDTH_RATIO > terminal_to_split.cols() + && terminal_to_split.rows() > terminal_to_split.min_height() * 2 + { + if let PaneId::Terminal(term_pid) = pid { + if let Some((top_winsize, bottom_winsize)) = + split(Direction::Horizontal, &terminal_ws) + { + let new_terminal = TerminalPane::new( term_pid, bottom_winsize, self.colors, next_selectable_pane_position, ); - if self.draw_pane_frames { - new_terminal.show_boundaries_frame(pane_title_only); - } else { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&bottom_winsize, &self.viewport); - new_terminal.offset_content_columns(pane_columns_offset); - new_terminal.offset_content_rows(pane_rows_offset); - } - self.os_api.set_terminal_size_using_fd( - new_terminal.pid, - new_terminal.get_content_columns() as u16, - new_terminal.get_content_rows() as u16, - ); - if self.draw_pane_frames { - let only_title = false; - terminal_to_split.show_boundaries_frame(only_title); - } else { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&top_winsize, &self.viewport); - terminal_to_split.offset_content_columns(pane_columns_offset); - terminal_to_split.offset_content_rows(pane_rows_offset); - } - terminal_to_split.change_pos_and_size(&top_winsize); - let terminal_to_split_content_columns = terminal_to_split.get_content_columns(); - let terminal_to_split_content_rows = terminal_to_split.get_content_rows(); + terminal_to_split.set_geom(top_winsize); self.panes.insert(pid, Box::new(new_terminal)); - if let PaneId::Terminal(terminal_id_to_split) = terminal_id_to_split { - self.os_api.set_terminal_size_using_fd( - terminal_id_to_split, - terminal_to_split_content_columns as u16, - terminal_to_split_content_rows as u16, - ); - } - self.active_terminal = Some(pid); + self.relayout_tab(Direction::Vertical); } - } else if terminal_to_split.columns() > terminal_to_split.min_width() * 2 { - if let PaneId::Terminal(term_pid) = pid { - let (left_winsize, right_winsize) = split_vertically(&terminal_ws); - let pane_title_only = next_selectable_pane_position == 1; - let mut new_terminal = TerminalPane::new( + } + } else if terminal_to_split.cols() > terminal_to_split.min_width() * 2 { + if let PaneId::Terminal(term_pid) = pid { + if let Some((left_winsize, right_winsize)) = + split(Direction::Vertical, &terminal_ws) + { + let new_terminal = TerminalPane::new( term_pid, right_winsize, self.colors, next_selectable_pane_position, ); - if self.draw_pane_frames { - new_terminal.show_boundaries_frame(pane_title_only); - } else { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&right_winsize, &self.viewport); - new_terminal.offset_content_columns(pane_columns_offset); - new_terminal.offset_content_rows(pane_rows_offset); - } - self.os_api.set_terminal_size_using_fd( - new_terminal.pid, - new_terminal.get_content_columns() as u16, - new_terminal.get_content_rows() as u16, - ); - if self.draw_pane_frames { - let only_title = false; - terminal_to_split.show_boundaries_frame(only_title); - } else { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&left_winsize, &self.viewport); - terminal_to_split.offset_content_columns(pane_columns_offset); - terminal_to_split.offset_content_rows(pane_rows_offset); - } - terminal_to_split.change_pos_and_size(&left_winsize); - let terminal_to_split_content_columns = terminal_to_split.get_content_columns(); - let terminal_to_split_content_rows = terminal_to_split.get_content_rows(); + terminal_to_split.set_geom(left_winsize); self.panes.insert(pid, Box::new(new_terminal)); - if let PaneId::Terminal(terminal_id_to_split) = terminal_id_to_split { - self.os_api.set_terminal_size_using_fd( - terminal_id_to_split, - terminal_to_split_content_columns as u16, - terminal_to_split_content_rows as u16, - ); - } + self.relayout_tab(Direction::Horizontal); } } - self.active_terminal = Some(pid); - self.render(); } + self.active_terminal = Some(pid); + self.render(); } pub fn horizontal_split(&mut self, pid: PaneId) { self.close_down_to_max_terminals(); if self.fullscreen_is_active { self.toggle_active_pane_fullscreen(); } - if !self.has_panes() { - if let PaneId::Terminal(term_pid) = pid { - let next_selectable_pane_position = self.get_next_selectable_pane_position(); - let pane_title_only = next_selectable_pane_position == 1; - let mut new_terminal = TerminalPane::new( - term_pid, - self.viewport, - self.colors, - next_selectable_pane_position, - ); - if self.draw_pane_frames { - new_terminal.show_boundaries_frame(pane_title_only); - } - self.os_api.set_terminal_size_using_fd( - new_terminal.pid, - new_terminal.get_content_columns() as u16, - new_terminal.get_content_rows() as u16, - ); - self.panes.insert(pid, Box::new(new_terminal)); - self.active_terminal = Some(pid); - } - } else if let PaneId::Terminal(term_pid) = pid { + if let PaneId::Terminal(term_pid) = pid { + let next_selectable_pane_position = self.get_next_selectable_pane_position(); let active_pane_id = &self.get_active_pane_id().unwrap(); let active_pane = self.panes.get_mut(active_pane_id).unwrap(); if active_pane.rows() < MIN_TERMINAL_HEIGHT * 2 { @@ -658,62 +474,21 @@ impl Tab { .unwrap(); return; } - let terminal_ws = PositionAndSize { - x: active_pane.x(), - y: active_pane.y(), - rows: active_pane.rows(), - cols: active_pane.columns(), - ..Default::default() - }; - let (top_winsize, bottom_winsize) = split_horizontally(&terminal_ws); - - if self.draw_pane_frames { - let only_title = false; - active_pane.show_boundaries_frame(only_title); - } else { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&top_winsize, &self.viewport); - active_pane.offset_content_columns(pane_columns_offset); - active_pane.offset_content_rows(pane_rows_offset); - } - active_pane.change_pos_and_size(&top_winsize); - - let active_pane_content_columns = active_pane.get_content_columns(); - let active_pane_content_rows = active_pane.get_content_rows(); - - let next_selectable_pane_position = self.get_next_selectable_pane_position(); - let pane_title_only = next_selectable_pane_position == 1; - let mut new_terminal = TerminalPane::new( - term_pid, - bottom_winsize, - self.colors, - next_selectable_pane_position, - ); - if self.draw_pane_frames { - new_terminal.show_boundaries_frame(pane_title_only); - } else { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&bottom_winsize, &self.viewport); - new_terminal.offset_content_columns(pane_columns_offset); - new_terminal.offset_content_rows(pane_rows_offset); - } - self.os_api.set_terminal_size_using_fd( - new_terminal.pid, - new_terminal.get_content_columns() as u16, - new_terminal.get_content_rows() as u16, - ); - self.panes.insert(pid, Box::new(new_terminal)); - - if let PaneId::Terminal(active_terminal_pid) = active_pane_id { - self.os_api.set_terminal_size_using_fd( - *active_terminal_pid, - active_pane_content_columns as u16, - active_pane_content_rows as u16, + let terminal_ws = active_pane.position_and_size(); + if let Some((top_winsize, bottom_winsize)) = split(Direction::Horizontal, &terminal_ws) + { + let new_terminal = TerminalPane::new( + term_pid, + bottom_winsize, + self.colors, + next_selectable_pane_position, ); + active_pane.set_geom(top_winsize); + self.panes.insert(pid, Box::new(new_terminal)); + self.active_terminal = Some(pid); + self.relayout_tab(Direction::Vertical); + self.render(); } - - self.active_terminal = Some(pid); - self.render(); } } pub fn vertical_split(&mut self, pid: PaneId) { @@ -721,107 +496,41 @@ impl Tab { if self.fullscreen_is_active { self.toggle_active_pane_fullscreen(); } - if !self.has_panes() { - if let PaneId::Terminal(term_pid) = pid { - let next_selectable_pane_position = self.get_next_selectable_pane_position(); - let pane_title_only = next_selectable_pane_position == 1; - let mut new_terminal = TerminalPane::new( - term_pid, - self.viewport, - self.colors, - next_selectable_pane_position, - ); - if self.draw_pane_frames { - new_terminal.show_boundaries_frame(pane_title_only); - } - self.os_api.set_terminal_size_using_fd( - new_terminal.pid, - new_terminal.get_content_columns() as u16, - new_terminal.get_content_rows() as u16, - ); - self.panes.insert(pid, Box::new(new_terminal)); - self.active_terminal = Some(pid); - } - } else if let PaneId::Terminal(term_pid) = pid { + if let PaneId::Terminal(term_pid) = pid { // TODO: check minimum size of active terminal + let next_selectable_pane_position = self.get_next_selectable_pane_position(); let active_pane_id = &self.get_active_pane_id().unwrap(); let active_pane = self.panes.get_mut(active_pane_id).unwrap(); - if active_pane.columns() < MIN_TERMINAL_WIDTH * 2 { + if active_pane.cols() < MIN_TERMINAL_WIDTH * 2 { self.senders .send_to_pty(PtyInstruction::ClosePane(pid)) // we can't open this pane, close the pty .unwrap(); return; } - let terminal_ws = PositionAndSize { - x: active_pane.x(), - y: active_pane.y(), - rows: active_pane.rows(), - cols: active_pane.columns(), - ..Default::default() - }; - let (left_winsize, right_winsize) = split_vertically(&terminal_ws); - - if self.draw_pane_frames { - let only_title = false; - active_pane.show_boundaries_frame(only_title); - } else { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&left_winsize, &self.viewport); - active_pane.offset_content_columns(pane_columns_offset); - active_pane.offset_content_rows(pane_rows_offset); - } - active_pane.change_pos_and_size(&left_winsize); - - let active_pane_content_columns = active_pane.get_content_columns(); - let active_pane_content_rows = active_pane.get_content_rows(); - - let next_selectable_pane_position = self.get_next_selectable_pane_position(); - let pane_title_only = next_selectable_pane_position == 1; - let mut new_terminal = TerminalPane::new( - term_pid, - right_winsize, - self.colors, - next_selectable_pane_position, - ); - if self.draw_pane_frames { - new_terminal.show_boundaries_frame(pane_title_only); - } else { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&right_winsize, &self.viewport); - new_terminal.offset_content_columns(pane_columns_offset); - new_terminal.offset_content_rows(pane_rows_offset); - } - self.os_api.set_terminal_size_using_fd( - new_terminal.pid, - new_terminal.get_content_columns() as u16, - new_terminal.get_content_rows() as u16, - ); - self.panes.insert(pid, Box::new(new_terminal)); - - if let PaneId::Terminal(active_terminal_pid) = active_pane_id { - self.os_api.set_terminal_size_using_fd( - *active_terminal_pid, - active_pane_content_columns as u16, - active_pane_content_rows as u16, + let terminal_ws = active_pane.position_and_size(); + if let Some((left_winsize, right_winsize)) = split(Direction::Vertical, &terminal_ws) { + let new_terminal = TerminalPane::new( + term_pid, + right_winsize, + self.colors, + next_selectable_pane_position, ); + active_pane.set_geom(left_winsize); + self.panes.insert(pid, Box::new(new_terminal)); } - self.active_terminal = Some(pid); + self.relayout_tab(Direction::Horizontal); self.render(); } } pub fn get_active_pane(&self) -> Option<&dyn Pane> { - // FIXME: Could use Option::map() here - match self.get_active_pane_id() { - Some(active_pane) => self.panes.get(&active_pane).map(Box::as_ref), - None => None, - } + self.get_active_pane_id() + .and_then(|ap| self.panes.get(&ap).map(Box::as_ref)) } fn get_active_pane_id(&self) -> Option { self.active_terminal } fn get_active_terminal_id(&self) -> Option { - // FIXME: Is there a better way to do this? if let Some(PaneId::Terminal(pid)) = self.active_terminal { Some(pid) } else { @@ -895,19 +604,17 @@ impl Tab { pane.set_should_render(true); pane.set_should_render_boundaries(true); } + let viewport_pane_ids: Vec<_> = self + .get_pane_ids() + .into_iter() + .filter(|id| !self.is_inside_viewport(id)) + .collect(); + for pid in viewport_pane_ids { + let viewport_pane = self.panes.get_mut(&pid).unwrap(); + viewport_pane.reset_size_and_position_override(); + } self.panes_to_hide.clear(); - let selectable_pane_count = self.get_selectable_pane_count(); let active_terminal = self.panes.get_mut(&active_pane_id).unwrap(); - if selectable_pane_count > 1 && self.draw_pane_frames { - let only_title = false; - active_terminal.show_boundaries_frame(only_title); - } - if !self.draw_pane_frames { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&active_terminal.position_and_size(), &self.viewport); - active_terminal.offset_content_columns(pane_columns_offset); - active_terminal.offset_content_rows(pane_rows_offset); - } active_terminal.reset_size_and_position_override(); } else { let panes = self.get_panes(); @@ -923,31 +630,29 @@ impl Tab { // nothing to do, pane is already as fullscreen as it can be, let's bail return; } else { - let active_terminal = self.panes.get_mut(&active_pane_id).unwrap(); - if self.draw_pane_frames { - // full screen panes don't need their full frame - let only_title = true; - active_terminal.show_boundaries_frame(only_title); - } else { - active_terminal.offset_content_rows(0); - active_terminal.offset_content_columns(0); + // For all of the panes outside of the viewport staying on the fullscreen + // screen, switch them to using override positions as well so that the resize + // system doesn't get confused by viewport and old panes that no longer line up + let viewport_pane_ids: Vec<_> = self + .get_pane_ids() + .into_iter() + .filter(|id| !self.is_inside_viewport(id)) + .collect(); + for pid in viewport_pane_ids { + let viewport_pane = self.panes.get_mut(&pid).unwrap(); + viewport_pane.get_geom_override(viewport_pane.position_and_size()); } - active_terminal.override_size_and_position( - self.viewport.x, - self.viewport.y, - &self.viewport, - ); + let active_terminal = self.panes.get_mut(&active_pane_id).unwrap(); + let full_screen_geom = PaneGeom { + x: self.viewport.x, + y: self.viewport.y, + ..Default::default() + }; + active_terminal.get_geom_override(full_screen_geom); } } - let active_terminal = self.panes.get(&active_pane_id).unwrap(); - if let PaneId::Terminal(active_pid) = active_pane_id { - self.os_api.set_terminal_size_using_fd( - active_pid, - active_terminal.get_content_columns() as u16, - active_terminal.get_content_rows() as u16, - ); - } self.set_force_render(); + self.resize_whole_tab(self.display_area); self.render(); self.toggle_fullscreen_is_active(); } @@ -975,32 +680,25 @@ impl Tab { { active_terminal.set_should_render(true) } - // .and_then(|active_terminal_id| self.panes.get_mut(&active_terminal_id)) { - // active_terminal.set_should_render(true) - // } } pub fn set_pane_frames(&mut self, draw_pane_frames: bool) { self.draw_pane_frames = draw_pane_frames; - let selectable_pane_count = self.panes.iter().filter(|(_, p)| p.selectable()).count(); for (pane_id, pane) in self.panes.iter_mut() { + pane.set_frame(draw_pane_frames); if draw_pane_frames { - let should_render_only_title = (selectable_pane_count == 1 - && self.active_terminal == Some(*pane_id)) - || (self.fullscreen_is_active && self.active_terminal == Some(*pane_id)); - pane.offset_content_rows(0); - pane.offset_content_columns(0); - pane.show_boundaries_frame(should_render_only_title); + pane.set_content_offset(Offset::frame(1)); } else { - let position_and_size = pane - .position_and_size_override() - .unwrap_or_else(|| pane.position_and_size()); - pane.remove_boundaries_frame(); - + let position_and_size = pane.current_geom(); let (pane_columns_offset, pane_rows_offset) = pane_content_offset(&position_and_size, &self.viewport); - pane.offset_content_columns(pane_columns_offset); - pane.offset_content_rows(pane_rows_offset); + pane.set_content_offset(Offset::shift(pane_rows_offset, pane_columns_offset)); } + // FIXME: The selectable thing is a massive Hack! Decouple borders from selectability + if !pane.selectable() { + pane.set_content_offset(Offset::default()); + } + // FIXME: This, and all other `set_terminal_size_using_fd` calls, would be best in + // `TerminalPane::reflow_lines` if let PaneId::Terminal(pid) = pane_id { self.os_api.set_terminal_size_using_fd( *pid, @@ -1020,7 +718,7 @@ impl Tab { return; } let mut output = String::new(); - let mut boundaries = Boundaries::new(&self.viewport); + let mut boundaries = Boundaries::new(self.viewport); let hide_cursor = "\u{1b}[?25l"; output.push_str(hide_cursor); if self.should_clear_display_before_rendering { @@ -1051,7 +749,7 @@ impl Tab { } false => { pane.set_boundary_color(None); - if !pane.invisible_borders() && !self.draw_pane_frames { + if !self.draw_pane_frames { boundaries.add_rect(pane.as_ref(), self.mode_info.mode, None); } } @@ -1098,13 +796,9 @@ impl Tab { fn get_panes(&self) -> impl Iterator)> { self.panes.iter() } - // FIXME: This is some shameful duplication... fn get_selectable_panes(&self) -> impl Iterator)> { self.panes.iter().filter(|(_, p)| p.selectable()) } - fn get_selectable_pane_count(&self) -> usize { - self.get_selectable_panes().count() - } fn get_next_selectable_pane_position(&self) -> usize { self.panes .iter() @@ -1115,19 +809,6 @@ impl Tab { .count() + 1 } - fn is_the_only_selectable_pane(&self, pane_id: &PaneId) -> bool { - let selectable_panes = self.get_selectable_panes(); - if selectable_panes.count() == 1 { - let pane = self.panes.get(pane_id); - pane.map(|pane| pane.selectable()).unwrap_or(false) - } else { - false - } - } - fn has_panes(&self) -> bool { - let mut all_terminals = self.get_panes(); - all_terminals.next().is_some() - } fn has_selectable_panes(&self) -> bool { let mut all_terminals = self.get_selectable_panes(); all_terminals.next().is_some() @@ -1146,7 +827,7 @@ impl Tab { return None; } for (&pid, terminal) in self.get_panes() { - if terminal.x() + terminal.columns() == terminal_to_check.x() { + if terminal.x() + terminal.cols() == terminal_to_check.x() { ids.push(pid); } } @@ -1160,7 +841,7 @@ impl Tab { let mut ids = vec![]; let terminal_to_check = self.panes.get(id).unwrap(); for (&pid, terminal) in self.get_panes() { - if terminal.x() == terminal_to_check.x() + terminal_to_check.columns() { + if terminal.x() == terminal_to_check.x() + terminal_to_check.cols() { ids.push(pid); } } @@ -1221,7 +902,7 @@ impl Tab { .map(|t_id| self.panes.get(t_id).unwrap().as_ref()) .filter(|terminal| { terminal.pid() != pane.pid() - && terminal.x() + terminal.columns() == pane.x() + pane.columns() + && terminal.x() + terminal.cols() == pane.x() + pane.cols() }) .collect() } @@ -1423,14 +1104,14 @@ impl Tab { top_aligned_terminals.sort_by_key(|a| Reverse(a.x())); for terminal in top_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.x() + terminal.columns() == terminal_to_check.x() { + if terminal.x() + terminal.cols() == terminal_to_check.x() { terminals.push(terminal); } } // leftmost border aligned with a pane border above let mut left_resize_border = 0; for terminal in &terminals { - let right_terminal_boundary = terminal.x() + terminal.columns(); + let right_terminal_boundary = terminal.x() + terminal.cols(); if terminal_borders_above .get(&right_terminal_boundary) .is_some() @@ -1462,7 +1143,7 @@ impl Tab { top_aligned_terminals.sort_by_key(|a| a.x()); for terminal in top_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.x() == terminal_to_check.x() + terminal_to_check.columns() { + if terminal.x() == terminal_to_check.x() + terminal_to_check.cols() { terminals.push(terminal); } } @@ -1478,11 +1159,11 @@ impl Tab { right_resize_border = left_terminal_boundary; } } - terminals.retain(|terminal| terminal.x() + terminal.columns() <= right_resize_border); + terminals.retain(|terminal| terminal.x() + terminal.cols() <= right_resize_border); // if there are no adjacent panes to resize, we use the border of the main pane we're // resizing let right_resize_border = if terminals.is_empty() { - terminal_to_check.x() + terminal_to_check.columns() + terminal_to_check.x() + terminal_to_check.cols() } else { right_resize_border }; @@ -1501,14 +1182,14 @@ impl Tab { // terminals that are next to each other up to current for terminal in bottom_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.x() + terminal.columns() == terminal_to_check.x() { + if terminal.x() + terminal.cols() == terminal_to_check.x() { terminals.push(terminal); } } // leftmost border aligned with a pane border above let mut left_resize_border = 0; for terminal in &terminals { - let right_terminal_boundary = terminal.x() + terminal.columns(); + let right_terminal_boundary = terminal.x() + terminal.cols(); if terminal_borders_below .get(&right_terminal_boundary) .is_some() @@ -1540,7 +1221,7 @@ impl Tab { // terminals that are next to each other up to current for terminal in bottom_aligned_terminals { let terminal_to_check = terminals.last().unwrap_or(&terminal_to_check); - if terminal.x() == terminal_to_check.x() + terminal_to_check.columns() { + if terminal.x() == terminal_to_check.x() + terminal_to_check.cols() { terminals.push(terminal); } } @@ -1556,160 +1237,30 @@ impl Tab { right_resize_border = left_terminal_boundary; } } - terminals.retain(|terminal| terminal.x() + terminal.columns() <= right_resize_border); - + terminals.retain(|terminal| terminal.x() + terminal.cols() <= right_resize_border); let right_resize_border = if terminals.is_empty() { - terminal_to_check.x() + terminal_to_check.columns() + terminal_to_check.x() + terminal_to_check.cols() } else { right_resize_border }; let terminal_ids: Vec = terminals.iter().map(|t| t.pid()).collect(); (right_resize_border, terminal_ids) } - fn reduce_pane_height_down(&mut self, id: &PaneId, count: usize) { + fn reduce_pane_height(&mut self, id: &PaneId, percent: f64) { let terminal = self.panes.get_mut(id).unwrap(); - terminal.reduce_height_down(count); - let position_and_size = terminal.position_and_size(); - - if !self.draw_pane_frames { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&position_and_size, &self.viewport); - terminal.offset_content_columns(pane_columns_offset); - terminal.offset_content_rows(pane_rows_offset); - } - if let PaneId::Terminal(pid) = id { - self.os_api.set_terminal_size_using_fd( - *pid, - terminal.get_content_columns() as u16, - terminal.get_content_rows() as u16, - ); - } + terminal.reduce_height(percent); } - fn reduce_pane_height_up(&mut self, id: &PaneId, count: usize) { + fn increase_pane_height(&mut self, id: &PaneId, percent: f64) { let terminal = self.panes.get_mut(id).unwrap(); - terminal.reduce_height_up(count); - let position_and_size = terminal.position_and_size(); - if !self.draw_pane_frames { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&position_and_size, &self.viewport); - terminal.offset_content_columns(pane_columns_offset); - terminal.offset_content_rows(pane_rows_offset); - } - if let PaneId::Terminal(pid) = id { - self.os_api.set_terminal_size_using_fd( - *pid, - terminal.get_content_columns() as u16, - terminal.get_content_rows() as u16, - ); - } + terminal.increase_height(percent); } - fn increase_pane_height_down(&mut self, id: &PaneId, count: usize) { + fn increase_pane_width(&mut self, id: &PaneId, percent: f64) { let terminal = self.panes.get_mut(id).unwrap(); - terminal.increase_height_down(count); - let position_and_size = terminal.position_and_size(); - if !self.draw_pane_frames { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&position_and_size, &self.viewport); - terminal.offset_content_columns(pane_columns_offset); - terminal.offset_content_rows(pane_rows_offset); - } - if let PaneId::Terminal(pid) = terminal.pid() { - self.os_api.set_terminal_size_using_fd( - pid, - terminal.get_content_columns() as u16, - terminal.get_content_rows() as u16, - ); - } + terminal.increase_width(percent); } - fn increase_pane_height_up(&mut self, id: &PaneId, count: usize) { + fn reduce_pane_width(&mut self, id: &PaneId, percent: f64) { let terminal = self.panes.get_mut(id).unwrap(); - terminal.increase_height_up(count); - let position_and_size = terminal.position_and_size(); - if !self.draw_pane_frames { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&position_and_size, &self.viewport); - terminal.offset_content_columns(pane_columns_offset); - terminal.offset_content_rows(pane_rows_offset); - } - if let PaneId::Terminal(pid) = terminal.pid() { - self.os_api.set_terminal_size_using_fd( - pid, - terminal.get_content_columns() as u16, - terminal.get_content_rows() as u16, - ); - } - } - fn increase_pane_width_right(&mut self, id: &PaneId, count: usize) { - let terminal = self.panes.get_mut(id).unwrap(); - terminal.increase_width_right(count); - let position_and_size = terminal.position_and_size(); - if !self.draw_pane_frames { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&position_and_size, &self.viewport); - terminal.offset_content_columns(pane_columns_offset); - terminal.offset_content_rows(pane_rows_offset); - } - if let PaneId::Terminal(pid) = terminal.pid() { - self.os_api.set_terminal_size_using_fd( - pid, - terminal.get_content_columns() as u16, - terminal.get_content_rows() as u16, - ); - } - } - fn increase_pane_width_left(&mut self, id: &PaneId, count: usize) { - let terminal = self.panes.get_mut(id).unwrap(); - terminal.increase_width_left(count); - let position_and_size = terminal.position_and_size(); - if !self.draw_pane_frames { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&position_and_size, &self.viewport); - terminal.offset_content_columns(pane_columns_offset); - terminal.offset_content_rows(pane_rows_offset); - } - if let PaneId::Terminal(pid) = terminal.pid() { - self.os_api.set_terminal_size_using_fd( - pid, - terminal.get_content_columns() as u16, - terminal.get_content_rows() as u16, - ); - } - } - fn reduce_pane_width_right(&mut self, id: &PaneId, count: usize) { - let terminal = self.panes.get_mut(id).unwrap(); - terminal.reduce_width_right(count); - let position_and_size = terminal.position_and_size(); - if !self.draw_pane_frames { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&position_and_size, &self.viewport); - terminal.offset_content_columns(pane_columns_offset); - terminal.offset_content_rows(pane_rows_offset); - } - if let PaneId::Terminal(pid) = terminal.pid() { - self.os_api.set_terminal_size_using_fd( - pid, - terminal.get_content_columns() as u16, - terminal.get_content_rows() as u16, - ); - } - } - fn reduce_pane_width_left(&mut self, id: &PaneId, count: usize) { - let terminal = self.panes.get_mut(id).unwrap(); - terminal.reduce_width_left(count); - let position_and_size = terminal.position_and_size(); - if !self.draw_pane_frames { - let (pane_columns_offset, pane_rows_offset) = - pane_content_offset(&position_and_size, &self.viewport); - terminal.offset_content_columns(pane_columns_offset); - terminal.offset_content_rows(pane_rows_offset); - } - if let PaneId::Terminal(pid) = terminal.pid() { - self.os_api.set_terminal_size_using_fd( - pid, - terminal.get_content_columns() as u16, - terminal.get_content_rows() as u16, - ); - } + terminal.reduce_width(percent); } fn pane_is_between_vertical_borders( &self, @@ -1721,7 +1272,7 @@ impl Tab { .panes .get(id) .expect("could not find terminal to check between borders"); - terminal.x() >= left_border_x && terminal.x() + terminal.columns() <= right_border_x + terminal.x() >= left_border_x && terminal.x() + terminal.cols() <= right_border_x } fn pane_is_between_horizontal_borders( &self, @@ -1735,7 +1286,7 @@ impl Tab { .expect("could not find terminal to check between borders"); terminal.y() >= top_border_y && terminal.y() + terminal.rows() <= bottom_border_y } - fn reduce_pane_and_surroundings_up(&mut self, id: &PaneId, count: usize) { + fn reduce_pane_and_surroundings_up(&mut self, id: &PaneId, percent: f64) { let mut terminals_below = self .pane_ids_directly_below(id) .expect("can't reduce pane size up if there are no terminals below"); @@ -1751,29 +1302,30 @@ impl Tab { self.pane_is_between_vertical_borders(t, left_resize_border, right_resize_border) }); + // FIXME: This checks that we aren't violating the resize constraints of the aligned panes + // above and below this one. This should be moved to a `can_resize` function eventually. for terminal_id in terminals_to_the_left .iter() .chain(terminals_to_the_right.iter()) { let pane = self.panes.get(terminal_id).unwrap(); - if (pane.rows() as isize) - (count as isize) < pane.min_height() as isize { - // dirty, dirty hack - should be fixed by the resizing overhaul + if pane.current_geom().rows.as_percent().unwrap() - percent < RESIZE_PERCENT { return; } } - self.reduce_pane_height_up(id, count); + self.reduce_pane_height(id, percent); for terminal_id in terminals_below { - self.increase_pane_height_up(&terminal_id, count); + self.increase_pane_height(&terminal_id, percent); } for terminal_id in terminals_to_the_left .iter() .chain(terminals_to_the_right.iter()) { - self.reduce_pane_height_up(terminal_id, count); + self.reduce_pane_height(terminal_id, percent); } } - fn reduce_pane_and_surroundings_down(&mut self, id: &PaneId, count: usize) { + fn reduce_pane_and_surroundings_down(&mut self, id: &PaneId, percent: f64) { let mut terminals_above = self .pane_ids_directly_above(id) .expect("can't reduce pane size down if there are no terminals above"); @@ -1789,29 +1341,30 @@ impl Tab { self.pane_is_between_vertical_borders(t, left_resize_border, right_resize_border) }); + // FIXME: This checks that we aren't violating the resize constraints of the aligned panes + // above and below this one. This should be moved to a `can_resize` function eventually. for terminal_id in terminals_to_the_left .iter() .chain(terminals_to_the_right.iter()) { let pane = self.panes.get(terminal_id).unwrap(); - if (pane.rows() as isize) - (count as isize) < pane.min_height() as isize { - // dirty, dirty hack - should be fixed by the resizing overhaul + if pane.current_geom().rows.as_percent().unwrap() - percent < RESIZE_PERCENT { return; } } - self.reduce_pane_height_down(id, count); + self.reduce_pane_height(id, percent); for terminal_id in terminals_above { - self.increase_pane_height_down(&terminal_id, count); + self.increase_pane_height(&terminal_id, percent); } for terminal_id in terminals_to_the_left .iter() .chain(terminals_to_the_right.iter()) { - self.reduce_pane_height_down(terminal_id, count); + self.reduce_pane_height(terminal_id, percent); } } - fn reduce_pane_and_surroundings_right(&mut self, id: &PaneId, count: usize) { + fn reduce_pane_and_surroundings_right(&mut self, id: &PaneId, percent: f64) { let mut terminals_to_the_left = self .pane_ids_directly_left_of(id) .expect("can't reduce pane size right if there are no terminals to the left"); @@ -1827,23 +1380,24 @@ impl Tab { self.pane_is_between_horizontal_borders(t, top_resize_border, bottom_resize_border) }); + // FIXME: This checks that we aren't violating the resize constraints of the aligned panes + // above and below this one. This should be moved to a `can_resize` function eventually. for terminal_id in terminals_above.iter().chain(terminals_below.iter()) { let pane = self.panes.get(terminal_id).unwrap(); - if (pane.columns() as isize) - (count as isize) < pane.min_width() as isize { - // dirty, dirty hack - should be fixed by the resizing overhaul + if pane.current_geom().cols.as_percent().unwrap() - percent < RESIZE_PERCENT { return; } } - self.reduce_pane_width_right(id, count); + self.reduce_pane_width(id, percent); for terminal_id in terminals_to_the_left { - self.increase_pane_width_right(&terminal_id, count); + self.increase_pane_width(&terminal_id, percent); } for terminal_id in terminals_above.iter().chain(terminals_below.iter()) { - self.reduce_pane_width_right(terminal_id, count); + self.reduce_pane_width(terminal_id, percent); } } - fn reduce_pane_and_surroundings_left(&mut self, id: &PaneId, count: usize) { + fn reduce_pane_and_surroundings_left(&mut self, id: &PaneId, percent: f64) { let mut terminals_to_the_right = self .pane_ids_directly_right_of(id) .expect("can't reduce pane size left if there are no terminals to the right"); @@ -1859,23 +1413,24 @@ impl Tab { self.pane_is_between_horizontal_borders(t, top_resize_border, bottom_resize_border) }); + // FIXME: This checks that we aren't violating the resize constraints of the aligned panes + // above and below this one. This should be moved to a `can_resize` function eventually. for terminal_id in terminals_above.iter().chain(terminals_below.iter()) { let pane = self.panes.get(terminal_id).unwrap(); - if (pane.columns() as isize) - (count as isize) < pane.min_width() as isize { - // dirty, dirty hack - should be fixed by the resizing overhaul + if pane.current_geom().cols.as_percent().unwrap() - percent < RESIZE_PERCENT { return; } } - self.reduce_pane_width_left(id, count); + self.reduce_pane_width(id, percent); for terminal_id in terminals_to_the_right { - self.increase_pane_width_left(&terminal_id, count); + self.increase_pane_width(&terminal_id, percent); } for terminal_id in terminals_above.iter().chain(terminals_below.iter()) { - self.reduce_pane_width_left(terminal_id, count); + self.reduce_pane_width(terminal_id, percent); } } - fn increase_pane_and_surroundings_up(&mut self, id: &PaneId, count: usize) { + fn increase_pane_and_surroundings_up(&mut self, id: &PaneId, percent: f64) { let mut terminals_above = self .pane_ids_directly_above(id) .expect("can't increase pane size up if there are no terminals above"); @@ -1890,18 +1445,18 @@ impl Tab { terminals_above.retain(|t| { self.pane_is_between_vertical_borders(t, left_resize_border, right_resize_border) }); - self.increase_pane_height_up(id, count); + self.increase_pane_height(id, percent); for terminal_id in terminals_above { - self.reduce_pane_height_up(&terminal_id, count); + self.reduce_pane_height(&terminal_id, percent); } for terminal_id in terminals_to_the_left .iter() .chain(terminals_to_the_right.iter()) { - self.increase_pane_height_up(terminal_id, count); + self.increase_pane_height(terminal_id, percent); } } - fn increase_pane_and_surroundings_down(&mut self, id: &PaneId, count: usize) { + fn increase_pane_and_surroundings_down(&mut self, id: &PaneId, percent: f64) { let mut terminals_below = self .pane_ids_directly_below(id) .expect("can't increase pane size down if there are no terminals below"); @@ -1916,18 +1471,18 @@ impl Tab { terminals_below.retain(|t| { self.pane_is_between_vertical_borders(t, left_resize_border, right_resize_border) }); - self.increase_pane_height_down(id, count); + self.increase_pane_height(id, percent); for terminal_id in terminals_below { - self.reduce_pane_height_down(&terminal_id, count); + self.reduce_pane_height(&terminal_id, percent); } for terminal_id in terminals_to_the_left .iter() .chain(terminals_to_the_right.iter()) { - self.increase_pane_height_down(terminal_id, count); + self.increase_pane_height(terminal_id, percent); } } - fn increase_pane_and_surroundings_right(&mut self, id: &PaneId, count: usize) { + fn increase_pane_and_surroundings_right(&mut self, id: &PaneId, percent: f64) { let mut terminals_to_the_right = self .pane_ids_directly_right_of(id) .expect("can't increase pane size right if there are no terminals to the right"); @@ -1944,15 +1499,15 @@ impl Tab { terminals_to_the_right.retain(|t| { self.pane_is_between_horizontal_borders(t, top_resize_border, bottom_resize_border) }); - self.increase_pane_width_right(id, count); + self.increase_pane_width(id, percent); for terminal_id in terminals_to_the_right { - self.reduce_pane_width_right(&terminal_id, count); + self.reduce_pane_width(&terminal_id, percent); } for terminal_id in terminals_above.iter().chain(terminals_below.iter()) { - self.increase_pane_width_right(terminal_id, count); + self.increase_pane_width(terminal_id, percent); } } - fn increase_pane_and_surroundings_left(&mut self, id: &PaneId, count: usize) { + fn increase_pane_and_surroundings_left(&mut self, id: &PaneId, percent: f64) { let mut terminals_to_the_left = self .pane_ids_directly_left_of(id) .expect("can't increase pane size right if there are no terminals to the right"); @@ -1967,249 +1522,209 @@ impl Tab { terminals_to_the_left.retain(|t| { self.pane_is_between_horizontal_borders(t, top_resize_border, bottom_resize_border) }); - self.increase_pane_width_left(id, count); + self.increase_pane_width(id, percent); for terminal_id in terminals_to_the_left { - self.reduce_pane_width_left(&terminal_id, count); + self.reduce_pane_width(&terminal_id, percent); } for terminal_id in terminals_above.iter().chain(terminals_below.iter()) { - self.increase_pane_width_left(terminal_id, count); + self.increase_pane_width(terminal_id, percent); } } - fn can_increase_pane_and_surroundings_right( - &self, - pane_id: &PaneId, - increase_by: usize, - ) -> bool { - let pane = self.panes.get(pane_id).unwrap(); - let can_increase_pane_size = pane - .max_width() - .map(|max_width| pane.columns() + increase_by <= max_width) - .unwrap_or(true); // no max width, increase to your heart's content - if !can_increase_pane_size { - return false; - } - let mut new_pos_and_size_for_pane = pane.position_and_size(); - new_pos_and_size_for_pane.cols += increase_by; - + // FIXME: The if-let nesting and explicit `false`s are... suboptimal. + // FIXME: Quite a lot of duplication between these functions... + fn can_increase_pane_and_surroundings_right(&self, pane_id: &PaneId, increase_by: f64) -> bool { if let Some(panes_to_the_right) = self.pane_ids_directly_right_of(pane_id) { - return panes_to_the_right.iter().all(|id| { + panes_to_the_right.iter().all(|id| { let p = self.panes.get(id).unwrap(); - p.columns() > increase_by && p.columns() - increase_by >= p.min_width() - }); + if let Some(cols) = p.position_and_size().cols.as_percent() { + cols - increase_by >= RESIZE_PERCENT + } else { + false + } + }) } else { false } } - fn can_increase_pane_and_surroundings_left( - &self, - pane_id: &PaneId, - increase_by: usize, - ) -> bool { - let pane = self.panes.get(pane_id).unwrap(); - let can_increase_pane_size = pane - .max_width() - .map(|max_width| pane.columns() + increase_by <= max_width) - .unwrap_or(true); // no max width, increase to your heart's content - if !can_increase_pane_size { - return false; - } - let mut new_pos_and_size_for_pane = pane.position_and_size(); - new_pos_and_size_for_pane.x = new_pos_and_size_for_pane.x.saturating_sub(increase_by); - + fn can_increase_pane_and_surroundings_left(&self, pane_id: &PaneId, increase_by: f64) -> bool { if let Some(panes_to_the_left) = self.pane_ids_directly_left_of(pane_id) { - return panes_to_the_left.iter().all(|id| { + panes_to_the_left.iter().all(|id| { let p = self.panes.get(id).unwrap(); - p.columns() > increase_by && p.columns() - increase_by >= p.min_width() - }); + if let Some(cols) = p.position_and_size().cols.as_percent() { + cols - increase_by >= RESIZE_PERCENT + } else { + false + } + }) } else { false } } - fn can_increase_pane_and_surroundings_down( - &self, - pane_id: &PaneId, - increase_by: usize, - ) -> bool { - let pane = self.panes.get(pane_id).unwrap(); - let can_increase_pane_size = pane - .max_height() - .map(|max_height| pane.rows() + increase_by <= max_height) - .unwrap_or(true); // no max width, increase to your heart's content - if !can_increase_pane_size { - return false; - } - let mut new_pos_and_size_for_pane = pane.position_and_size(); - new_pos_and_size_for_pane.rows += increase_by; - + fn can_increase_pane_and_surroundings_down(&self, pane_id: &PaneId, increase_by: f64) -> bool { if let Some(panes_below) = self.pane_ids_directly_below(pane_id) { - return panes_below.iter().all(|id| { + panes_below.iter().all(|id| { let p = self.panes.get(id).unwrap(); - p.rows() > increase_by && p.rows() - increase_by >= p.min_height() - }); + if let Some(rows) = p.position_and_size().rows.as_percent() { + rows - increase_by >= RESIZE_PERCENT + } else { + false + } + }) } else { false } } - fn can_increase_pane_and_surroundings_up(&self, pane_id: &PaneId, increase_by: usize) -> bool { - let pane = self.panes.get(pane_id).unwrap(); - let can_increase_pane_size = pane - .max_height() - .map(|max_height| pane.rows() + increase_by <= max_height) - .unwrap_or(true); // no max width, increase to your heart's content - if !can_increase_pane_size { - return false; - } - let mut new_pos_and_size_for_pane = pane.position_and_size(); - new_pos_and_size_for_pane.y = new_pos_and_size_for_pane.y.saturating_sub(increase_by); - + fn can_increase_pane_and_surroundings_up(&self, pane_id: &PaneId, increase_by: f64) -> bool { if let Some(panes_above) = self.pane_ids_directly_above(pane_id) { - return panes_above.iter().all(|id| { + panes_above.iter().all(|id| { let p = self.panes.get(id).unwrap(); - p.rows() > increase_by && p.rows() - increase_by >= p.min_height() - }); + if let Some(rows) = p.position_and_size().rows.as_percent() { + rows - increase_by >= RESIZE_PERCENT + } else { + false + } + }) } else { false } } - fn can_reduce_pane_and_surroundings_right(&self, pane_id: &PaneId, reduce_by: usize) -> bool { + fn can_reduce_pane_and_surroundings_right(&self, pane_id: &PaneId, reduce_by: f64) -> bool { let pane = self.panes.get(pane_id).unwrap(); - let pane_columns = pane.columns(); - let can_reduce_pane_size = - pane_columns > reduce_by && pane_columns - reduce_by >= pane.min_width(); - if !can_reduce_pane_size { - return false; - } - if let Some(panes_to_the_left) = self.pane_ids_directly_left_of(pane_id) { - return panes_to_the_left.iter().all(|id| { - let p = self.panes.get(id).unwrap(); - p.max_width() - .map(|max_width| p.columns() + reduce_by <= max_width) - .unwrap_or(true) // no max width, increase to your heart's content - }); + if let Some(cols) = pane.position_and_size().cols.as_percent() { + let ids_left = self.pane_ids_directly_left_of(pane_id); + let flexible_left = self.ids_are_flexible(Direction::Horizontal, ids_left); + cols - reduce_by >= RESIZE_PERCENT && flexible_left } else { false } } - fn can_reduce_pane_and_surroundings_left(&self, pane_id: &PaneId, reduce_by: usize) -> bool { + fn can_reduce_pane_and_surroundings_left(&self, pane_id: &PaneId, reduce_by: f64) -> bool { let pane = self.panes.get(pane_id).unwrap(); - let pane_columns = pane.columns(); - let can_reduce_pane_size = - pane_columns > reduce_by && pane_columns - reduce_by >= pane.min_width(); - if !can_reduce_pane_size { - return false; - } - if let Some(panes_to_the_right) = self.pane_ids_directly_right_of(pane_id) { - return panes_to_the_right.iter().all(|id| { - let p = self.panes.get(id).unwrap(); - p.max_width() - .map(|max_width| p.columns() + reduce_by <= max_width) - .unwrap_or(true) // no max width, increase to your heart's content - }); + if let Some(cols) = pane.position_and_size().cols.as_percent() { + let ids_right = self.pane_ids_directly_right_of(pane_id); + let flexible_right = self.ids_are_flexible(Direction::Horizontal, ids_right); + cols - reduce_by >= RESIZE_PERCENT && flexible_right } else { false } } - fn can_reduce_pane_and_surroundings_down(&self, pane_id: &PaneId, reduce_by: usize) -> bool { + fn can_reduce_pane_and_surroundings_down(&self, pane_id: &PaneId, reduce_by: f64) -> bool { let pane = self.panes.get(pane_id).unwrap(); - let pane_rows = pane.rows(); - let can_reduce_pane_size = - pane_rows > reduce_by && pane_rows - reduce_by >= pane.min_height(); - if !can_reduce_pane_size { - return false; - } - if let Some(panes_above) = self.pane_ids_directly_above(pane_id) { - return panes_above.iter().all(|id| { - let p = self.panes.get(id).unwrap(); - p.max_height() - .map(|max_height| p.rows() + reduce_by <= max_height) - .unwrap_or(true) // no max height, increase to your heart's content - }); + if let Some(rows) = pane.position_and_size().rows.as_percent() { + let ids_above = self.pane_ids_directly_above(pane_id); + let flexible_above = self.ids_are_flexible(Direction::Vertical, ids_above); + rows - reduce_by >= RESIZE_PERCENT && flexible_above } else { false } } - fn can_reduce_pane_and_surroundings_up(&self, pane_id: &PaneId, reduce_by: usize) -> bool { + fn can_reduce_pane_and_surroundings_up(&self, pane_id: &PaneId, reduce_by: f64) -> bool { let pane = self.panes.get(pane_id).unwrap(); - let pane_rows = pane.rows(); - let can_reduce_pane_size = - pane_rows > reduce_by && pane_rows - reduce_by >= pane.min_height(); - if !can_reduce_pane_size { - return false; - } - if let Some(panes_below) = self.pane_ids_directly_below(pane_id) { - return panes_below.iter().all(|id| { - let p = self.panes.get(id).unwrap(); - p.max_height() - .map(|max_height| p.rows() + reduce_by <= max_height) - .unwrap_or(true) // no max height, increase to your heart's content - }); + if let Some(rows) = pane.position_and_size().rows.as_percent() { + let ids_below = self.pane_ids_directly_below(pane_id); + let flexible_below = self.ids_are_flexible(Direction::Vertical, ids_below); + rows - reduce_by >= RESIZE_PERCENT && flexible_below } else { false } } - pub fn resize_whole_tab(&mut self, new_screen_size: PositionAndSize) { - if self.fullscreen_is_active { - // this is not ideal, we can improve this - self.toggle_active_pane_fullscreen(); - } - if let Some((column_difference, row_difference)) = - PaneResizer::new(&mut self.panes, &mut self.os_api) - .resize(self.display_area, new_screen_size) - { - self.should_clear_display_before_rendering = true; - - self.viewport.cols = (self.viewport.cols as isize + column_difference) as usize; - self.viewport.rows = (self.viewport.rows as isize + row_difference) as usize; - self.display_area.cols = (self.display_area.cols as isize + column_difference) as usize; - self.display_area.rows = (self.display_area.rows as isize + row_difference) as usize; + fn ids_are_flexible(&self, direction: Direction, pane_ids: Option>) -> bool { + pane_ids.is_some() + && pane_ids.unwrap().iter().all(|id| { + let geom = self.panes[id].current_geom(); + let dimension = match direction { + Direction::Vertical => geom.rows, + Direction::Horizontal => geom.cols, + }; + !dimension.is_fixed() + }) + } + pub fn relayout_tab(&mut self, direction: Direction) { + let mut resizer = PaneResizer::new(&mut self.panes.iter_mut(), &mut self.os_api); + let result = match direction { + Direction::Horizontal => resizer.layout(direction, self.display_area.cols), + Direction::Vertical => resizer.layout(direction, self.display_area.rows), }; + if let Err(e) = &result { + log::error!("{:?} relayout of the tab failed: {}", direction, e); + } + self.set_pane_frames(self.draw_pane_frames); + } + pub fn resize_whole_tab(&mut self, new_screen_size: Size) { + // FIXME: I *think* that Rust 2021 will let me just write this: + // let panes = self.panes.iter_mut().filter(|(pid, _)| !self.panes_to_hide.contains(pid)); + // In the meantime, let's appease our borrow-checker overlords: + let temp_panes_to_hide = &self.panes_to_hide; + let panes = self + .panes + .iter_mut() + .filter(|(pid, _)| !temp_panes_to_hide.contains(pid)); + let Size { rows, cols } = new_screen_size; + let mut resizer = PaneResizer::new(panes, &mut self.os_api); + if resizer.layout(Direction::Horizontal, cols).is_ok() { + let column_difference = cols as isize - self.display_area.cols as isize; + // FIXME: Should the viewport be an Offset? + self.viewport.cols = (self.viewport.cols as isize + column_difference) as usize; + self.display_area.cols = cols; + } else { + log::error!("Failed to horizontally resize the tab!!!"); + } + if resizer.layout(Direction::Vertical, rows).is_ok() { + let row_difference = rows as isize - self.display_area.rows as isize; + self.viewport.rows = (self.viewport.rows as isize + row_difference) as usize; + self.display_area.rows = rows; + } else { + log::error!("Failed to vertically resize the tab!!!"); + } + self.should_clear_display_before_rendering = true; + self.set_pane_frames(self.draw_pane_frames); } pub fn resize_left(&mut self) { // TODO: find out by how much we actually reduced and only reduce by that much - let count = 10; if let Some(active_pane_id) = self.get_active_pane_id() { - if self.can_increase_pane_and_surroundings_left(&active_pane_id, count) { - self.increase_pane_and_surroundings_left(&active_pane_id, count); - } else if self.can_reduce_pane_and_surroundings_left(&active_pane_id, count) { - self.reduce_pane_and_surroundings_left(&active_pane_id, count); + if self.can_increase_pane_and_surroundings_left(&active_pane_id, RESIZE_PERCENT) { + self.increase_pane_and_surroundings_left(&active_pane_id, RESIZE_PERCENT); + } else if self.can_reduce_pane_and_surroundings_left(&active_pane_id, RESIZE_PERCENT) { + self.reduce_pane_and_surroundings_left(&active_pane_id, RESIZE_PERCENT); } } + self.relayout_tab(Direction::Horizontal); self.render(); } pub fn resize_right(&mut self) { // TODO: find out by how much we actually reduced and only reduce by that much - let count = 10; if let Some(active_pane_id) = self.get_active_pane_id() { - if self.can_increase_pane_and_surroundings_right(&active_pane_id, count) { - self.increase_pane_and_surroundings_right(&active_pane_id, count); - } else if self.can_reduce_pane_and_surroundings_right(&active_pane_id, count) { - self.reduce_pane_and_surroundings_right(&active_pane_id, count); + if self.can_increase_pane_and_surroundings_right(&active_pane_id, RESIZE_PERCENT) { + self.increase_pane_and_surroundings_right(&active_pane_id, RESIZE_PERCENT); + } else if self.can_reduce_pane_and_surroundings_right(&active_pane_id, RESIZE_PERCENT) { + self.reduce_pane_and_surroundings_right(&active_pane_id, RESIZE_PERCENT); } } + self.relayout_tab(Direction::Horizontal); self.render(); } pub fn resize_down(&mut self) { // TODO: find out by how much we actually reduced and only reduce by that much - let count = 2; if let Some(active_pane_id) = self.get_active_pane_id() { - if self.can_increase_pane_and_surroundings_down(&active_pane_id, count) { - self.increase_pane_and_surroundings_down(&active_pane_id, count); - } else if self.can_reduce_pane_and_surroundings_down(&active_pane_id, count) { - self.reduce_pane_and_surroundings_down(&active_pane_id, count); + if self.can_increase_pane_and_surroundings_down(&active_pane_id, RESIZE_PERCENT) { + self.increase_pane_and_surroundings_down(&active_pane_id, RESIZE_PERCENT); + } else if self.can_reduce_pane_and_surroundings_down(&active_pane_id, RESIZE_PERCENT) { + self.reduce_pane_and_surroundings_down(&active_pane_id, RESIZE_PERCENT); } } + self.relayout_tab(Direction::Vertical); self.render(); } pub fn resize_up(&mut self) { // TODO: find out by how much we actually reduced and only reduce by that much - let count = 2; if let Some(active_pane_id) = self.get_active_pane_id() { - if self.can_increase_pane_and_surroundings_up(&active_pane_id, count) { - self.increase_pane_and_surroundings_up(&active_pane_id, count); - } else if self.can_reduce_pane_and_surroundings_up(&active_pane_id, count) { - self.reduce_pane_and_surroundings_up(&active_pane_id, count); + if self.can_increase_pane_and_surroundings_up(&active_pane_id, RESIZE_PERCENT) { + self.increase_pane_and_surroundings_up(&active_pane_id, RESIZE_PERCENT); + } else if self.can_reduce_pane_and_surroundings_up(&active_pane_id, RESIZE_PERCENT) { + self.reduce_pane_and_surroundings_up(&active_pane_id, RESIZE_PERCENT); } } + self.relayout_tab(Direction::Vertical); self.render(); } pub fn move_focus(&mut self) { @@ -2451,7 +1966,7 @@ impl Tab { terminals.iter().fold(HashSet::new(), |mut borders, t| { let terminal = self.panes.get(t).unwrap(); borders.insert(terminal.y()); - borders.insert(terminal.y() + terminal.rows() + 1); // 1 for the border width + borders.insert(terminal.y() + terminal.rows()); borders }) } @@ -2459,28 +1974,32 @@ impl Tab { terminals.iter().fold(HashSet::new(), |mut borders, t| { let terminal = self.panes.get(t).unwrap(); borders.insert(terminal.x()); - borders.insert(terminal.x() + terminal.columns() + 1); // 1 for the border width + borders.insert(terminal.x() + terminal.cols()); borders }) } fn panes_to_the_left_between_aligning_borders(&self, id: PaneId) -> Option> { if let Some(terminal) = self.panes.get(&id) { let upper_close_border = terminal.y(); - let lower_close_border = terminal.y() + terminal.rows() + 1; + let lower_close_border = terminal.y() + terminal.rows(); - if let Some(mut terminals_to_the_left) = self.pane_ids_directly_left_of(&id) { - let terminal_borders_to_the_left = self.horizontal_borders(&terminals_to_the_left); + if let Some(terminals_to_the_left) = self.pane_ids_directly_left_of(&id) { + let mut selectable_panes: Vec<_> = terminals_to_the_left + .into_iter() + .filter(|pid| self.panes[pid].selectable()) + .collect(); + let terminal_borders_to_the_left = self.horizontal_borders(&selectable_panes); if terminal_borders_to_the_left.contains(&upper_close_border) && terminal_borders_to_the_left.contains(&lower_close_border) { - terminals_to_the_left.retain(|t| { + selectable_panes.retain(|t| { self.pane_is_between_horizontal_borders( t, upper_close_border, lower_close_border, ) }); - return Some(terminals_to_the_left); + return Some(selectable_panes); } } } @@ -2489,22 +2008,25 @@ impl Tab { fn panes_to_the_right_between_aligning_borders(&self, id: PaneId) -> Option> { if let Some(terminal) = self.panes.get(&id) { let upper_close_border = terminal.y(); - let lower_close_border = terminal.y() + terminal.rows() + 1; + let lower_close_border = terminal.y() + terminal.rows(); - if let Some(mut terminals_to_the_right) = self.pane_ids_directly_right_of(&id) { - let terminal_borders_to_the_right = - self.horizontal_borders(&terminals_to_the_right); + if let Some(terminals_to_the_right) = self.pane_ids_directly_right_of(&id) { + let mut selectable_panes: Vec<_> = terminals_to_the_right + .into_iter() + .filter(|pid| self.panes[pid].selectable()) + .collect(); + let terminal_borders_to_the_right = self.horizontal_borders(&selectable_panes); if terminal_borders_to_the_right.contains(&upper_close_border) && terminal_borders_to_the_right.contains(&lower_close_border) { - terminals_to_the_right.retain(|t| { + selectable_panes.retain(|t| { self.pane_is_between_horizontal_borders( t, upper_close_border, lower_close_border, ) }); - return Some(terminals_to_the_right); + return Some(selectable_panes); } } } @@ -2513,21 +2035,25 @@ impl Tab { fn panes_above_between_aligning_borders(&self, id: PaneId) -> Option> { if let Some(terminal) = self.panes.get(&id) { let left_close_border = terminal.x(); - let right_close_border = terminal.x() + terminal.columns() + 1; + let right_close_border = terminal.x() + terminal.cols(); - if let Some(mut terminals_above) = self.pane_ids_directly_above(&id) { - let terminal_borders_above = self.vertical_borders(&terminals_above); + if let Some(terminals_above) = self.pane_ids_directly_above(&id) { + let mut selectable_panes: Vec<_> = terminals_above + .into_iter() + .filter(|pid| self.panes[pid].selectable()) + .collect(); + let terminal_borders_above = self.vertical_borders(&selectable_panes); if terminal_borders_above.contains(&left_close_border) && terminal_borders_above.contains(&right_close_border) { - terminals_above.retain(|t| { + selectable_panes.retain(|t| { self.pane_is_between_vertical_borders( t, left_close_border, right_close_border, ) }); - return Some(terminals_above); + return Some(selectable_panes); } } } @@ -2536,21 +2062,25 @@ impl Tab { fn panes_below_between_aligning_borders(&self, id: PaneId) -> Option> { if let Some(terminal) = self.panes.get(&id) { let left_close_border = terminal.x(); - let right_close_border = terminal.x() + terminal.columns() + 1; + let right_close_border = terminal.x() + terminal.cols(); - if let Some(mut terminals_below) = self.pane_ids_directly_below(&id) { - let terminal_borders_below = self.vertical_borders(&terminals_below); + if let Some(terminals_below) = self.pane_ids_directly_below(&id) { + let mut selectable_panes: Vec<_> = terminals_below + .into_iter() + .filter(|pid| self.panes[pid].selectable()) + .collect(); + let terminal_borders_below = self.vertical_borders(&selectable_panes); if terminal_borders_below.contains(&left_close_border) && terminal_borders_below.contains(&right_close_border) { - terminals_below.retain(|t| { + selectable_panes.retain(|t| { self.pane_is_between_vertical_borders( t, left_close_border, right_close_border, ) }); - return Some(terminals_below); + return Some(selectable_panes); } } } @@ -2563,7 +2093,7 @@ impl Tab { self.senders .send_to_pty(PtyInstruction::ClosePane(pid)) .unwrap(); - self.close_pane_without_rerender(pid); + self.close_pane(pid); } } } @@ -2577,145 +2107,73 @@ impl Tab { self.active_terminal = self.next_active_pane(&self.get_pane_ids()) } } - } - pub fn set_pane_invisible_borders(&mut self, id: PaneId, invisible_borders: bool) { - if let Some(pane) = self.panes.get_mut(&id) { - pane.set_invisible_borders(invisible_borders); - } - } - pub fn set_pane_fixed_height(&mut self, id: PaneId, fixed_height: usize) { - if let Some(pane) = self.panes.get_mut(&id) { - pane.set_fixed_height(fixed_height); - } - } - pub fn set_pane_fixed_width(&mut self, id: PaneId, fixed_width: usize) { - if let Some(pane) = self.panes.get_mut(&id) { - pane.set_fixed_width(fixed_width); - } + // FIXME: This is a super, super nasty hack while borderless-ness is still tied to + // selectability. Delete this once those are decoupled + self.set_pane_frames(self.draw_pane_frames); + self.render(); } pub fn close_pane(&mut self, id: PaneId) { - if self.panes.get(&id).is_some() { - self.close_pane_without_rerender(id); - } - } - pub fn close_pane_without_rerender(&mut self, id: PaneId) { if self.fullscreen_is_active { self.toggle_active_pane_fullscreen(); } if let Some(pane_to_close) = self.panes.get(&id) { - let pane_to_close_width = pane_to_close.columns(); - let pane_to_close_height = pane_to_close.rows(); - if let Some(panes) = self.panes_to_the_left_between_aligning_borders(id) { - if panes.iter().all(|p| { - let pane = self.panes.get(p).unwrap(); - pane.can_increase_width_by(pane_to_close_width) - }) { + let freed_space = pane_to_close.position_and_size(); + if let (Some(freed_width), Some(freed_height)) = + (freed_space.cols.as_percent(), freed_space.rows.as_percent()) + { + if let Some(panes) = self.panes_to_the_left_between_aligning_borders(id) { + for pane_id in panes.iter() { + self.increase_pane_width(pane_id, freed_width); + } self.panes.remove(&id); if self.active_terminal == Some(id) { let next_active_pane = self.next_active_pane(&panes); self.active_terminal = next_active_pane; - if let Some(next_active_pane) = next_active_pane { - if self.is_the_only_selectable_pane(&next_active_pane) - && self.draw_pane_frames - { - let should_render_only_title = true; - self.panes - .get_mut(&next_active_pane) - .unwrap() - .show_boundaries_frame(should_render_only_title); - } - } - } - for pane_id in panes.iter() { - self.increase_pane_width_right(pane_id, pane_to_close_width); } + self.relayout_tab(Direction::Horizontal); return; } - } - if let Some(panes) = self.panes_to_the_right_between_aligning_borders(id) { - if panes.iter().all(|p| { - let pane = self.panes.get(p).unwrap(); - pane.can_increase_width_by(pane_to_close_width) - }) { + if let Some(panes) = self.panes_to_the_right_between_aligning_borders(id) { + for pane_id in panes.iter() { + self.increase_pane_width(pane_id, freed_width); + } self.panes.remove(&id); if self.active_terminal == Some(id) { let next_active_pane = self.next_active_pane(&panes); self.active_terminal = next_active_pane; - if let Some(next_active_pane) = next_active_pane { - if self.is_the_only_selectable_pane(&next_active_pane) - && self.draw_pane_frames - { - let should_render_only_title = true; - self.panes - .get_mut(&next_active_pane) - .unwrap() - .show_boundaries_frame(should_render_only_title); - } - } - } - for pane_id in panes.iter() { - self.increase_pane_width_left(pane_id, pane_to_close_width); } + self.relayout_tab(Direction::Horizontal); return; } - } - if let Some(panes) = self.panes_above_between_aligning_borders(id) { - if panes.iter().all(|p| { - let pane = self.panes.get(p).unwrap(); - pane.can_increase_height_by(pane_to_close_height) - }) { + if let Some(panes) = self.panes_above_between_aligning_borders(id) { + for pane_id in panes.iter() { + self.increase_pane_height(pane_id, freed_height); + } self.panes.remove(&id); if self.active_terminal == Some(id) { let next_active_pane = self.next_active_pane(&panes); self.active_terminal = next_active_pane; - if let Some(next_active_pane) = next_active_pane { - if self.is_the_only_selectable_pane(&next_active_pane) - && self.draw_pane_frames - { - let should_render_only_title = true; - self.panes - .get_mut(&next_active_pane) - .unwrap() - .show_boundaries_frame(should_render_only_title); - } - } - } - for pane_id in panes.iter() { - self.increase_pane_height_down(pane_id, pane_to_close_height); } + self.relayout_tab(Direction::Vertical); return; } - } - if let Some(panes) = self.panes_below_between_aligning_borders(id) { - if panes.iter().all(|p| { - let pane = self.panes.get(p).unwrap(); - pane.can_increase_height_by(pane_to_close_height) - }) { + if let Some(panes) = self.panes_below_between_aligning_borders(id) { + for pane_id in panes.iter() { + self.increase_pane_height(pane_id, freed_height); + } self.panes.remove(&id); if self.active_terminal == Some(id) { let next_active_pane = self.next_active_pane(&panes); self.active_terminal = next_active_pane; - if let Some(next_active_pane) = next_active_pane { - if self.is_the_only_selectable_pane(&next_active_pane) - && self.draw_pane_frames - { - let should_render_only_title = true; - self.panes - .get_mut(&next_active_pane) - .unwrap() - .show_boundaries_frame(should_render_only_title); - } - } - } - for pane_id in panes.iter() { - self.increase_pane_height_up(pane_id, pane_to_close_height); } + self.relayout_tab(Direction::Vertical); return; } } // if we reached here, this is either the last pane or there's some sort of // configuration error (eg. we're trying to close a pane surrounded by fixed panes) self.panes.remove(&id); + self.resize_whole_tab(self.display_area); } } pub fn close_focused_pane(&mut self) { @@ -2887,12 +2345,12 @@ impl Tab { .unwrap(); } fn is_inside_viewport(&self, pane_id: &PaneId) -> bool { - let pane_position_and_size = self.panes.get(pane_id).unwrap().position_and_size(); + let pane_position_and_size = self.panes.get(pane_id).unwrap().current_geom(); pane_position_and_size.y >= self.viewport.y - && pane_position_and_size.y + pane_position_and_size.rows + && pane_position_and_size.y + pane_position_and_size.rows.as_usize() <= self.viewport.y + self.viewport.rows } - fn offset_viewport(&mut self, position_and_size: &PositionAndSize) { + fn offset_viewport(&mut self, position_and_size: &Viewport) { if position_and_size.x == self.viewport.x && position_and_size.x + position_and_size.cols == self.viewport.x + self.viewport.cols { diff --git a/zellij-server/src/ui/boundaries.rs b/zellij-server/src/ui/boundaries.rs index b25f1cc0..a912664c 100644 --- a/zellij-server/src/ui/boundaries.rs +++ b/zellij-server/src/ui/boundaries.rs @@ -1,5 +1,4 @@ -use zellij_utils::pane_size::PositionAndSize; -use zellij_utils::zellij_tile; +use zellij_utils::{pane_size::Viewport, zellij_tile}; use crate::tab::Pane; use ansi_term::Colour::{Fixed, RGB}; @@ -39,10 +38,6 @@ impl BoundarySymbol { color: Some(PaletteColor::EightBit(colors::GRAY)), } } - pub fn invisible(mut self) -> Self { - self.invisible = true; - self - } pub fn color(&mut self, color: Option) -> Self { self.color = color; *self @@ -407,14 +402,14 @@ impl Coordinates { } pub struct Boundaries { - position_and_size: PositionAndSize, + viewport: Viewport, boundary_characters: HashMap, } impl Boundaries { - pub fn new(position_and_size: &PositionAndSize) -> Self { + pub fn new(viewport: Viewport) -> Self { Boundaries { - position_and_size: *position_and_size, + viewport, boundary_characters: HashMap::new(), } } @@ -429,26 +424,22 @@ impl Boundaries { }, false => None, }; - if rect.x() > self.position_and_size.x { + if rect.x() > self.viewport.x { // left boundary let boundary_x_coords = rect.x() - 1; let first_row_coordinates = self.rect_right_boundary_row_start(rect); let last_row_coordinates = self.rect_right_boundary_row_end(rect); for row in first_row_coordinates..last_row_coordinates { let coordinates = Coordinates::new(boundary_x_coords, row); - let mut symbol_to_add = - if row == first_row_coordinates && row != self.position_and_size.y { - BoundarySymbol::new(boundary_type::TOP_LEFT).color(color) - } else if row == last_row_coordinates - 1 - && row != self.position_and_size.y + self.position_and_size.rows - 1 - { - BoundarySymbol::new(boundary_type::BOTTOM_LEFT).color(color) - } else { - BoundarySymbol::new(boundary_type::VERTICAL).color(color) - }; - if rect.invisible_borders() { - symbol_to_add = symbol_to_add.invisible(); - } + let symbol_to_add = if row == first_row_coordinates && row != self.viewport.y { + BoundarySymbol::new(boundary_type::TOP_LEFT).color(color) + } else if row == last_row_coordinates - 1 + && row != self.viewport.y + self.viewport.rows - 1 + { + BoundarySymbol::new(boundary_type::BOTTOM_LEFT).color(color) + } else { + BoundarySymbol::new(boundary_type::VERTICAL).color(color) + }; let next_symbol = self .boundary_characters .remove(&coordinates) @@ -457,26 +448,20 @@ impl Boundaries { self.boundary_characters.insert(coordinates, next_symbol); } } - if rect.y() > self.position_and_size.y { + if rect.y() > self.viewport.y { // top boundary let boundary_y_coords = rect.y() - 1; let first_col_coordinates = self.rect_bottom_boundary_col_start(rect); let last_col_coordinates = self.rect_bottom_boundary_col_end(rect); for col in first_col_coordinates..last_col_coordinates { let coordinates = Coordinates::new(col, boundary_y_coords); - let mut symbol_to_add = if col == first_col_coordinates - && col != self.position_and_size.x - { + let symbol_to_add = if col == first_col_coordinates && col != self.viewport.x { BoundarySymbol::new(boundary_type::TOP_LEFT).color(color) - } else if col == last_col_coordinates - 1 && col != self.position_and_size.cols - 1 - { + } else if col == last_col_coordinates - 1 && col != self.viewport.cols - 1 { BoundarySymbol::new(boundary_type::TOP_RIGHT).color(color) } else { BoundarySymbol::new(boundary_type::HORIZONTAL).color(color) }; - if rect.invisible_borders() { - symbol_to_add = symbol_to_add.invisible(); - } let next_symbol = self .boundary_characters .remove(&coordinates) @@ -492,19 +477,15 @@ impl Boundaries { let last_row_coordinates = self.rect_right_boundary_row_end(rect); for row in first_row_coordinates..last_row_coordinates { let coordinates = Coordinates::new(boundary_x_coords, row); - let mut symbol_to_add = - if row == first_row_coordinates && row != self.position_and_size.y { - BoundarySymbol::new(boundary_type::TOP_RIGHT).color(color) - } else if row == last_row_coordinates - 1 - && row != self.position_and_size.y + self.position_and_size.rows - 1 - { - BoundarySymbol::new(boundary_type::BOTTOM_RIGHT).color(color) - } else { - BoundarySymbol::new(boundary_type::VERTICAL).color(color) - }; - if rect.invisible_borders() { - symbol_to_add = symbol_to_add.invisible(); - } + let symbol_to_add = if row == first_row_coordinates && row != self.viewport.y { + BoundarySymbol::new(boundary_type::TOP_RIGHT).color(color) + } else if row == last_row_coordinates - 1 + && row != self.viewport.y + self.viewport.rows - 1 + { + BoundarySymbol::new(boundary_type::BOTTOM_RIGHT).color(color) + } else { + BoundarySymbol::new(boundary_type::VERTICAL).color(color) + }; let next_symbol = self .boundary_characters .remove(&coordinates) @@ -520,19 +501,13 @@ impl Boundaries { let last_col_coordinates = self.rect_bottom_boundary_col_end(rect); for col in first_col_coordinates..last_col_coordinates { let coordinates = Coordinates::new(col, boundary_y_coords); - let mut symbol_to_add = if col == first_col_coordinates - && col != self.position_and_size.x - { + let symbol_to_add = if col == first_col_coordinates && col != self.viewport.x { BoundarySymbol::new(boundary_type::BOTTOM_LEFT).color(color) - } else if col == last_col_coordinates - 1 && col != self.position_and_size.cols - 1 - { + } else if col == last_col_coordinates - 1 && col != self.viewport.cols - 1 { BoundarySymbol::new(boundary_type::BOTTOM_RIGHT).color(color) } else { BoundarySymbol::new(boundary_type::HORIZONTAL).color(color) }; - if rect.invisible_borders() { - symbol_to_add = symbol_to_add.invisible(); - } let next_symbol = self .boundary_characters .remove(&coordinates) @@ -555,16 +530,16 @@ impl Boundaries { vte_output } fn rect_right_boundary_is_before_screen_edge(&self, rect: &dyn Pane) -> bool { - rect.x() + rect.columns() < self.position_and_size.cols + rect.x() + rect.cols() < self.viewport.cols } fn rect_bottom_boundary_is_before_screen_edge(&self, rect: &dyn Pane) -> bool { - rect.y() + rect.rows() < self.position_and_size.y + self.position_and_size.rows + rect.y() + rect.rows() < self.viewport.y + self.viewport.rows } fn rect_right_boundary_row_start(&self, rect: &dyn Pane) -> usize { - if rect.y() > self.position_and_size.y { + if rect.y() > self.viewport.y { rect.y() - 1 } else { - self.position_and_size.y + self.viewport.y } } fn rect_right_boundary_row_end(&self, rect: &dyn Pane) -> usize { @@ -578,12 +553,12 @@ impl Boundaries { } } fn rect_bottom_boundary_col_end(&self, rect: &dyn Pane) -> usize { - rect.x() + rect.columns() + rect.x() + rect.cols() } fn is_fully_inside_screen(&self, rect: &dyn Pane) -> bool { - rect.x() >= self.position_and_size.x - && rect.x() + rect.columns() <= self.position_and_size.x + self.position_and_size.cols - && rect.y() >= self.position_and_size.y - && rect.y() + rect.rows() <= self.position_and_size.y + self.position_and_size.rows + rect.x() >= self.viewport.x + && rect.x() + rect.cols() <= self.viewport.x + self.viewport.cols + && rect.y() >= self.viewport.y + && rect.y() + rect.rows() <= self.viewport.y + self.viewport.rows } } diff --git a/zellij-server/src/ui/mod.rs b/zellij-server/src/ui/mod.rs index beb70bf0..6ebc4683 100644 --- a/zellij-server/src/ui/mod.rs +++ b/zellij-server/src/ui/mod.rs @@ -1,4 +1,3 @@ pub mod boundaries; pub mod pane_boundaries_frame; pub mod pane_resizer; -pub mod pane_resizer_beta; diff --git a/zellij-server/src/ui/pane_boundaries_frame.rs b/zellij-server/src/ui/pane_boundaries_frame.rs index 0ae454d9..d3cd6d5a 100644 --- a/zellij-server/src/ui/pane_boundaries_frame.rs +++ b/zellij-server/src/ui/pane_boundaries_frame.rs @@ -1,7 +1,7 @@ use crate::ui::boundaries::boundary_type; use ansi_term::Colour::{Fixed, RGB}; use ansi_term::Style; -use zellij_utils::pane_size::PositionAndSize; +use zellij_utils::pane_size::Viewport; use zellij_utils::zellij_tile::prelude::PaletteColor; fn color_string(character: &str, color: Option) -> String { @@ -18,93 +18,15 @@ fn color_string(character: &str, color: Option) -> String { } } -pub struct PaneBoundariesFrame { - pub position_and_size: PositionAndSize, - base_title: String, - title: String, - scroll_position: (usize, usize), // (position, length) +#[derive(Default, PartialEq)] +pub struct PaneFrame { + pub geom: Viewport, + pub title: String, + pub scroll_position: (usize, usize), // (position, length) pub color: Option, - draw_title_only: bool, - should_render: bool, } -impl PaneBoundariesFrame { - pub fn new(position_and_size: PositionAndSize, title: String) -> Self { - PaneBoundariesFrame { - position_and_size, - color: None, - base_title: title.clone(), - title, - scroll_position: (0, 0), - draw_title_only: false, - should_render: true, - } - } - pub fn frame_title_only(mut self) -> Self { - // TODO: remove this? - self.draw_title_only = true; - self.should_render = true; - self - } - pub fn render_only_title(&mut self, should_render_only_title: bool) { - if should_render_only_title != self.draw_title_only { - self.should_render = true; - self.draw_title_only = should_render_only_title; - } - } - pub fn change_pos_and_size(&mut self, position_and_size: PositionAndSize) { - if position_and_size != self.position_and_size { - self.position_and_size = position_and_size; - self.should_render = true; - } - } - pub fn set_color(&mut self, color: Option) { - if color != self.color { - self.color = color; - self.should_render = true; - } - } - pub fn update_scroll(&mut self, scroll_position: (usize, usize)) { - if scroll_position != self.scroll_position { - self.scroll_position = scroll_position; - self.should_render = true; - } - } - pub fn update_title(&mut self, title: Option<&String>) { - match title { - Some(title) => { - if title != &self.title { - self.title = title.clone(); - self.should_render = true; - } - } - None => { - self.title = self.base_title.clone(); - self.should_render = true; - } - } - } - pub fn content_position_and_size(&self) -> PositionAndSize { - if self.draw_title_only { - self.position_and_size.reduce_top_line() - } else { - self.position_and_size.reduce_outer_frame(1) - } - } - pub fn content_offset(&self) -> (usize, usize) { - // (column_difference, row_difference) - let content_position_and_size = self.content_position_and_size(); - let column_difference = content_position_and_size - .x - .saturating_sub(self.position_and_size.x); - let row_difference = content_position_and_size - .y - .saturating_sub(self.position_and_size.y); - (column_difference, row_difference) - } - pub fn set_should_render(&mut self, should_render: bool) { - self.should_render = should_render; - } +impl PaneFrame { fn render_title_right_side(&self, max_length: usize) -> Option { if self.scroll_position.0 > 0 || self.scroll_position.1 > 0 { let prefix = " SCROLL: "; @@ -156,17 +78,9 @@ impl PaneBoundariesFrame { } } fn render_title(&self, vte_output: &mut String) { - let total_title_length = self.position_and_size.cols - 2; // 2 for the left and right corners - let left_boundary = if self.draw_title_only { - boundary_type::HORIZONTAL - } else { - boundary_type::TOP_LEFT - }; - let right_boundary = if self.draw_title_only { - boundary_type::HORIZONTAL - } else { - boundary_type::TOP_RIGHT - }; + let total_title_length = self.geom.cols.saturating_sub(2); // 2 for the left and right corners + let left_boundary = boundary_type::TOP_LEFT; + let right_boundary = boundary_type::TOP_RIGHT; let left_side = self.render_title_left_side(total_title_length); let right_side = left_side.as_ref().and_then(|left_side| { let space_left = total_title_length.saturating_sub(left_side.chars().count() + 1); // 1 for a middle separator @@ -205,73 +119,60 @@ impl PaneBoundariesFrame { }; vte_output.push_str(&format!( "\u{1b}[{};{}H\u{1b}[m{}", - self.position_and_size.y + 1, // +1 because goto is 1 indexed - self.position_and_size.x + 1, // +1 because goto is 1 indexed + self.geom.y + 1, // +1 because goto is 1 indexed + self.geom.x + 1, // +1 because goto is 1 indexed color_string(&title_text, self.color), )); // goto row/col + boundary character } - pub fn render(&mut self) -> Option { - if !self.should_render { - return None; - } + pub fn render(&self) -> String { let mut vte_output = String::new(); - if self.draw_title_only { - self.render_title(&mut vte_output); - } else { - for row in - self.position_and_size.y..(self.position_and_size.y + self.position_and_size.rows) - { - if row == self.position_and_size.y { - // top row - self.render_title(&mut vte_output); - } else if row == self.position_and_size.y + self.position_and_size.rows - 1 { - // bottom row - for col in self.position_and_size.x - ..(self.position_and_size.x + self.position_and_size.cols) - { - if col == self.position_and_size.x { - // bottom left corner - vte_output.push_str(&format!( - "\u{1b}[{};{}H\u{1b}[m{}", - row + 1, // +1 because goto is 1 indexed - col + 1, - color_string(boundary_type::BOTTOM_LEFT, self.color), - )); // goto row/col + boundary character - } else if col == self.position_and_size.x + self.position_and_size.cols - 1 - { - // bottom right corner - vte_output.push_str(&format!( - "\u{1b}[{};{}H\u{1b}[m{}", - row + 1, // +1 because goto is 1 indexed - col + 1, - color_string(boundary_type::BOTTOM_RIGHT, self.color), - )); // goto row/col + boundary character - } else { - vte_output.push_str(&format!( - "\u{1b}[{};{}H\u{1b}[m{}", - row + 1, // +1 because goto is 1 indexed - col + 1, - color_string(boundary_type::HORIZONTAL, self.color), - )); // goto row/col + boundary character - } + for row in self.geom.y..(self.geom.y + self.geom.rows) { + if row == self.geom.y { + // top row + self.render_title(&mut vte_output); + } else if row == self.geom.y + self.geom.rows - 1 { + // bottom row + for col in self.geom.x..(self.geom.x + self.geom.cols) { + if col == self.geom.x { + // bottom left corner + vte_output.push_str(&format!( + "\u{1b}[{};{}H\u{1b}[m{}", + row + 1, // +1 because goto is 1 indexed + col + 1, + color_string(boundary_type::BOTTOM_LEFT, self.color), + )); // goto row/col + boundary character + } else if col == self.geom.x + self.geom.cols - 1 { + // bottom right corner + vte_output.push_str(&format!( + "\u{1b}[{};{}H\u{1b}[m{}", + row + 1, // +1 because goto is 1 indexed + col + 1, + color_string(boundary_type::BOTTOM_RIGHT, self.color), + )); // goto row/col + boundary character + } else { + vte_output.push_str(&format!( + "\u{1b}[{};{}H\u{1b}[m{}", + row + 1, // +1 because goto is 1 indexed + col + 1, + color_string(boundary_type::HORIZONTAL, self.color), + )); // goto row/col + boundary character } - } else { - vte_output.push_str(&format!( - "\u{1b}[{};{}H\u{1b}[m{}", - row + 1, // +1 because goto is 1 indexed - self.position_and_size.x + 1, - color_string(boundary_type::VERTICAL, self.color), - )); // goto row/col + boundary character - vte_output.push_str(&format!( - "\u{1b}[{};{}H\u{1b}[m{}", - row + 1, // +1 because goto is 1 indexed - self.position_and_size.x + self.position_and_size.cols, - color_string(boundary_type::VERTICAL, self.color), - )); // goto row/col + boundary character } + } else { + vte_output.push_str(&format!( + "\u{1b}[{};{}H\u{1b}[m{}", + row + 1, // +1 because goto is 1 indexed + self.geom.x + 1, + color_string(boundary_type::VERTICAL, self.color), + )); // goto row/col + boundary character + vte_output.push_str(&format!( + "\u{1b}[{};{}H\u{1b}[m{}", + row + 1, // +1 because goto is 1 indexed + self.geom.x + self.geom.cols, + color_string(boundary_type::VERTICAL, self.color), + )); // goto row/col + boundary character } } - self.should_render = false; - Some(vte_output) + vte_output } } diff --git a/zellij-server/src/ui/pane_resizer.rs b/zellij-server/src/ui/pane_resizer.rs index 1b5ddabf..0213f6d5 100644 --- a/zellij-server/src/ui/pane_resizer.rs +++ b/zellij-server/src/ui/pane_resizer.rs @@ -1,537 +1,253 @@ use crate::{os_input_output::ServerOsApi, panes::PaneId, tab::Pane}; -use std::{ - cmp::Ordering, - collections::{BTreeMap, HashSet}, +use cassowary::{ + strength::{REQUIRED, STRONG}, + Expression, Solver, Variable, + WeightedRelation::EQ, +}; +use std::collections::{HashMap, HashSet}; +use zellij_utils::{ + input::layout::Direction, + pane_size::{Constraint, Dimension, PaneGeom}, }; -use zellij_utils::pane_size::PositionAndSize; -pub(crate) struct PaneResizer<'a> { - panes: &'a mut BTreeMap>, +pub struct PaneResizer<'a> { + panes: HashMap<&'a PaneId, &'a mut Box>, os_api: &'a mut Box, + vars: HashMap, + solver: Solver, } -// TODO: currently there are some functions here duplicated with Tab -// all resizing functions should move here +// FIXME: Just hold a mutable Pane reference instead of the PaneId, fixed, pos, and size? +// Do this after panes are no longer trait-objects! +#[derive(Debug, Clone, Copy)] +struct Span { + pid: PaneId, + direction: Direction, + pos: usize, + size: Dimension, + size_var: Variable, +} + +type Grid = Vec>; impl<'a> PaneResizer<'a> { pub fn new( - panes: &'a mut BTreeMap>, + panes: impl Iterator)>, os_api: &'a mut Box, ) -> Self { - PaneResizer { panes, os_api } + let panes: HashMap<_, _> = panes.collect(); + let mut vars = HashMap::new(); + for &&k in panes.keys() { + vars.insert(k, Variable::new()); + } + PaneResizer { + panes, + os_api, + vars, + solver: Solver::new(), + } } - pub fn resize( - &mut self, - mut current_size: PositionAndSize, - new_size: PositionAndSize, - ) -> Option<(isize, isize)> { - // (column_difference, row_difference) - let mut successfully_resized = false; - let mut column_difference: isize = 0; - let mut row_difference: isize = 0; - match new_size.cols.cmp(¤t_size.cols) { - Ordering::Greater => { - let increase_by = new_size.cols - current_size.cols; - if let Some(panes_to_resize) = find_increasable_vertical_chain( - self.panes, - increase_by, - current_size.cols, - current_size.rows, - ) { - self.increase_panes_right_and_push_adjacents_right( - panes_to_resize, - increase_by, - ); - column_difference = new_size.cols as isize - current_size.cols as isize; - current_size.cols = (current_size.cols as isize + column_difference) as usize; - successfully_resized = true; - }; + + pub fn layout(&mut self, direction: Direction, space: usize) -> Result<(), String> { + self.solver.reset(); + let grid = self.solve(direction, space)?; + let spans = self.discretize_spans(grid, space)?; + self.apply_spans(spans); + Ok(()) + } + + fn solve(&mut self, direction: Direction, space: usize) -> Result { + let grid: Grid = self + .grid_boundaries(direction) + .into_iter() + .map(|b| self.spans_in_boundary(direction, b)) + .collect(); + + let constraints: HashSet<_> = grid + .iter() + .flat_map(|s| constrain_spans(space, s)) + .collect(); + + self.solver + .add_constraints(&constraints) + .map_err(|e| format!("{:?}", e))?; + + Ok(grid) + } + + fn discretize_spans(&mut self, mut grid: Grid, space: usize) -> Result, String> { + let mut rounded_sizes: HashMap<_, _> = grid + .iter() + .flatten() + .map(|s| { + ( + s.size_var, + stable_round(self.solver.get_value(s.size_var)) as isize, + ) + }) + .collect(); + + // Round f64 pane sizes to usize without gaps or overlap + let mut finalised = Vec::new(); + for spans in grid.iter_mut() { + let rounded_size: isize = spans.iter().map(|s| rounded_sizes[&s.size_var]).sum(); + let mut error = space as isize - rounded_size; + let mut flex_spans: Vec<_> = spans + .iter_mut() + .filter(|s| !s.size.is_fixed() && !finalised.contains(&s.pid)) + .collect(); + flex_spans.sort_by_key(|s| rounded_sizes[&s.size_var]); + if error < 0 { + flex_spans.reverse(); } - Ordering::Less => { - let reduce_by = current_size.cols - new_size.cols; - if let Some(panes_to_resize) = find_reducible_vertical_chain( - self.panes, - reduce_by, - current_size.cols, - current_size.rows, - ) { - self.reduce_panes_left_and_pull_adjacents_left(panes_to_resize, reduce_by); - column_difference = new_size.cols as isize - current_size.cols as isize; - current_size.cols = (current_size.cols as isize + column_difference) as usize; - successfully_resized = true; - }; + for span in flex_spans { + rounded_sizes + .entry(span.size_var) + .and_modify(|s| *s += error.signum()); + error -= error.signum(); } - Ordering::Equal => (), + finalised.extend(spans.iter().map(|s| s.pid)); } - match new_size.rows.cmp(¤t_size.rows) { - Ordering::Greater => { - let increase_by = new_size.rows - current_size.rows; - if let Some(panes_to_resize) = find_increasable_horizontal_chain( - self.panes, - increase_by, - current_size.cols, - current_size.rows, - ) { - self.increase_panes_down_and_push_down_adjacents(panes_to_resize, increase_by); - row_difference = new_size.rows as isize - current_size.rows as isize; - current_size.rows = (current_size.rows as isize + row_difference) as usize; - successfully_resized = true; - }; + + // Update span positions based on their rounded sizes + for spans in grid.iter_mut() { + let mut offset = 0; + for span in spans.iter_mut() { + span.pos = offset; + let sz = rounded_sizes[&span.size_var]; + if sz < 1 { + return Err("Ran out of room for spans".into()); + } + span.size.set_inner(sz as usize); + offset += span.size.as_usize(); } - Ordering::Less => { - let reduce_by = current_size.rows - new_size.rows; - if let Some(panes_to_resize) = find_reducible_horizontal_chain( - self.panes, - reduce_by, - current_size.cols, - current_size.rows, - ) { - self.reduce_panes_up_and_pull_adjacents_up(panes_to_resize, reduce_by); - row_difference = new_size.rows as isize - current_size.rows as isize; - current_size.rows = (current_size.rows as isize + row_difference) as usize; - successfully_resized = true; - }; - } - Ordering::Equal => (), } - if successfully_resized { - Some((column_difference, row_difference)) + + Ok(grid.into_iter().flatten().collect()) + } + + fn apply_spans(&mut self, spans: Vec) { + for span in spans { + let pane = self.panes.get_mut(&span.pid).unwrap(); + let new_geom = match span.direction { + Direction::Horizontal => PaneGeom { + x: span.pos, + cols: span.size, + ..pane.current_geom() + }, + Direction::Vertical => PaneGeom { + y: span.pos, + rows: span.size, + ..pane.current_geom() + }, + }; + if pane.geom_override().is_some() { + pane.get_geom_override(new_geom); + } else { + pane.set_geom(new_geom); + } + if let PaneId::Terminal(pid) = pane.pid() { + self.os_api.set_terminal_size_using_fd( + pid, + pane.get_content_columns() as u16, + pane.get_content_rows() as u16, + ); + } + } + } + + // FIXME: Functions like this should have unit tests! + fn grid_boundaries(&self, direction: Direction) -> Vec<(usize, usize)> { + // Select the spans running *perpendicular* to the direction of resize + let spans: Vec = self + .panes + .values() + .map(|p| self.get_span(!direction, p.as_ref())) + .collect(); + + let mut last_edge = 0; + let mut bounds = Vec::new(); + let mut edges: Vec = spans.iter().map(|s| s.pos + s.size.as_usize()).collect(); + edges.sort_unstable(); + edges.dedup(); + for next in edges { + let next_edge = next; + bounds.push((last_edge, next_edge)); + last_edge = next_edge; + } + bounds + } + + fn spans_in_boundary(&self, direction: Direction, boundary: (usize, usize)) -> Vec { + let bwn = |v, (s, e)| s <= v && v < e; + let mut spans: Vec<_> = self + .panes + .values() + .filter(|p| { + let s = self.get_span(!direction, p.as_ref()); + let span_bounds = (s.pos, s.pos + s.size.as_usize()); + bwn(span_bounds.0, boundary) + || (bwn(boundary.0, span_bounds) + && (bwn(boundary.1, span_bounds) || boundary.1 == span_bounds.1)) + }) + .map(|p| self.get_span(direction, p.as_ref())) + .collect(); + spans.sort_unstable_by_key(|s| s.pos); + spans + } + + fn get_span(&self, direction: Direction, pane: &dyn Pane) -> Span { + let pas = pane.current_geom(); + let size_var = self.vars[&pane.pid()]; + match direction { + Direction::Horizontal => Span { + pid: pane.pid(), + direction, + pos: pas.x, + size: pas.cols, + size_var, + }, + Direction::Vertical => Span { + pid: pane.pid(), + direction, + pos: pas.y, + size: pas.rows, + size_var, + }, + } + } +} + +fn constrain_spans(space: usize, spans: &[Span]) -> HashSet { + let mut constraints = HashSet::new(); + + // Calculating "flexible" space (space not consumed by fixed-size spans) + let new_flex_space = spans.iter().fold(space, |a, s| { + if let Constraint::Fixed(sz) = s.size.constraint { + a.saturating_sub(sz) } else { - None - } - } - fn reduce_panes_left_and_pull_adjacents_left( - &mut self, - panes_to_reduce: Vec, - reduce_by: usize, - ) { - let mut pulled_panes: HashSet = HashSet::new(); - for pane_id in panes_to_reduce { - let (pane_x, pane_y, pane_columns, pane_rows) = { - let pane = self.panes.get(&pane_id).unwrap(); - (pane.x(), pane.y(), pane.columns(), pane.rows()) - }; - let panes_to_pull = self.panes.values_mut().filter(|p| { - p.x() >= pane_x + pane_columns - && (p.y() <= pane_y && p.y() + p.rows() >= pane_y - || p.y() >= pane_y && p.y() + p.rows() <= pane_y + pane_rows) - }); - for pane in panes_to_pull { - if !pulled_panes.contains(&pane.pid()) { - pane.pull_left(reduce_by); - pulled_panes.insert(pane.pid()); - } - } - self.reduce_pane_width_left(&pane_id, reduce_by); - } - } - fn reduce_panes_up_and_pull_adjacents_up( - &mut self, - panes_to_reduce: Vec, - reduce_by: usize, - ) { - let mut pulled_panes: HashSet = HashSet::new(); - for pane_id in panes_to_reduce { - let (pane_x, pane_y, pane_columns, pane_rows) = { - let pane = self.panes.get(&pane_id).unwrap(); - (pane.x(), pane.y(), pane.columns(), pane.rows()) - }; - let panes_to_pull = self.panes.values_mut().filter(|p| { - p.y() >= pane_y + pane_rows - && (p.x() <= pane_x && p.x() + p.columns() >= pane_x - || p.x() >= pane_x && p.x() + p.columns() <= pane_x + pane_columns) - }); - for pane in panes_to_pull { - if !pulled_panes.contains(&pane.pid()) { - pane.pull_up(reduce_by); - pulled_panes.insert(pane.pid()); - } - } - self.reduce_pane_height_up(&pane_id, reduce_by); - } - } - fn increase_panes_down_and_push_down_adjacents( - &mut self, - panes_to_increase: Vec, - increase_by: usize, - ) { - let mut pushed_panes: HashSet = HashSet::new(); - for pane_id in panes_to_increase { - let (pane_x, pane_y, pane_columns, pane_rows) = { - let pane = self.panes.get(&pane_id).unwrap(); - (pane.x(), pane.y(), pane.columns(), pane.rows()) - }; - let panes_to_push = self.panes.values_mut().filter(|p| { - p.y() >= pane_y + pane_rows - && (p.x() <= pane_x && p.x() + p.columns() >= pane_x - || p.x() >= pane_x && p.x() + p.columns() <= pane_x + pane_columns) - }); - for pane in panes_to_push { - if !pushed_panes.contains(&pane.pid()) { - pane.push_down(increase_by); - pushed_panes.insert(pane.pid()); - } - } - self.increase_pane_height_down(&pane_id, increase_by); - } - } - fn increase_panes_right_and_push_adjacents_right( - &mut self, - panes_to_increase: Vec, - increase_by: usize, - ) { - let mut pushed_panes: HashSet = HashSet::new(); - for pane_id in panes_to_increase { - let (pane_x, pane_y, pane_columns, pane_rows) = { - let pane = self.panes.get(&pane_id).unwrap(); - (pane.x(), pane.y(), pane.columns(), pane.rows()) - }; - let panes_to_push = self.panes.values_mut().filter(|p| { - p.x() >= pane_x + pane_columns - && (p.y() <= pane_y && p.y() + p.rows() >= pane_y - || p.y() >= pane_y && p.y() + p.rows() <= pane_y + pane_rows) - }); - for pane in panes_to_push { - if !pushed_panes.contains(&pane.pid()) { - pane.push_right(increase_by); - pushed_panes.insert(pane.pid()); - } - } - self.increase_pane_width_right(&pane_id, increase_by); - } - } - fn reduce_pane_height_up(&mut self, id: &PaneId, count: usize) { - let pane = self.panes.get_mut(id).unwrap(); - pane.reduce_height_up(count); - if let PaneId::Terminal(pid) = id { - self.os_api.set_terminal_size_using_fd( - *pid, - pane.get_content_columns() as u16, - pane.get_content_rows() as u16, - ); - } - } - fn increase_pane_height_down(&mut self, id: &PaneId, count: usize) { - let pane = self.panes.get_mut(id).unwrap(); - pane.increase_height_down(count); - if let PaneId::Terminal(pid) = pane.pid() { - self.os_api.set_terminal_size_using_fd( - pid, - pane.get_content_columns() as u16, - pane.get_content_rows() as u16, - ); - } - } - fn increase_pane_width_right(&mut self, id: &PaneId, count: usize) { - let pane = self.panes.get_mut(id).unwrap(); - pane.increase_width_right(count); - if let PaneId::Terminal(pid) = pane.pid() { - self.os_api.set_terminal_size_using_fd( - pid, - pane.get_content_columns() as u16, - pane.get_content_rows() as u16, - ); - } - } - fn reduce_pane_width_left(&mut self, id: &PaneId, count: usize) { - let pane = self.panes.get_mut(id).unwrap(); - pane.reduce_width_left(count); - if let PaneId::Terminal(pid) = pane.pid() { - self.os_api.set_terminal_size_using_fd( - pid, - pane.get_content_columns() as u16, - pane.get_content_rows() as u16, - ); + a } + }); + + // Spans must use all of the available space + let full_size = spans + .iter() + .fold(Expression::from_constant(0.0), |acc, s| acc + s.size_var); + constraints.insert(full_size | EQ(REQUIRED) | space as f64); + + // Try to maintain ratios and lock non-flexible sizes + for span in spans { + match span.size.constraint { + Constraint::Fixed(s) => constraints.insert(span.size_var | EQ(REQUIRED) | s as f64), + Constraint::Percent(p) => constraints + .insert((span.size_var / new_flex_space as f64) | EQ(STRONG) | (p / 100.0)), + }; } + + constraints } -fn find_next_increasable_horizontal_pane( - panes: &BTreeMap>, - right_of: &dyn Pane, - increase_by: usize, -) -> Option { - let next_pane_candidates = panes.values().filter( - |p| p.x() == right_of.x() + right_of.columns() && p.horizontally_overlaps_with(right_of), // TODO: the name here is wrong, it should be vertically_overlaps_with - ); - let resizable_candidates = - next_pane_candidates.filter(|p| p.can_increase_height_by(increase_by)); - resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id { - Some(next_pane) => { - let next_pane = panes.get(&next_pane).unwrap(); - if next_pane.y() < p.y() { - next_pane_id - } else { - Some(p.pid()) - } - } - None => Some(p.pid()), - }) -} - -fn find_next_increasable_vertical_pane( - panes: &BTreeMap>, - below: &dyn Pane, - increase_by: usize, -) -> Option { - let next_pane_candidates = panes.values().filter( - |p| p.y() == below.y() + below.rows() && p.vertically_overlaps_with(below), // TODO: the name here is wrong, it should be horizontally_overlaps_with - ); - let resizable_candidates = - next_pane_candidates.filter(|p| p.can_increase_width_by(increase_by)); - resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id { - Some(next_pane) => { - let next_pane = panes.get(&next_pane).unwrap(); - if next_pane.x() < p.x() { - next_pane_id - } else { - Some(p.pid()) - } - } - None => Some(p.pid()), - }) -} - -fn find_next_reducible_vertical_pane( - panes: &BTreeMap>, - below: &dyn Pane, - reduce_by: usize, -) -> Option { - let next_pane_candidates = panes.values().filter( - |p| p.y() == below.y() + below.rows() && p.vertically_overlaps_with(below), // TODO: the name here is wrong, it should be horizontally_overlaps_with - ); - let resizable_candidates = next_pane_candidates.filter(|p| p.can_reduce_width_by(reduce_by)); - resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id { - Some(next_pane) => { - let next_pane = panes.get(&next_pane).unwrap(); - if next_pane.x() < p.x() { - next_pane_id - } else { - Some(p.pid()) - } - } - None => Some(p.pid()), - }) -} - -fn find_next_reducible_horizontal_pane( - panes: &BTreeMap>, - right_of: &dyn Pane, - reduce_by: usize, -) -> Option { - let next_pane_candidates = panes.values().filter( - |p| p.x() == right_of.x() + right_of.columns() && p.horizontally_overlaps_with(right_of), // TODO: the name here is wrong, it should be vertically_overlaps_with - ); - let resizable_candidates = next_pane_candidates.filter(|p| p.can_reduce_height_by(reduce_by)); - resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id { - Some(next_pane) => { - let next_pane = panes.get(&next_pane).unwrap(); - if next_pane.y() < p.y() { - next_pane_id - } else { - Some(p.pid()) - } - } - None => Some(p.pid()), - }) -} - -fn find_increasable_horizontal_chain( - panes: &BTreeMap>, - increase_by: usize, - screen_width: usize, - screen_height: usize, // TODO: this is the previous size (make this clearer) -) -> Option> { - let mut horizontal_coordinate = 0; - loop { - if horizontal_coordinate == screen_height { - return None; - } - - match panes - .values() - .find(|p| p.x() == 0 && p.y() == horizontal_coordinate) - { - Some(leftmost_pane) => { - if !leftmost_pane.can_increase_height_by(increase_by) { - horizontal_coordinate = leftmost_pane.y() + leftmost_pane.rows(); - continue; - } - let mut panes_to_resize = vec![]; - let mut current_pane = leftmost_pane; - loop { - panes_to_resize.push(current_pane.pid()); - if current_pane.x() + current_pane.columns() == screen_width { - return Some(panes_to_resize); - } - match find_next_increasable_horizontal_pane( - panes, - current_pane.as_ref(), - increase_by, - ) { - Some(next_pane_id) => { - current_pane = panes.get(&next_pane_id).unwrap(); - } - None => { - horizontal_coordinate = leftmost_pane.y() + leftmost_pane.rows(); - break; - } - }; - } - } - None => { - return None; - } - } - } -} - -fn find_increasable_vertical_chain( - panes: &BTreeMap>, - increase_by: usize, - screen_width: usize, - screen_height: usize, // TODO: this is the previous size (make this clearer) -) -> Option> { - let mut vertical_coordinate = 0; - loop { - if vertical_coordinate == screen_width { - return None; - } - - match panes - .values() - .find(|p| p.y() == 0 && p.x() == vertical_coordinate) - { - Some(topmost_pane) => { - if !topmost_pane.can_increase_width_by(increase_by) { - vertical_coordinate = topmost_pane.x() + topmost_pane.columns(); - continue; - } - let mut panes_to_resize = vec![]; - let mut current_pane = topmost_pane; - loop { - panes_to_resize.push(current_pane.pid()); - if current_pane.y() + current_pane.rows() == screen_height { - return Some(panes_to_resize); - } - match find_next_increasable_vertical_pane( - panes, - current_pane.as_ref(), - increase_by, - ) { - Some(next_pane_id) => { - current_pane = panes.get(&next_pane_id).unwrap(); - } - None => { - vertical_coordinate = topmost_pane.x() + topmost_pane.columns(); - break; - } - }; - } - } - None => { - return None; - } - } - } -} - -fn find_reducible_horizontal_chain( - panes: &BTreeMap>, - reduce_by: usize, - screen_width: usize, - screen_height: usize, // TODO: this is the previous size (make this clearer) -) -> Option> { - let mut horizontal_coordinate = 0; - loop { - if horizontal_coordinate == screen_height { - return None; - } - - match panes - .values() - .find(|p| p.x() == 0 && p.y() == horizontal_coordinate) - { - Some(leftmost_pane) => { - if !leftmost_pane.can_reduce_height_by(reduce_by) { - horizontal_coordinate = leftmost_pane.y() + leftmost_pane.rows(); - continue; - } - let mut panes_to_resize = vec![]; - let mut current_pane = leftmost_pane; - loop { - panes_to_resize.push(current_pane.pid()); - if current_pane.x() + current_pane.columns() == screen_width { - return Some(panes_to_resize); - } - match find_next_reducible_horizontal_pane( - panes, - current_pane.as_ref(), - reduce_by, - ) { - Some(next_pane_id) => { - current_pane = panes.get(&next_pane_id).unwrap(); - } - None => { - horizontal_coordinate = leftmost_pane.y() + leftmost_pane.rows(); - break; - } - }; - } - } - None => { - return None; - } - } - } -} - -fn find_reducible_vertical_chain( - panes: &BTreeMap>, - increase_by: usize, - screen_width: usize, - screen_height: usize, // TODO: this is the previous size (make this clearer) -) -> Option> { - let mut vertical_coordinate = 0; - loop { - if vertical_coordinate == screen_width { - return None; - } - - match panes - .values() - .find(|p| p.y() == 0 && p.x() == vertical_coordinate) - { - Some(topmost_pane) => { - if !topmost_pane.can_reduce_width_by(increase_by) { - vertical_coordinate = topmost_pane.x() + topmost_pane.columns(); - continue; - } - let mut panes_to_resize = vec![]; - let mut current_pane = topmost_pane; - loop { - panes_to_resize.push(current_pane.pid()); - if current_pane.y() + current_pane.rows() == screen_height { - return Some(panes_to_resize); - } - match find_next_reducible_vertical_pane( - panes, - current_pane.as_ref(), - increase_by, - ) { - Some(next_pane_id) => { - current_pane = panes.get(&next_pane_id).unwrap(); - } - None => { - vertical_coordinate = topmost_pane.x() + topmost_pane.columns(); - break; - } - }; - } - } - None => { - return None; - } - } - } +fn stable_round(x: f64) -> f64 { + ((x * 100.0).round() / 100.0).round() } diff --git a/zellij-server/src/ui/pane_resizer_beta.rs b/zellij-server/src/ui/pane_resizer_beta.rs deleted file mode 100644 index b6ffd784..00000000 --- a/zellij-server/src/ui/pane_resizer_beta.rs +++ /dev/null @@ -1,248 +0,0 @@ -#![allow(dead_code)] -use crate::{os_input_output::ServerOsApi, panes::PaneId, tab::Pane}; -use cassowary::{ - strength::{REQUIRED, STRONG}, - Constraint, Solver, Variable, - WeightedRelation::*, -}; -use std::{ - collections::{BTreeMap, HashSet}, - ops::Not, -}; -use zellij_utils::pane_size::PositionAndSize; - -const GAP_SIZE: usize = 1; // Panes are separated by this number of rows / columns - -pub struct PaneResizer<'a> { - panes: &'a mut BTreeMap>, - vars: BTreeMap, - solver: Solver, - os_api: &'a mut Box, -} - -#[derive(Debug, Clone, Copy)] -enum Direction { - Horizontal, - Vertical, -} - -impl Not for Direction { - type Output = Self; - - fn not(self) -> Self::Output { - match self { - Direction::Horizontal => Direction::Vertical, - Direction::Vertical => Direction::Horizontal, - } - } -} - -#[derive(Debug, Clone, Copy)] -struct Span { - pid: PaneId, - direction: Direction, - fixed: bool, - pos: usize, - size: usize, - pos_var: Variable, - size_var: Variable, -} - -// TODO: currently there are some functions here duplicated with Tab -// all resizing functions should move here - -// FIXME: -// 1. Rounding causes a loss of ratios, I need to store an internal f64 for -// each pane as well as the displayed usize and add custom rounding logic. -// 2. Vertical resizing doesn't seem to respect the space consumed by the tab -// and status bars? -// 3. A 2x2 layout and simultaneous vertical + horizontal resizing sometimes -// leads to unsolvable constraints? Maybe related to 2 (and possibly 1). -// I should sanity-check the `spans_in_boundary()` here! - -impl<'a> PaneResizer<'a> { - pub fn new( - panes: &'a mut BTreeMap>, - os_api: &'a mut Box, - ) -> Self { - let mut vars = BTreeMap::new(); - for &k in panes.keys() { - vars.insert(k, (Variable::new(), Variable::new())); - } - PaneResizer { - panes, - vars, - solver: Solver::new(), - os_api, - } - } - - pub fn resize( - &mut self, - current_size: PositionAndSize, - new_size: PositionAndSize, - ) -> Option<(isize, isize)> { - let col_delta = new_size.cols as isize - current_size.cols as isize; - let row_delta = new_size.rows as isize - current_size.rows as isize; - if col_delta != 0 { - let spans = self.solve_direction(Direction::Horizontal, new_size.cols)?; - self.collapse_spans(&spans); - } - self.solver.reset(); - if row_delta != 0 { - let spans = self.solve_direction(Direction::Vertical, new_size.rows)?; - self.collapse_spans(&spans); - } - Some((col_delta, row_delta)) - } - - fn solve_direction(&mut self, direction: Direction, space: usize) -> Option> { - let mut grid = Vec::new(); - for boundary in self.grid_boundaries(direction) { - grid.push(self.spans_in_boundary(direction, boundary)); - } - - let constraints: Vec<_> = grid - .iter() - .flat_map(|s| constrain_spans(space, s)) - .collect(); - - // FIXME: This line needs to be restored before merging! - //self.solver.add_constraints(&constraints).ok()?; - self.solver.add_constraints(&constraints).unwrap(); - Some(grid.into_iter().flatten().collect()) - } - - fn grid_boundaries(&self, direction: Direction) -> Vec<(usize, usize)> { - // Select the spans running *perpendicular* to the direction of resize - let spans: Vec = self - .panes - .values() - .map(|p| self.get_span(!direction, p.as_ref())) - .collect(); - - let mut last_edge = 0; - let mut bounds = Vec::new(); - loop { - let mut spans_on_edge: Vec<&Span> = - spans.iter().filter(|p| p.pos == last_edge).collect(); - spans_on_edge.sort_unstable_by_key(|s| s.size); - if let Some(next) = spans_on_edge.first() { - let next_edge = last_edge + next.size; - bounds.push((last_edge, next_edge)); - last_edge = next_edge + GAP_SIZE; - } else { - break; - } - } - bounds - } - - fn spans_in_boundary(&self, direction: Direction, boundary: (usize, usize)) -> Vec { - let (start, end) = boundary; - let bwn = |v| start <= v && v < end; - let mut spans: Vec<_> = self - .panes - .values() - .filter(|p| { - let s = self.get_span(!direction, p.as_ref()); - bwn(s.pos) || bwn(s.pos + s.size) - }) - .map(|p| self.get_span(direction, p.as_ref())) - .collect(); - spans.sort_unstable_by_key(|s| s.pos); - spans - } - - fn get_span(&self, direction: Direction, pane: &dyn Pane) -> Span { - let pas = pane.position_and_size(); - let (pos_var, size_var) = self.vars[&pane.pid()]; - match direction { - Direction::Horizontal => Span { - pid: pane.pid(), - direction, - fixed: pas.cols_fixed, - pos: pas.x, - size: pas.cols, - pos_var, - size_var, - }, - Direction::Vertical => Span { - pid: pane.pid(), - direction, - fixed: pas.rows_fixed, - pos: pas.y, - size: pas.rows, - pos_var, - size_var, - }, - } - } - - fn collapse_spans(&mut self, spans: &[Span]) { - for span in spans { - let solver = &self.solver; // Hand-holding the borrow-checker - let pane = self.panes.get_mut(&span.pid).unwrap(); - let fetch_usize = |v| solver.get_value(v).round() as usize; - match span.direction { - Direction::Horizontal => pane.change_pos_and_size(&PositionAndSize { - x: fetch_usize(span.pos_var), - cols: fetch_usize(span.size_var), - ..pane.position_and_size() - }), - Direction::Vertical => pane.change_pos_and_size(&PositionAndSize { - y: fetch_usize(span.pos_var), - rows: fetch_usize(span.size_var), - ..pane.position_and_size() - }), - } - if let PaneId::Terminal(pid) = pane.pid() { - self.os_api.set_terminal_size_using_fd( - pid, - pane.columns() as u16, - pane.rows() as u16, - ); - } - } - } -} - -fn constrain_spans(space: usize, spans: &[Span]) -> HashSet { - let mut constraints = HashSet::new(); - - // The first span needs to start at 0 - constraints.insert(spans[0].pos_var | EQ(REQUIRED) | 0.0); - - // Calculating "flexible" space (space not consumed by fixed-size spans) - let gap_space = GAP_SIZE * (spans.len() - 1); - let old_flex_space = spans - .iter() - .fold(0, |a, s| if !s.fixed { a + s.size } else { a }); - let new_flex_space = spans.iter().fold( - space - gap_space, - |a, s| if s.fixed { a - s.size } else { a }, - ); - - // Keep spans stuck together - for pair in spans.windows(2) { - let (ls, rs) = (pair[0], pair[1]); - constraints - .insert((ls.pos_var + ls.size_var + GAP_SIZE as f64) | EQ(REQUIRED) | rs.pos_var); - } - - // Try to maintain ratios and lock non-flexible sizes - for span in spans { - if span.fixed { - constraints.insert(span.size_var | EQ(REQUIRED) | span.size as f64); - } else { - let ratio = span.size as f64 / old_flex_space as f64; - constraints.insert((span.size_var / new_flex_space as f64) | EQ(STRONG) | ratio); - } - } - - // The last pane needs to end at the end of the space - let last = spans.last().unwrap(); - constraints.insert((last.pos_var + last.size_var) | EQ(REQUIRED) | space as f64); - - constraints -} diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index 6248ded2..2d080886 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -6,7 +6,9 @@ use crate::{ SessionState, }; use std::sync::{Arc, RwLock}; -use zellij_utils::{input::command::TerminalAction, pane_size::PositionAndSize}; +use zellij_utils::input::command::TerminalAction; +use zellij_utils::input::layout::LayoutTemplate; +use zellij_utils::pane_size::Size; use std::os::unix::io::RawFd; @@ -73,12 +75,12 @@ impl ServerOsApi for FakeInputOutput { } } -fn create_new_screen(position_and_size: PositionAndSize) -> Screen { +fn create_new_screen(size: Size) -> Screen { let mut bus: Bus = Bus::empty(); let fake_os_input = FakeInputOutput {}; bus.os_input = Some(Box::new(fake_os_input)); let mut client_attributes = ClientAttributes::default(); - client_attributes.position_and_size = position_and_size; + client_attributes.size = size; let max_panes = None; let mode_info = ModeInfo::default(); let session_state = Arc::new(RwLock::new(SessionState::Attached)); @@ -92,19 +94,20 @@ fn create_new_screen(position_and_size: PositionAndSize) -> Screen { ) } +fn new_tab(screen: &mut Screen, pid: i32) { + screen.apply_layout(LayoutTemplate::default().into(), vec![pid]); +} + #[test] fn open_new_tab() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut screen = create_new_screen(position_and_size); + let mut screen = create_new_screen(size); - screen.new_tab(1); - screen.new_tab(2); + new_tab(&mut screen, 1); + new_tab(&mut screen, 2); assert_eq!(screen.tabs.len(), 2, "Screen now has two tabs"); assert_eq!( @@ -116,17 +119,14 @@ fn open_new_tab() { #[test] pub fn switch_to_prev_tab() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut screen = create_new_screen(position_and_size); + let mut screen = create_new_screen(size); - screen.new_tab(1); - screen.new_tab(2); + new_tab(&mut screen, 1); + new_tab(&mut screen, 2); screen.switch_tab_prev(); assert_eq!( @@ -138,17 +138,14 @@ pub fn switch_to_prev_tab() { #[test] pub fn switch_to_next_tab() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut screen = create_new_screen(position_and_size); + let mut screen = create_new_screen(size); - screen.new_tab(1); - screen.new_tab(2); + new_tab(&mut screen, 1); + new_tab(&mut screen, 2); screen.switch_tab_prev(); screen.switch_tab_next(); @@ -161,17 +158,14 @@ pub fn switch_to_next_tab() { #[test] pub fn close_tab() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut screen = create_new_screen(position_and_size); + let mut screen = create_new_screen(size); - screen.new_tab(1); - screen.new_tab(2); + new_tab(&mut screen, 1); + new_tab(&mut screen, 2); screen.close_tab(); assert_eq!(screen.tabs.len(), 1, "Only one tab left"); @@ -184,20 +178,32 @@ pub fn close_tab() { #[test] pub fn close_the_middle_tab() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut screen = create_new_screen(position_and_size); + let mut screen = create_new_screen(size); - screen.new_tab(1); - screen.new_tab(2); - screen.new_tab(3); + new_tab(&mut screen, 1); + new_tab(&mut screen, 2); + new_tab(&mut screen, 3); + dbg!(screen + .tabs + .values() + .map(|t| (t.index, t.position, t.name.clone(), t.get_pane_ids())) + .collect::>()); screen.switch_tab_prev(); + dbg!(screen + .tabs + .values() + .map(|t| (t.index, t.position, t.name.clone(), t.get_pane_ids())) + .collect::>()); screen.close_tab(); + dbg!(screen + .tabs + .values() + .map(|t| (t.index, t.position, t.name.clone(), t.get_pane_ids())) + .collect::>()); assert_eq!(screen.tabs.len(), 2, "Two tabs left"); assert_eq!( @@ -209,18 +215,15 @@ pub fn close_the_middle_tab() { #[test] fn move_focus_left_at_left_screen_edge_changes_tab() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut screen = create_new_screen(position_and_size); + let mut screen = create_new_screen(size); - screen.new_tab(1); - screen.new_tab(2); - screen.new_tab(3); + new_tab(&mut screen, 1); + new_tab(&mut screen, 2); + new_tab(&mut screen, 3); screen.switch_tab_prev(); screen.move_focus_left_or_previous_tab(); @@ -233,18 +236,15 @@ fn move_focus_left_at_left_screen_edge_changes_tab() { #[test] fn move_focus_right_at_right_screen_edge_changes_tab() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut screen = create_new_screen(position_and_size); + let mut screen = create_new_screen(size); - screen.new_tab(1); - screen.new_tab(2); - screen.new_tab(3); + new_tab(&mut screen, 1); + new_tab(&mut screen, 2); + new_tab(&mut screen, 3); screen.switch_tab_prev(); screen.move_focus_right_or_next_tab(); @@ -257,17 +257,14 @@ fn move_focus_right_at_right_screen_edge_changes_tab() { #[test] pub fn toggle_to_previous_tab_simple() { - let position_and_size = PositionAndSize { + let position_and_size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; let mut screen = create_new_screen(position_and_size); - screen.new_tab(1); - screen.new_tab(2); + new_tab(&mut screen, 1); + new_tab(&mut screen, 2); screen.go_to_tab(1); screen.go_to_tab(2); @@ -288,18 +285,15 @@ pub fn toggle_to_previous_tab_simple() { #[test] pub fn toggle_to_previous_tab_create_tabs_only() { - let position_and_size = PositionAndSize { + let position_and_size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; let mut screen = create_new_screen(position_and_size); - screen.new_tab(1); - screen.new_tab(2); - screen.new_tab(3); + new_tab(&mut screen, 1); + new_tab(&mut screen, 2); + new_tab(&mut screen, 3); assert_eq!( screen.tab_history, @@ -341,19 +335,16 @@ pub fn toggle_to_previous_tab_create_tabs_only() { #[test] pub fn toggle_to_previous_tab_delete() { - let position_and_size = PositionAndSize { + let position_and_size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; let mut screen = create_new_screen(position_and_size); - screen.new_tab(1); // 0 - screen.new_tab(2); // 1 - screen.new_tab(3); // 2 - screen.new_tab(4); // 3 + new_tab(&mut screen, 1); // 0 + new_tab(&mut screen, 2); // 1 + new_tab(&mut screen, 3); // 2 + new_tab(&mut screen, 4); // 3 assert_eq!( screen.tab_history, diff --git a/zellij-server/src/unit/tab_tests.rs b/zellij-server/src/unit/tab_tests.rs index 08594397..ea96df62 100644 --- a/zellij-server/src/unit/tab_tests.rs +++ b/zellij-server/src/unit/tab_tests.rs @@ -7,7 +7,8 @@ use crate::{ SessionState, }; use std::sync::{Arc, RwLock}; -use zellij_utils::pane_size::PositionAndSize; +use zellij_utils::input::layout::LayoutTemplate; +use zellij_utils::pane_size::Size; use std::os::unix::io::RawFd; @@ -73,43 +74,40 @@ impl ServerOsApi for FakeInputOutput { } } -fn create_new_tab(position_and_size: PositionAndSize) -> Tab { +fn create_new_tab(size: Size) -> Tab { let index = 0; let position = 0; let name = String::new(); let os_api = Box::new(FakeInputOutput {}); let senders = ThreadSenders::default().silently_fail_on_send(); let max_panes = None; - let first_pane_id = Some(PaneId::Terminal(1)); let mode_info = ModeInfo::default(); let colors = Palette::default(); let session_state = Arc::new(RwLock::new(SessionState::Attached)); - Tab::new( + let mut tab = Tab::new( index, position, name, - &position_and_size, + size, os_api, senders, max_panes, - first_pane_id, mode_info, colors, session_state, true, // draw pane frames - ) + ); + tab.apply_layout(LayoutTemplate::default().into(), vec![1], index); + tab } #[test] fn split_panes_vertically() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.vertical_split(new_pane_id); assert_eq!(tab.panes.len(), 2, "The tab has two panes"); @@ -136,7 +134,8 @@ fn split_panes_vertically() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "first pane column count" ); @@ -145,7 +144,8 @@ fn split_panes_vertically() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "first pane row count" ); @@ -172,7 +172,8 @@ fn split_panes_vertically() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "second pane column count" ); @@ -181,7 +182,8 @@ fn split_panes_vertically() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "second pane row count" ); @@ -189,14 +191,11 @@ fn split_panes_vertically() { #[test] fn split_panes_horizontally() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.horizontal_split(new_pane_id); assert_eq!(tab.panes.len(), 2, "The tab has two panes"); @@ -224,7 +223,8 @@ fn split_panes_horizontally() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "first pane column count" ); @@ -233,7 +233,8 @@ fn split_panes_horizontally() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "first pane row count" ); @@ -261,7 +262,8 @@ fn split_panes_horizontally() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "second pane column count" ); @@ -270,7 +272,8 @@ fn split_panes_horizontally() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "second pane row count" ); @@ -278,14 +281,11 @@ fn split_panes_horizontally() { #[test] fn split_largest_pane() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); for i in 2..5 { let new_pane_id = PaneId::Terminal(i); tab.new_pane(new_pane_id); @@ -315,7 +315,8 @@ fn split_largest_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "first pane column count" ); @@ -324,7 +325,8 @@ fn split_largest_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "first pane row count" ); @@ -352,7 +354,8 @@ fn split_largest_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "second pane column count" ); @@ -361,7 +364,8 @@ fn split_largest_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "second pane row count" ); @@ -389,7 +393,8 @@ fn split_largest_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "third pane column count" ); @@ -398,7 +403,8 @@ fn split_largest_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "third pane row count" ); @@ -426,7 +432,8 @@ fn split_largest_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "fourth pane column count" ); @@ -435,7 +442,8 @@ fn split_largest_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "fourth pane row count" ); @@ -443,56 +451,35 @@ fn split_largest_pane() { #[test] pub fn cannot_split_panes_vertically_when_active_pane_is_too_small() { - let position_and_size = PositionAndSize { - cols: 8, - rows: 20, - x: 0, - y: 0, - ..Default::default() - }; - let mut tab = create_new_tab(position_and_size); + let size = Size { cols: 8, rows: 20 }; + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); assert_eq!(tab.panes.len(), 1, "Tab still has only one pane"); } #[test] pub fn cannot_split_panes_horizontally_when_active_pane_is_too_small() { - let position_and_size = PositionAndSize { - cols: 121, - rows: 4, - x: 0, - y: 0, - ..Default::default() - }; - let mut tab = create_new_tab(position_and_size); + let size = Size { cols: 121, rows: 4 }; + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); assert_eq!(tab.panes.len(), 1, "Tab still has only one pane"); } #[test] pub fn cannot_split_largest_pane_when_there_is_no_room() { - let position_and_size = PositionAndSize { - cols: 8, - rows: 4, - x: 0, - y: 0, - ..Default::default() - }; - let mut tab = create_new_tab(position_and_size); + let size = Size { cols: 8, rows: 4 }; + let mut tab = create_new_tab(size); tab.new_pane(PaneId::Terminal(2)); assert_eq!(tab.panes.len(), 1, "Tab still has only one pane"); } #[test] pub fn toggle_focused_pane_fullscreen() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); for i in 2..5 { let new_pane_id = PaneId::Terminal(i); tab.new_pane(new_pane_id); @@ -509,7 +496,7 @@ pub fn toggle_focused_pane_fullscreen() { "Pane y is on screen edge" ); assert_eq!( - tab.panes.get(&PaneId::Terminal(4)).unwrap().columns(), + tab.panes.get(&PaneId::Terminal(4)).unwrap().cols(), 121, "Pane cols match fullscreen cols" ); @@ -530,7 +517,7 @@ pub fn toggle_focused_pane_fullscreen() { "Pane y is on screen edge" ); assert_eq!( - tab.panes.get(&PaneId::Terminal(4)).unwrap().columns(), + tab.panes.get(&PaneId::Terminal(4)).unwrap().cols(), 60, "Pane cols match fullscreen cols" ); @@ -545,14 +532,11 @@ pub fn toggle_focused_pane_fullscreen() { #[test] pub fn move_focus_is_disabled_in_fullscreen() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); for i in 2..5 { let new_pane_id = PaneId::Terminal(i); tab.new_pane(new_pane_id); @@ -570,7 +554,7 @@ pub fn move_focus_is_disabled_in_fullscreen() { "Pane y is on screen edge" ); assert_eq!( - tab.panes.get(&PaneId::Terminal(4)).unwrap().columns(), + tab.panes.get(&PaneId::Terminal(4)).unwrap().cols(), 121, "Pane cols match fullscreen cols" ); @@ -592,14 +576,11 @@ pub fn close_pane_with_another_pane_above_it() { // └───────────┘ └───────────┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.horizontal_split(new_pane_id); tab.close_focused_pane(); @@ -628,7 +609,8 @@ pub fn close_pane_with_another_pane_above_it() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "remaining pane column count" ); @@ -637,7 +619,8 @@ pub fn close_pane_with_another_pane_above_it() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "remaining pane row count" ); @@ -654,14 +637,11 @@ pub fn close_pane_with_another_pane_below_it() { // └───────────┘ └───────────┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.horizontal_split(new_pane_id); tab.move_focus_up(); @@ -691,7 +671,8 @@ pub fn close_pane_with_another_pane_below_it() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "remaining pane column count" ); @@ -700,7 +681,8 @@ pub fn close_pane_with_another_pane_below_it() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "remaining pane row count" ); @@ -714,14 +696,11 @@ pub fn close_pane_with_another_pane_to_the_left() { // │xxxxx│█████│ │xxxxxxxxxx│ // └─────┴─────┘ └──────────┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.vertical_split(new_pane_id); tab.close_focused_pane(); @@ -750,7 +729,8 @@ pub fn close_pane_with_another_pane_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "remaining pane column count" ); @@ -759,7 +739,8 @@ pub fn close_pane_with_another_pane_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "remaining pane row count" ); @@ -773,14 +754,11 @@ pub fn close_pane_with_another_pane_to_the_right() { // │█████│xxxxx│ │xxxxxxxxxx│ // └─────┴─────┘ └──────────┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.vertical_split(new_pane_id); tab.move_focus_left(); @@ -810,7 +788,8 @@ pub fn close_pane_with_another_pane_to_the_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "remaining pane column count" ); @@ -819,7 +798,8 @@ pub fn close_pane_with_another_pane_to_the_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "remaining pane row count" ); @@ -835,14 +815,11 @@ pub fn close_pane_with_multiple_panes_above_it() { // │███████████│ │xxxxx│xxxxx│ // └───────────┘ └─────┴─────┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); tab.horizontal_split(new_pane_id_1); @@ -875,7 +852,8 @@ pub fn close_pane_with_multiple_panes_above_it() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "first remaining pane column count" ); @@ -884,7 +862,8 @@ pub fn close_pane_with_multiple_panes_above_it() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "first remaining pane row count" ); @@ -912,7 +891,8 @@ pub fn close_pane_with_multiple_panes_above_it() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "second remaining pane column count" ); @@ -921,7 +901,8 @@ pub fn close_pane_with_multiple_panes_above_it() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "second remaining pane row count" ); @@ -937,14 +918,11 @@ pub fn close_pane_with_multiple_panes_below_it() { // │xxxxx│xxxxx│ │xxxxx│xxxxx│ // └─────┴─────┘ └─────┴─────┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); tab.horizontal_split(new_pane_id_1); @@ -976,7 +954,8 @@ pub fn close_pane_with_multiple_panes_below_it() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "first remaining pane column count" ); @@ -985,7 +964,8 @@ pub fn close_pane_with_multiple_panes_below_it() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "first remaining pane row count" ); @@ -1013,7 +993,8 @@ pub fn close_pane_with_multiple_panes_below_it() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "second remaining pane column count" ); @@ -1022,7 +1003,8 @@ pub fn close_pane_with_multiple_panes_below_it() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "second remaining pane row count" ); @@ -1038,14 +1020,11 @@ pub fn close_pane_with_multiple_panes_to_the_left() { // │xxxxx│█████│ │xxxxxxxxxx│ // └─────┴─────┘ └──────────┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); tab.vertical_split(new_pane_id_1); @@ -1078,7 +1057,8 @@ pub fn close_pane_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "first remaining pane column count" ); @@ -1087,7 +1067,8 @@ pub fn close_pane_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "first remaining pane row count" ); @@ -1115,7 +1096,8 @@ pub fn close_pane_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "second remaining pane column count" ); @@ -1124,7 +1106,8 @@ pub fn close_pane_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "second remaining pane row count" ); @@ -1140,14 +1123,11 @@ pub fn close_pane_with_multiple_panes_to_the_right() { // │█████│xxxxx│ │xxxxxxxxxx│ // └─────┴─────┘ └──────────┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); tab.vertical_split(new_pane_id_1); @@ -1179,7 +1159,8 @@ pub fn close_pane_with_multiple_panes_to_the_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "first remaining pane column count" ); @@ -1188,7 +1169,8 @@ pub fn close_pane_with_multiple_panes_to_the_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "first remaining pane row count" ); @@ -1216,7 +1198,8 @@ pub fn close_pane_with_multiple_panes_to_the_right() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "second remaining pane column count" ); @@ -1225,7 +1208,8 @@ pub fn close_pane_with_multiple_panes_to_the_right() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "second remaining pane row count" ); @@ -1241,14 +1225,11 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { // │xxx│███████│xxx│ │xxx│xxx│xxx│xxx│ // └───┴───────┴───┘ └───┴───┴───┴───┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); @@ -1297,7 +1278,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "first remaining pane column count" ); @@ -1306,7 +1288,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "first remaining pane row count" ); @@ -1334,7 +1317,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 15, "second remaining pane column count" ); @@ -1343,7 +1327,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "second remaining pane row count" ); @@ -1371,7 +1356,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "third remaining pane column count" ); @@ -1380,7 +1366,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "third remaining pane row count" ); @@ -1408,7 +1395,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "fourth remaining pane column count" ); @@ -1417,7 +1405,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "fourth remaining pane row count" ); @@ -1445,7 +1434,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "sixths remaining pane column count" ); @@ -1454,7 +1444,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "sixths remaining pane row count" ); @@ -1482,7 +1473,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 15, "seventh remaining pane column count" ); @@ -1491,7 +1483,8 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "seventh remaining pane row count" ); @@ -1508,14 +1501,11 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { // └───┴───┴───┴───┘ └───┴───┴───┴───┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); @@ -1563,7 +1553,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "first remaining pane column count" ); @@ -1572,7 +1563,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "first remaining pane row count" ); @@ -1600,7 +1592,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "third remaining pane column count" ); @@ -1609,7 +1602,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "third remaining pane row count" ); @@ -1637,7 +1631,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "fourth remaining pane column count" ); @@ -1646,7 +1641,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "fourth remaining pane row count" ); @@ -1674,7 +1670,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 15, "second remaining pane column count" ); @@ -1683,7 +1680,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "second remaining pane row count" ); @@ -1711,7 +1709,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "sixths remaining pane column count" ); @@ -1720,7 +1719,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "sixths remaining pane row count" ); @@ -1748,7 +1748,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 15, "seventh remaining pane column count" ); @@ -1757,7 +1758,8 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "seventh remaining pane row count" ); @@ -1776,14 +1778,11 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { // └────┴──────┘ └────┴──────┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); @@ -1804,6 +1803,7 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { tab.move_focus_left(); tab.resize_right(); tab.resize_up(); + tab.resize_up(); tab.horizontal_split(new_pane_id_6); tab.move_focus_right(); tab.close_focused_pane(); @@ -1833,7 +1833,8 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "first remaining pane column count" ); @@ -1842,8 +1843,9 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 12, "first remaining pane row count" ); @@ -1862,7 +1864,7 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .unwrap() .position_and_size() .y, - 13, + 12, "third remaining pane y position" ); assert_eq!( @@ -1870,7 +1872,8 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "third remaining pane column count" ); @@ -1879,7 +1882,8 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "third remaining pane row count" ); @@ -1899,7 +1903,7 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .unwrap() .position_and_size() .y, - 23, + 22, "fourth remaining pane y position" ); assert_eq!( @@ -1907,7 +1911,8 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "fourth remaining pane column count" ); @@ -1916,8 +1921,9 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 7, + .rows + .as_usize(), + 8, "fourth remaining pane row count" ); @@ -1944,7 +1950,8 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "second remaining pane column count" ); @@ -1953,8 +1960,9 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 12, "second remaining pane row count" ); @@ -1973,7 +1981,7 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .unwrap() .position_and_size() .y, - 23, + 22, "sixths remaining pane y position" ); assert_eq!( @@ -1981,7 +1989,8 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "sixths remaining pane column count" ); @@ -1990,8 +1999,9 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, - 7, + .rows + .as_usize(), + 8, "sixths remaining pane row count" ); @@ -2010,7 +2020,7 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .unwrap() .position_and_size() .y, - 18, + 17, "seventh remaining pane y position" ); assert_eq!( @@ -2018,7 +2028,8 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "seventh remaining pane column count" ); @@ -2027,7 +2038,8 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "seventh remaining pane row count" ); @@ -2046,14 +2058,11 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { // └────┴──────┘ └────┴──────┘ // █ == pane being closed - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); @@ -2073,6 +2082,7 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { tab.move_focus_up(); tab.resize_left(); tab.resize_up(); + tab.resize_up(); tab.horizontal_split(new_pane_id_6); tab.move_focus_left(); tab.close_focused_pane(); @@ -2102,7 +2112,8 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "first remaining pane column count" ); @@ -2111,8 +2122,9 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 11, "first remaining pane row count" ); @@ -2131,7 +2143,7 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .unwrap() .position_and_size() .y, - 23, + 22, "fourth remaining pane y position" ); assert_eq!( @@ -2139,7 +2151,8 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "fourth remaining pane column count" ); @@ -2148,8 +2161,9 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 7, + .rows + .as_usize(), + 8, "fourth remaining pane row count" ); @@ -2176,7 +2190,8 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "second remaining pane column count" ); @@ -2185,8 +2200,9 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 11, "second remaining pane row count" ); @@ -2205,7 +2221,7 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .unwrap() .position_and_size() .y, - 13, + 11, "third remaining pane y position" ); assert_eq!( @@ -2213,7 +2229,8 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "third remaining pane column count" ); @@ -2222,8 +2239,9 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 5, + .rows + .as_usize(), + 6, "third remaining pane row count" ); @@ -2242,7 +2260,7 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .unwrap() .position_and_size() .y, - 23, + 22, "sixths remaining pane y position" ); assert_eq!( @@ -2250,7 +2268,8 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "sixths remaining pane column count" ); @@ -2259,8 +2278,9 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, - 7, + .rows + .as_usize(), + 8, "sixths remaining pane row count" ); @@ -2279,7 +2299,7 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .unwrap() .position_and_size() .y, - 18, + 17, "seventh remaining pane y position" ); assert_eq!( @@ -2287,7 +2307,8 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "seventh remaining pane column count" ); @@ -2296,7 +2317,8 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "seventh remaining pane row count" ); @@ -2304,14 +2326,11 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { #[test] pub fn move_focus_down() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.horizontal_split(new_pane_id); @@ -2327,14 +2346,11 @@ pub fn move_focus_down() { #[test] pub fn move_focus_down_to_the_most_recently_used_pane() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); @@ -2359,14 +2375,11 @@ pub fn move_focus_down_to_the_most_recently_used_pane() { #[test] pub fn move_focus_up() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.horizontal_split(new_pane_id); @@ -2381,14 +2394,11 @@ pub fn move_focus_up() { #[test] pub fn move_focus_up_to_the_most_recently_used_pane() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); @@ -2414,14 +2424,11 @@ pub fn move_focus_up_to_the_most_recently_used_pane() { #[test] pub fn move_focus_left() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.vertical_split(new_pane_id); @@ -2436,14 +2443,11 @@ pub fn move_focus_left() { #[test] pub fn move_focus_left_to_the_most_recently_used_pane() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); @@ -2469,14 +2473,11 @@ pub fn move_focus_left_to_the_most_recently_used_pane() { #[test] pub fn move_focus_right() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.vertical_split(new_pane_id); @@ -2492,14 +2493,11 @@ pub fn move_focus_right() { #[test] pub fn move_focus_right_to_the_most_recently_used_pane() { - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); @@ -2533,14 +2531,11 @@ pub fn resize_down_with_pane_above() { // │███████████│ │███████████│ // └───────────┘ └───────────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.horizontal_split(new_pane_id); tab.resize_down(); @@ -2552,7 +2547,7 @@ pub fn resize_down_with_pane_above() { ); assert_eq!( tab.panes.get(&new_pane_id).unwrap().position_and_size().y, - 12, + 11, "focused pane y position" ); assert_eq!( @@ -2560,7 +2555,8 @@ pub fn resize_down_with_pane_above() { .get(&new_pane_id) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "focused pane column count" ); @@ -2569,8 +2565,9 @@ pub fn resize_down_with_pane_above() { .get(&new_pane_id) .unwrap() .position_and_size() - .rows, - 8, + .rows + .as_usize(), + 9, "focused pane row count" ); @@ -2597,7 +2594,8 @@ pub fn resize_down_with_pane_above() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane above column count" ); @@ -2606,8 +2604,9 @@ pub fn resize_down_with_pane_above() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 12, + .rows + .as_usize(), + 11, "pane above row count" ); } @@ -2622,14 +2621,11 @@ pub fn resize_down_with_pane_below() { // │ │ │ │ // └───────────┘ └───────────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let new_pane_id = PaneId::Terminal(2); tab.horizontal_split(new_pane_id); tab.move_focus_up(); @@ -2642,7 +2638,7 @@ pub fn resize_down_with_pane_below() { ); assert_eq!( tab.panes.get(&new_pane_id).unwrap().position_and_size().y, - 12, + 11, "pane below y position" ); assert_eq!( @@ -2650,7 +2646,8 @@ pub fn resize_down_with_pane_below() { .get(&new_pane_id) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane below column count" ); @@ -2659,8 +2656,9 @@ pub fn resize_down_with_pane_below() { .get(&new_pane_id) .unwrap() .position_and_size() - .rows, - 8, + .rows + .as_usize(), + 9, "pane below row count" ); @@ -2687,7 +2685,8 @@ pub fn resize_down_with_pane_below() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "focused pane column count" ); @@ -2696,8 +2695,9 @@ pub fn resize_down_with_pane_below() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 12, + .rows + .as_usize(), + 11, "focused pane row count" ); } @@ -2716,14 +2716,11 @@ pub fn resize_down_with_panes_above_and_below() { // │ │ │ │ // └───────────┘ └───────────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let first_pane_id = PaneId::Terminal(1); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); @@ -2747,7 +2744,8 @@ pub fn resize_down_with_panes_above_and_below() { .get(&new_pane_id_1) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "focused pane column count" ); @@ -2756,8 +2754,9 @@ pub fn resize_down_with_panes_above_and_below() { .get(&new_pane_id_1) .unwrap() .position_and_size() - .rows, - 10, + .rows + .as_usize(), + 9, "focused pane row count" ); @@ -2768,7 +2767,7 @@ pub fn resize_down_with_panes_above_and_below() { ); assert_eq!( tab.panes.get(&new_pane_id_2).unwrap().position_and_size().y, - 25, + 24, "pane below y position" ); assert_eq!( @@ -2776,7 +2775,8 @@ pub fn resize_down_with_panes_above_and_below() { .get(&new_pane_id_2) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane below column count" ); @@ -2785,8 +2785,9 @@ pub fn resize_down_with_panes_above_and_below() { .get(&new_pane_id_2) .unwrap() .position_and_size() - .rows, - 5, + .rows + .as_usize(), + 6, "pane below row count" ); @@ -2805,7 +2806,8 @@ pub fn resize_down_with_panes_above_and_below() { .get(&first_pane_id) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane above column count" ); @@ -2814,7 +2816,8 @@ pub fn resize_down_with_panes_above_and_below() { .get(&first_pane_id) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane above row count" ); @@ -2830,14 +2833,11 @@ pub fn resize_down_with_multiple_panes_above() { // │███████████│ │███████████│ // └───────────┘ └───────────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let first_pane_id = PaneId::Terminal(1); let new_pane_id_1 = PaneId::Terminal(2); let new_pane_id_2 = PaneId::Terminal(3); @@ -2854,7 +2854,7 @@ pub fn resize_down_with_multiple_panes_above() { ); assert_eq!( tab.panes.get(&new_pane_id_1).unwrap().position_and_size().y, - 17, + 16, "focused pane y position" ); assert_eq!( @@ -2862,7 +2862,8 @@ pub fn resize_down_with_multiple_panes_above() { .get(&new_pane_id_1) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "focused pane column count" ); @@ -2871,8 +2872,9 @@ pub fn resize_down_with_multiple_panes_above() { .get(&new_pane_id_1) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "focused pane row count" ); @@ -2891,7 +2893,8 @@ pub fn resize_down_with_multiple_panes_above() { .get(&new_pane_id_2) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "first pane above column count" ); @@ -2900,8 +2903,9 @@ pub fn resize_down_with_multiple_panes_above() { .get(&new_pane_id_2) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "first pane above row count" ); @@ -2920,7 +2924,8 @@ pub fn resize_down_with_multiple_panes_above() { .get(&first_pane_id) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "second pane above column count" ); @@ -2929,8 +2934,9 @@ pub fn resize_down_with_multiple_panes_above() { .get(&first_pane_id) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "second pane above row count" ); } @@ -2945,14 +2951,11 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { // │ │█████│ │ │█████│ // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let pane_above_and_left = PaneId::Terminal(1); let pane_to_the_left = PaneId::Terminal(2); let focused_pane = PaneId::Terminal(3); @@ -2971,7 +2974,7 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { ); assert_eq!( tab.panes.get(&focused_pane).unwrap().position_and_size().y, - 17, + 16, "focused pane y position" ); assert_eq!( @@ -2979,7 +2982,8 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { .get(&focused_pane) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "focused pane column count" ); @@ -2988,8 +2992,9 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { .get(&focused_pane) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "focused pane row count" ); @@ -3016,7 +3021,8 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { .get(&pane_above_and_left) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane above and to the left column count" ); @@ -3025,7 +3031,8 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { .get(&pane_above_and_left) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane above and to the left row count" ); @@ -3041,13 +3048,23 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { "pane above y position" ); assert_eq!( - tab.panes.get(&pane_above).unwrap().position_and_size().cols, + tab.panes + .get(&pane_above) + .unwrap() + .position_and_size() + .cols + .as_usize(), 60, "pane above column count" ); assert_eq!( - tab.panes.get(&pane_above).unwrap().position_and_size().rows, - 17, + tab.panes + .get(&pane_above) + .unwrap() + .position_and_size() + .rows + .as_usize(), + 16, "pane above row count" ); @@ -3074,7 +3091,8 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { .get(&pane_to_the_left) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane to the left column count" ); @@ -3083,7 +3101,8 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { .get(&pane_to_the_left) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane to the left row count" ); @@ -3100,14 +3119,11 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let pane_to_the_left = PaneId::Terminal(1); let pane_below_and_left = PaneId::Terminal(2); let pane_below = PaneId::Terminal(3); @@ -3133,7 +3149,8 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { .get(&focused_pane) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "focused pane column count" ); @@ -3142,8 +3159,9 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { .get(&focused_pane) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "focused pane row count" ); @@ -3170,7 +3188,8 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { .get(&pane_to_the_left) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane above and to the left column count" ); @@ -3179,7 +3198,8 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { .get(&pane_to_the_left) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane above and to the left row count" ); @@ -3191,17 +3211,27 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { ); assert_eq!( tab.panes.get(&pane_below).unwrap().position_and_size().y, - 17, + 16, "pane above y position" ); assert_eq!( - tab.panes.get(&pane_below).unwrap().position_and_size().cols, + tab.panes + .get(&pane_below) + .unwrap() + .position_and_size() + .cols + .as_usize(), 60, "pane above column count" ); assert_eq!( - tab.panes.get(&pane_below).unwrap().position_and_size().rows, - 13, + tab.panes + .get(&pane_below) + .unwrap() + .position_and_size() + .rows + .as_usize(), + 14, "pane above row count" ); @@ -3228,7 +3258,8 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { .get(&pane_below_and_left) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane to the left column count" ); @@ -3237,7 +3268,8 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { .get(&pane_below_and_left) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane to the left row count" ); @@ -3254,14 +3286,11 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let pane_above = PaneId::Terminal(1); let focused_pane = PaneId::Terminal(2); let pane_to_the_right = PaneId::Terminal(3); @@ -3281,7 +3310,7 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { ); assert_eq!( tab.panes.get(&focused_pane).unwrap().position_and_size().y, - 17, + 16, "focused pane y position" ); assert_eq!( @@ -3289,7 +3318,8 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { .get(&focused_pane) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "focused pane column count" ); @@ -3298,8 +3328,9 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { .get(&focused_pane) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "focused pane row count" ); @@ -3314,13 +3345,23 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { "pane above y position" ); assert_eq!( - tab.panes.get(&pane_above).unwrap().position_and_size().cols, + tab.panes + .get(&pane_above) + .unwrap() + .position_and_size() + .cols + .as_usize(), 61, "pane above column count" ); assert_eq!( - tab.panes.get(&pane_above).unwrap().position_and_size().rows, - 17, + tab.panes + .get(&pane_above) + .unwrap() + .position_and_size() + .rows + .as_usize(), + 16, "pane above row count" ); @@ -3347,7 +3388,8 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { .get(&pane_to_the_right) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane to the right column count" ); @@ -3356,7 +3398,8 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { .get(&pane_to_the_right) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane to the right row count" ); @@ -3384,7 +3427,8 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { .get(&pane_above_and_right) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane above and to the right column count" ); @@ -3393,7 +3437,8 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { .get(&pane_above_and_right) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane above and to the right row count" ); @@ -3410,14 +3455,11 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); let focused_pane = PaneId::Terminal(1); let pane_below = PaneId::Terminal(2); let pane_below_and_right = PaneId::Terminal(3); @@ -3444,7 +3486,8 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { .get(&focused_pane) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "focused pane column count" ); @@ -3453,8 +3496,9 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { .get(&focused_pane) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "focused pane row count" ); @@ -3465,17 +3509,27 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { ); assert_eq!( tab.panes.get(&pane_below).unwrap().position_and_size().y, - 17, + 16, "pane below y position" ); assert_eq!( - tab.panes.get(&pane_below).unwrap().position_and_size().cols, + tab.panes + .get(&pane_below) + .unwrap() + .position_and_size() + .cols + .as_usize(), 61, "pane below column count" ); assert_eq!( - tab.panes.get(&pane_below).unwrap().position_and_size().rows, - 13, + tab.panes + .get(&pane_below) + .unwrap() + .position_and_size() + .rows + .as_usize(), + 14, "pane below row count" ); @@ -3502,7 +3556,8 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { .get(&pane_below_and_right) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane below and to the right column count" ); @@ -3511,7 +3566,8 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { .get(&pane_below_and_right) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane below and to the right row count" ); @@ -3539,7 +3595,8 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { .get(&pane_to_the_right) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane to the right column count" ); @@ -3548,7 +3605,8 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { .get(&pane_to_the_right) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane to the right row count" ); @@ -3565,14 +3623,11 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { // └───┴───┴───┘ └───┴───┴───┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.vertical_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -3606,7 +3661,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -3615,7 +3671,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -3643,7 +3700,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 2 column count" ); @@ -3652,7 +3710,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -3672,7 +3731,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .unwrap() .position_and_size() .y, - 17, + 16, "pane 3 y position" ); assert_eq!( @@ -3680,7 +3739,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 3 column count" ); @@ -3689,8 +3749,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 3 row count" ); @@ -3717,7 +3778,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 4 column count" ); @@ -3726,7 +3788,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -3754,7 +3817,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 5 column count" ); @@ -3763,8 +3827,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 5 row count" ); @@ -3791,7 +3856,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 6 column count" ); @@ -3800,7 +3866,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 6 row count" ); @@ -3817,14 +3884,11 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { // └───┴───┴───┘ └───┴───┴───┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.vertical_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -3857,7 +3921,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -3866,7 +3931,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -3894,7 +3960,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 2 column count" ); @@ -3903,7 +3970,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -3923,7 +3991,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .unwrap() .position_and_size() .y, - 17, + 16, "pane 3 y position" ); assert_eq!( @@ -3931,7 +3999,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 3 column count" ); @@ -3940,8 +4009,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 3 row count" ); @@ -3968,7 +4038,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 4 column count" ); @@ -3977,7 +4048,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -4005,7 +4077,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 5 column count" ); @@ -4014,8 +4087,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 5 row count" ); @@ -4042,7 +4116,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 6 column count" ); @@ -4051,7 +4126,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 6 row count" ); @@ -4068,14 +4144,11 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef // └─┴─┴───┴─┴─┘ └─┴─┴───┴─┴─┘ // █ == focused pane - let position_and_size = PositionAndSize { - cols: 121, + let size = Size { + cols: 122, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.vertical_split(PaneId::Terminal(3)); @@ -4112,8 +4185,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 61, + .cols + .as_usize(), + 60, "pane 1 column count" ); assert_eq!( @@ -4121,7 +4195,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -4149,8 +4224,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 61, + .cols + .as_usize(), + 60, "pane 2 column count" ); assert_eq!( @@ -4158,7 +4234,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -4169,7 +4246,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .unwrap() .position_and_size() .x, - 61, + 60, "pane 3 x position" ); assert_eq!( @@ -4186,8 +4263,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 3 column count" ); assert_eq!( @@ -4195,8 +4273,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 3 row count" ); @@ -4223,8 +4302,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 4 column count" ); assert_eq!( @@ -4232,7 +4312,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -4243,7 +4324,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .unwrap() .position_and_size() .x, - 61, + 60, "pane 5 x position" ); assert_eq!( @@ -4252,7 +4333,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .unwrap() .position_and_size() .y, - 17, + 16, "pane 5 y position" ); assert_eq!( @@ -4260,7 +4341,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 15, "pane 5 column count" ); @@ -4269,8 +4351,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 5 row count" ); @@ -4297,8 +4380,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 6 column count" ); assert_eq!( @@ -4306,7 +4390,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 6 row count" ); @@ -4317,7 +4402,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .unwrap() .position_and_size() .x, - 76, + 75, "pane 7 x position" ); assert_eq!( @@ -4326,7 +4411,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .unwrap() .position_and_size() .y, - 17, + 16, "pane 7 y position" ); assert_eq!( @@ -4334,7 +4419,8 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 8, "pane 7 column count" ); @@ -4343,8 +4429,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 7 row count" ); @@ -4354,7 +4441,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .unwrap() .position_and_size() .x, - 84, + 83, "pane 8 x position" ); assert_eq!( @@ -4363,7 +4450,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .unwrap() .position_and_size() .y, - 17, + 16, "pane 8 y position" ); assert_eq!( @@ -4371,8 +4458,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .cols, - 7, + .cols + .as_usize(), + 8, "pane 8 column count" ); assert_eq!( @@ -4380,8 +4468,9 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 8 row count" ); } @@ -4397,14 +4486,11 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ // └─┴───────┴─┘ └─┴───────┴─┘ // █ == focused pane - let position_and_size = PositionAndSize { - cols: 121, + let size = Size { + cols: 122, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.vertical_split(PaneId::Terminal(3)); @@ -4443,8 +4529,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 61, + .cols + .as_usize(), + 60, "pane 1 column count" ); assert_eq!( @@ -4452,7 +4539,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -4480,8 +4568,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 61, + .cols + .as_usize(), + 60, "pane 2 column count" ); assert_eq!( @@ -4489,7 +4578,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -4500,7 +4590,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .unwrap() .position_and_size() .x, - 61, + 60, "pane 3 x position" ); assert_eq!( @@ -4517,7 +4607,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 15, "pane 3 column count" ); @@ -4526,8 +4617,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 3 row count" ); @@ -4554,8 +4646,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 4 column count" ); assert_eq!( @@ -4563,7 +4656,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -4574,7 +4668,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .unwrap() .position_and_size() .x, - 76, + 75, "pane 5 x position" ); assert_eq!( @@ -4591,7 +4685,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 8, "pane 5 column count" ); @@ -4600,8 +4695,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 5 row count" ); @@ -4611,7 +4707,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .unwrap() .position_and_size() .x, - 84, + 83, "pane 6 x position" ); assert_eq!( @@ -4628,8 +4724,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, - 7, + .cols + .as_usize(), + 8, "pane 6 column count" ); assert_eq!( @@ -4637,8 +4734,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 6 row count" ); @@ -4648,7 +4746,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .unwrap() .position_and_size() .x, - 61, + 60, "pane 7 x position" ); assert_eq!( @@ -4657,7 +4755,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .unwrap() .position_and_size() .y, - 17, + 16, "pane 7 y position" ); assert_eq!( @@ -4665,8 +4763,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 7 column count" ); assert_eq!( @@ -4674,8 +4773,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 7 row count" ); @@ -4702,8 +4802,9 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 8 column count" ); assert_eq!( @@ -4711,7 +4812,8 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 8 row count" ); @@ -4726,14 +4828,11 @@ pub fn cannot_resize_down_when_pane_below_is_at_minimum_height() { // └───────────┘ └───────────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 10, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.resize_down(); @@ -4743,7 +4842,8 @@ pub fn cannot_resize_down_when_pane_below_is_at_minimum_height() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 1 height stayed the same" ); @@ -4752,7 +4852,8 @@ pub fn cannot_resize_down_when_pane_below_is_at_minimum_height() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 2 height stayed the same" ); @@ -4767,14 +4868,11 @@ pub fn resize_left_with_pane_to_the_left() { // └─────┴─────┘ └───┴───────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.resize_left(); @@ -4801,8 +4899,9 @@ pub fn resize_left_with_pane_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 1 column count" ); assert_eq!( @@ -4810,7 +4909,8 @@ pub fn resize_left_with_pane_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 1 row count" ); @@ -4821,7 +4921,7 @@ pub fn resize_left_with_pane_to_the_left() { .unwrap() .position_and_size() .x, - 51, + 54, "pane 2 x position" ); assert_eq!( @@ -4838,8 +4938,9 @@ pub fn resize_left_with_pane_to_the_left() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 2 column count" ); assert_eq!( @@ -4847,7 +4948,8 @@ pub fn resize_left_with_pane_to_the_left() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 2 row count" ); @@ -4861,14 +4963,11 @@ pub fn resize_left_with_pane_to_the_right() { // │█████│ │ │███│ │ // └─────┴─────┘ └───┴───────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.move_focus_left(); tab.resize_left(); @@ -4896,8 +4995,9 @@ pub fn resize_left_with_pane_to_the_right() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 1 column count" ); assert_eq!( @@ -4905,7 +5005,8 @@ pub fn resize_left_with_pane_to_the_right() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 1 row count" ); @@ -4916,7 +5017,7 @@ pub fn resize_left_with_pane_to_the_right() { .unwrap() .position_and_size() .x, - 51, + 54, "pane 2 x position" ); assert_eq!( @@ -4933,8 +5034,9 @@ pub fn resize_left_with_pane_to_the_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 2 column count" ); assert_eq!( @@ -4942,7 +5044,8 @@ pub fn resize_left_with_pane_to_the_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 2 row count" ); @@ -4957,14 +5060,11 @@ pub fn resize_left_with_panes_to_the_left_and_right() { // └─────┴─────┴─────┘ └─────┴───┴───────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.vertical_split(PaneId::Terminal(3)); tab.move_focus_left(); @@ -4993,8 +5093,9 @@ pub fn resize_left_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 1 column count" ); assert_eq!( @@ -5002,7 +5103,8 @@ pub fn resize_left_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 1 row count" ); @@ -5013,7 +5115,7 @@ pub fn resize_left_with_panes_to_the_left_and_right() { .unwrap() .position_and_size() .x, - 51, + 54, "pane 2 x position" ); assert_eq!( @@ -5030,8 +5132,9 @@ pub fn resize_left_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 40, + .cols + .as_usize(), + 36, "pane 2 column count" ); assert_eq!( @@ -5039,7 +5142,8 @@ pub fn resize_left_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 2 row count" ); @@ -5050,7 +5154,7 @@ pub fn resize_left_with_panes_to_the_left_and_right() { .unwrap() .position_and_size() .x, - 91, + 90, "pane 2 x position" ); assert_eq!( @@ -5067,8 +5171,9 @@ pub fn resize_left_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 2 column count" ); assert_eq!( @@ -5076,7 +5181,8 @@ pub fn resize_left_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 2 row count" ); @@ -5090,14 +5196,11 @@ pub fn resize_left_with_multiple_panes_to_the_left() { // │ │█████│ │ │███████│ // └─────┴─────┘ └───┴───────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.move_focus_left(); tab.horizontal_split(PaneId::Terminal(3)); @@ -5127,8 +5230,9 @@ pub fn resize_left_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 1 column count" ); assert_eq!( @@ -5136,7 +5240,8 @@ pub fn resize_left_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 1 row count" ); @@ -5147,7 +5252,7 @@ pub fn resize_left_with_multiple_panes_to_the_left() { .unwrap() .position_and_size() .x, - 51, + 54, "pane 2 x position" ); assert_eq!( @@ -5164,8 +5269,9 @@ pub fn resize_left_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 2 column count" ); assert_eq!( @@ -5173,7 +5279,8 @@ pub fn resize_left_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 2 row count" ); @@ -5201,8 +5308,9 @@ pub fn resize_left_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -5210,7 +5318,8 @@ pub fn resize_left_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 2 row count" ); @@ -5225,14 +5334,11 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { // └─────┴─────┘ └───┴───────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.vertical_split(PaneId::Terminal(3)); tab.move_focus_up(); @@ -5263,7 +5369,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -5272,7 +5379,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -5300,8 +5408,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -5309,7 +5418,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -5320,7 +5430,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { .unwrap() .position_and_size() .x, - 51, + 54, "pane 3 x position" ); assert_eq!( @@ -5337,8 +5447,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 3 column count" ); assert_eq!( @@ -5346,7 +5457,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 3 row count" ); @@ -5374,7 +5486,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -5383,7 +5496,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -5398,14 +5512,11 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { // └─────┴─────┘ └───┴───────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.vertical_split(PaneId::Terminal(3)); tab.move_focus_up(); @@ -5437,7 +5548,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -5446,7 +5558,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -5474,8 +5587,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -5483,7 +5597,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -5494,7 +5609,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { .unwrap() .position_and_size() .x, - 51, + 54, "pane 3 x position" ); assert_eq!( @@ -5511,8 +5626,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 3 column count" ); assert_eq!( @@ -5520,7 +5636,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 3 row count" ); @@ -5548,7 +5665,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -5557,7 +5675,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -5572,14 +5691,11 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.vertical_split(PaneId::Terminal(3)); tab.move_focus_up(); @@ -5609,8 +5725,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 1 column count" ); assert_eq!( @@ -5618,7 +5735,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -5646,7 +5764,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 2 column count" ); @@ -5655,7 +5774,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -5683,7 +5803,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 3 column count" ); @@ -5692,7 +5813,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 3 row count" ); @@ -5703,7 +5825,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { .unwrap() .position_and_size() .x, - 51, + 54, "pane 4 x position" ); assert_eq!( @@ -5720,8 +5842,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 4 column count" ); assert_eq!( @@ -5729,7 +5852,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -5744,14 +5868,11 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.vertical_split(PaneId::Terminal(3)); tab.move_focus_up(); @@ -5782,8 +5903,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 1 column count" ); assert_eq!( @@ -5791,7 +5913,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -5819,7 +5942,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 2 column count" ); @@ -5828,7 +5952,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -5856,7 +5981,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 3 column count" ); @@ -5865,7 +5991,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 3 row count" ); @@ -5876,7 +6003,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { .unwrap() .position_and_size() .x, - 51, + 54, "pane 4 x position" ); assert_eq!( @@ -5893,8 +6020,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 4 column count" ); assert_eq!( @@ -5902,7 +6030,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -5919,14 +6048,11 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.horizontal_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -5960,7 +6086,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -5969,8 +6096,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 15, + .rows + .as_usize(), + 14, "pane 1 row count" ); @@ -5989,7 +6117,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .unwrap() .position_and_size() .y, - 15, + 14, "pane 2 y position" ); assert_eq!( @@ -5997,8 +6125,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -6006,7 +6135,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 8, "pane 2 row count" ); @@ -6026,7 +6156,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .unwrap() .position_and_size() .y, - 23, + 22, "pane 3 y position" ); assert_eq!( @@ -6034,7 +6164,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 3 column count" ); @@ -6043,8 +6174,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 7, + .rows + .as_usize(), + 8, "pane 3 row count" ); @@ -6063,7 +6195,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .unwrap() .position_and_size() .y, - 23, + 22, "pane 4 y position" ); assert_eq!( @@ -6071,7 +6203,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -6080,8 +6213,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, - 7, + .rows + .as_usize(), + 8, "pane 4 row count" ); @@ -6091,7 +6225,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .unwrap() .position_and_size() .x, - 51, + 54, "pane 5 x position" ); assert_eq!( @@ -6100,7 +6234,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .unwrap() .position_and_size() .y, - 15, + 14, "pane 5 y position" ); assert_eq!( @@ -6108,8 +6242,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 5 column count" ); assert_eq!( @@ -6117,7 +6252,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 8, "pane 5 row count" ); @@ -6145,7 +6281,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 6 column count" ); @@ -6154,8 +6291,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, - 15, + .rows + .as_usize(), + 14, "pane 6 row count" ); } @@ -6171,14 +6309,11 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.horizontal_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -6213,7 +6348,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -6222,8 +6358,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 15, + .rows + .as_usize(), + 14, "pane 1 row count" ); @@ -6242,7 +6379,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .unwrap() .position_and_size() .y, - 15, + 14, "pane 2 y position" ); assert_eq!( @@ -6250,8 +6387,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -6259,7 +6397,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 8, "pane 2 row count" ); @@ -6279,7 +6418,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .unwrap() .position_and_size() .y, - 23, + 22, "pane 3 y position" ); assert_eq!( @@ -6287,7 +6426,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 3 column count" ); @@ -6296,8 +6436,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 7, + .rows + .as_usize(), + 8, "pane 3 row count" ); @@ -6316,7 +6457,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .unwrap() .position_and_size() .y, - 23, + 22, "pane 4 y position" ); assert_eq!( @@ -6324,7 +6465,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -6333,8 +6475,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, - 7, + .rows + .as_usize(), + 8, "pane 4 row count" ); @@ -6344,7 +6487,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .unwrap() .position_and_size() .x, - 51, + 54, "pane 5 x position" ); assert_eq!( @@ -6353,7 +6496,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .unwrap() .position_and_size() .y, - 15, + 14, "pane 5 y position" ); assert_eq!( @@ -6361,8 +6504,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 5 column count" ); assert_eq!( @@ -6370,7 +6514,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 8, "pane 5 row count" ); @@ -6398,7 +6543,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 6 column count" ); @@ -6407,8 +6553,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, - 15, + .rows + .as_usize(), + 14, "pane 6 row count" ); } @@ -6424,14 +6571,11 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 70, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.horizontal_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -6469,7 +6613,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -6478,7 +6623,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 35, "pane 1 row count" ); @@ -6506,8 +6652,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -6515,8 +6662,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, - 20, + .rows + .as_usize(), + 21, "pane 2 row count" ); @@ -6535,7 +6683,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .unwrap() .position_and_size() .y, - 55, + 56, "pane 3 y position" ); assert_eq!( @@ -6543,7 +6691,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 3 column count" ); @@ -6552,8 +6701,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 15, + .rows + .as_usize(), + 14, "pane 3 row count" ); @@ -6572,7 +6722,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .unwrap() .position_and_size() .y, - 55, + 56, "pane 4 y position" ); assert_eq!( @@ -6580,7 +6730,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -6589,8 +6740,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, - 15, + .rows + .as_usize(), + 14, "pane 4 row count" ); @@ -6617,7 +6769,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 5 column count" ); @@ -6626,7 +6779,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 35, "pane 5 row count" ); @@ -6637,7 +6791,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .unwrap() .position_and_size() .x, - 51, + 54, "pane 6 x position" ); assert_eq!( @@ -6654,8 +6808,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 6 column count" ); assert_eq!( @@ -6663,8 +6818,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, - 10, + .rows + .as_usize(), + 11, "pane 6 row count" ); @@ -6674,7 +6830,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .unwrap() .position_and_size() .x, - 51, + 54, "pane 7 x position" ); assert_eq!( @@ -6683,7 +6839,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .unwrap() .position_and_size() .y, - 45, + 46, "pane 7 y position" ); assert_eq!( @@ -6691,8 +6847,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 7 column count" ); assert_eq!( @@ -6700,7 +6857,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 7 row count" ); @@ -6711,7 +6869,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .unwrap() .position_and_size() .x, - 51, + 54, "pane 8 x position" ); assert_eq!( @@ -6720,7 +6878,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .unwrap() .position_and_size() .y, - 50, + 51, "pane 8 y position" ); assert_eq!( @@ -6728,8 +6886,9 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 8 column count" ); assert_eq!( @@ -6737,7 +6896,8 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 8 row count" ); @@ -6754,14 +6914,11 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 70, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.horizontal_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -6800,7 +6957,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -6809,7 +6967,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 35, "pane 1 row count" ); @@ -6837,8 +6996,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -6846,8 +7006,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, - 10, + .rows + .as_usize(), + 11, "pane 2 row count" ); @@ -6866,7 +7027,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .y, - 55, + 56, "pane 3 y position" ); assert_eq!( @@ -6874,7 +7035,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 3 column count" ); @@ -6883,8 +7045,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 15, + .rows + .as_usize(), + 14, "pane 3 row count" ); @@ -6903,7 +7066,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .y, - 55, + 56, "pane 4 y position" ); assert_eq!( @@ -6911,7 +7074,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -6920,8 +7084,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, - 15, + .rows + .as_usize(), + 14, "pane 4 row count" ); @@ -6948,7 +7113,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 5 column count" ); @@ -6957,7 +7123,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 35, "pane 5 row count" ); @@ -6968,7 +7135,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .x, - 51, + 54, "pane 6 x position" ); assert_eq!( @@ -6985,8 +7152,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, - 70, + .cols + .as_usize(), + 67, "pane 6 column count" ); assert_eq!( @@ -6994,8 +7162,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, - 20, + .rows + .as_usize(), + 21, "pane 6 row count" ); @@ -7014,7 +7183,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .y, - 45, + 46, "pane 7 y position" ); assert_eq!( @@ -7022,8 +7191,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 7 column count" ); assert_eq!( @@ -7031,7 +7201,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 7 row count" ); @@ -7051,7 +7222,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .y, - 50, + 51, "pane 8 y position" ); assert_eq!( @@ -7059,8 +7230,9 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .cols, - 51, + .cols + .as_usize(), + 54, "pane 8 column count" ); assert_eq!( @@ -7068,7 +7240,8 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 8 row count" ); @@ -7083,14 +7256,8 @@ pub fn cannot_resize_left_when_pane_to_the_left_is_at_minimum_width() { // └─┴─┘ └─┴─┘ // █ == focused pane - let position_and_size = PositionAndSize { - cols: 10, - rows: 20, - x: 0, - y: 0, - ..Default::default() - }; - let mut tab = create_new_tab(position_and_size); + let size = Size { cols: 10, rows: 20 }; + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.resize_left(); @@ -7099,7 +7266,8 @@ pub fn cannot_resize_left_when_pane_to_the_left_is_at_minimum_width() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 5, "pane 1 columns stayed the same" ); @@ -7108,7 +7276,8 @@ pub fn cannot_resize_left_when_pane_to_the_left_is_at_minimum_width() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 5, "pane 2 columns stayed the same" ); @@ -7123,14 +7292,11 @@ pub fn resize_right_with_pane_to_the_left() { // └─────┴─────┘ └───────┴───┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.resize_right(); @@ -7157,8 +7323,9 @@ pub fn resize_right_with_pane_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 1 column count" ); assert_eq!( @@ -7166,7 +7333,8 @@ pub fn resize_right_with_pane_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 1 row count" ); @@ -7177,7 +7345,7 @@ pub fn resize_right_with_pane_to_the_left() { .unwrap() .position_and_size() .x, - 71, + 67, "pane 2 x position" ); assert_eq!( @@ -7194,8 +7362,9 @@ pub fn resize_right_with_pane_to_the_left() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -7203,7 +7372,8 @@ pub fn resize_right_with_pane_to_the_left() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 2 row count" ); @@ -7218,14 +7388,11 @@ pub fn resize_right_with_pane_to_the_right() { // └─────┴─────┘ └───────┴───┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.move_focus_left(); tab.resize_right(); @@ -7253,8 +7420,9 @@ pub fn resize_right_with_pane_to_the_right() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 1 column count" ); assert_eq!( @@ -7262,7 +7430,8 @@ pub fn resize_right_with_pane_to_the_right() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 1 row count" ); @@ -7273,7 +7442,7 @@ pub fn resize_right_with_pane_to_the_right() { .unwrap() .position_and_size() .x, - 71, + 67, "pane 2 x position" ); assert_eq!( @@ -7290,8 +7459,9 @@ pub fn resize_right_with_pane_to_the_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -7299,7 +7469,8 @@ pub fn resize_right_with_pane_to_the_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 2 row count" ); @@ -7314,14 +7485,11 @@ pub fn resize_right_with_panes_to_the_left_and_right() { // └─────┴─────┴─────┘ └─────┴───────┴───┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.vertical_split(PaneId::Terminal(3)); tab.move_focus_left(); @@ -7350,7 +7518,8 @@ pub fn resize_right_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -7359,7 +7528,8 @@ pub fn resize_right_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 1 row count" ); @@ -7387,8 +7557,9 @@ pub fn resize_right_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 40, + .cols + .as_usize(), + 36, "pane 2 column count" ); assert_eq!( @@ -7396,7 +7567,8 @@ pub fn resize_right_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 2 row count" ); @@ -7407,7 +7579,7 @@ pub fn resize_right_with_panes_to_the_left_and_right() { .unwrap() .position_and_size() .x, - 101, + 97, "pane 2 x position" ); assert_eq!( @@ -7424,8 +7596,9 @@ pub fn resize_right_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, - 20, + .cols + .as_usize(), + 24, "pane 2 column count" ); assert_eq!( @@ -7433,7 +7606,8 @@ pub fn resize_right_with_panes_to_the_left_and_right() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 2 row count" ); @@ -7448,14 +7622,11 @@ pub fn resize_right_with_multiple_panes_to_the_left() { // └─────┴─────┘ └───────┴───┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.move_focus_left(); tab.horizontal_split(PaneId::Terminal(3)); @@ -7485,8 +7656,9 @@ pub fn resize_right_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 1 column count" ); assert_eq!( @@ -7494,7 +7666,8 @@ pub fn resize_right_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 1 row count" ); @@ -7505,7 +7678,7 @@ pub fn resize_right_with_multiple_panes_to_the_left() { .unwrap() .position_and_size() .x, - 71, + 67, "pane 2 x position" ); assert_eq!( @@ -7522,8 +7695,9 @@ pub fn resize_right_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -7531,7 +7705,8 @@ pub fn resize_right_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 20, "pane 2 row count" ); @@ -7559,8 +7734,9 @@ pub fn resize_right_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 3 column count" ); assert_eq!( @@ -7568,7 +7744,8 @@ pub fn resize_right_with_multiple_panes_to_the_left() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 3 row count" ); @@ -7583,14 +7760,11 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { // └─────┴─────┘ └───────┴───┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.move_focus_left(); tab.horizontal_split(PaneId::Terminal(3)); @@ -7621,7 +7795,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -7630,7 +7805,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 1 row count" ); @@ -7658,7 +7834,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 2 column count" ); @@ -7667,7 +7844,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 2 row count" ); @@ -7695,8 +7873,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 3 column count" ); assert_eq!( @@ -7704,7 +7883,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 3 row count" ); @@ -7715,7 +7895,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { .unwrap() .position_and_size() .x, - 71, + 67, "pane 4 x position" ); assert_eq!( @@ -7732,8 +7912,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 4 column count" ); assert_eq!( @@ -7741,7 +7922,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 4 row count" ); @@ -7755,14 +7937,11 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { // │█████│ │ │███████│ │ // └─────┴─────┘ └───────┴───┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.move_focus_left(); tab.horizontal_split(PaneId::Terminal(3)); @@ -7794,7 +7973,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -7803,7 +7983,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 1 row count" ); @@ -7831,7 +8012,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 2 column count" ); @@ -7840,7 +8022,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 2 row count" ); @@ -7868,8 +8051,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 3 column count" ); assert_eq!( @@ -7877,7 +8061,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 3 row count" ); @@ -7888,7 +8073,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { .unwrap() .position_and_size() .x, - 71, + 67, "pane 4 x position" ); assert_eq!( @@ -7905,8 +8090,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 4 column count" ); assert_eq!( @@ -7914,7 +8100,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 4 row count" ); @@ -7929,14 +8116,11 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.move_focus_left(); tab.horizontal_split(PaneId::Terminal(3)); @@ -7968,8 +8152,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 1 column count" ); assert_eq!( @@ -7977,7 +8162,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 1 row count" ); @@ -7988,7 +8174,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { .unwrap() .position_and_size() .x, - 71, + 67, "pane 2 x position" ); assert_eq!( @@ -8005,8 +8191,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -8014,7 +8201,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 2 row count" ); @@ -8042,7 +8230,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 3 column count" ); @@ -8051,7 +8240,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 3 row count" ); @@ -8079,7 +8269,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -8088,7 +8279,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 4 row count" ); @@ -8103,14 +8295,11 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.move_focus_left(); tab.horizontal_split(PaneId::Terminal(3)); @@ -8143,8 +8332,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 1 column count" ); assert_eq!( @@ -8152,7 +8342,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 1 row count" ); @@ -8163,7 +8354,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { .unwrap() .position_and_size() .x, - 71, + 67, "pane 2 x position" ); assert_eq!( @@ -8180,8 +8371,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 2 column count" ); assert_eq!( @@ -8189,7 +8381,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 2 row count" ); @@ -8217,7 +8410,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 3 column count" ); @@ -8226,7 +8420,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 3 row count" ); @@ -8254,7 +8449,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -8263,7 +8459,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 4 row count" ); @@ -8280,14 +8477,11 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.horizontal_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -8321,7 +8515,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -8330,7 +8525,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 1 row count" ); @@ -8358,8 +8554,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 2 column count" ); assert_eq!( @@ -8367,7 +8564,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 2 row count" ); @@ -8395,7 +8593,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 3 column count" ); @@ -8404,7 +8603,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 3 row count" ); @@ -8432,7 +8632,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -8441,7 +8642,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 4 row count" ); @@ -8452,7 +8654,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .unwrap() .position_and_size() .x, - 71, + 67, "pane 5 x position" ); assert_eq!( @@ -8469,8 +8671,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 5 column count" ); assert_eq!( @@ -8478,7 +8681,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 5 row count" ); @@ -8506,7 +8710,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 6 column count" ); @@ -8515,7 +8720,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 6 row count" ); @@ -8531,14 +8737,11 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ // │ │ │ │ │ │ // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.horizontal_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -8573,7 +8776,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -8582,7 +8786,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 1 row count" ); @@ -8610,8 +8815,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 2 column count" ); assert_eq!( @@ -8619,7 +8825,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 2 row count" ); @@ -8647,7 +8854,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 3 column count" ); @@ -8656,7 +8864,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 3 row count" ); @@ -8684,7 +8893,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -8693,7 +8903,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 4 row count" ); @@ -8704,7 +8915,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .unwrap() .position_and_size() .x, - 71, + 67, "pane 5 x position" ); assert_eq!( @@ -8721,8 +8932,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 5 column count" ); assert_eq!( @@ -8730,7 +8942,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 5 row count" ); @@ -8758,7 +8971,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 6 column count" ); @@ -8767,7 +8981,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 10, "pane 6 row count" ); @@ -8783,14 +8998,11 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo // ├─────┼─────┤ ├─────┬─┴───┤ // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 70, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.horizontal_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -8828,7 +9040,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -8837,8 +9050,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 33, + .rows + .as_usize(), + 31, "pane 1 row count" ); @@ -8857,7 +9071,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .y, - 33, + 31, "pane 2 y position" ); assert_eq!( @@ -8865,8 +9079,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 2 column count" ); assert_eq!( @@ -8874,8 +9089,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, - 20, + .rows + .as_usize(), + 21, "pane 2 row count" ); @@ -8894,7 +9110,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .y, - 53, + 52, "pane 3 y position" ); assert_eq!( @@ -8902,7 +9118,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 3 column count" ); @@ -8911,8 +9128,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 18, "pane 3 row count" ); @@ -8931,7 +9149,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .y, - 53, + 52, "pane 4 y position" ); assert_eq!( @@ -8939,7 +9157,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -8948,8 +9167,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 18, "pane 4 row count" ); @@ -8976,7 +9196,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 5 column count" ); @@ -8985,8 +9206,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 33, + .rows + .as_usize(), + 31, "pane 5 row count" ); @@ -8996,7 +9218,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .x, - 71, + 67, "pane 6 x position" ); assert_eq!( @@ -9005,7 +9227,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .y, - 33, + 31, "pane 6 y position" ); assert_eq!( @@ -9013,8 +9235,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 6 column count" ); assert_eq!( @@ -9022,8 +9245,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, - 10, + .rows + .as_usize(), + 11, "pane 6 row count" ); @@ -9033,7 +9257,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .x, - 71, + 67, "pane 7 x position" ); assert_eq!( @@ -9042,7 +9266,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .y, - 43, + 42, "pane 7 y position" ); assert_eq!( @@ -9050,8 +9274,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 7 column count" ); assert_eq!( @@ -9059,7 +9284,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 7 row count" ); @@ -9070,7 +9296,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .x, - 71, + 67, "pane 8 x position" ); assert_eq!( @@ -9079,7 +9305,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .unwrap() .position_and_size() .y, - 48, + 47, "pane 8 y position" ); assert_eq!( @@ -9087,8 +9313,9 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 8 column count" ); assert_eq!( @@ -9096,7 +9323,8 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 8 row count" ); @@ -9112,14 +9340,11 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab // ├─────┼─────┤ ├─────┬─┴───┤ // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 70, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.horizontal_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -9158,7 +9383,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -9167,8 +9393,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 33, + .rows + .as_usize(), + 31, "pane 1 row count" ); @@ -9187,7 +9414,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .unwrap() .position_and_size() .y, - 33, + 31, "pane 2 y position" ); assert_eq!( @@ -9195,8 +9422,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 2 column count" ); assert_eq!( @@ -9204,8 +9432,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, - 10, + .rows + .as_usize(), + 11, "pane 2 row count" ); @@ -9224,7 +9453,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .unwrap() .position_and_size() .y, - 53, + 52, "pane 3 y position" ); assert_eq!( @@ -9232,7 +9461,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 3 column count" ); @@ -9241,8 +9471,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 18, "pane 3 row count" ); @@ -9261,7 +9492,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .unwrap() .position_and_size() .y, - 53, + 52, "pane 4 y position" ); assert_eq!( @@ -9269,7 +9500,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -9278,8 +9510,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 18, "pane 4 row count" ); @@ -9306,7 +9539,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 5 column count" ); @@ -9315,8 +9549,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 33, + .rows + .as_usize(), + 31, "pane 5 row count" ); @@ -9326,7 +9561,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .unwrap() .position_and_size() .x, - 71, + 67, "pane 6 x position" ); assert_eq!( @@ -9335,7 +9570,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .unwrap() .position_and_size() .y, - 33, + 31, "pane 6 y position" ); assert_eq!( @@ -9343,8 +9578,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, - 50, + .cols + .as_usize(), + 54, "pane 6 column count" ); assert_eq!( @@ -9352,8 +9588,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, - 20, + .rows + .as_usize(), + 21, "pane 6 row count" ); @@ -9372,7 +9609,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .unwrap() .position_and_size() .y, - 43, + 42, "pane 7 y position" ); assert_eq!( @@ -9380,8 +9617,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 7 column count" ); assert_eq!( @@ -9389,7 +9627,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 7 row count" ); @@ -9409,7 +9648,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .unwrap() .position_and_size() .y, - 48, + 47, "pane 8 y position" ); assert_eq!( @@ -9417,8 +9656,9 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .cols, - 71, + .cols + .as_usize(), + 67, "pane 8 column count" ); assert_eq!( @@ -9426,7 +9666,8 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 8 row count" ); @@ -9440,14 +9681,8 @@ pub fn cannot_resize_right_when_pane_to_the_left_is_at_minimum_width() { // │ │█│ │ │█│ // └─┴─┘ └─┴─┘ // █ == focused pane - let position_and_size = PositionAndSize { - cols: 10, - rows: 20, - x: 0, - y: 0, - ..Default::default() - }; - let mut tab = create_new_tab(position_and_size); + let size = Size { cols: 10, rows: 20 }; + let mut tab = create_new_tab(size); tab.vertical_split(PaneId::Terminal(2)); tab.resize_right(); @@ -9456,7 +9691,8 @@ pub fn cannot_resize_right_when_pane_to_the_left_is_at_minimum_width() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 5, "pane 1 columns stayed the same" ); @@ -9465,7 +9701,8 @@ pub fn cannot_resize_right_when_pane_to_the_left_is_at_minimum_width() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 5, "pane 2 columns stayed the same" ); @@ -9481,14 +9718,11 @@ pub fn resize_up_with_pane_above() { // │███████████│ │███████████│ // └───────────┘ └───────────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.resize_up(); @@ -9515,7 +9749,8 @@ pub fn resize_up_with_pane_above() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane 1 column count" ); @@ -9524,8 +9759,9 @@ pub fn resize_up_with_pane_above() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 8, + .rows + .as_usize(), + 9, "pane 1 row count" ); @@ -9544,7 +9780,7 @@ pub fn resize_up_with_pane_above() { .unwrap() .position_and_size() .y, - 8, + 9, "pane 2 y position" ); assert_eq!( @@ -9552,7 +9788,8 @@ pub fn resize_up_with_pane_above() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane 2 column count" ); @@ -9561,8 +9798,9 @@ pub fn resize_up_with_pane_above() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, - 12, + .rows + .as_usize(), + 11, "pane 2 row count" ); } @@ -9577,14 +9815,11 @@ pub fn resize_up_with_pane_below() { // │ │ │ │ // └───────────┘ └───────────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 20, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.resize_up(); @@ -9612,7 +9847,8 @@ pub fn resize_up_with_pane_below() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane 1 column count" ); @@ -9621,8 +9857,9 @@ pub fn resize_up_with_pane_below() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 8, + .rows + .as_usize(), + 9, "pane 1 row count" ); @@ -9641,7 +9878,7 @@ pub fn resize_up_with_pane_below() { .unwrap() .position_and_size() .y, - 8, + 9, "pane 2 y position" ); assert_eq!( @@ -9649,7 +9886,8 @@ pub fn resize_up_with_pane_below() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane 2 column count" ); @@ -9658,8 +9896,9 @@ pub fn resize_up_with_pane_below() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, - 12, + .rows + .as_usize(), + 11, "pane 2 row count" ); } @@ -9677,14 +9916,11 @@ pub fn resize_up_with_panes_above_and_below() { // │ │ │ │ // └───────────┘ └───────────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.horizontal_split(PaneId::Terminal(3)); tab.move_focus_up(); @@ -9713,7 +9949,8 @@ pub fn resize_up_with_panes_above_and_below() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane 1 column count" ); @@ -9722,7 +9959,8 @@ pub fn resize_up_with_panes_above_and_below() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 13, "pane 1 row count" ); @@ -9750,7 +9988,8 @@ pub fn resize_up_with_panes_above_and_below() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane 2 column count" ); @@ -9759,8 +9998,9 @@ pub fn resize_up_with_panes_above_and_below() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, - 10, + .rows + .as_usize(), + 9, "pane 2 row count" ); @@ -9779,7 +10019,7 @@ pub fn resize_up_with_panes_above_and_below() { .unwrap() .position_and_size() .y, - 23, + 22, "pane 3 y position" ); assert_eq!( @@ -9787,7 +10027,8 @@ pub fn resize_up_with_panes_above_and_below() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane 3 column count" ); @@ -9796,8 +10037,9 @@ pub fn resize_up_with_panes_above_and_below() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 7, + .rows + .as_usize(), + 8, "pane 3 row count" ); } @@ -9811,14 +10053,11 @@ pub fn resize_up_with_multiple_panes_above() { // │███████████│ │███████████│ // └───────────┘ └───────────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.vertical_split(PaneId::Terminal(3)); @@ -9848,7 +10087,8 @@ pub fn resize_up_with_multiple_panes_above() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -9857,8 +10097,9 @@ pub fn resize_up_with_multiple_panes_above() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 1 row count" ); @@ -9877,7 +10118,7 @@ pub fn resize_up_with_multiple_panes_above() { .unwrap() .position_and_size() .y, - 13, + 14, "pane 2 y position" ); assert_eq!( @@ -9885,7 +10126,8 @@ pub fn resize_up_with_multiple_panes_above() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 121, "pane 2 column count" ); @@ -9894,8 +10136,9 @@ pub fn resize_up_with_multiple_panes_above() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 2 row count" ); @@ -9922,7 +10165,8 @@ pub fn resize_up_with_multiple_panes_above() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 3 column count" ); @@ -9931,8 +10175,9 @@ pub fn resize_up_with_multiple_panes_above() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 3 row count" ); } @@ -9945,14 +10190,11 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { // │ │█████│ │ │█████│ // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.vertical_split(PaneId::Terminal(3)); @@ -9983,7 +10225,8 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -9992,7 +10235,8 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -10020,7 +10264,8 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 2 column count" ); @@ -10029,7 +10274,8 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -10057,7 +10303,8 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 3 column count" ); @@ -10066,8 +10313,9 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 3 row count" ); @@ -10086,7 +10334,7 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { .unwrap() .position_and_size() .y, - 13, + 14, "pane 4 y position" ); assert_eq!( @@ -10094,7 +10342,8 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -10103,8 +10352,9 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 4 row count" ); } @@ -10119,14 +10369,11 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { // │ │ │ │ │ │ // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.vertical_split(PaneId::Terminal(3)); @@ -10158,7 +10405,8 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -10167,7 +10415,8 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -10195,7 +10444,8 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 2 column count" ); @@ -10204,7 +10454,8 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -10232,7 +10483,8 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 3 column count" ); @@ -10241,8 +10493,9 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 3 row count" ); @@ -10261,7 +10514,7 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { .unwrap() .position_and_size() .y, - 13, + 14, "pane 4 y position" ); assert_eq!( @@ -10269,7 +10522,8 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -10278,8 +10532,9 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 4 row count" ); } @@ -10294,14 +10549,11 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { // │█████│ │ │█████│ │ // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.vertical_split(PaneId::Terminal(3)); @@ -10333,7 +10585,8 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -10342,8 +10595,9 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 1 row count" ); @@ -10362,7 +10616,7 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { .unwrap() .position_and_size() .y, - 13, + 14, "pane 2 y position" ); assert_eq!( @@ -10370,7 +10624,8 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 2 column count" ); @@ -10379,8 +10634,9 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 2 row count" ); @@ -10407,7 +10663,8 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 3 column count" ); @@ -10416,7 +10673,8 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 3 row count" ); @@ -10444,7 +10702,8 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -10453,7 +10712,8 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -10469,14 +10729,11 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { // │ │ │ │ │ │ // └─────┴─────┘ └─────┴─────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.vertical_split(PaneId::Terminal(3)); @@ -10509,7 +10766,8 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -10518,8 +10776,9 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 1 row count" ); @@ -10538,7 +10797,7 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { .unwrap() .position_and_size() .y, - 13, + 14, "pane 2 y position" ); assert_eq!( @@ -10546,7 +10805,8 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 2 column count" ); @@ -10555,8 +10815,9 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 2 row count" ); @@ -10583,7 +10844,8 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 3 column count" ); @@ -10592,7 +10854,8 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 3 row count" ); @@ -10620,7 +10883,8 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 60, "pane 4 column count" ); @@ -10629,7 +10893,8 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -10645,14 +10910,11 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { // │ │███│ │ │ │███│ │ // └───┴───┴───┘ └───┴───┴───┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.vertical_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -10685,7 +10947,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -10694,7 +10957,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -10722,7 +10986,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 2 column count" ); @@ -10731,7 +10996,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -10751,7 +11017,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .unwrap() .position_and_size() .y, - 13, + 14, "pane 3 y position" ); assert_eq!( @@ -10759,7 +11025,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 3 column count" ); @@ -10768,8 +11035,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 3 row count" ); @@ -10796,7 +11064,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 4 column count" ); @@ -10805,7 +11074,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -10833,7 +11103,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 5 column count" ); @@ -10842,8 +11113,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 5 row count" ); @@ -10870,7 +11142,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 6 column count" ); @@ -10879,7 +11152,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 6 row count" ); @@ -10895,14 +11169,11 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { // │ │ │ │ │ │ │ │ // └───┴───┴───┘ └───┴───┴───┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.vertical_split(PaneId::Terminal(3)); tab.vertical_split(PaneId::Terminal(4)); @@ -10936,7 +11207,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 1 column count" ); @@ -10945,7 +11217,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -10973,7 +11246,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 61, "pane 2 column count" ); @@ -10982,7 +11256,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -11002,7 +11277,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .unwrap() .position_and_size() .y, - 13, + 14, "pane 3 y position" ); assert_eq!( @@ -11010,7 +11285,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 3 column count" ); @@ -11019,8 +11295,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 3 row count" ); @@ -11047,7 +11324,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 4 column count" ); @@ -11056,7 +11334,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -11084,7 +11363,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 5 column count" ); @@ -11093,8 +11373,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 5 row count" ); @@ -11121,7 +11402,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 30, "pane 6 column count" ); @@ -11130,7 +11412,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 6 row count" ); @@ -11146,14 +11429,11 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ // │ │ │███│ │ │ │ │ │███│ │ │ // └─┴─┴───┴─┴─┘ └─┴─┴───┴─┴─┘ // █ == focused pane - let position_and_size = PositionAndSize { - cols: 121, + let size = Size { + cols: 122, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.vertical_split(PaneId::Terminal(3)); @@ -11190,8 +11470,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 61, + .cols + .as_usize(), + 60, "pane 1 column count" ); assert_eq!( @@ -11199,7 +11480,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -11227,8 +11509,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 61, + .cols + .as_usize(), + 60, "pane 2 column count" ); assert_eq!( @@ -11236,7 +11519,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -11247,7 +11531,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .unwrap() .position_and_size() .x, - 61, + 60, "pane 3 x position" ); assert_eq!( @@ -11264,8 +11548,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 3 column count" ); assert_eq!( @@ -11273,8 +11558,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 3 row count" ); @@ -11301,8 +11587,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 4 column count" ); assert_eq!( @@ -11310,7 +11597,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -11321,7 +11609,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .unwrap() .position_and_size() .x, - 61, + 60, "pane 5 x position" ); assert_eq!( @@ -11330,7 +11618,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .unwrap() .position_and_size() .y, - 13, + 14, "pane 5 y position" ); assert_eq!( @@ -11338,7 +11626,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 15, "pane 5 column count" ); @@ -11347,8 +11636,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 5 row count" ); @@ -11375,8 +11665,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 6 column count" ); assert_eq!( @@ -11384,7 +11675,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 6 row count" ); @@ -11395,7 +11687,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .unwrap() .position_and_size() .x, - 76, + 75, "pane 7 x position" ); assert_eq!( @@ -11404,7 +11696,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .unwrap() .position_and_size() .y, - 13, + 14, "pane 7 y position" ); assert_eq!( @@ -11412,7 +11704,8 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 8, "pane 7 column count" ); @@ -11421,8 +11714,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 7 row count" ); @@ -11432,7 +11726,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .unwrap() .position_and_size() .x, - 84, + 83, "pane 8 x position" ); assert_eq!( @@ -11441,7 +11735,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .unwrap() .position_and_size() .y, - 13, + 14, "pane 8 y position" ); assert_eq!( @@ -11449,8 +11743,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .cols, - 7, + .cols + .as_usize(), + 8, "pane 8 column count" ); assert_eq!( @@ -11458,8 +11753,9 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 8 row count" ); } @@ -11474,14 +11770,11 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri // │ │ │ │ │ │ │ │ // └─┴───────┴─┘ └─┴───────┴─┘ // █ == focused pane - let position_and_size = PositionAndSize { - cols: 121, + let size = Size { + cols: 122, rows: 30, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.move_focus_up(); tab.vertical_split(PaneId::Terminal(3)); @@ -11519,8 +11812,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .cols, - 61, + .cols + .as_usize(), + 60, "pane 1 column count" ); assert_eq!( @@ -11528,7 +11822,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 1 row count" ); @@ -11556,8 +11851,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .cols, - 61, + .cols + .as_usize(), + 60, "pane 2 column count" ); assert_eq!( @@ -11565,7 +11861,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 2 row count" ); @@ -11576,7 +11873,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .unwrap() .position_and_size() .x, - 61, + 60, "pane 3 x position" ); assert_eq!( @@ -11593,7 +11890,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 15, "pane 3 column count" ); @@ -11602,8 +11900,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(3)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 3 row count" ); @@ -11630,8 +11929,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 4 column count" ); assert_eq!( @@ -11639,7 +11939,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(4)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 4 row count" ); @@ -11650,7 +11951,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .unwrap() .position_and_size() .x, - 61, + 60, "pane 5 x position" ); assert_eq!( @@ -11659,7 +11960,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .unwrap() .position_and_size() .y, - 13, + 14, "pane 5 y position" ); assert_eq!( @@ -11667,8 +11968,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 5 column count" ); assert_eq!( @@ -11676,8 +11978,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(5)) .unwrap() .position_and_size() - .rows, - 17, + .rows + .as_usize(), + 16, "pane 5 row count" ); @@ -11704,8 +12007,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .cols, - 30, + .cols + .as_usize(), + 31, "pane 6 column count" ); assert_eq!( @@ -11713,7 +12017,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(6)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 15, "pane 6 row count" ); @@ -11724,7 +12029,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .unwrap() .position_and_size() .x, - 76, + 75, "pane 7 x position" ); assert_eq!( @@ -11741,7 +12046,8 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .cols, + .cols + .as_usize(), 8, "pane 7 column count" ); @@ -11750,8 +12056,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(7)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 7 row count" ); @@ -11761,7 +12068,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .unwrap() .position_and_size() .x, - 84, + 83, "pane 8 x position" ); assert_eq!( @@ -11778,8 +12085,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .cols, - 7, + .cols + .as_usize(), + 8, "pane 8 column count" ); assert_eq!( @@ -11787,8 +12095,9 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri .get(&PaneId::Terminal(8)) .unwrap() .position_and_size() - .rows, - 13, + .rows + .as_usize(), + 14, "pane 8 row count" ); } @@ -11802,14 +12111,11 @@ pub fn cannot_resize_up_when_pane_above_is_at_minimum_height() { // └───────────┘ └───────────┘ // █ == focused pane - let position_and_size = PositionAndSize { + let size = Size { cols: 121, rows: 10, - x: 0, - y: 0, - ..Default::default() }; - let mut tab = create_new_tab(position_and_size); + let mut tab = create_new_tab(size); tab.horizontal_split(PaneId::Terminal(2)); tab.resize_down(); @@ -11818,7 +12124,8 @@ pub fn cannot_resize_up_when_pane_above_is_at_minimum_height() { .get(&PaneId::Terminal(1)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 1 height stayed the same" ); @@ -11827,7 +12134,8 @@ pub fn cannot_resize_up_when_pane_above_is_at_minimum_height() { .get(&PaneId::Terminal(2)) .unwrap() .position_and_size() - .rows, + .rows + .as_usize(), 5, "pane 2 height stayed the same" ); diff --git a/zellij-server/src/wasm_vm.rs b/zellij-server/src/wasm_vm.rs index 0f6b721e..e8d9344e 100644 --- a/zellij-server/src/wasm_vm.rs +++ b/zellij-server/src/wasm_vm.rs @@ -170,9 +170,6 @@ pub(crate) fn zellij_exports(store: &Store, plugin_env: &PluginEnv) -> ImportObj zellij_export! { host_subscribe, host_unsubscribe, - host_set_invisible_borders, - host_set_fixed_height, - host_set_fixed_width, host_set_selectable, host_get_plugin_ids, host_open_file, @@ -204,42 +201,6 @@ fn host_set_selectable(plugin_env: &PluginEnv, selectable: i32) { .unwrap() } -fn host_set_fixed_height(plugin_env: &PluginEnv, fixed_height: i32) { - let fixed_height = fixed_height as usize; - plugin_env - .senders - .send_to_screen(ScreenInstruction::SetFixedHeight( - PaneId::Plugin(plugin_env.plugin_id), - fixed_height, - plugin_env.tab_index, - )) - .unwrap() -} - -fn host_set_fixed_width(plugin_env: &PluginEnv, fixed_width: i32) { - let fixed_width = fixed_width as usize; - plugin_env - .senders - .send_to_screen(ScreenInstruction::SetFixedWidth( - PaneId::Plugin(plugin_env.plugin_id), - fixed_width, - plugin_env.tab_index, - )) - .unwrap() -} - -fn host_set_invisible_borders(plugin_env: &PluginEnv, invisible_borders: i32) { - let invisible_borders = invisible_borders != 0; - plugin_env - .senders - .send_to_screen(ScreenInstruction::SetInvisibleBorders( - PaneId::Plugin(plugin_env.plugin_id), - invisible_borders, - plugin_env.tab_index, - )) - .unwrap() -} - fn host_get_plugin_ids(plugin_env: &PluginEnv) { let ids = PluginIds { plugin_id: plugin_env.plugin_id, @@ -289,7 +250,6 @@ fn host_set_timeout(plugin_env: &PluginEnv, secs: f64) { // Helper Functions --------------------------------------------------------------------------------------------------- -// FIXME: Unwrap city pub fn wasi_read_string(wasi_env: &WasiEnv) -> String { let mut state = wasi_env.state(); let wasi_file = state.fs.stdout_mut().unwrap().as_mut().unwrap(); diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs index ed033d4b..b514b55a 100644 --- a/zellij-tile/src/shim.rs +++ b/zellij-tile/src/shim.rs @@ -17,22 +17,10 @@ pub fn unsubscribe(event_types: &[EventType]) { // Plugin Settings -pub fn set_fixed_height(fixed_height: i32) { - unsafe { host_set_fixed_height(fixed_height) }; -} - -pub fn set_fixed_width(fixed_width: i32) { - unsafe { host_set_fixed_width(fixed_width) }; -} - pub fn set_selectable(selectable: bool) { unsafe { host_set_selectable(if selectable { 1 } else { 0 }) }; } -pub fn set_invisible_borders(invisible_borders: bool) { - unsafe { host_set_invisible_borders(if invisible_borders { 1 } else { 0 }) }; -} - // Query Functions pub fn get_plugin_ids() -> PluginIds { unsafe { host_get_plugin_ids() }; @@ -68,10 +56,7 @@ pub fn object_to_stdout(object: &impl Serialize) { extern "C" { fn host_subscribe(); fn host_unsubscribe(); - fn host_set_fixed_height(fixed_height: i32); - fn host_set_fixed_width(fixed_width: i32); fn host_set_selectable(selectable: i32); - fn host_set_invisible_borders(invisible_borders: i32); fn host_get_plugin_ids(); fn host_open_file(); fn host_set_timeout(secs: f64); diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index cd4ca464..915f2dad 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -22,7 +22,7 @@ pub enum Direction { // They might need to be adjusted in the default config // as well `../../assets/config/default.yaml` /// Actions that can be bound to keys. -#[derive(Eq, Clone, Debug, PartialEq, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub enum Action { /// Quit Zellij. Quit, diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs index a3da6aba..be71130c 100644 --- a/zellij-utils/src/input/layout.rs +++ b/zellij-utils/src/input/layout.rs @@ -10,28 +10,43 @@ // then [`zellij-utils`] could be a proper place. use crate::{ input::{command::RunCommand, config::ConfigError}, - pane_size::PositionAndSize, + pane_size::{Dimension, PaneGeom}, setup, }; use crate::{serde, serde_yaml}; use serde::{Deserialize, Serialize}; -use std::path::{Path, PathBuf}; use std::vec::Vec; +use std::{ + cmp::max, + ops::Not, + path::{Path, PathBuf}, +}; use std::{fs::File, io::prelude::*}; -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Copy)] #[serde(crate = "self::serde")] pub enum Direction { Horizontal, Vertical, } -#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] +impl Not for Direction { + type Output = Self; + + fn not(self) -> Self::Output { + match self { + Direction::Horizontal => Direction::Vertical, + Direction::Vertical => Direction::Horizontal, + } + } +} + +#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)] #[serde(crate = "self::serde")] pub enum SplitSize { - Percent(u8), // 1 to 100 - Fixed(u16), // An absolute number of columns or rows + Percent(f64), // 1 to 100 + Fixed(usize), // An absolute number of columns or rows } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] @@ -44,7 +59,7 @@ pub enum Run { } // The layout struct ultimately used to build the layouts. -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(crate = "self::serde")] pub struct Layout { pub direction: Direction, @@ -58,7 +73,7 @@ pub struct Layout { // The struct that is used to deserialize the layout from // a yaml configuration file -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(crate = "self::serde")] #[serde(default)] pub struct LayoutFromYaml { @@ -148,7 +163,7 @@ impl LayoutFromYaml { // The struct that carries the information template that is used to // construct the layout -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(crate = "self::serde")] pub struct LayoutTemplate { pub direction: Direction, @@ -191,7 +206,7 @@ impl LayoutTemplate { } // The tab-layout struct used to specify each individual tab. -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(crate = "self::serde")] pub struct TabLayout { pub direction: Direction, @@ -238,10 +253,7 @@ impl Layout { run_instructions } - pub fn position_panes_in_space( - &self, - space: &PositionAndSize, - ) -> Vec<(Layout, PositionAndSize)> { + pub fn position_panes_in_space(&self, space: &PaneGeom) -> Vec<(Layout, PaneGeom)> { split_space(space, self) } @@ -268,149 +280,90 @@ impl Layout { } } -fn split_space_to_parts_vertically( - space_to_split: &PositionAndSize, - sizes: Vec>, -) -> Vec { - let mut split_parts = Vec::new(); - let mut current_x_position = space_to_split.x; - let mut current_width = 0; - let max_width = space_to_split.cols; - - let mut parts_to_grow = Vec::new(); - - // First fit in the parameterized sizes - for size in sizes { - let columns = match size { - Some(SplitSize::Percent(percent)) => { - (max_width as f32 * (percent as f32 / 100.0)) as usize - } // TODO: round properly - Some(SplitSize::Fixed(size)) => size as usize, - None => { - parts_to_grow.push(current_x_position); - 1 // This is grown later on - } - }; - split_parts.push(PositionAndSize { - x: current_x_position, - y: space_to_split.y, - cols: columns, - rows: space_to_split.rows, - ..Default::default() - }); - current_width += columns; - current_x_position += columns; - } - - if current_width > max_width { - panic!("Layout contained too many columns to fit onto the screen!"); - } - - let mut last_flexible_index = split_parts.len() - 1; - if let Some(new_columns) = (max_width - current_width).checked_div(parts_to_grow.len()) { - current_width = 0; - current_x_position = 0; - for (idx, part) in split_parts.iter_mut().enumerate() { - part.x = current_x_position; - if parts_to_grow.contains(&part.x) { - part.cols = new_columns; - last_flexible_index = idx; - } - current_width += part.cols; - current_x_position += part.cols; +fn layout_size(direction: Direction, layout: &Layout) -> usize { + fn child_layout_size( + direction: Direction, + parent_direction: Direction, + layout: &Layout, + ) -> usize { + let size = if parent_direction == direction { 1 } else { 0 }; + if layout.parts.is_empty() { + size + } else { + let children_size = layout + .parts + .iter() + .map(|p| child_layout_size(direction, layout.direction, p)) + .sum::(); + max(size, children_size) } } - - if current_width < max_width { - // we have some extra space left, let's add it to the last flexible part - let extra = max_width - current_width; - let mut last_part = split_parts.get_mut(last_flexible_index).unwrap(); - last_part.cols += extra; - for part in (&mut split_parts[last_flexible_index + 1..]).iter_mut() { - part.x += extra; - } - } - split_parts + child_layout_size(direction, direction, layout) } -fn split_space_to_parts_horizontally( - space_to_split: &PositionAndSize, - sizes: Vec>, -) -> Vec { - let mut split_parts = Vec::new(); - let mut current_y_position = space_to_split.y; - let mut current_height = 0; - let max_height = space_to_split.rows; - - let mut parts_to_grow = Vec::new(); - - for size in sizes { - let rows = match size { - Some(SplitSize::Percent(percent)) => { - (max_height as f32 * (percent as f32 / 100.0)) as usize - } // TODO: round properly - Some(SplitSize::Fixed(size)) => size as usize, - None => { - parts_to_grow.push(current_y_position); - 1 // This is grown later on - } - }; - split_parts.push(PositionAndSize { - x: space_to_split.x, - y: current_y_position, - cols: space_to_split.cols, - rows, - ..Default::default() - }); - current_height += rows; - current_y_position += rows; - } - - if current_height > max_height { - panic!("Layout contained too many rows to fit onto the screen!"); - } - - let mut last_flexible_index = split_parts.len() - 1; - if let Some(new_rows) = (max_height - current_height).checked_div(parts_to_grow.len()) { - current_height = 0; - current_y_position = 0; - - for (idx, part) in split_parts.iter_mut().enumerate() { - part.y = current_y_position; - if parts_to_grow.contains(&part.y) { - part.rows = new_rows; - last_flexible_index = idx; - } - current_height += part.rows; - current_y_position += part.rows; - } - } - - if current_height < max_height { - // we have some extra space left, let's add it to the last flexible part - let extra = max_height - current_height; - let mut last_part = split_parts.get_mut(last_flexible_index).unwrap(); - last_part.rows += extra; - for part in (&mut split_parts[last_flexible_index + 1..]).iter_mut() { - part.y += extra; - } - } - split_parts -} - -fn split_space( - space_to_split: &PositionAndSize, - layout: &Layout, -) -> Vec<(Layout, PositionAndSize)> { +fn split_space(space_to_split: &PaneGeom, layout: &Layout) -> Vec<(Layout, PaneGeom)> { let mut pane_positions = Vec::new(); let sizes: Vec> = layout.parts.iter().map(|part| part.split_size).collect(); - let split_parts = match layout.direction { - Direction::Vertical => split_space_to_parts_vertically(space_to_split, sizes), - Direction::Horizontal => split_space_to_parts_horizontally(space_to_split, sizes), - }; + let mut split_geom = Vec::new(); + let (mut current_position, split_dimension_space, mut inherited_dimension) = + match layout.direction { + Direction::Vertical => (space_to_split.x, space_to_split.cols, space_to_split.rows), + Direction::Horizontal => (space_to_split.y, space_to_split.rows, space_to_split.cols), + }; + + let flex_parts = sizes.iter().filter(|s| s.is_none()).count(); + + for (&size, part) in sizes.iter().zip(&layout.parts) { + let split_dimension = match size { + Some(SplitSize::Percent(percent)) => Dimension::percent(percent), + Some(SplitSize::Fixed(size)) => Dimension::fixed(size), + None => { + let free_percent = if let Some(p) = split_dimension_space.as_percent() { + p - sizes + .iter() + .map(|&s| { + if let Some(SplitSize::Percent(ip)) = s { + ip + } else { + 0.0 + } + }) + .sum::() + } else { + panic!("Implicit sizing within fixed-size panes is not supported"); + }; + Dimension::percent(free_percent / flex_parts as f64) + } + }; + inherited_dimension.set_inner( + layout + .parts + .iter() + .map(|p| layout_size(!layout.direction, p)) + .max() + .unwrap(), + ); + let geom = match layout.direction { + Direction::Vertical => PaneGeom { + x: current_position, + y: space_to_split.y, + cols: split_dimension, + rows: inherited_dimension, + }, + Direction::Horizontal => PaneGeom { + x: space_to_split.x, + y: current_position, + cols: inherited_dimension, + rows: split_dimension, + }, + }; + split_geom.push(geom); + current_position += layout_size(layout.direction, part); + } + for (i, part) in layout.parts.iter().enumerate() { - let part_position_and_size = split_parts.get(i).unwrap(); + let part_position_and_size = split_geom.get(i).unwrap(); if !part.parts.is_empty() { let mut part_positions = split_space(part_position_and_size, part); pane_positions.append(&mut part_positions); diff --git a/zellij-utils/src/input/unit/layout_test.rs b/zellij-utils/src/input/unit/layout_test.rs index 23c57b3d..abce56a4 100644 --- a/zellij-utils/src/input/unit/layout_test.rs +++ b/zellij-utils/src/input/unit/layout_test.rs @@ -163,7 +163,7 @@ fn three_panes_with_tab_merged_correctly() { direction: Direction::Horizontal, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, Layout { @@ -174,14 +174,14 @@ fn three_panes_with_tab_merged_correctly() { direction: Direction::Vertical, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, Layout { direction: Direction::Vertical, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, ], @@ -263,7 +263,7 @@ fn three_panes_with_tab_and_default_plugins_merged_correctly() { direction: Direction::Horizontal, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, Layout { @@ -274,14 +274,14 @@ fn three_panes_with_tab_and_default_plugins_merged_correctly() { direction: Direction::Vertical, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, Layout { direction: Direction::Vertical, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, ], @@ -380,7 +380,7 @@ fn deeply_nested_tab_merged_correctly() { direction: Direction::Horizontal, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(21)), + split_size: Some(SplitSize::Percent(21.0)), run: None, }, Layout { @@ -391,7 +391,7 @@ fn deeply_nested_tab_merged_correctly() { direction: Direction::Horizontal, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(22)), + split_size: Some(SplitSize::Percent(22.0)), run: None, }, Layout { @@ -402,47 +402,47 @@ fn deeply_nested_tab_merged_correctly() { direction: Direction::Horizontal, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(23)), + split_size: Some(SplitSize::Percent(23.0)), run: None, }, Layout { direction: Direction::Horizontal, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(24)), + split_size: Some(SplitSize::Percent(24.0)), run: None, }, ], - split_size: Some(SplitSize::Percent(78)), + split_size: Some(SplitSize::Percent(78.0)), run: None, }, ], - split_size: Some(SplitSize::Percent(79)), + split_size: Some(SplitSize::Percent(79.0)), run: None, }, ], - split_size: Some(SplitSize::Percent(90)), + split_size: Some(SplitSize::Percent(90.0)), run: None, }, Layout { direction: Direction::Vertical, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(15)), + split_size: Some(SplitSize::Percent(15.0)), run: None, }, Layout { direction: Direction::Vertical, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(15)), + split_size: Some(SplitSize::Percent(15.0)), run: None, }, Layout { direction: Direction::Vertical, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(15)), + split_size: Some(SplitSize::Percent(15.0)), run: None, }, ], @@ -484,7 +484,7 @@ fn three_tabs_tab_one_merged_correctly() { direction: Direction::Horizontal, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, Layout { @@ -523,7 +523,7 @@ fn three_tabs_tab_two_merged_correctly() { direction: Direction::Horizontal, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, Layout { @@ -534,7 +534,7 @@ fn three_tabs_tab_two_merged_correctly() { run: None, }, ], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, Layout { @@ -573,7 +573,7 @@ fn three_tabs_tab_three_merged_correctly() { direction: Direction::Vertical, borderless: false, parts: vec![], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, Layout { @@ -584,7 +584,7 @@ fn three_tabs_tab_three_merged_correctly() { run: None, }, ], - split_size: Some(SplitSize::Percent(50)), + split_size: Some(SplitSize::Percent(50.0)), run: None, }, Layout { diff --git a/zellij-utils/src/ipc.rs b/zellij-utils/src/ipc.rs index 009d99a3..a7cda977 100644 --- a/zellij-utils/src/ipc.rs +++ b/zellij-utils/src/ipc.rs @@ -4,7 +4,7 @@ use crate::{ cli::CliArgs, errors::{get_current_ctx, ErrorContext}, input::{actions::Action, layout::LayoutFromYaml, options::Options}, - pane_size::PositionAndSize, + pane_size::Size, }; use interprocess::local_socket::LocalSocketStream; use nix::unistd::dup; @@ -39,7 +39,7 @@ pub enum ClientType { #[derive(Default, Serialize, Deserialize, Debug, Clone, Copy)] pub struct ClientAttributes { - pub position_and_size: PositionAndSize, + pub size: Size, pub palette: Palette, } @@ -57,13 +57,8 @@ pub enum ClientToServerMsg { DetachSession(SessionId), // Disconnect from the session we're connected to DisconnectFromSession,*/ - TerminalResize(PositionAndSize), - NewClient( - ClientAttributes, - Box, - Box, - Option, - ), + TerminalResize(Size), + NewClient(ClientAttributes, Box, Box, LayoutFromYaml), AttachClient(ClientAttributes, bool, Options), Action(Action), ClientExited, diff --git a/zellij-utils/src/pane_size.rs b/zellij-utils/src/pane_size.rs index db439b61..8ae76630 100644 --- a/zellij-utils/src/pane_size.rs +++ b/zellij-utils/src/pane_size.rs @@ -1,49 +1,144 @@ -use nix::pty::Winsize; use serde::{Deserialize, Serialize}; use crate::position::Position; /// Contains the position and size of a [`Pane`], or more generally of any terminal, measured /// in character rows and columns. +#[derive(Clone, Copy, Default, PartialEq, Debug, Serialize, Deserialize)] +pub struct PaneGeom { + pub x: usize, + pub y: usize, + pub rows: Dimension, + pub cols: Dimension, +} + #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] -pub struct PositionAndSize { +pub struct Viewport { pub x: usize, pub y: usize, pub rows: usize, pub cols: usize, - // FIXME: Honestly, these shouldn't exist and rows / columns should be enums like: - // Dimension::Flex(usize) / Dimension::Fixed(usize), but 400+ compiler errors is more than - // I'm in the mood for right now... - pub rows_fixed: bool, - pub cols_fixed: bool, } -impl From for PositionAndSize { - fn from(winsize: Winsize) -> PositionAndSize { - PositionAndSize { - cols: winsize.ws_col as usize, - rows: winsize.ws_row as usize, +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)] +pub struct Offset { + pub top: usize, + pub bottom: usize, + pub right: usize, + pub left: usize, +} + +#[derive(Clone, Copy, Default, PartialEq, Debug, Serialize, Deserialize)] +pub struct Size { + pub rows: usize, + pub cols: usize, +} + +#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)] +pub struct Dimension { + pub constraint: Constraint, + inner: usize, +} + +impl Default for Dimension { + fn default() -> Self { + Self::percent(100.0) + } +} + +impl Dimension { + pub fn fixed(size: usize) -> Dimension { + Self { + constraint: Constraint::Fixed(size), + inner: 1, + } + } + + pub fn percent(percent: f64) -> Dimension { + Self { + constraint: Constraint::Percent(percent), + inner: 1, + } + } + + pub fn as_usize(&self) -> usize { + self.inner + } + + pub fn as_percent(&self) -> Option { + if let Constraint::Percent(p) = self.constraint { + Some(p) + } else { + None + } + } + + pub fn set_inner(&mut self, inner: usize) { + self.inner = inner; + } + + pub fn is_fixed(&self) -> bool { + matches!(self.constraint, Constraint::Fixed(_)) + } +} + +#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)] +pub enum Constraint { + /// Constrains the dimension to a fixed, integer number of rows / columns + Fixed(usize), + /// Constrains the dimension to a flexible percent size of the total screen + Percent(f64), +} + +impl PaneGeom { + pub fn contains(&self, point: &Position) -> bool { + let col = point.column.0 as usize; + let row = point.line.0 as usize; + self.x <= col + && col < self.x + self.cols.as_usize() + && self.y <= row + && row < self.y + self.rows.as_usize() + } +} + +impl Offset { + pub fn frame(size: usize) -> Self { + Self { + top: size, + bottom: size, + right: size, + left: size, + } + } + + // FIXME: This should be top and left, not bottom and right, but `boundaries.rs` would need + // some changing + pub fn shift(bottom: usize, right: usize) -> Self { + Self { + bottom, + right, ..Default::default() } } } -impl PositionAndSize { - pub fn contains(&self, point: &Position) -> bool { - let col = point.column.0 as usize; - let row = point.line.0 as usize; - self.x <= col && col < self.x + self.cols && self.y <= row && row < self.y + self.rows - } - pub fn reduce_outer_frame(mut self, frame_width: usize) -> Self { - self.x += frame_width; - self.rows -= frame_width * 2; - self.y += frame_width; - self.cols -= frame_width * 2; - self - } - pub fn reduce_top_line(mut self) -> Self { - self.y += 1; - self.rows -= 1; - self +impl From for Viewport { + fn from(pane: PaneGeom) -> Self { + Self { + x: pane.x, + y: pane.y, + rows: pane.rows.as_usize(), + cols: pane.cols.as_usize(), + } + } +} + +impl From for Viewport { + fn from(size: Size) -> Self { + Self { + rows: size.rows, + cols: size.cols, + ..Default::default() + } } } diff --git a/zellij-utils/src/position.rs b/zellij-utils/src/position.rs index 71547424..56fcd638 100644 --- a/zellij-utils/src/position.rs +++ b/zellij-utils/src/position.rs @@ -1,7 +1,5 @@ use serde::{Deserialize, Serialize}; -use crate::pane_size::PositionAndSize; - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Deserialize, Serialize)] pub struct Position { pub line: Line, @@ -16,10 +14,10 @@ impl Position { } } - pub fn relative_to(&self, position_and_size: &PositionAndSize) -> Self { + pub fn relative_to(&self, line: usize, column: usize) -> Self { Self { - line: Line(self.line.0 - position_and_size.y as isize), - column: Column(self.column.0.saturating_sub(position_and_size.x)), + line: Line(self.line.0 - line as isize), + column: Column(self.column.0.saturating_sub(column)), } } } diff --git a/zellij-utils/src/shared.rs b/zellij-utils/src/shared.rs index b1edb97f..4b3ba974 100644 --- a/zellij-utils/src/shared.rs +++ b/zellij-utils/src/shared.rs @@ -2,12 +2,11 @@ use std::{iter, str::from_utf8}; -use strip_ansi_escapes::strip; - use colors_transform::{Color, Rgb}; use std::os::unix::fs::PermissionsExt; use std::path::Path; use std::{fs, io}; +use strip_ansi_escapes::strip; use zellij_tile::data::{Palette, PaletteColor, PaletteSource, ThemeHue}; const UNIX_PERMISSIONS: u32 = 0o700;