diff --git a/Cargo.lock b/Cargo.lock index c71bef9d..fe7883f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -310,6 +310,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "colors-transform" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9226dbc05df4fb986f48d730b001532580883c4c06c5d1c213f4b34c1c157178" + [[package]] name = "concurrent-queue" version = "1.2.2" @@ -1040,16 +1046,6 @@ dependencies = [ "rand 0.3.23", ] -[[package]] -name = "nb-connect" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19900e7eee95eb2b3c2e26d12a874cc80aaf750e31be6fcbe743ead369fa45d" -dependencies = [ - "libc", - "socket2", -] - [[package]] name = "nix" version = "0.19.1" @@ -1131,6 +1127,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + [[package]] name = "polling" version = "2.0.3" @@ -1334,9 +1336,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +checksum = "8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041" dependencies = [ "bitflags", ] @@ -2247,6 +2249,27 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +[[package]] +name = "x11" +version = "2.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ecd092546cb16f25783a5451538e73afc8d32e242648d54f4ae5459ba1e773" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "xrdb" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2dd91a21c92e87678e22f95956a03bfd314ce3232f39dbedd49dddb50f0c6d" +dependencies = [ + "libc", + "scopeguard", + "x11", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -2264,6 +2287,7 @@ dependencies = [ "async-std", "backtrace", "bincode", + "colors-transform", "directories-next", "futures", "insta", @@ -2288,6 +2312,9 @@ dependencies = [ "vte 0.8.0", "wasmer", "wasmer-wasi", + "xrdb", + "zellij-tile", + "zellij-tile-extra", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 8b8ccc17..3b3064c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,10 @@ wasmer = "1.0.0" wasmer-wasi = "1.0.0" interprocess = "1.1.1" names = "0.11.0" -zellij-tile = { path = "zellij-tile/", version = "0.5.0" } +xrdb = "0.1.1" +colors-transform = "0.2.5" +zellij-tile = { path = "zellij-tile/", version = "1.1.0" } +zellij-tile-extra = { path = "zellij-tile-extra/", version="1.0.0" } [dependencies.async-std] version = "1.3.0" diff --git a/src/cli.rs b/src/cli.rs index 9f2bfd36..91b0ed39 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,8 +1,9 @@ use super::common::utils::consts::{ZELLIJ_CONFIG_DIR_ENV, ZELLIJ_CONFIG_FILE_ENV}; +use serde::{Deserialize, Serialize}; use std::path::PathBuf; use structopt::StructOpt; -#[derive(StructOpt, Default, Debug, Clone)] +#[derive(StructOpt, Default, Debug, Clone, Serialize, Deserialize)] #[structopt(name = "zellij")] pub struct CliArgs { /// Maximum panes on screen, caution: opening more panes will close old ones @@ -32,7 +33,7 @@ pub struct CliArgs { pub debug: bool, } -#[derive(Debug, StructOpt, Clone)] +#[derive(Debug, StructOpt, Clone, Serialize, Deserialize)] pub enum ConfigCli { /// Change the behaviour of zellij #[structopt(name = "option")] diff --git a/src/client/mod.rs b/src/client/mod.rs index 2bf814c2..8a5834f0 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -29,31 +29,25 @@ pub enum ClientInstruction { Exit, } -pub fn start_client(mut os_input: Box, opts: CliArgs) { +pub fn start_client(mut os_input: Box, opts: CliArgs, config: Config) { let take_snapshot = "\u{1b}[?1049h"; os_input.unset_raw_mode(0); let _ = os_input .get_stdout_writer() .write(take_snapshot.as_bytes()) .unwrap(); - - let config = Config::from_cli_config(opts.config) - .map_err(|e| { - eprintln!("There was an error in the config file:\n{}", e); - std::process::exit(1); - }) - .unwrap(); + std::env::set_var(&"ZELLIJ", "0"); let mut command_is_executing = CommandIsExecuting::new(); let full_screen_ws = os_input.get_terminal_size_using_fd(0); os_input.connect_to_server(); - os_input.send_to_server(ServerInstruction::NewClient(full_screen_ws)); + os_input.send_to_server(ServerInstruction::NewClient(full_screen_ws, opts)); os_input.set_raw_mode(0); let (send_client_instructions, receive_client_instructions): SyncChannelWithContext< ClientInstruction, - > = mpsc::sync_channel(500); + > = mpsc::sync_channel(50); let send_client_instructions = SenderWithContext::new(SenderType::SyncSender(send_client_instructions)); diff --git a/src/client/tab.rs b/src/client/tab.rs index 36d03e87..0098d78b 100644 --- a/src/client/tab.rs +++ b/src/client/tab.rs @@ -1,7 +1,6 @@ //! `Tab`s holds multiple panes. It tracks their coordinates (x/y) and size, //! as well as how they should be resized -use crate::boundaries::colors; use crate::client::pane_resizer::PaneResizer; use crate::common::{input::handler::parse_keys, SenderWithContext}; use crate::layout::Layout; @@ -15,11 +14,12 @@ use crate::{boundaries::Boundaries, panes::PluginPane}; use serde::{Deserialize, Serialize}; use std::os::unix::io::RawFd; use std::sync::mpsc::channel; +use std::time::Instant; use std::{ cmp::Reverse, collections::{BTreeMap, HashSet}, }; -use zellij_tile::data::{Event, ModeInfo}; +use zellij_tile::data::{Event, InputMode, ModeInfo, Palette}; const CURSOR_HEIGHT_WIDTH_RATIO: usize = 4; // this is not accurate and kind of a magic number, TODO: look into this @@ -72,7 +72,7 @@ pub struct Tab { send_plugin_instructions: SenderWithContext, send_pty_instructions: SenderWithContext, send_server_instructions: SenderWithContext, - expansion_boundary: Option, + synchronize_is_active: bool, should_clear_display_before_rendering: bool, pub mode_info: ModeInfo, pub input_mode: InputMode, @@ -264,7 +264,6 @@ impl Tab { send_plugin_instructions, send_pty_instructions, send_server_instructions, - expansion_boundary: None, should_clear_display_before_rendering: false, mode_info, input_mode, @@ -492,6 +491,7 @@ impl Tab { y: active_pane.y(), rows: active_pane.rows(), columns: active_pane.columns(), + ..Default::default() }; let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws); @@ -548,6 +548,7 @@ impl Tab { y: active_pane.y(), rows: active_pane.rows(), columns: active_pane.columns(), + ..Default::default() }; let (left_winsize, right_winsize) = split_vertically_with_gap(&terminal_ws); @@ -724,6 +725,11 @@ impl Tab { // in that case, we should not render as the app is exiting return; } + // if any pane contain widechar, all pane in the same row will messup. We should render them every time + // FIXME: remove this when we can handle widechars correctly + if self.panes_contain_widechar() { + self.set_force_render() + } let mut output = String::new(); let mut boundaries = Boundaries::new( self.full_screen_ws.columns as u16, diff --git a/src/common/input/handler.rs b/src/common/input/handler.rs index 7a4a4e52..75f9f8b1 100644 --- a/src/common/input/handler.rs +++ b/src/common/input/handler.rs @@ -11,7 +11,7 @@ use crate::server::ServerInstruction; use crate::CommandIsExecuting; use termion::input::{TermRead, TermReadEventsAndRaw}; -use zellij_tile::data::{InputMode, Key, ModeInfo}; +use zellij_tile::data::{InputMode, Key, ModeInfo, Palette}; /// Handles the dispatching of [`Action`]s according to the current /// [`InputMode`], and keep tracks of the current [`InputMode`]. @@ -48,7 +48,6 @@ impl InputHandler { fn handle_input(&mut self) { let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow()); err_ctx.add_call(ContextType::StdinHandler); - let keybinds = self.config.keybinds.clone(); let alt_left_bracket = vec![27, 91]; loop { if self.should_exit { @@ -60,14 +59,14 @@ impl InputHandler { Ok((event, raw_bytes)) => match event { termion::event::Event::Key(key) => { let key = cast_termion_key(key); - self.handle_key(&key, raw_bytes, &keybinds); + self.handle_key(&key, raw_bytes); } termion::event::Event::Unsupported(unsupported_key) => { // we have to do this because of a bug in termion // this should be a key event and not an unsupported event if unsupported_key == alt_left_bracket { let key = Key::Alt('['); - self.handle_key(&key, raw_bytes, &keybinds); + self.handle_key(&key, raw_bytes); } } termion::event::Event::Mouse(_) => { diff --git a/src/common/os_input_output.rs b/src/common/os_input_output.rs index a339b08d..7bf39757 100644 --- a/src/common/os_input_output.rs +++ b/src/common/os_input_output.rs @@ -1,3 +1,12 @@ +use crate::client::ClientInstruction; +use crate::common::{ + ipc::{IpcReceiverWithContext, IpcSenderWithContext}, + utils::consts::ZELLIJ_IPC_PIPE, +}; +use crate::errors::ErrorContext; +use crate::panes::PositionAndSize; +use crate::server::ServerInstruction; +use crate::utils::shared::{default_palette, detect_theme, hex_to_rgb}; use interprocess::local_socket::LocalSocketStream; use nix::fcntl::{fcntl, FcntlArg, OFlag}; use nix::pty::{forkpty, Winsize}; @@ -13,15 +22,8 @@ use std::os::unix::io::RawFd; use std::path::PathBuf; use std::process::{Child, Command}; use std::sync::{Arc, Mutex}; - -use crate::client::ClientInstruction; -use crate::common::{ - ipc::{IpcReceiverWithContext, IpcSenderWithContext}, - utils::consts::ZELLIJ_IPC_PIPE, -}; -use crate::errors::ErrorContext; -use crate::panes::PositionAndSize; -use crate::server::ServerInstruction; +use xrdb::Colors; +use zellij_tile::data::{Palette, PaletteSource}; fn into_raw_mode(pid: RawFd) { let mut tio = termios::tcgetattr(pid).expect("could not get terminal attribute"); @@ -194,6 +196,7 @@ pub trait ServerOsApi: Send + Sync { fn add_client_sender(&mut self); /// Update the receiver socket for the client fn update_receiver(&mut self, stream: LocalSocketStream); + fn load_palette(&self) -> Palette; } impl ServerOsApi for ServerOsInputOutput { @@ -258,6 +261,51 @@ impl ServerOsApi for ServerOsInputOutput { self.receive_instructions_from_client = Some(Arc::new(Mutex::new(IpcReceiverWithContext::new(stream)))); } + fn load_palette(&self) -> Palette { + let palette = match Colors::new("xresources") { + Some(palette) => { + let fg = if let Some(foreground) = palette.fg.as_deref().map(hex_to_rgb) { + foreground + } else { + return default_palette(); + }; + + let bg = if let Some(background) = palette.bg.as_deref().map(hex_to_rgb) { + background + } else { + return default_palette(); + }; + + // NOTE: `16` is the same as the length of `palette.colors`. + let mut colors: [(u8, u8, u8); 16] = [(0, 0, 0); 16]; + for (idx, color) in palette.colors.iter().enumerate() { + if let Some(c) = color { + colors[idx] = hex_to_rgb(c); + } else { + return default_palette(); + } + } + let theme = detect_theme(bg); + Palette { + source: PaletteSource::Xresources, + theme, + fg, + bg, + black: colors[0], + red: colors[1], + green: colors[2], + yellow: colors[3], + blue: colors[4], + magenta: colors[5], + cyan: colors[6], + white: colors[7], + orange: colors[9], + } + } + None => default_palette(), + }; + palette + } } impl Clone for Box { diff --git a/src/common/pty_bus.rs b/src/common/pty_bus.rs index 10be6d52..31696186 100644 --- a/src/common/pty_bus.rs +++ b/src/common/pty_bus.rs @@ -165,9 +165,9 @@ fn stream_terminal_bytes( impl PtyBus { pub fn new( receive_pty_instructions: Receiver<(PtyInstruction, ErrorContext)>, - os_input: Box, send_screen_instructions: SenderWithContext, send_plugin_instructions: SenderWithContext, + os_input: Box, debug_to_file: bool, ) -> Self { PtyBus { @@ -193,8 +193,7 @@ impl PtyBus { self.id_to_child_pid.insert(pid_primary, pid_secondary); pid_primary } - pub fn spawn_terminals_for_layout(&mut self, layout_path: PathBuf) { - let layout = Layout::new(layout_path.clone()); + pub fn spawn_terminals_for_layout(&mut self, layout: Layout) { let total_panes = layout.total_terminal_panes(); let mut new_pane_pids = vec![]; for _ in 0..total_panes { @@ -204,7 +203,7 @@ impl PtyBus { } self.send_screen_instructions .send(ScreenInstruction::ApplyLayout( - layout_path, + layout, new_pane_pids.clone(), )) .unwrap(); diff --git a/src/common/screen.rs b/src/common/screen.rs index c30cf251..c5e4f9a5 100644 --- a/src/common/screen.rs +++ b/src/common/screen.rs @@ -2,7 +2,6 @@ use std::collections::BTreeMap; use std::os::unix::io::RawFd; -use std::path::PathBuf; use std::str; use std::sync::mpsc::Receiver; @@ -49,7 +48,7 @@ pub enum ScreenInstruction { SetMaxHeight(PaneId, usize), SetInvisibleBorders(PaneId, bool), ClosePane(PaneId), - ApplyLayout(PathBuf, Vec), + ApplyLayout(Layout, Vec), NewTab(RawFd), SwitchTabNext, SwitchTabPrev, @@ -83,6 +82,8 @@ pub struct Screen { /// The [`ClientOsApi`] this [`Screen`] uses. os_api: Box, mode_info: ModeInfo, + input_mode: InputMode, + colors: Palette, } impl Screen { diff --git a/src/common/utils/consts.rs b/src/common/utils/consts.rs index c21e3029..3a783914 100644 --- a/src/common/utils/consts.rs +++ b/src/common/utils/consts.rs @@ -9,12 +9,19 @@ pub const ZELLIJ_TMP_DIR: &str = "/tmp/zellij"; pub const ZELLIJ_TMP_LOG_DIR: &str = "/tmp/zellij/zellij-log"; pub const ZELLIJ_TMP_LOG_FILE: &str = "/tmp/zellij/zellij-log/log.txt"; +pub const ZELLIJ_CONFIG_FILE_ENV: &str = "ZELLIJ_CONFIG_FILE"; +pub const ZELLIJ_CONFIG_DIR_ENV: &str = "ZELLIJ_CONFIG_DIR"; + +// TODO: ${PREFIX} argument in makefile +pub const SYSTEM_DEFAULT_CONFIG_DIR: &str = "/etc/zellij"; + lazy_static! { static ref UID: Uid = Uid::current(); pub static ref SESSION_NAME: String = names::Generator::default().next().unwrap(); + pub static ref ZELLIJ_PROJ_DIR: ProjectDirs = + ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap(); pub static ref ZELLIJ_IPC_PIPE: PathBuf = { - let project_dir = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap(); - let mut ipc_dir = project_dir + let mut ipc_dir = ZELLIJ_PROJ_DIR .runtime_dir() .map(|p| p.to_owned()) .unwrap_or_else(|| PathBuf::from("/tmp/zellij-".to_string() + &format!("{}", *UID))); diff --git a/src/common/wasm_vm.rs b/src/common/wasm_vm.rs index 5c234403..db52c2bb 100644 --- a/src/common/wasm_vm.rs +++ b/src/common/wasm_vm.rs @@ -27,7 +27,8 @@ pub struct PluginEnv { pub plugin_id: u32, // FIXME: This should be a big bundle of all of the channels pub send_screen_instructions: SenderWithContext, - pub send_pty_instructions: SenderWithContext, // FIXME: This should be a big bundle of all of the channels + pub send_pty_instructions: SenderWithContext, + pub send_plugin_instructions: SenderWithContext, pub wasi_env: WasiEnv, pub subscriptions: Arc>>, } @@ -70,14 +71,6 @@ fn host_unsubscribe(plugin_env: &PluginEnv) { subscriptions.retain(|k| !old.contains(k)); } -fn host_open_file(plugin_env: &PluginEnv) { - let path = PathBuf::from(wasi_stdout(&plugin_env.wasi_env).lines().next().unwrap()); - plugin_env - .send_pty_instructions - .send(PtyInstruction::SpawnTerminal(Some(path))) - .unwrap(); -} - fn host_set_selectable(plugin_env: &PluginEnv, selectable: i32) { let selectable = selectable != 0; plugin_env diff --git a/src/main.rs b/src/main.rs index e6edfdfd..6ee344bc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,69 +2,67 @@ mod cli; mod client; mod common; mod server; +#[cfg(test)] +mod tests; use client::{boundaries, layout, panes, start_client, tab}; -use common::{command_is_executing, errors, os_input_output, pty_bus, screen, utils, wasm_vm}; -use directories_next::ProjectDirs; +use common::{ + command_is_executing, errors, os_input_output, pty_bus, screen, setup, utils, wasm_vm, +}; use server::start_server; - use structopt::StructOpt; use crate::cli::CliArgs; use crate::command_is_executing::CommandIsExecuting; +use crate::common::input::config::Config; use crate::os_input_output::{get_client_os_input, get_server_os_input, ClientOsApi, ServerOsApi}; use crate::utils::{ consts::{ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR}, logging::*, }; -use client::{boundaries, layout, panes, tab}; -use common::{ - command_is_executing, errors, os_input_output, pty_bus, screen, setup, start, utils, wasm_vm, - ApiCommand, -}; use std::convert::TryFrom; -use std::io::Write; -use std::os::unix::net::UnixStream; -use structopt::StructOpt; pub fn main() { - // First run installation of default plugins & layouts - let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap(); - let data_dir = project_dirs.data_dir(); - let mut assets = asset_map! { - "assets/layouts/default.yaml" => "layouts/default.yaml", - "assets/layouts/strider.yaml" => "layouts/strider.yaml", - }; - assets.extend(asset_map! { - "assets/plugins/status-bar.wasm" => "plugins/status-bar.wasm", - "assets/plugins/tab-bar.wasm" => "plugins/tab-bar.wasm", - "assets/plugins/strider.wasm" => "plugins/strider.wasm", - }); - - for (path, bytes) in assets { - let path = data_dir.join(path); - std::fs::create_dir_all(path.parent().unwrap()).unwrap(); - if !path.exists() { - std::fs::write(path, bytes).expect("Failed to install default assets!"); - } - } - let opts = CliArgs::from_args(); - atomic_create_dir(ZELLIJ_TMP_DIR).unwrap(); - atomic_create_dir(ZELLIJ_TMP_LOG_DIR).unwrap(); - let server_os_input = get_server_os_input(); - let os_input = get_client_os_input(); - start(Box::new(os_input), opts, Box::new(server_os_input)); + let config = match Config::try_from(&opts) { + Ok(config) => config, + Err(e) => { + eprintln!("There was an error in the config file:\n{}", e); + std::process::exit(1); + } + }; + if let Some(crate::cli::ConfigCli::GenerateCompletion { shell }) = opts.option { + let shell = match shell.as_ref() { + "bash" => structopt::clap::Shell::Bash, + "fish" => structopt::clap::Shell::Fish, + "zsh" => structopt::clap::Shell::Zsh, + "powerShell" => structopt::clap::Shell::PowerShell, + "elvish" => structopt::clap::Shell::Elvish, + other => { + eprintln!("Unsupported shell: {}", other); + std::process::exit(1); + } + }; + let mut out = std::io::stdout(); + CliArgs::clap().gen_completions_to("zellij", shell, &mut out); + } else if let Some(crate::cli::ConfigCli::Setup { .. }) = opts.option { + setup::dump_default_config().expect("Failed to print to stdout"); + std::process::exit(1); + } else { + atomic_create_dir(ZELLIJ_TMP_DIR).unwrap(); + atomic_create_dir(ZELLIJ_TMP_LOG_DIR).unwrap(); + let server_os_input = get_server_os_input(); + let os_input = get_client_os_input(); + start(Box::new(os_input), opts, Box::new(server_os_input), config); + } } - -/// Start Zellij with the specified [`ClientOsApi`], [`ServerOsApi`] and command-line arguments. -// FIXME this should definitely be modularized and split into different functions. pub fn start( client_os_input: Box, opts: CliArgs, server_os_input: Box, + config: Config, ) { - let ipc_thread = start_server(server_os_input, opts.clone()); - start_client(client_os_input, opts); + let ipc_thread = start_server(server_os_input); + start_client(client_os_input, opts, config); drop(ipc_thread.join()); } diff --git a/src/server/mod.rs b/src/server/mod.rs index 25a95222..27539c09 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,4 +1,3 @@ -use directories_next::ProjectDirs; use interprocess::local_socket::LocalSocketListener; use serde::{Deserialize, Serialize}; use std::path::PathBuf; @@ -12,7 +11,7 @@ use std::{ }; use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value}; use wasmer_wasi::{Pipe, WasiState}; -use zellij_tile::data::{Event, EventType, ModeInfo}; +use zellij_tile::data::{Event, EventType, InputMode, ModeInfo}; use crate::cli::CliArgs; use crate::client::ClientInstruction; @@ -23,8 +22,9 @@ use crate::common::{ os_input_output::ServerOsApi, pty_bus::{PtyBus, PtyInstruction}, screen::{Screen, ScreenInstruction}, - utils::consts::ZELLIJ_IPC_PIPE, - wasm_vm::{wasi_stdout, wasi_write_string, zellij_imports, PluginEnv, PluginInstruction}, + setup::install::populate_data_dir, + utils::consts::{ZELLIJ_IPC_PIPE, ZELLIJ_PROJ_DIR}, + wasm_vm::{wasi_read_string, wasi_write_object, zellij_exports, PluginEnv, PluginInstruction}, ChannelWithContext, SenderType, SenderWithContext, }; use crate::layout::Layout; @@ -36,7 +36,7 @@ use crate::panes::PositionAndSize; #[derive(Serialize, Deserialize, Debug, Clone)] pub enum ServerInstruction { TerminalResize(PositionAndSize), - NewClient(PositionAndSize), + NewClient(PositionAndSize, CliArgs), Action(Action), Render(Option), UnblockInputThread, @@ -63,7 +63,7 @@ impl Drop for SessionMetaData { } } -pub fn start_server(os_input: Box, opts: CliArgs) -> thread::JoinHandle<()> { +pub fn start_server(os_input: Box) -> thread::JoinHandle<()> { let (send_server_instructions, receive_server_instructions): ChannelWithContext< ServerInstruction, > = channel(); @@ -111,10 +111,10 @@ pub fn start_server(os_input: Box, opts: CliArgs) -> thread::Jo let (instruction, mut err_ctx) = receive_server_instructions.recv().unwrap(); err_ctx.add_call(ContextType::IPCServer(ServerContext::from(&instruction))); match instruction { - ServerInstruction::NewClient(full_screen_ws) => { + ServerInstruction::NewClient(full_screen_ws, opts) => { let session_data = init_session( os_input.clone(), - opts.clone(), + opts, send_server_instructions.clone(), full_screen_ws, ); @@ -164,7 +164,7 @@ fn handle_client( break; } ServerInstruction::Action(action) => { - route_action(action, rlocked_sessions.as_ref().unwrap()); + route_action(action, rlocked_sessions.as_ref().unwrap(), &*os_input); } ServerInstruction::TerminalResize(new_size) => { rlocked_sessions @@ -174,7 +174,7 @@ fn handle_client( .send(ScreenInstruction::TerminalResize(new_size)) .unwrap(); } - ServerInstruction::NewClient(_) => { + ServerInstruction::NewClient(..) => { os_input.add_client_sender(); send_server_instructions.send(instruction).unwrap(); } @@ -207,18 +207,27 @@ fn init_session( channel(); let send_pty_instructions = SenderWithContext::new(SenderType::Sender(send_pty_instructions)); + // Determine and initialize the data directory + let data_dir = opts + .data_dir + .unwrap_or_else(|| ZELLIJ_PROJ_DIR.data_dir().to_path_buf()); + populate_data_dir(&data_dir); + // Don't use default layouts in tests, but do everywhere else #[cfg(not(test))] let default_layout = Some(PathBuf::from("default")); #[cfg(test)] let default_layout = None; - let maybe_layout = opts.layout.or(default_layout); + let maybe_layout = opts + .layout + .map(|p| Layout::new(&p, &data_dir)) + .or_else(|| default_layout.map(|p| Layout::from_defaults(&p, &data_dir))); let mut pty_bus = PtyBus::new( receive_pty_instructions, - os_input.clone(), send_screen_instructions.clone(), send_plugin_instructions.clone(), + os_input.clone(), opts.debug, ); @@ -293,6 +302,7 @@ fn init_session( let send_pty_instructions = send_pty_instructions.clone(); let send_server_instructions = send_server_instructions; let max_panes = opts.max_panes; + let colors = os_input.load_palette(); move || { let mut screen = Screen::new( @@ -303,7 +313,12 @@ fn init_session( &full_screen_ws, os_input, max_panes, - ModeInfo::default(), + ModeInfo { + palette: colors, + ..ModeInfo::default() + }, + InputMode::Normal, + colors, ); loop { let (event, mut err_ctx) = screen @@ -355,10 +370,11 @@ fn init_session( .unwrap(); } ScreenInstruction::WriteCharacter(bytes) => { - screen - .get_active_tab_mut() - .unwrap() - .write_to_active_terminal(bytes); + let active_tab = screen.get_active_tab_mut().unwrap(); + match active_tab.is_sync_panes_active() { + true => active_tab.write_to_terminals_on_current_tab(bytes), + false => active_tab.write_to_active_terminal(bytes), + } } ScreenInstruction::ResizeLeft => { screen.get_active_tab_mut().unwrap().resize_left(); @@ -405,6 +421,18 @@ fn init_session( .unwrap() .scroll_active_terminal_down(); } + ScreenInstruction::PageScrollUp => { + screen + .get_active_tab_mut() + .unwrap() + .scroll_active_terminal_up_page(); + } + ScreenInstruction::PageScrollDown => { + screen + .get_active_tab_mut() + .unwrap() + .scroll_active_terminal_down_page(); + } ScreenInstruction::ClearScroll => { screen .get_active_tab_mut() @@ -473,7 +501,7 @@ fn init_session( .unwrap(); } ScreenInstruction::ApplyLayout(layout, new_pane_pids) => { - screen.apply_layout(Layout::new(layout), new_pane_pids); + screen.apply_layout(layout, new_pane_pids); screen .send_server_instructions .send(ServerInstruction::UnblockInputThread) @@ -493,11 +521,18 @@ fn init_session( .send(ServerInstruction::UnblockInputThread) .unwrap(); } + ScreenInstruction::TerminalResize(new_size) => { + screen.resize_to_screen(new_size); + } ScreenInstruction::ChangeMode(mode_info) => { screen.change_mode(mode_info); } - ScreenInstruction::TerminalResize(new_size) => { - screen.resize_to_screen(new_size); + ScreenInstruction::ToggleActiveSyncPanes => { + screen + .get_active_tab_mut() + .unwrap() + .toggle_sync_panes_is_active(); + screen.update_tabs(); } ScreenInstruction::Exit => { break; @@ -513,6 +548,7 @@ fn init_session( .spawn({ let send_screen_instructions = send_screen_instructions.clone(); let send_pty_instructions = send_pty_instructions.clone(); + let send_plugin_instructions = send_plugin_instructions.clone(); let store = Store::default(); let mut plugin_id = 0; @@ -524,9 +560,7 @@ fn init_session( err_ctx.add_call(ContextType::Plugin(PluginContext::from(&event))); match event { PluginInstruction::Load(pid_tx, path) => { - let project_dirs = - ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap(); - let plugin_dir = project_dirs.data_dir().join("plugins/"); + let plugin_dir = data_dir.join("plugins/"); let wasm_bytes = fs::read(&path) .or_else(|_| fs::read(&path.with_extension("wasm"))) .or_else(|_| fs::read(&plugin_dir.join(&path).with_extension("wasm"))) @@ -558,11 +592,12 @@ fn init_session( plugin_id, send_screen_instructions: send_screen_instructions.clone(), send_pty_instructions: send_pty_instructions.clone(), + send_plugin_instructions: send_plugin_instructions.clone(), wasi_env, subscriptions: Arc::new(Mutex::new(HashSet::new())), }; - let zellij = zellij_imports(&store, &plugin_env); + let zellij = zellij_exports(&store, &plugin_env); let instance = Instance::new(&module, &zellij.chain_back(wasi)).unwrap(); let start = instance.exports.get_function("_start").unwrap(); @@ -581,10 +616,7 @@ fn init_session( let event_type = EventType::from_str(&event.to_string()).unwrap(); if (pid.is_none() || pid == Some(i)) && subs.contains(&event_type) { let update = instance.exports.get_function("update").unwrap(); - wasi_write_string( - &plugin_env.wasi_env, - &serde_json::to_string(&event).unwrap(), - ); + wasi_write_object(&plugin_env.wasi_env, &event); update.call(&[]).unwrap(); } } @@ -599,7 +631,7 @@ fn init_session( .call(&[Value::I32(rows as i32), Value::I32(cols as i32)]) .unwrap(); - buf_tx.send(wasi_stdout(&plugin_env.wasi_env)).unwrap(); + buf_tx.send(wasi_read_string(&plugin_env.wasi_env)).unwrap(); } PluginInstruction::Unload(pid) => drop(plugin_map.remove(&pid)), PluginInstruction::Exit => break, @@ -617,7 +649,7 @@ fn init_session( } } -fn route_action(action: Action, session: &SessionMetaData) { +fn route_action(action: Action, session: &SessionMetaData, os_input: &dyn ServerOsApi) { match action { Action::Write(val) => { session @@ -630,16 +662,17 @@ fn route_action(action: Action, session: &SessionMetaData) { .unwrap(); } Action::SwitchToMode(mode) => { + let palette = os_input.load_palette(); session .send_plugin_instructions .send(PluginInstruction::Update( None, - Event::ModeUpdate(get_mode_info(mode)), + Event::ModeUpdate(get_mode_info(mode, palette)), )) .unwrap(); session .send_screen_instructions - .send(ScreenInstruction::ChangeMode(get_mode_info(mode))) + .send(ScreenInstruction::ChangeMode(get_mode_info(mode, palette))) .unwrap(); session .send_screen_instructions @@ -694,6 +727,18 @@ fn route_action(action: Action, session: &SessionMetaData) { .send(ScreenInstruction::ScrollDown) .unwrap(); } + Action::PageScrollUp => { + session + .send_screen_instructions + .send(ScreenInstruction::PageScrollUp) + .unwrap(); + } + Action::PageScrollDown => { + session + .send_screen_instructions + .send(ScreenInstruction::PageScrollDown) + .unwrap(); + } Action::ToggleFocusFullscreen => { session .send_screen_instructions @@ -735,6 +780,12 @@ fn route_action(action: Action, session: &SessionMetaData) { .send(ScreenInstruction::SwitchTabPrev) .unwrap(); } + Action::ToggleActiveSyncPanes => { + session + .send_screen_instructions + .send(ScreenInstruction::ToggleActiveSyncPanes) + .unwrap(); + } Action::CloseTab => { session .send_screen_instructions diff --git a/src/tests/fakes.rs b/src/tests/fakes.rs index bc18d6fd..711d48ad 100644 --- a/src/tests/fakes.rs +++ b/src/tests/fakes.rs @@ -14,6 +14,8 @@ use crate::os_input_output::{ClientOsApi, ServerOsApi}; use crate::server::ServerInstruction; use crate::tests::possible_tty_inputs::{get_possible_tty_inputs, Bytes}; use crate::tests::utils::commands::{QUIT, SLEEP}; +use crate::utils::shared::colors; +use zellij_tile::data::{Palette, PaletteSource, Theme}; const MIN_TIME_BETWEEN_SNAPSHOTS: Duration = Duration::from_millis(150); @@ -81,6 +83,7 @@ pub struct FakeInputOutput { receive_instructions_from_client: Arc>>, should_trigger_sigwinch: Arc<(Mutex, Condvar)>, sigwinch_event: Option, + palette: Arc>, } impl FakeInputOutput { @@ -96,6 +99,21 @@ impl FakeInputOutput { let send_instructions_to_server = SenderWithContext::new(SenderType::Sender(server_sender)); win_sizes.insert(0, winsize); // 0 is the current terminal + let palette: Palette = Palette { + source: PaletteSource::Default, + theme: Theme::Dark, + fg: colors::BRIGHT_GRAY, + bg: colors::GRAY, + black: colors::BLACK, + red: colors::RED, + green: colors::GREEN, + yellow: colors::GRAY, + blue: colors::GRAY, + magenta: colors::GRAY, + cyan: colors::GRAY, + white: colors::WHITE, + orange: colors::ORANGE, + }; FakeInputOutput { read_buffers: Arc::new(Mutex::new(HashMap::new())), stdin_writes: Arc::new(Mutex::new(HashMap::new())), @@ -112,6 +130,7 @@ impl FakeInputOutput { send_instructions_to_client, should_trigger_sigwinch: Arc::new((Mutex::new(false), Condvar::new())), sigwinch_event: None, + palette: Arc::new(Mutex::new(palette)), } } pub fn with_tty_inputs(mut self, tty_inputs: HashMap) -> Self { @@ -289,4 +308,22 @@ impl ServerOsApi for FakeInputOutput { } fn add_client_sender(&mut self) {} fn update_receiver(&mut self, _stream: LocalSocketStream) {} + fn load_palette(&self) -> Palette { + let palette: Palette = Palette { + source: PaletteSource::Default, + theme: Theme::Dark, + fg: colors::BRIGHT_GRAY, + bg: colors::GRAY, + black: colors::BLACK, + red: colors::RED, + green: colors::GREEN, + yellow: colors::GRAY, + blue: colors::GRAY, + magenta: colors::GRAY, + cyan: colors::GRAY, + white: colors::WHITE, + orange: colors::ORANGE, + }; + palette + } } diff --git a/src/tests/integration/basic.rs b/src/tests/integration/basic.rs index 406e6174..c8305cab 100644 --- a/src/tests/integration/basic.rs +++ b/src/tests/integration/basic.rs @@ -31,6 +31,7 @@ pub fn starts_with_one_terminal() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -58,6 +59,7 @@ pub fn split_terminals_vertically() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -85,6 +87,7 @@ pub fn split_terminals_horizontally() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -119,6 +122,7 @@ pub fn split_largest_terminal() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -146,6 +150,7 @@ pub fn cannot_split_terminals_vertically_when_active_terminal_is_too_small() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -173,6 +178,7 @@ pub fn cannot_split_terminals_horizontally_when_active_terminal_is_too_small() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -200,6 +206,7 @@ pub fn cannot_split_largest_terminal_when_there_is_no_room() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -235,6 +242,7 @@ pub fn scrolling_up_inside_a_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -272,6 +280,80 @@ pub fn scrolling_down_inside_a_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), + ); + let output_frames = fake_input_output + .stdout_writer + .output_frames + .lock() + .unwrap(); + let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size); + let snapshot_before_quit = + get_next_to_last_snapshot(snapshots).expect("could not find snapshot"); + assert_snapshot!(snapshot_before_quit); +} + +#[test] +pub fn scrolling_page_up_inside_a_pane() { + let fake_win_size = PositionAndSize { + columns: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut fake_input_output = get_fake_os_input(&fake_win_size); + fake_input_output.add_terminal_input(&[ + &PANE_MODE, + &SPLIT_DOWN_IN_PANE_MODE, + &SPLIT_RIGHT_IN_PANE_MODE, + &SCROLL_MODE, + &SCROLL_PAGE_UP_IN_SCROLL_MODE, + &QUIT, + ]); + start( + Box::new(fake_input_output.clone()), + CliArgs::default(), + Box::new(fake_input_output.clone()), + Config::default(), + ); + let output_frames = fake_input_output + .stdout_writer + .output_frames + .lock() + .unwrap(); + let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size); + let snapshot_before_quit = + get_next_to_last_snapshot(snapshots).expect("could not find snapshot"); + assert_snapshot!(snapshot_before_quit); +} + +#[test] +pub fn scrolling_page_down_inside_a_pane() { + let fake_win_size = PositionAndSize { + columns: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut fake_input_output = get_fake_os_input(&fake_win_size); + fake_input_output.add_terminal_input(&[ + &PANE_MODE, + &SPLIT_DOWN_IN_PANE_MODE, + &SPLIT_RIGHT_IN_PANE_MODE, + &SCROLL_MODE, + &SCROLL_PAGE_UP_IN_SCROLL_MODE, + &SCROLL_PAGE_UP_IN_SCROLL_MODE, + &SCROLL_PAGE_DOWN_IN_SCROLL_MODE, + &SCROLL_PAGE_DOWN_IN_SCROLL_MODE, + &QUIT, + ]); + start( + Box::new(fake_input_output.clone()), + CliArgs::default(), + Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -310,6 +392,7 @@ pub fn max_panes() { Box::new(fake_input_output.clone()), opts, Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -346,6 +429,7 @@ pub fn toggle_focused_pane_fullscreen() { Box::new(fake_input_output.clone()), opts, Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer diff --git a/src/tests/integration/close_pane.rs b/src/tests/integration/close_pane.rs index 5feee241..869debed 100644 --- a/src/tests/integration/close_pane.rs +++ b/src/tests/integration/close_pane.rs @@ -44,6 +44,7 @@ pub fn close_pane_with_another_pane_above_it() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -86,6 +87,7 @@ pub fn close_pane_with_another_pane_below_it() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -125,6 +127,7 @@ pub fn close_pane_with_another_pane_to_the_left() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -165,6 +168,7 @@ pub fn close_pane_with_another_pane_to_the_right() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -210,6 +214,7 @@ pub fn close_pane_with_multiple_panes_above_it() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -253,6 +258,7 @@ pub fn close_pane_with_multiple_panes_below_it() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -298,6 +304,7 @@ pub fn close_pane_with_multiple_panes_to_the_left() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -341,6 +348,7 @@ pub fn close_pane_with_multiple_panes_to_the_right() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -406,6 +414,7 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -467,6 +476,7 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -530,6 +540,7 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -593,6 +604,7 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -629,6 +641,7 @@ pub fn closing_last_pane_exits_app() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output diff --git a/src/tests/integration/compatibility.rs b/src/tests/integration/compatibility.rs index 861d5a05..77d3b67e 100644 --- a/src/tests/integration/compatibility.rs +++ b/src/tests/integration/compatibility.rs @@ -47,6 +47,7 @@ pub fn run_bandwhich_from_fish_shell() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -75,6 +76,7 @@ pub fn fish_tab_completion_options() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -108,6 +110,7 @@ pub fn fish_select_tab_completion_options() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -145,6 +148,7 @@ pub fn vim_scroll_region_down() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -179,6 +183,7 @@ pub fn vim_ctrl_d() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -212,6 +217,7 @@ pub fn vim_ctrl_u() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -240,6 +246,7 @@ pub fn htop() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -268,6 +275,7 @@ pub fn htop_scrolling() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -296,6 +304,7 @@ pub fn htop_right_scrolling() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -332,6 +341,7 @@ pub fn vim_overwrite() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -363,6 +373,7 @@ pub fn clear_scroll_region() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -391,6 +402,7 @@ pub fn display_tab_characters_properly() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -419,6 +431,7 @@ pub fn neovim_insert_mode() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -449,6 +462,7 @@ pub fn bash_cursor_linewrap() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -479,6 +493,7 @@ pub fn fish_paste_multiline() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -507,6 +522,7 @@ pub fn git_log() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -537,6 +553,7 @@ pub fn git_diff_scrollup() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -565,6 +582,7 @@ pub fn emacs_longbuf() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -593,6 +611,7 @@ pub fn top_and_quit() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -627,6 +646,7 @@ pub fn exa_plus_omf_theme() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer diff --git a/src/tests/integration/layouts.rs b/src/tests/integration/layouts.rs index 753453c9..a07995f6 100644 --- a/src/tests/integration/layouts.rs +++ b/src/tests/integration/layouts.rs @@ -32,6 +32,7 @@ pub fn accepts_basic_layout() { Box::new(fake_input_output.clone()), opts, Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer diff --git a/src/tests/integration/move_focus_down.rs b/src/tests/integration/move_focus_down.rs index ca487be5..8ea953c6 100644 --- a/src/tests/integration/move_focus_down.rs +++ b/src/tests/integration/move_focus_down.rs @@ -36,6 +36,7 @@ pub fn move_focus_down() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -72,6 +73,7 @@ pub fn move_focus_down_to_the_most_recently_used_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output diff --git a/src/tests/integration/move_focus_left.rs b/src/tests/integration/move_focus_left.rs index 60f89ffd..3b87bb95 100644 --- a/src/tests/integration/move_focus_left.rs +++ b/src/tests/integration/move_focus_left.rs @@ -35,6 +35,7 @@ pub fn move_focus_left() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -72,6 +73,7 @@ pub fn move_focus_left_to_the_most_recently_used_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output diff --git a/src/tests/integration/move_focus_right.rs b/src/tests/integration/move_focus_right.rs index 22f09136..c6c17a75 100644 --- a/src/tests/integration/move_focus_right.rs +++ b/src/tests/integration/move_focus_right.rs @@ -36,6 +36,7 @@ pub fn move_focus_right() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -72,6 +73,7 @@ pub fn move_focus_right_to_the_most_recently_used_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output diff --git a/src/tests/integration/move_focus_up.rs b/src/tests/integration/move_focus_up.rs index 4f0416d4..62b64ed1 100644 --- a/src/tests/integration/move_focus_up.rs +++ b/src/tests/integration/move_focus_up.rs @@ -35,6 +35,7 @@ pub fn move_focus_up() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -72,6 +73,7 @@ pub fn move_focus_up_to_the_most_recently_used_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output diff --git a/src/tests/integration/resize_down.rs b/src/tests/integration/resize_down.rs index 745ba109..58104fe1 100644 --- a/src/tests/integration/resize_down.rs +++ b/src/tests/integration/resize_down.rs @@ -47,6 +47,7 @@ pub fn resize_down_with_pane_above() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -91,6 +92,7 @@ pub fn resize_down_with_pane_below() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -141,6 +143,7 @@ pub fn resize_down_with_panes_above_and_below() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -190,6 +193,7 @@ pub fn resize_down_with_multiple_panes_above() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -241,6 +245,7 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -291,6 +296,7 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -339,6 +345,7 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -388,6 +395,7 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -440,6 +448,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -494,6 +503,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -565,6 +575,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -638,6 +649,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_ Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -679,6 +691,7 @@ pub fn cannot_resize_down_when_pane_below_is_at_minimum_height() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output diff --git a/src/tests/integration/resize_left.rs b/src/tests/integration/resize_left.rs index 307198b1..d31dd6d2 100644 --- a/src/tests/integration/resize_left.rs +++ b/src/tests/integration/resize_left.rs @@ -43,6 +43,7 @@ pub fn resize_left_with_pane_to_the_left() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -85,6 +86,7 @@ pub fn resize_left_with_pane_to_the_right() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -129,6 +131,7 @@ pub fn resize_left_with_panes_to_the_left_and_right() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -176,6 +179,7 @@ pub fn resize_left_with_multiple_panes_to_the_left() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -225,6 +229,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -271,6 +276,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -319,6 +325,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -366,6 +373,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -418,6 +426,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -472,6 +481,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -543,6 +553,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -617,6 +628,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -658,6 +670,7 @@ pub fn cannot_resize_left_when_pane_to_the_left_is_at_minimum_width() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output diff --git a/src/tests/integration/resize_right.rs b/src/tests/integration/resize_right.rs index 05553de1..e5ea1b9d 100644 --- a/src/tests/integration/resize_right.rs +++ b/src/tests/integration/resize_right.rs @@ -43,6 +43,7 @@ pub fn resize_right_with_pane_to_the_left() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -85,6 +86,7 @@ pub fn resize_right_with_pane_to_the_right() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -129,6 +131,7 @@ pub fn resize_right_with_panes_to_the_left_and_right() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -176,6 +179,7 @@ pub fn resize_right_with_multiple_panes_to_the_left() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -225,6 +229,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -271,6 +276,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -319,6 +325,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -366,6 +373,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -418,6 +426,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -472,6 +481,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_ Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -543,6 +553,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -616,6 +627,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -657,6 +669,7 @@ pub fn cannot_resize_right_when_pane_to_the_left_is_at_minimum_width() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output diff --git a/src/tests/integration/resize_up.rs b/src/tests/integration/resize_up.rs index 6330b074..14819331 100644 --- a/src/tests/integration/resize_up.rs +++ b/src/tests/integration/resize_up.rs @@ -45,6 +45,7 @@ pub fn resize_up_with_pane_above() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -89,6 +90,7 @@ pub fn resize_up_with_pane_below() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -138,6 +140,7 @@ pub fn resize_up_with_panes_above_and_below() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -186,6 +189,7 @@ pub fn resize_up_with_multiple_panes_above() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -235,6 +239,7 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -285,6 +290,7 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -333,6 +339,7 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -382,6 +389,7 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -434,6 +442,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -488,6 +497,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -559,6 +569,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_ Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -632,6 +643,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -673,6 +685,7 @@ pub fn cannot_resize_up_when_pane_above_is_at_minimum_height() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output diff --git a/src/tests/integration/tabs.rs b/src/tests/integration/tabs.rs index d45ec18a..0c751634 100644 --- a/src/tests/integration/tabs.rs +++ b/src/tests/integration/tabs.rs @@ -37,6 +37,7 @@ pub fn open_new_tab() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -72,6 +73,7 @@ pub fn switch_to_prev_tab() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -107,6 +109,7 @@ pub fn switch_to_next_tab() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -142,6 +145,7 @@ pub fn close_tab() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -178,6 +182,7 @@ pub fn close_last_pane_in_a_tab() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -216,6 +221,7 @@ pub fn close_the_middle_tab() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -259,6 +265,7 @@ pub fn close_the_tab_that_has_a_pane_in_fullscreen() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -294,6 +301,7 @@ pub fn closing_last_tab_exits_the_app() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output diff --git a/src/tests/integration/terminal_window_resize.rs b/src/tests/integration/terminal_window_resize.rs index 5aa13e15..057c2523 100644 --- a/src/tests/integration/terminal_window_resize.rs +++ b/src/tests/integration/terminal_window_resize.rs @@ -34,6 +34,7 @@ pub fn window_width_decrease_with_one_pane() { Box::new(fake_input_output.clone()), opts, Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -69,6 +70,7 @@ pub fn window_width_increase_with_one_pane() { Box::new(fake_input_output.clone()), opts, Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -104,6 +106,7 @@ pub fn window_height_increase_with_one_pane() { Box::new(fake_input_output.clone()), opts, Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer @@ -139,6 +142,7 @@ pub fn window_width_and_height_decrease_with_one_pane() { Box::new(fake_input_output.clone()), opts, Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output .stdout_writer diff --git a/src/tests/integration/toggle_fullscreen.rs b/src/tests/integration/toggle_fullscreen.rs index 83a8f215..0e967bd2 100644 --- a/src/tests/integration/toggle_fullscreen.rs +++ b/src/tests/integration/toggle_fullscreen.rs @@ -36,6 +36,7 @@ pub fn adding_new_terminal_in_fullscreen() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output @@ -70,6 +71,7 @@ pub fn move_focus_is_disabled_in_fullscreen() { Box::new(fake_input_output.clone()), CliArgs::default(), Box::new(fake_input_output.clone()), + Config::default(), ); let output_frames = fake_input_output