From a9088264eb56f79d3f5d27b7806bdd1671654756 Mon Sep 17 00:00:00 2001 From: a-kenji Date: Wed, 16 Jun 2021 16:59:56 +0200 Subject: [PATCH] Change `layout` directory from `data` to `config` * default layouts won't be installed by anymore, instead they will be directly loaded * `layout-dir` is now a subdirectory of the `config-dir` by default, instead of the `data-dir` POSSIBLE BREAKING CHANGE: In case of having custom layouts in the previous `layout-dir` one can switch either the layouts to the new dir, or set the `layout-dir` to be the current `layout-dir` * it is possible to change the location of the `layout-dir`: - `zellij options --layout-dir [LAYOUR_DIR]` - `layout_dir: [LAYOUT_DIR]` --- src/install.rs | 7 +-- src/main.rs | 13 +++-- src/tests/integration/layouts.rs | 2 +- .../assets}/layouts/default.yaml | 0 .../assets}/layouts/disable-status-bar.yaml | 0 .../assets}/layouts/strider.yaml | 0 zellij-utils/src/consts.rs | 1 + zellij-utils/src/input/layout.rs | 51 ++++++++++++++++--- zellij-utils/src/input/options.rs | 11 ++++ zellij-utils/src/setup.rs | 22 ++++++++ 10 files changed, 89 insertions(+), 18 deletions(-) rename {assets => zellij-utils/assets}/layouts/default.yaml (100%) rename {assets => zellij-utils/assets}/layouts/disable-status-bar.yaml (100%) rename {assets => zellij-utils/assets}/layouts/strider.yaml (100%) diff --git a/src/install.rs b/src/install.rs index 4fb6937639..e7778dde27 100644 --- a/src/install.rs +++ b/src/install.rs @@ -17,15 +17,10 @@ macro_rules! asset_map { pub(crate) fn populate_data_dir(data_dir: &Path) { // First run installation of default plugins & layouts let mut assets = asset_map! { - "assets/layouts/default.yaml" => "layouts/default.yaml", - "assets/layouts/strider.yaml" => "layouts/strider.yaml", - "assets/layouts/disable-status-bar.yaml" => "layouts/disable-status-bar.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", - }); + }; assets.insert("VERSION", VERSION.as_bytes().to_vec()); let last_version = fs::read_to_string(data_dir.join("VERSION")).unwrap_or_default(); diff --git a/src/main.rs b/src/main.rs index 1c0dc3904b..6bcfa87235 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ use zellij_utils::{ input::layout::Layout, input::options::Options, logging::*, - setup::{get_default_data_dir, Setup}, + setup::{find_default_config_dir, get_default_data_dir, get_layout_dir, Setup}, structopt::StructOpt, }; @@ -36,6 +36,8 @@ pub fn main() { process::exit(1); } }; + let config_options = Options::from_cli(&config.options, opts.command.clone()); + atomic_create_dir(&*ZELLIJ_TMP_DIR).unwrap(); atomic_create_dir(&*ZELLIJ_TMP_LOG_DIR).unwrap(); if let Some(path) = opts.server { @@ -66,8 +68,6 @@ pub fn main() { session_name = Some(get_active_session()); } - let config_options = Options::from_cli(&config.options, opts.command.clone()); - start_client( Box::new(os_input), opts, @@ -81,16 +81,19 @@ pub fn main() { .clone() .unwrap_or_else(|| names::Generator::default().next().unwrap()); assert_session_ne(&session_name); + // Determine and initialize the data directory let data_dir = opts.data_dir.clone().unwrap_or_else(get_default_data_dir); - #[cfg(not(disable_automatic_asset_installation))] populate_data_dir(&data_dir); + let layout_dir = config_options.layout_dir.or_else(|| { + get_layout_dir(opts.config_dir.clone().or_else(find_default_config_dir)) + }); let layout = Layout::from_path_or_default( opts.layout.as_ref(), opts.layout_path.as_ref(), - &data_dir, + layout_dir, ); start_client( diff --git a/src/tests/integration/layouts.rs b/src/tests/integration/layouts.rs index 29f8beac7f..6b91ba04db 100644 --- a/src/tests/integration/layouts.rs +++ b/src/tests/integration/layouts.rs @@ -32,7 +32,7 @@ pub fn accepts_basic_layout() { let layout = zellij_utils::input::layout::Layout::from_path_or_default( None, opts.layout_path.as_ref(), - std::path::Path::new("unused"), + Some(std::path::Path::new("unused").into()), ); start( diff --git a/assets/layouts/default.yaml b/zellij-utils/assets/layouts/default.yaml similarity index 100% rename from assets/layouts/default.yaml rename to zellij-utils/assets/layouts/default.yaml diff --git a/assets/layouts/disable-status-bar.yaml b/zellij-utils/assets/layouts/disable-status-bar.yaml similarity index 100% rename from assets/layouts/disable-status-bar.yaml rename to zellij-utils/assets/layouts/disable-status-bar.yaml diff --git a/assets/layouts/strider.yaml b/zellij-utils/assets/layouts/strider.yaml similarity index 100% rename from assets/layouts/strider.yaml rename to zellij-utils/assets/layouts/strider.yaml diff --git a/zellij-utils/src/consts.rs b/zellij-utils/src/consts.rs index f22dd48934..697e9024d2 100644 --- a/zellij-utils/src/consts.rs +++ b/zellij-utils/src/consts.rs @@ -10,6 +10,7 @@ use std::{env, fs}; pub const ZELLIJ_CONFIG_FILE_ENV: &str = "ZELLIJ_CONFIG_FILE"; pub const ZELLIJ_CONFIG_DIR_ENV: &str = "ZELLIJ_CONFIG_DIR"; +pub const ZELLIJ_LAYOUT_DIR_ENV: &str = "ZELLIJ_LAYOUT_DIR"; pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const SYSTEM_DEFAULT_CONFIG_DIR: &str = "/etc/zellij"; diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs index 939e291545..f694423a24 100644 --- a/zellij-utils/src/input/layout.rs +++ b/zellij-utils/src/input/layout.rs @@ -8,7 +8,7 @@ // place. // If plugins should be able to depend on the layout system // then [`zellij-utils`] could be a proper place. -use crate::{input::config::ConfigError, pane_size::PositionAndSize}; +use crate::{input::config::ConfigError, pane_size::PositionAndSize, setup}; use crate::{serde, serde_yaml}; use serde::{Deserialize, Serialize}; @@ -55,22 +55,26 @@ impl Layout { // It wants to use Path here, but that doesn't compile. #[allow(clippy::ptr_arg)] - pub fn from_dir(layout: &PathBuf, data_dir: &Path) -> LayoutResult { - Self::new(&data_dir.join("layouts/").join(layout)) + pub fn from_dir(layout: &PathBuf, layout_dir: Option<&PathBuf>) -> LayoutResult { + match layout_dir { + Some(dir) => Self::new(&dir.join(layout)) + .or_else(|_| Self::from_default_assets(layout.as_path())), + None => Self::from_default_assets(layout.as_path()), + } } pub fn from_path_or_default( layout: Option<&PathBuf>, layout_path: Option<&PathBuf>, - data_dir: &Path, + layout_dir: Option, ) -> Option { let layout_result = layout - .map(|p| Layout::from_dir(&p, &data_dir)) + .map(|p| Layout::from_dir(&p, layout_dir.as_ref())) .or_else(|| layout_path.map(|p| Layout::new(&p))) .or_else(|| { Some(Layout::from_dir( &std::path::PathBuf::from("default"), - &data_dir, + layout_dir.as_ref(), )) }); @@ -84,6 +88,41 @@ impl Layout { } } + // Currently still needed but on nightly + // this is already possible: + // HashMap<&'static str, Vec> + pub fn from_default_assets(path: &Path) -> LayoutResult { + match path.to_str() { + Some("default") => Self::default_from_assets(), + Some("strider") => Self::strider_from_assets(), + Some("disable-status-bar") => Self::disable_status_from_assets(), + None | Some(_) => Err(ConfigError::IoPath( + std::io::Error::new(std::io::ErrorKind::Other, "The layout was not found"), + path.into(), + )), + } + } + + // TODO Deserialize the assets from bytes &[u8], + // once serde-yaml supports zero-copy + pub fn default_from_assets() -> LayoutResult { + let layout: Layout = + serde_yaml::from_str(String::from_utf8(setup::DEFAULT_LAYOUT.to_vec())?.as_str())?; + Ok(layout) + } + + pub fn strider_from_assets() -> LayoutResult { + let layout: Layout = + serde_yaml::from_str(String::from_utf8(setup::STRIDER_LAYOUT.to_vec())?.as_str())?; + Ok(layout) + } + + pub fn disable_status_from_assets() -> LayoutResult { + let layout: Layout = + serde_yaml::from_str(String::from_utf8(setup::NO_STATUS_LAYOUT.to_vec())?.as_str())?; + Ok(layout) + } + pub fn total_terminal_panes(&self) -> usize { let mut total_panes = 0; total_panes += self.parts.len(); diff --git a/zellij-utils/src/input/options.rs b/zellij-utils/src/input/options.rs index 04bca61273..8850395947 100644 --- a/zellij-utils/src/input/options.rs +++ b/zellij-utils/src/input/options.rs @@ -1,6 +1,7 @@ //! Handles cli and configuration options use crate::cli::Command; use serde::{Deserialize, Serialize}; +use std::path::PathBuf; use structopt::StructOpt; use zellij_tile::data::InputMode; @@ -19,6 +20,10 @@ pub struct Options { /// Set the default mode #[structopt(long)] pub default_mode: Option, + /// Set the layout_dir, defaults to + /// subdirectory of config dir + #[structopt(long, parse(from_os_str))] + pub layout_dir: Option, } impl Options { @@ -45,6 +50,11 @@ impl Options { other => other, }; + let layout_dir = match other.layout_dir { + None => self.layout_dir.clone(), + other => other, + }; + let theme = match other.theme { None => self.theme.clone(), other => other, @@ -54,6 +64,7 @@ impl Options { simplified_ui, theme, default_mode, + layout_dir, } } diff --git a/zellij-utils/src/setup.rs b/zellij-utils/src/setup.rs index f09ec49e75..de441e0b20 100644 --- a/zellij-utils/src/setup.rs +++ b/zellij-utils/src/setup.rs @@ -66,6 +66,10 @@ pub fn home_config_dir() -> Option { } } +pub fn get_layout_dir(config_dir: Option) -> Option { + config_dir.map(|dir| dir.join("layouts")) +} + pub fn dump_asset(asset: &[u8]) -> std::io::Result<()> { std::io::stdout().write_all(&asset)?; Ok(()) @@ -77,6 +81,24 @@ pub const DEFAULT_CONFIG: &[u8] = include_bytes!(concat!( "assets/config/default.yaml" )); +pub const DEFAULT_LAYOUT: &[u8] = include_bytes!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/", + "assets/layouts/default.yaml" +)); + +pub const STRIDER_LAYOUT: &[u8] = include_bytes!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/", + "assets/layouts/strider.yaml" +)); + +pub const NO_STATUS_LAYOUT: &[u8] = include_bytes!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/", + "assets/layouts/default.yaml" +)); + pub fn dump_default_config() -> std::io::Result<()> { dump_asset(DEFAULT_CONFIG) }