summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--Cargo.lock1
-rw-r--r--Cargo.toml1
-rw-r--r--src/common/input/config.rs135
-rw-r--r--src/common/mod.rs11
-rw-r--r--src/main.rs11
-rw-r--r--src/tests/integration/basic.rs71
-rw-r--r--src/tests/integration/close_pane.rs79
-rw-r--r--src/tests/integration/compatibility.rs121
-rw-r--r--src/tests/integration/layouts.rs3
-rw-r--r--src/tests/integration/move_focus_down.rs13
-rw-r--r--src/tests/integration/move_focus_left.rs13
-rw-r--r--src/tests/integration/move_focus_right.rs13
-rw-r--r--src/tests/integration/move_focus_up.rs13
-rw-r--r--src/tests/integration/resize_down.rs79
-rw-r--r--src/tests/integration/resize_left.rs79
-rw-r--r--src/tests/integration/resize_right.rs79
-rw-r--r--src/tests/integration/resize_up.rs79
-rw-r--r--src/tests/integration/tabs.rs49
-rw-r--r--src/tests/integration/terminal_window_resize.rs9
-rw-r--r--src/tests/integration/toggle_fullscreen.rs13
21 files changed, 688 insertions, 185 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76dd7497f..20878035f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
## [Unreleased]
* Fix the tab '(Sync)' suffix in named tabs (https://github.com/zellij-org/zellij/pull/410)
* Improve performance when multiple panes are open (https://github.com/zellij-org/zellij/pull/318)
+* Improve error reporting and tests of configuration (https://github.com/zellij-org/zellij/pull/423)
## [0.6.0] - 2021-04-29
* Doesn't quit anymore on single `q` press while in tab mode (https://github.com/zellij-org/zellij/pull/342)
diff --git a/Cargo.lock b/Cargo.lock
index 0b18bd6bb..d5a0de39d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2239,6 +2239,7 @@ dependencies = [
"strip-ansi-escapes",
"structopt",
"strum",
+ "tempfile",
"termion",
"termios",
"unicode-truncate",
diff --git a/Cargo.toml b/Cargo.toml
index 1988dffa3..bfdfa8843 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -46,6 +46,7 @@ features = ["unstable"]
[dev-dependencies]
insta = "1.6.0"
+tempfile = "3.2.0"
[build-dependencies]
structopt = "0.3"
diff --git a/src/common/input/config.rs b/src/common/input/config.rs
index 62ec3dfe1..daa52b03b 100644
--- a/src/common/input/config.rs
+++ b/src/common/input/config.rs
@@ -6,14 +6,17 @@ use std::io::{self, Read};
use std::path::{Path, PathBuf};
use super::keybinds::{Keybinds, KeybindsFromYaml};
-use crate::cli::ConfigCli;
+use crate::cli::{CliArgs, ConfigCli};
use crate::common::install;
use serde::Deserialize;
+use std::convert::TryFrom;
+
+const DEFAULT_CONFIG_FILE_NAME: &str = "config.yaml";
type ConfigResult = Result<Config, ConfigError>;
-/// Intermediate deserialisation config struct
+/// Intermediate deserialization config struct
#[derive(Debug, Deserialize)]
pub struct ConfigFromYaml {
pub keybinds: Option<KeybindsFromYaml>,
@@ -27,13 +30,13 @@ pub struct Config {
#[derive(Debug)]
pub enum ConfigError {
- // Deserialisation error
+ // Deserialization error
Serde(serde_yaml::Error),
// Io error
Io(io::Error),
// Io error with path context
IoPath(io::Error, PathBuf),
- // Internal Deserialisation Error
+ // Internal Deserialization Error
FromUtf8(std::string::FromUtf8Error),
}
@@ -44,6 +47,35 @@ impl Default for Config {
}
}
+impl TryFrom<&CliArgs> for Config {
+ type Error = ConfigError;
+
+ fn try_from(opts: &CliArgs) -> ConfigResult {
+ if let Some(ref path) = opts.config {
+ return Config::new(&path);
+ }
+
+ if let Some(ConfigCli::Config { clean, .. }) = opts.option {
+ if clean {
+ return Config::from_default_assets();
+ }
+ }
+
+ let config_dir = opts.config_dir.clone().or_else(install::default_config_dir);
+
+ if let Some(ref config) = config_dir {
+ let path = config.join(DEFAULT_CONFIG_FILE_NAME);
+ if path.exists() {
+ Config::new(&path)
+ } else {
+ Config::from_default_assets()
+ }
+ } else {
+ Config::from_default_assets()
+ }
+ }
+}
+
impl Config {
/// Uses defaults, but lets config override them.
pub fn from_yaml(yaml_config: &str) -> ConfigResult {
@@ -71,45 +103,6 @@ impl Config {
pub fn from_default_assets() -> ConfigResult {
Self::from_yaml(String::from_utf8(install::DEFAULT_CONFIG.to_vec())?.as_str())
}
-
- /// Entry point of the configuration
- #[cfg(not(test))]
- pub fn from_cli_config(
- location: Option<PathBuf>,
- cli_config: Option<ConfigCli>,
- config_dir: Option<PathBuf>,
- ) -> ConfigResult {
- if let Some(path) = location {
- return Config::new(&path);
- }
-
- if let Some(ConfigCli::Config { clean, .. }) = cli_config {
- if clean {
- return Config::from_default_assets();
- }
- }
-
- if let Some(config) = config_dir {
- let path = config.join("config.yaml");
- if path.exists() {
- Config::new(&path)
- } else {
- Config::from_default_assets()
- }
- } else {
- Config::from_default_assets()
- }
- }
-
- /// In order not to mess up tests from changing configurations
- #[cfg(test)]
- pub fn from_cli_config(
- _: Option<PathBuf>,
- _: Option<ConfigCli>,
- _: Option<PathBuf>,
- ) -> ConfigResult {
- Ok(Config::default())
- }
}
impl Display for ConfigError {
@@ -119,7 +112,7 @@ impl Display for ConfigError {
ConfigError::IoPath(ref err, ref path) => {
write!(formatter, "IoError: {}, File: {}", err, path.display(),)
}
- ConfigError::Serde(ref err) => write!(formatter, "Deserialisation error: {}", err),
+ ConfigError::Serde(ref err) => write!(formatter, "Deserialization error: {}", err),
ConfigError::FromUtf8(ref err) => write!(formatter, "FromUtf8Error: {}", err),
}
}
@@ -157,20 +150,56 @@ impl From<std::string::FromUtf8Error> for ConfigError {
// The unit test location.
#[cfg(test)]
mod config_test {
+ use std::io::Write;
+
+ use tempfile::tempdir;
+
use super::*;
#[test]
- fn clean_option_equals_default_config() {
- let cli_config = ConfigCli::Config { clean: true };
- let config = Config::from_cli_config(None, Some(cli_config), None).unwrap();
- let default = Config::default();
- assert_eq!(config, default);
+ fn try_from_cli_args_with_config() {
+ let arbitrary_config = PathBuf::from("nonexistent.yaml");
+ let mut opts = CliArgs::default();
+ opts.config = Some(arbitrary_config);
+ println!("OPTS= {:?}", opts);
+ let result = Config::try_from(&opts);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn try_from_cli_args_with_option_clean() {
+ let mut opts = CliArgs::default();
+ opts.option = Some(ConfigCli::Config { clean: true });
+ let result = Config::try_from(&opts);
+ assert!(result.is_ok());
+ }
+
+ #[test]
+ fn try_from_cli_args_with_config_dir() {
+ let mut opts = CliArgs::default();
+ let tmp = tempdir().unwrap();
+ File::create(tmp.path().join(DEFAULT_CONFIG_FILE_NAME))
+ .unwrap()
+ .write_all(b"keybinds: invalid\n")
+ .unwrap();
+ opts.config_dir = Some(tmp.path().to_path_buf());
+ let result = Config::try_from(&opts);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn try_from_cli_args_with_config_dir_without_config() {
+ let mut opts = CliArgs::default();
+ let tmp = tempdir().unwrap();
+ opts.config_dir = Some(tmp.path().to_path_buf());
+ let result = Config::try_from(&opts);
+ assert_eq!(result.unwrap(), Config::default());
}
#[test]
- fn no_config_option_file_equals_default_config() {
- let config = Config::from_cli_config(None, None, None).unwrap();
- let default = Config::default();
- assert_eq!(config, default);
+ fn try_from_cli_args_default() {
+ let opts = CliArgs::default();
+ let result = Config::try_from(&opts);
+ assert_eq!(result.unwrap(), Config::default());
}
}
diff --git a/src/common/mod.rs b/src/common/mod.rs
index c9b8e0e26..b17fce34e 100644
--- a/src/common/mod.rs
+++ b/src/common/mod.rs
@@ -120,7 +120,7 @@ pub enum AppInstruction {
/// Start Zellij with the specified [`OsApi`] and command-line arguments.
// FIXME this should definitely be modularized and split into different functions.
-pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
+pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs, config: Config) {
let take_snapshot = "\u{1b}[?1049h";
os_input.unset_raw_mode(0);
let _ = os_input
@@ -130,15 +130,6 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
env::set_var(&"ZELLIJ", "0");
- let config_dir = opts.config_dir.or_else(install::default_config_dir);
-
- let config = Config::from_cli_config(opts.config, opts.option, config_dir)
- .map_err(|e| {
- eprintln!("There was an error in the config file:\n{}", e);
- std::process::exit(1);
- })
- .unwrap();
-
let command_is_executing = CommandIsExecuting::new();
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
diff --git a/src/main.rs b/src/main.rs
index 12269ae91..e95471fb0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,6 +7,7 @@ mod client;
use crate::cli::CliArgs;
use crate::command_is_executing::CommandIsExecuting;
+use crate::common::input::config::Config;
use crate::os_input_output::get_os_input;
use crate::utils::{
consts::{ZELLIJ_IPC_PIPE, ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR},
@@ -17,12 +18,20 @@ use common::{
command_is_executing, errors, install, os_input_output, pty_bus, screen, 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() {
let opts = CliArgs::from_args();
+ 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(split_dir) = opts.split {
match split_dir {
'h' => {
@@ -66,6 +75,6 @@ pub fn main() {
let os_input = get_os_input();
atomic_create_dir(ZELLIJ_TMP_DIR).unwrap();
atomic_create_dir(ZELLIJ_TMP_LOG_DIR).unwrap();
- start(Box::new(os_input), opts);
+ start(Box::new(os_input), opts, config);
}
}
diff --git a/src/tests/integration/basic.rs b/src/tests/integration/basic.rs
index 9b1b2bdd7..f785666aa 100644
--- a/src/tests/integration/basic.rs
+++ b/src/tests/integration/basic.rs
@@ -1,6 +1,7 @@
use crate::panes::PositionAndSize;
use ::insta::assert_snapshot;
+use crate::common::input::config::Config;
use crate::tests::fakes::FakeInputOutput;
use crate::tests::utils::commands::{
PANE_MODE, QUIT, SCROLL_DOWN_IN_SCROLL_MODE, SCROLL_MODE, SCROLL_PAGE_DOWN_IN_SCROLL_MODE,
@@ -26,7 +27,11 @@ pub fn starts_with_one_terminal() {
};
let mut fake_input_output = get_fake_os_input(&fake_win_size);
fake_input_output.add_terminal_input(&[&QUIT]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -49,7 +54,11 @@ pub fn split_terminals_vertically() {
};
let mut fake_input_output = get_fake_os_input(&fake_win_size);
fake_input_output.add_terminal_input(&[&PANE_MODE, &SPLIT_RIGHT_IN_PANE_MODE, &QUIT]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -72,7 +81,11 @@ pub fn split_terminals_horizontally() {
};
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, &QUIT]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -102,7 +115,11 @@ pub fn split_largest_terminal() {
&SPAWN_TERMINAL_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -125,7 +142,11 @@ pub fn cannot_split_terminals_vertically_when_active_terminal_is_too_small() {
};
let mut fake_input_output = get_fake_os_input(&fake_win_size);
fake_input_output.add_terminal_input(&[&PANE_MODE, &SPLIT_RIGHT_IN_PANE_MODE, &QUIT]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -148,7 +169,11 @@ pub fn cannot_split_terminals_horizontally_when_active_terminal_is_too_small() {
};
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, &QUIT]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -171,7 +196,11 @@ pub fn cannot_split_largest_terminal_when_there_is_no_room() {
};
let mut fake_input_output = get_fake_os_input(&fake_win_size);
fake_input_output.add_terminal_input(&[&PANE_MODE, &SPAWN_TERMINAL_IN_PANE_MODE, &QUIT]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -202,7 +231,11 @@ pub fn scrolling_up_inside_a_pane() {
&SCROLL_UP_IN_SCROLL_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -235,7 +268,11 @@ pub fn scrolling_down_inside_a_pane() {
&SCROLL_DOWN_IN_SCROLL_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -265,7 +302,11 @@ pub fn scrolling_page_up_inside_a_pane() {
&SCROLL_PAGE_UP_IN_SCROLL_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -298,7 +339,11 @@ pub fn scrolling_page_down_inside_a_pane() {
&SCROLL_PAGE_DOWN_IN_SCROLL_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -332,7 +377,7 @@ pub fn max_panes() {
]);
let mut opts = CliArgs::default();
opts.max_panes = Some(4);
- start(Box::new(fake_input_output.clone()), opts);
+ start(Box::new(fake_input_output.clone()), opts, Config::default());
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -364,7 +409,7 @@ pub fn toggle_focused_pane_fullscreen() {
]);
let mut opts = CliArgs::default();
opts.max_panes = Some(4);
- start(Box::new(fake_input_output.clone()), opts);
+ start(Box::new(fake_input_output.clone()), opts, Config::default());
let output_frames = fake_input_output
.stdout_writer
.output_frames
diff --git a/src/tests/integration/close_pane.rs b/src/tests/integration/close_pane.rs
index c7ce2038d..f73f4027d 100644
--- a/src/tests/integration/close_pane.rs
+++ b/src/tests/integration/close_pane.rs
@@ -5,6 +5,7 @@ use crate::tests::fakes::FakeInputOutput;
use crate::tests::utils::{get_next_to_last_snapshot, get_output_frame_snapshots};
use crate::{start, CliArgs};
+use crate::common::input::config::Config;
use crate::tests::utils::commands::{
CLOSE_PANE_IN_PANE_MODE, ESC, MOVE_FOCUS_IN_PANE_MODE, PANE_MODE, QUIT,
RESIZE_DOWN_IN_RESIZE_MODE, RESIZE_LEFT_IN_RESIZE_MODE, RESIZE_MODE, RESIZE_UP_IN_RESIZE_MODE,
@@ -39,7 +40,11 @@ pub fn close_pane_with_another_pane_above_it() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -77,7 +82,11 @@ pub fn close_pane_with_another_pane_below_it() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -112,7 +121,11 @@ pub fn close_pane_with_another_pane_to_the_left() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -148,7 +161,11 @@ pub fn close_pane_with_another_pane_to_the_right() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -189,7 +206,11 @@ pub fn close_pane_with_multiple_panes_above_it() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -228,7 +249,11 @@ pub fn close_pane_with_multiple_panes_below_it() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -269,7 +294,11 @@ pub fn close_pane_with_multiple_panes_to_the_left() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -308,7 +337,11 @@ pub fn close_pane_with_multiple_panes_to_the_right() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -369,7 +402,11 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -426,7 +463,11 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -485,7 +526,11 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() {
&CLOSE_PANE_IN_PANE_MODE,
&QUIT,
]);
- start(Box::new(fake_input_output.clone()), CliArgs::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ CliArgs::default(),
+ Config::default(),
+ );
let output_frames = fake_input_output
.stdout_writer
@@ -544,7 +589,11 @@ pub fn