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]`
This commit is contained in:
a-kenji 2021-06-16 16:59:56 +02:00
parent 8e097c258a
commit a9088264eb
10 changed files with 89 additions and 18 deletions

View file

@ -17,15 +17,10 @@ macro_rules! asset_map {
pub(crate) fn populate_data_dir(data_dir: &Path) { pub(crate) fn populate_data_dir(data_dir: &Path) {
// First run installation of default plugins & layouts // First run installation of default plugins & layouts
let mut assets = asset_map! { 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/status-bar.wasm" => "plugins/status-bar.wasm",
"assets/plugins/tab-bar.wasm" => "plugins/tab-bar.wasm", "assets/plugins/tab-bar.wasm" => "plugins/tab-bar.wasm",
"assets/plugins/strider.wasm" => "plugins/strider.wasm", "assets/plugins/strider.wasm" => "plugins/strider.wasm",
}); };
assets.insert("VERSION", VERSION.as_bytes().to_vec()); assets.insert("VERSION", VERSION.as_bytes().to_vec());
let last_version = fs::read_to_string(data_dir.join("VERSION")).unwrap_or_default(); let last_version = fs::read_to_string(data_dir.join("VERSION")).unwrap_or_default();

View file

@ -16,7 +16,7 @@ use zellij_utils::{
input::layout::Layout, input::layout::Layout,
input::options::Options, input::options::Options,
logging::*, logging::*,
setup::{get_default_data_dir, Setup}, setup::{find_default_config_dir, get_default_data_dir, get_layout_dir, Setup},
structopt::StructOpt, structopt::StructOpt,
}; };
@ -36,6 +36,8 @@ pub fn main() {
process::exit(1); 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_DIR).unwrap();
atomic_create_dir(&*ZELLIJ_TMP_LOG_DIR).unwrap(); atomic_create_dir(&*ZELLIJ_TMP_LOG_DIR).unwrap();
if let Some(path) = opts.server { if let Some(path) = opts.server {
@ -66,8 +68,6 @@ pub fn main() {
session_name = Some(get_active_session()); session_name = Some(get_active_session());
} }
let config_options = Options::from_cli(&config.options, opts.command.clone());
start_client( start_client(
Box::new(os_input), Box::new(os_input),
opts, opts,
@ -81,16 +81,19 @@ pub fn main() {
.clone() .clone()
.unwrap_or_else(|| names::Generator::default().next().unwrap()); .unwrap_or_else(|| names::Generator::default().next().unwrap());
assert_session_ne(&session_name); assert_session_ne(&session_name);
// Determine and initialize the data directory // Determine and initialize the data directory
let data_dir = opts.data_dir.clone().unwrap_or_else(get_default_data_dir); let data_dir = opts.data_dir.clone().unwrap_or_else(get_default_data_dir);
#[cfg(not(disable_automatic_asset_installation))] #[cfg(not(disable_automatic_asset_installation))]
populate_data_dir(&data_dir); 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( let layout = Layout::from_path_or_default(
opts.layout.as_ref(), opts.layout.as_ref(),
opts.layout_path.as_ref(), opts.layout_path.as_ref(),
&data_dir, layout_dir,
); );
start_client( start_client(

View file

@ -32,7 +32,7 @@ pub fn accepts_basic_layout() {
let layout = zellij_utils::input::layout::Layout::from_path_or_default( let layout = zellij_utils::input::layout::Layout::from_path_or_default(
None, None,
opts.layout_path.as_ref(), opts.layout_path.as_ref(),
std::path::Path::new("unused"), Some(std::path::Path::new("unused").into()),
); );
start( start(

View file

@ -10,6 +10,7 @@ use std::{env, fs};
pub const ZELLIJ_CONFIG_FILE_ENV: &str = "ZELLIJ_CONFIG_FILE"; pub const ZELLIJ_CONFIG_FILE_ENV: &str = "ZELLIJ_CONFIG_FILE";
pub const ZELLIJ_CONFIG_DIR_ENV: &str = "ZELLIJ_CONFIG_DIR"; 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 VERSION: &str = env!("CARGO_PKG_VERSION");
pub const SYSTEM_DEFAULT_CONFIG_DIR: &str = "/etc/zellij"; pub const SYSTEM_DEFAULT_CONFIG_DIR: &str = "/etc/zellij";

View file

@ -8,7 +8,7 @@
// place. // place.
// If plugins should be able to depend on the layout system // If plugins should be able to depend on the layout system
// then [`zellij-utils`] could be a proper place. // 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 crate::{serde, serde_yaml};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -55,22 +55,26 @@ impl Layout {
// It wants to use Path here, but that doesn't compile. // It wants to use Path here, but that doesn't compile.
#[allow(clippy::ptr_arg)] #[allow(clippy::ptr_arg)]
pub fn from_dir(layout: &PathBuf, data_dir: &Path) -> LayoutResult { pub fn from_dir(layout: &PathBuf, layout_dir: Option<&PathBuf>) -> LayoutResult {
Self::new(&data_dir.join("layouts/").join(layout)) 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( pub fn from_path_or_default(
layout: Option<&PathBuf>, layout: Option<&PathBuf>,
layout_path: Option<&PathBuf>, layout_path: Option<&PathBuf>,
data_dir: &Path, layout_dir: Option<PathBuf>,
) -> Option<Layout> { ) -> Option<Layout> {
let layout_result = layout 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(|| layout_path.map(|p| Layout::new(&p)))
.or_else(|| { .or_else(|| {
Some(Layout::from_dir( Some(Layout::from_dir(
&std::path::PathBuf::from("default"), &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<u8>>
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 { pub fn total_terminal_panes(&self) -> usize {
let mut total_panes = 0; let mut total_panes = 0;
total_panes += self.parts.len(); total_panes += self.parts.len();

View file

@ -1,6 +1,7 @@
//! Handles cli and configuration options //! Handles cli and configuration options
use crate::cli::Command; use crate::cli::Command;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use structopt::StructOpt; use structopt::StructOpt;
use zellij_tile::data::InputMode; use zellij_tile::data::InputMode;
@ -19,6 +20,10 @@ pub struct Options {
/// Set the default mode /// Set the default mode
#[structopt(long)] #[structopt(long)]
pub default_mode: Option<InputMode>, pub default_mode: Option<InputMode>,
/// Set the layout_dir, defaults to
/// subdirectory of config dir
#[structopt(long, parse(from_os_str))]
pub layout_dir: Option<PathBuf>,
} }
impl Options { impl Options {
@ -45,6 +50,11 @@ impl Options {
other => other, other => other,
}; };
let layout_dir = match other.layout_dir {
None => self.layout_dir.clone(),
other => other,
};
let theme = match other.theme { let theme = match other.theme {
None => self.theme.clone(), None => self.theme.clone(),
other => other, other => other,
@ -54,6 +64,7 @@ impl Options {
simplified_ui, simplified_ui,
theme, theme,
default_mode, default_mode,
layout_dir,
} }
} }

View file

@ -66,6 +66,10 @@ pub fn home_config_dir() -> Option<PathBuf> {
} }
} }
pub fn get_layout_dir(config_dir: Option<PathBuf>) -> Option<PathBuf> {
config_dir.map(|dir| dir.join("layouts"))
}
pub fn dump_asset(asset: &[u8]) -> std::io::Result<()> { pub fn dump_asset(asset: &[u8]) -> std::io::Result<()> {
std::io::stdout().write_all(&asset)?; std::io::stdout().write_all(&asset)?;
Ok(()) Ok(())
@ -77,6 +81,24 @@ pub const DEFAULT_CONFIG: &[u8] = include_bytes!(concat!(
"assets/config/default.yaml" "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<()> { pub fn dump_default_config() -> std::io::Result<()> {
dump_asset(DEFAULT_CONFIG) dump_asset(DEFAULT_CONFIG)
} }