mirror of
https://github.com/zellij-org/zellij.git
synced 2024-12-28 11:42:41 +03:00
Add check
flag to the setup subcommand
* The check option communicates default and config options to the user as well as optional compile time features * Move generate-completion from a subcommand to a flag in the setup subcommand
This commit is contained in:
parent
a24c7f79f1
commit
d667e5ed81
15
src/cli.rs
15
src/cli.rs
@ -1,5 +1,6 @@
|
|||||||
use super::common::utils::consts::{ZELLIJ_CONFIG_DIR_ENV, ZELLIJ_CONFIG_FILE_ENV};
|
use super::common::utils::consts::{ZELLIJ_CONFIG_DIR_ENV, ZELLIJ_CONFIG_FILE_ENV};
|
||||||
use crate::common::input::options::Options;
|
use crate::common::input::options::Options;
|
||||||
|
use crate::common::setup::Setup;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
@ -40,17 +41,7 @@ pub enum ConfigCli {
|
|||||||
#[structopt(name = "options")]
|
#[structopt(name = "options")]
|
||||||
Options(Options),
|
Options(Options),
|
||||||
|
|
||||||
#[structopt(name = "generate-completion")]
|
/// Setup zellij and check its configuration
|
||||||
GenerateCompletion { shell: String },
|
|
||||||
|
|
||||||
#[structopt(name = "setup")]
|
#[structopt(name = "setup")]
|
||||||
Setup {
|
Setup(Setup),
|
||||||
/// Dump the default configuration file to stdout
|
|
||||||
#[structopt(long)]
|
|
||||||
dump_config: bool,
|
|
||||||
/// Disables loading of configuration file at default location,
|
|
||||||
/// loads the defaults that zellij ships with
|
|
||||||
#[structopt(long)]
|
|
||||||
clean: bool,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,8 @@ impl TryFrom<&CliArgs> for Config {
|
|||||||
return Config::new(&path);
|
return Config::new(&path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ConfigCli::Setup { clean, .. }) = opts.option {
|
if let Some(ConfigCli::Setup(setup)) = opts.option.clone() {
|
||||||
if clean {
|
if setup.clean {
|
||||||
return Config::from_default_assets();
|
return Config::from_default_assets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,11 +177,12 @@ mod config_test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn try_from_cli_args_with_option_clean() {
|
fn try_from_cli_args_with_option_clean() {
|
||||||
|
use crate::common::setup::Setup;
|
||||||
let mut opts = CliArgs::default();
|
let mut opts = CliArgs::default();
|
||||||
opts.option = Some(ConfigCli::Setup {
|
opts.option = Some(ConfigCli::Setup(Setup {
|
||||||
clean: true,
|
clean: true,
|
||||||
dump_config: false,
|
..Setup::default()
|
||||||
});
|
}));
|
||||||
let result = Config::try_from(&opts);
|
let result = Config::try_from(&opts);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
|
use crate::cli::CliArgs;
|
||||||
use crate::common::utils::consts::{
|
use crate::common::utils::consts::{
|
||||||
SYSTEM_DEFAULT_CONFIG_DIR, SYSTEM_DEFAULT_DATA_DIR_PREFIX, VERSION, ZELLIJ_PROJ_DIR,
|
FEATURES, SYSTEM_DEFAULT_CONFIG_DIR, SYSTEM_DEFAULT_DATA_DIR_PREFIX, VERSION, ZELLIJ_PROJ_DIR,
|
||||||
};
|
};
|
||||||
use crate::os_input_output::set_permissions;
|
use crate::os_input_output::set_permissions;
|
||||||
use directories_next::BaseDirs;
|
use directories_next::BaseDirs;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::{fs, path::Path, path::PathBuf};
|
use std::{fs, path::Path, path::PathBuf};
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
const CONFIG_LOCATION: &str = ".config/zellij";
|
const CONFIG_LOCATION: &str = ".config/zellij";
|
||||||
|
const CONFIG_NAME: &str = "config.yaml";
|
||||||
|
static ARROW_SEPARATOR: &str = "";
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! asset_map {
|
macro_rules! asset_map {
|
||||||
@ -56,15 +61,11 @@ pub mod install {
|
|||||||
/// Goes through a predefined list and checks for an already
|
/// Goes through a predefined list and checks for an already
|
||||||
/// existing config directory, returns the first match
|
/// existing config directory, returns the first match
|
||||||
pub fn find_default_config_dir() -> Option<PathBuf> {
|
pub fn find_default_config_dir() -> Option<PathBuf> {
|
||||||
vec![
|
default_config_dirs()
|
||||||
home_config_dir(),
|
.into_iter()
|
||||||
Some(xdg_config_dir()),
|
.filter(|p| p.is_some())
|
||||||
Some(Path::new(SYSTEM_DEFAULT_CONFIG_DIR).to_path_buf()),
|
.find(|p| p.clone().unwrap().exists())
|
||||||
]
|
.flatten()
|
||||||
.into_iter()
|
|
||||||
.filter(|p| p.is_some())
|
|
||||||
.find(|p| p.clone().unwrap().exists())
|
|
||||||
.flatten()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -72,6 +73,15 @@ pub fn find_default_config_dir() -> Option<PathBuf> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Order in which config directories are checked
|
||||||
|
fn default_config_dirs() -> Vec<Option<PathBuf>> {
|
||||||
|
vec![
|
||||||
|
home_config_dir(),
|
||||||
|
Some(xdg_config_dir()),
|
||||||
|
Some(Path::new(SYSTEM_DEFAULT_CONFIG_DIR).to_path_buf()),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
/// Looks for an existing dir, uses that, else returns a
|
/// Looks for an existing dir, uses that, else returns a
|
||||||
/// dir matching the config spec.
|
/// dir matching the config spec.
|
||||||
pub fn get_default_data_dir() -> PathBuf {
|
pub fn get_default_data_dir() -> PathBuf {
|
||||||
@ -115,3 +125,116 @@ pub const DEFAULT_CONFIG: &[u8] = include_bytes!(concat!(
|
|||||||
pub fn dump_default_config() -> std::io::Result<()> {
|
pub fn dump_default_config() -> std::io::Result<()> {
|
||||||
dump_asset(DEFAULT_CONFIG)
|
dump_asset(DEFAULT_CONFIG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, StructOpt, Serialize, Deserialize)]
|
||||||
|
pub struct Setup {
|
||||||
|
/// Dump the default configuration file to stdout
|
||||||
|
#[structopt(long)]
|
||||||
|
pub dump_config: bool,
|
||||||
|
/// Disables loading of configuration file at default location,
|
||||||
|
/// loads the defaults that zellij ships with
|
||||||
|
#[structopt(long)]
|
||||||
|
pub clean: bool,
|
||||||
|
/// Checks the configuration of zellij and displays
|
||||||
|
/// currently used directories
|
||||||
|
#[structopt(long)]
|
||||||
|
pub check: bool,
|
||||||
|
|
||||||
|
#[structopt(long)]
|
||||||
|
pub generate_completion: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Setup {
|
||||||
|
/// Entrypoint from main
|
||||||
|
pub fn from_cli(&self, opts: CliArgs) -> std::io::Result<()> {
|
||||||
|
if self.dump_config {
|
||||||
|
dump_default_config()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.check {
|
||||||
|
Setup::check_defaults_config(opts)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(shell) = &self.generate_completion {
|
||||||
|
Self::generate_completion(shell.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_defaults_config(opts: CliArgs) -> std::io::Result<()> {
|
||||||
|
let data_dir = opts.data_dir.unwrap_or_else(get_default_data_dir);
|
||||||
|
let config_dir = opts.config_dir.or_else(find_default_config_dir);
|
||||||
|
let plugin_dir = data_dir.join("plugins");
|
||||||
|
let layout_dir = data_dir.join("layouts");
|
||||||
|
let system_data_dir = PathBuf::from(SYSTEM_DEFAULT_DATA_DIR_PREFIX).join("share/zellij");
|
||||||
|
let config_file = opts
|
||||||
|
.config
|
||||||
|
.or_else(|| config_dir.clone().map(|p| p.join(CONFIG_NAME)));
|
||||||
|
|
||||||
|
let mut message = String::new();
|
||||||
|
|
||||||
|
message.push_str(&format!("[Version]: {:?}\n", VERSION));
|
||||||
|
if let Some(config_dir) = config_dir {
|
||||||
|
message.push_str(&format!("[CONFIG DIR]: {:?}\n", config_dir));
|
||||||
|
} else {
|
||||||
|
message.push_str(&"[CONFIG DIR]: Not Found\n");
|
||||||
|
let mut default_config_dirs = default_config_dirs()
|
||||||
|
.iter()
|
||||||
|
.filter_map(|p| p.clone())
|
||||||
|
.collect::<Vec<PathBuf>>();
|
||||||
|
default_config_dirs.dedup();
|
||||||
|
message.push_str(
|
||||||
|
&" On your system zellij looks in the following config directories by default:\n",
|
||||||
|
);
|
||||||
|
for dir in default_config_dirs {
|
||||||
|
message.push_str(&format!(" {:?}\n", dir));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(config_file) = config_file {
|
||||||
|
use crate::common::input::config::Config;
|
||||||
|
message.push_str(&format!("[CONFIG FILE]: {:?}\n", config_file));
|
||||||
|
match Config::new(&config_file) {
|
||||||
|
Ok(_) => message.push_str(&"[CONFIG FILE]: Well defined.\n"),
|
||||||
|
Err(e) => message.push_str(&format!("[CONFIG ERROR]: {}\n", e)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.push_str(&"[CONFIG FILE]: Not Found\n");
|
||||||
|
message.push_str(&format!(
|
||||||
|
" By default zellij looks for a file called [{}] in the configuration directory\n",
|
||||||
|
CONFIG_NAME
|
||||||
|
));
|
||||||
|
}
|
||||||
|
message.push_str(&format!("[DATA DIR]: {:?}\n", data_dir));
|
||||||
|
message.push_str(&format!("[PLUGIN DIR]: {:?}\n", plugin_dir));
|
||||||
|
message.push_str(&format!("[LAYOUT DIR]: {:?}\n", layout_dir));
|
||||||
|
message.push_str(&format!("[SYSTEM DATA DIR]: {:?}\n", system_data_dir));
|
||||||
|
|
||||||
|
message.push_str(&format!("[ARROW SEPARATOR]: {}\n", ARROW_SEPARATOR));
|
||||||
|
message.push_str(&" Is the [ARROW_SEPARATOR] displayed correctly?\n");
|
||||||
|
message.push_str(&" If not you may want to either start zellij with a compatible mode 'zellij options --simple-ui'\n");
|
||||||
|
message.push_str(&" Or check the font that is in use:\n https://zellij.dev/documentation/compatibility.html#the-status-bar-fonts-dont-render-correctly\n");
|
||||||
|
|
||||||
|
message.push_str(&format!("[FEATURES]: {:?}\n", FEATURES));
|
||||||
|
message.push_str(&"[DOCUMENTATION]: zellij.dev/documentation/\n");
|
||||||
|
|
||||||
|
std::io::stdout().write_all(message.as_bytes())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn generate_completion(shell: String) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -47,3 +47,8 @@ lazy_static! {
|
|||||||
pub static ref ZELLIJ_TMP_LOG_DIR: PathBuf = ZELLIJ_TMP_DIR.join("zellij-log");
|
pub static ref ZELLIJ_TMP_LOG_DIR: PathBuf = ZELLIJ_TMP_DIR.join("zellij-log");
|
||||||
pub static ref ZELLIJ_TMP_LOG_FILE: PathBuf = ZELLIJ_TMP_LOG_DIR.join("log.txt");
|
pub static ref ZELLIJ_TMP_LOG_FILE: PathBuf = ZELLIJ_TMP_LOG_DIR.join("log.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const FEATURES: &[&str] = &[
|
||||||
|
#[cfg(feature = "enable_automatic_asset_installation")]
|
||||||
|
"enable_automatic_asset_installation",
|
||||||
|
];
|
||||||
|
36
src/main.rs
36
src/main.rs
@ -6,7 +6,9 @@ mod server;
|
|||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use client::{boundaries, layout, panes, start_client, tab};
|
use client::{boundaries, layout, panes, start_client, tab};
|
||||||
use common::{command_is_executing, errors, os_input_output, pty, screen, setup, utils, wasm_vm};
|
use common::{
|
||||||
|
command_is_executing, errors, os_input_output, pty, screen, setup::Setup, utils, wasm_vm,
|
||||||
|
};
|
||||||
use server::start_server;
|
use server::start_server;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
@ -22,33 +24,19 @@ use std::convert::TryFrom;
|
|||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let opts = CliArgs::from_args();
|
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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let config_options = Options::from_cli(&config.options, opts.option.clone());
|
|
||||||
|
|
||||||
if let Some(crate::cli::ConfigCli::GenerateCompletion { shell }) = opts.option {
|
if let Some(crate::cli::ConfigCli::Setup(setup)) = opts.option.clone() {
|
||||||
let shell = match shell.as_ref() {
|
Setup::from_cli(&setup, opts).expect("Failed to print to stdout");
|
||||||
"bash" => structopt::clap::Shell::Bash,
|
std::process::exit(0);
|
||||||
"fish" => structopt::clap::Shell::Fish,
|
} else {
|
||||||
"zsh" => structopt::clap::Shell::Zsh,
|
let config = match Config::try_from(&opts) {
|
||||||
"powerShell" => structopt::clap::Shell::PowerShell,
|
Ok(config) => config,
|
||||||
"elvish" => structopt::clap::Shell::Elvish,
|
Err(e) => {
|
||||||
other => {
|
eprintln!("There was an error in the config file:\n{}", e);
|
||||||
eprintln!("Unsupported shell: {}", other);
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut out = std::io::stdout();
|
let config_options = Options::from_cli(&config.options, opts.option.clone());
|
||||||
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(0);
|
|
||||||
} else {
|
|
||||||
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();
|
||||||
let server_os_input = get_server_os_input();
|
let server_os_input = get_server_os_input();
|
||||||
|
Loading…
Reference in New Issue
Block a user