From 61657a70c71f772d87ab6c1cbcb94800a340bbcf Mon Sep 17 00:00:00 2001 From: Arijit Basu Date: Mon, 23 Aug 2021 10:33:36 +0530 Subject: [PATCH] Add support for loading extra config files Use `-C` / `--extra-config` to load Lua files to overwrite the default or user defined config. This helps with integration, where integrating xplr with another tool requires xplr to overwrite some config, without requiring the users to install an xplr plugin or update the xplr config. Example: ```bash xplr -C one.lua two.lua # Or xplr -C one.lua -C two.lua ``` > **WARNING:** > > Extra config doesn't require specifying the `version`, hence, it's the > integration author or the user's responsibility to assert > compatibility using the globally exposed `version` in the extra config > files, similar to xplr plugins. Ref: https://github.com/sayanarijit/xplr/issues/316 --- Cargo.lock | 80 ++++++++++++-------------------------------- Cargo.toml | 14 ++++---- benches/criterion.rs | 6 ++-- src/app.rs | 36 +++++++++++++------- src/bin/xplr.rs | 20 +++++++++-- src/init.lua | 4 +-- src/runner.rs | 17 +++++++--- 7 files changed, 87 insertions(+), 90 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b003992..6bdfa30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,24 +2,24 @@ # It is not intended for manual editing. [[package]] name = "ansi-to-tui" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78688ae13e204ce559701516a0198d5fb54530b73eb1b3ecf404b4b79ed48dbf" +checksum = "27ee8aff7256290439849cfde35078b996c3ce0a3cd5e0703f6c08384f0bc4a6" dependencies = [ "tui", ] [[package]] name = "anyhow" -version = "1.0.42" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" +checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf" [[package]] name = "assert_cmd" -version = "1.0.7" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d20831bd004dda4c7c372c19cdabff369f794a95e955b3f13fe460e3e1ae95f" +checksum = "54f002ce7d0c5e809ebb02be78fd503aeed4a511fd0fcaff6e6914cbdabbfa33" dependencies = [ "bstr", "doc-comment", @@ -202,22 +202,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "crossterm" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c" -dependencies = [ - "bitflags", - "crossterm_winapi 0.7.0", - "lazy_static", - "libc", - "mio", - "parking_lot", - "signal-hook 0.1.17", - "winapi", -] - [[package]] name = "crossterm" version = "0.20.0" @@ -225,24 +209,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ebde6a9dd5e331cd6c6f48253254d117642c31653baa475e394657c59c1f7d" dependencies = [ "bitflags", - "crossterm_winapi 0.8.0", + "crossterm_winapi", "libc", "mio", "parking_lot", - "signal-hook 0.3.9", + "signal-hook", "signal-hook-mio", "winapi", ] -[[package]] -name = "crossterm_winapi" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da8964ace4d3e4a044fd027919b2237000b24315a37c916f61809f1ff2140b9" -dependencies = [ - "winapi", -] - [[package]] name = "crossterm_winapi" version = "0.8.0" @@ -417,9 +392,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.98" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" [[package]] name = "linked-hash-map" @@ -796,9 +771,9 @@ checksum = "5f3aac57ee7f3272d8395c6e4f502f434f0e289fcd62876f70daa008c20dcabe" [[package]] name = "serde" -version = "1.0.126" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +checksum = "1056a0db1978e9dbf0f6e4fca677f6f9143dc1c19de346f22cac23e422196834" dependencies = [ "serde_derive", ] @@ -815,9 +790,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.126" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +checksum = "13af2fbb8b60a8950d6c72a56d2095c28870367cc8e10c55e9745bac4995a2c4" dependencies = [ "proc-macro2", "quote", @@ -837,27 +812,16 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.17" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" +checksum = "6375dbd828ed6964c3748e4ef6d18e7a175d408ffe184bca01698d0c73f915a9" dependencies = [ "dtoa", - "linked-hash-map", + "indexmap", "serde", "yaml-rust", ] -[[package]] -name = "signal-hook" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729" -dependencies = [ - "libc", - "mio", - "signal-hook-registry", -] - [[package]] name = "signal-hook" version = "0.3.9" @@ -876,7 +840,7 @@ checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4" dependencies = [ "libc", "mio", - "signal-hook 0.3.9", + "signal-hook", ] [[package]] @@ -943,13 +907,13 @@ checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" [[package]] name = "tui" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "861d8f3ad314ede6219bcb2ab844054b1de279ee37a9bc38e3d606f9d3fb2a71" +checksum = "39c8ce4e27049eed97cfa363a5048b09d995e209994634a0efc26a14ab6c0c23" dependencies = [ "bitflags", "cassowary", - "crossterm 0.19.0", + "crossterm", "serde", "unicode-segmentation", "unicode-width", @@ -1118,7 +1082,7 @@ dependencies = [ "assert_cmd", "chrono", "criterion", - "crossterm 0.20.0", + "crossterm", "dirs", "humansize", "indexmap", diff --git a/Cargo.toml b/Cargo.toml index b65e3a6..ffb640d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,25 +18,25 @@ categories = ["command-line-interface", "command-line-utilities"] name = "xplr" [dependencies] -tui = { version = "0.15.0", default-features = false, features = ['crossterm', 'serde'] } +tui = { version = "0.16.0", default-features = false, features = ['crossterm', 'serde'] } crossterm = "0.20.0" dirs = "3.0.2" -serde = { version = "1.0.126", features = ["derive"] } -serde_yaml = "0.8.17" +serde = { version = "1.0.128", features = ["derive"] } +serde_yaml = "0.8.19" mime_guess = "2.0.3" -anyhow = "1.0.42" +anyhow = "1.0.43" chrono = { version = "0.4.19", features = ["serde"] } lazy_static = "1.4.0" indexmap = { version = "1.7.0", features = ["serde"] } natord = "1.0.9" humansize = "1.1.1" mlua = { version = "0.6.2", features = ["luajit", "vendored", "serialize", "send"] } -ansi-to-tui = "0.3.0" -libc = "0.2.98" +ansi-to-tui = "0.4.0" +libc = "0.2.100" [dev-dependencies] criterion = "0.3.5" -assert_cmd = "1.0.7" +assert_cmd = "2.0.0" [[bench]] name = "criterion" diff --git a/benches/criterion.rs b/benches/criterion.rs index 93a36d6..e966bab 100644 --- a/benches/criterion.rs +++ b/benches/criterion.rs @@ -18,7 +18,8 @@ fn navigation_benchmark(c: &mut Criterion) { }); let lua = mlua::Lua::new(); - let mut app = app::App::create(PWD.into(), &lua, None).expect("failed to create app"); + let mut app = + app::App::create(PWD.into(), &lua, None, [].into()).expect("failed to create app"); app = app .clone() @@ -96,7 +97,8 @@ fn draw_benchmark(c: &mut Criterion) { }); let lua = mlua::Lua::new(); - let mut app = app::App::create(PWD.into(), &lua, None).expect("failed to create app"); + let mut app = + app::App::create(PWD.into(), &lua, None, [].into()).expect("failed to create app"); app = app .clone() diff --git a/src/app.rs b/src/app.rs index 00605f3..a2c4a1b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1536,8 +1536,13 @@ pub struct App { } impl App { - pub fn create(pwd: PathBuf, lua: &mlua::Lua, config_file: Option) -> Result { - let config = lua::init(lua)?; + pub fn create( + pwd: PathBuf, + lua: &mlua::Lua, + config_file: Option, + extra_config_files: Vec, + ) -> Result { + let mut config = lua::init(lua)?; let config_file = if let Some(path) = config_file { path @@ -1547,14 +1552,19 @@ impl App { PathBuf::from("/").join("etc").join("xplr").join("init.lua") }; - let (config, load_err) = if config_file.exists() { + let config_files = std::iter::once(config_file).chain(extra_config_files.into_iter()); + + let mut load_errs = vec![]; + for config_file in config_files { match lua::extend(lua, &config_file.to_string_lossy().to_string()) { - Ok(c) => (c, None), - Err(e) => (config, Some(e.to_string())), + Ok(c) => { + config = c; + } + Err(e) => { + load_errs.push(e.to_string()); + } } - } else { - (config, None) - }; + } let mode = match config.modes().get( &config @@ -1606,7 +1616,7 @@ impl App { env::set_current_dir(&pwd)?; let pwd = pwd.to_string_lossy().to_string(); - let app = Self { + let mut app = Self { version: VERSION.to_string(), config, pwd, @@ -1629,11 +1639,11 @@ impl App { fs::create_dir_all(app.session_path())?; - if let Some(err) = load_err { - app.log_error(err) - } else { - Ok(app) + for err in load_errs { + app = app.log_error(err)? } + + Ok(app) } pub fn focused_node(&self) -> Option<&Node> { diff --git a/src/bin/xplr.rs b/src/bin/xplr.rs index 54aff0d..db5d6ec 100644 --- a/src/bin/xplr.rs +++ b/src/bin/xplr.rs @@ -14,6 +14,7 @@ struct Cli { read_only: bool, path: Option, config: Option, + extra_config: Vec, on_load: Vec, } @@ -51,6 +52,17 @@ impl Cli { // Options "-c" | "--config" => cli.config = args.pop_front().map(PathBuf::from), + "-C" | "--extra-config" => { + while let Some(path) = args.pop_front() { + if path.starts_with('-') { + args.push_front(path); + break; + } else { + cli.extra_config.push(PathBuf::from(path)); + } + } + } + "--read-only" => cli.read_only = true, "--on-load" => { @@ -94,9 +106,10 @@ fn main() { -V, --version Prints version information"###; let options = r###" - -c, --config Specifies a custom config file (default is - "$HOME/.config/xplr/init.lua") - --on-load ... Sends messages when xplr loads"###; + -c, --config Specifies a custom config file (default is + "$HOME/.config/xplr/init.lua") + -C, --extra-config ... Specifies extra config files to load + --on-load ... Sends messages when xplr loads"###; let args = r###" Path to focus on, or enter if directory"###; @@ -120,6 +133,7 @@ fn main() { match app::runner(cli.path.clone()) .map(|a| a.with_on_load(cli.on_load.clone())) .map(|a| a.with_config(cli.config.clone())) + .map(|a| a.with_extra_config(cli.extra_config.clone())) .map(|a| a.with_read_only(cli.read_only)) .and_then(|a| a.run()) { diff --git a/src/init.lua b/src/init.lua index 84a2aad..9169272 100644 --- a/src/init.lua +++ b/src/init.lua @@ -2403,9 +2403,9 @@ xplr.fn.builtin.fmt_general_table_row_cols_2 = function(m) elseif p.other_execute == true and p.setuid == false then r = r .. bit("x", red, p.other_execute) elseif p.other_execute == false and p.setuid == true then - r = r .. bit("S", red, p.other_execute) + r = r .. bit("T", red, p.other_execute) else - r = r .. bit("s", red, p.other_execute) + r = r .. bit("t", red, p.other_execute) end return r diff --git a/src/runner.rs b/src/runner.rs index 9058fa7..69d96f7 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -99,7 +99,8 @@ fn start_fifo(path: &str, focus_path: &str) -> Result { pub struct Runner { pwd: PathBuf, focused_path: Option, - config: Option, + config_file: Option, + extra_config_files: Vec, on_load: Vec, read_only: bool, } @@ -120,7 +121,8 @@ impl Runner { Ok(Self { pwd, focused_path, - config: None, + config_file: Default::default(), + extra_config_files: Default::default(), on_load: Default::default(), read_only: Default::default(), }) @@ -131,8 +133,13 @@ impl Runner { self } - pub fn with_config(mut self, config: Option) -> Self { - self.config = config; + pub fn with_config(mut self, config_file: Option) -> Self { + self.config_file = config_file; + self + } + + pub fn with_extra_config(mut self, config_files: Vec) -> Self { + self.extra_config_files = config_files; self } @@ -144,7 +151,7 @@ impl Runner { pub fn run(self) -> Result> { // Why unsafe? See https://github.com/sayanarijit/xplr/issues/309 let lua = unsafe { mlua::Lua::unsafe_new() }; - let mut app = app::App::create(self.pwd, &lua, self.config)?; + let mut app = app::App::create(self.pwd, &lua, self.config_file, self.extra_config_files)?; app.config.general.set_read_only(self.read_only); fs::create_dir_all(app.session_path())?;