From 671d1b11fd9b3a4a539d692a845179d53d1b4f9e Mon Sep 17 00:00:00 2001 From: Tom van Dijk <18gatenmaker6@gmail.com> Date: Thu, 16 Sep 2021 16:59:18 +0200 Subject: [PATCH] Refactored parts of `runner::Runner` to take a Cli struct, instead of putting everything manually in `Runner`. --- examples/run.rs | 2 +- src/app.rs | 13 +++---- src/bin/xplr.rs | 94 ++----------------------------------------------- src/cli.rs | 87 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +- src/runner.rs | 78 ++++++++++++++++------------------------ 6 files changed, 126 insertions(+), 151 deletions(-) create mode 100644 src/cli.rs diff --git a/examples/run.rs b/examples/run.rs index 47b62de..1f42889 100644 --- a/examples/run.rs +++ b/examples/run.rs @@ -1,5 +1,5 @@ fn main() { - match xplr::runner(None).and_then(|a| a.run()) { + match xplr::runner::Runner::new(xplr::cli::Cli::default()).and_then(|a| a.run()) { Ok(Some(out)) => print!("{}", out), Ok(None) => {} Err(err) => { diff --git a/src/app.rs b/src/app.rs index 656458e..a5681dd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,3 +1,4 @@ +use crate::cli; use crate::config::Config; use crate::config::Mode; use crate::explorer; @@ -2342,10 +2343,8 @@ impl App { fn select(mut self) -> Result { if let Some(n) = self.focused_node().map(|n| n.to_owned()) { self.selection.insert(n); - Ok(self) - } else { - Ok(self) } + Ok(self) } fn select_path(mut self, path: String) -> Result { @@ -2357,10 +2356,8 @@ impl App { let filename = path.file_name().map(|p| p.to_string_lossy().to_string()); if let (Some(p), Some(n)) = (parent, filename) { self.selection.insert(Node::new(p, n)); - Ok(self) - } else { - Ok(self) } + Ok(self) } fn select_all(mut self) -> Result { @@ -2903,6 +2900,6 @@ impl App { } } -pub fn runner(path: Option) -> Result { - Runner::new(path) +pub fn runner(cli: cli::Cli) -> Result { + Runner::new(cli) } diff --git a/src/bin/xplr.rs b/src/bin/xplr.rs index db5d6ec..638ad3f 100644 --- a/src/bin/xplr.rs +++ b/src/bin/xplr.rs @@ -1,92 +1,8 @@ #![allow(clippy::too_many_arguments)] -use anyhow::Result; -use std::collections::VecDeque; use std::env; -use std::io; -use std::path::PathBuf; -use xplr::app; - -#[derive(Debug, Clone, Default)] -struct Cli { - version: bool, - help: bool, - read_only: bool, - path: Option, - config: Option, - extra_config: Vec, - on_load: Vec, -} -impl Cli { - fn parse(args: env::Args) -> Result { - let mut args: VecDeque = args.skip(1).collect(); - let mut cli = Self::default(); - - while let Some(arg) = args.pop_front() { - match arg.as_str() { - // Flags - "-" => { - let mut path = String::new(); - if io::stdin().read_line(&mut path).is_ok() { - cli.path = - Some(path.trim_end_matches("\r\n").trim_end_matches('\n').into()); - }; - } - - "-h" | "--help" => { - cli.help = true; - } - - "-V" | "--version" => { - cli.version = true; - } - - "--" => { - if cli.path.is_none() { - cli.path = args.pop_front().map(PathBuf::from); - } - return Ok(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" => { - while let Some(msg) = args.pop_front() { - if msg.starts_with('-') { - args.push_front(msg); - break; - } else { - cli.on_load.push(serde_yaml::from_str(&msg)?); - } - } - } - - // path - path => { - if cli.path.is_none() { - cli.path = Some(path.into()); - } - } - } - } - Ok(cli) - } -} +use xplr::{cli::Cli, runner::Runner}; fn main() { let cli = Cli::parse(env::args()).unwrap_or_else(|e| { @@ -130,13 +46,7 @@ fn main() { } else if cli.version { println!("xplr {}", xplr::app::VERSION); } else { - 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()) - { + match Runner::new(cli).and_then(|a| a.run()) { Ok(Some(out)) => print!("{}", out), Ok(None) => {} Err(err) => { diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..b8fa1a3 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,87 @@ +use anyhow::Result; +use std::collections::VecDeque; +use std::path::PathBuf; +use std::{env, io}; + +use crate::app; + +#[derive(Debug, Clone, Default)] +pub struct Cli { + pub version: bool, + pub help: bool, + pub read_only: bool, + pub path: Option, + pub config: Option, + pub extra_config: Vec, + pub on_load: Vec, +} + +impl Cli { + pub fn parse(args: env::Args) -> Result { + let mut args: VecDeque = args.skip(1).collect(); + let mut cli = Self::default(); + + while let Some(arg) = args.pop_front() { + match arg.as_str() { + // Flags + "-" => { + let mut path = String::new(); + if io::stdin().read_line(&mut path).is_ok() { + cli.path = + Some(path.trim_end_matches("\r\n").trim_end_matches('\n').into()); + }; + } + + "-h" | "--help" => { + cli.help = true; + } + + "-V" | "--version" => { + cli.version = true; + } + + "--" => { + if cli.path.is_none() { + cli.path = args.pop_front().map(PathBuf::from); + } + return Ok(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" => { + while let Some(msg) = args.pop_front() { + if msg.starts_with('-') { + args.push_front(msg); + break; + } else { + cli.on_load.push(serde_yaml::from_str(&msg)?); + } + } + } + + // path + path => { + if cli.path.is_none() { + cli.path = Some(path.into()); + } + } + } + } + Ok(cli) + } +} diff --git a/src/lib.rs b/src/lib.rs index 0bcdddd..973a1b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ #![allow(clippy::unnecessary_wraps)] pub mod app; +pub mod cli; pub mod config; pub mod event_reader; pub mod explorer; @@ -13,5 +14,3 @@ pub mod pipe_reader; pub mod pwd_watcher; pub mod runner; pub mod ui; - -pub use app::runner; diff --git a/src/runner.rs b/src/runner.rs index 69d96f7..51bc131 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -106,9 +106,10 @@ pub struct Runner { } impl Runner { - pub(crate) fn new(path: Option) -> Result { + pub fn new(cli: crate::cli::Cli) -> Result { let basedir = std::env::current_dir()?; - let mut pwd = path + let mut pwd = cli + .path .map(|p| if p.is_relative() { basedir.join(p) } else { p }) .unwrap_or_else(|| basedir.clone()); let mut focused_path = None; @@ -121,33 +122,13 @@ impl Runner { Ok(Self { pwd, focused_path, - config_file: Default::default(), - extra_config_files: Default::default(), - on_load: Default::default(), - read_only: Default::default(), + config_file: cli.config, + extra_config_files: cli.extra_config, + on_load: cli.on_load, + read_only: cli.read_only, }) } - pub fn with_on_load(mut self, on_load: Vec) -> Self { - self.on_load = on_load; - self - } - - 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 - } - - pub fn with_read_only(mut self, read_only: bool) -> Self { - self.read_only = read_only; - self - } - pub fn run(self) -> Result> { // Why unsafe? See https://github.com/sayanarijit/xplr/issues/309 let lua = unsafe { mlua::Lua::unsafe_new() }; @@ -231,55 +212,56 @@ impl Runner { Ok(a) => { app = a; while let Some(msg) = app.pop_msg_out() { + use app::MsgOut::*; match msg { // NOTE: Do not schedule critical tasks via tx_msg_in in this loop. // Try handling them immediately. - app::MsgOut::Enque(task) => { + Enque(task) => { tx_msg_in.send(task)?; } - app::MsgOut::Quit => { + Quit => { result = Ok(None); break 'outer; } - app::MsgOut::PrintPwdAndQuit => { + PrintPwdAndQuit => { result = Ok(Some(format!("{}\n", app.pwd()))); break 'outer; } - app::MsgOut::PrintFocusPathAndQuit => { + PrintFocusPathAndQuit => { result = Ok(app .focused_node() .map(|n| format!("{}\n", n.absolute_path()))); break 'outer; } - app::MsgOut::PrintSelectionAndQuit => { + PrintSelectionAndQuit => { result = Ok(Some(app.selection_str())); break 'outer; } - app::MsgOut::PrintResultAndQuit => { + PrintResultAndQuit => { result = Ok(Some(app.result_str())); break 'outer; } - app::MsgOut::PrintAppStateAndQuit => { + PrintAppStateAndQuit => { let out = serde_yaml::to_string(&app)?; result = Ok(Some(out)); break 'outer; } - app::MsgOut::Debug(path) => { + Debug(path) => { fs::write(&path, serde_yaml::to_string(&app)?)?; } - app::MsgOut::ClearScreen => { + ClearScreen => { terminal.clear()?; } - app::MsgOut::ExplorePwdAsync => { + ExplorePwdAsync => { explorer::explore_async( app.explorer_config().clone(), app.pwd().into(), @@ -290,7 +272,7 @@ impl Runner { tx_pwd_watcher.send(app.pwd().clone())?; } - app::MsgOut::ExploreParentsAsync => { + ExploreParentsAsync => { explorer::explore_recursive_async( app.explorer_config().clone(), app.pwd().into(), @@ -301,7 +283,7 @@ impl Runner { tx_pwd_watcher.send(app.pwd().clone())?; } - app::MsgOut::Refresh => { + Refresh => { // $PWD watcher tx_pwd_watcher.send(app.pwd().clone())?; // UI @@ -316,7 +298,7 @@ impl Runner { } } - app::MsgOut::EnableMouse => { + EnableMouse => { if !mouse_enabled { match execute!( terminal.backend_mut(), @@ -332,7 +314,7 @@ impl Runner { } } - app::MsgOut::ToggleMouse => { + ToggleMouse => { let msg = if mouse_enabled { app::ExternalMsg::DisableMouse } else { @@ -342,7 +324,7 @@ impl Runner { .handle_task(app::Task::new(app::MsgIn::External(msg), None))?; } - app::MsgOut::DisableMouse => { + DisableMouse => { if mouse_enabled { match execute!( terminal.backend_mut(), @@ -358,7 +340,7 @@ impl Runner { } } - app::MsgOut::StartFifo(path) => { + StartFifo(path) => { fifo = match start_fifo(&path, &app.focused_node_str()) { Ok(file) => Some(file), Err(e) => { @@ -368,14 +350,14 @@ impl Runner { } } - app::MsgOut::StopFifo => { + StopFifo => { if let Some(file) = fifo { fifo = None; std::mem::drop(file); } } - app::MsgOut::ToggleFifo(path) => { + ToggleFifo(path) => { if let Some(file) = fifo { fifo = None; std::mem::drop(file); @@ -390,7 +372,7 @@ impl Runner { } } - app::MsgOut::CallLuaSilently(func) => { + CallLuaSilently(func) => { tx_event_reader.send(true)?; match call_lua(&app, &lua, &func, false) { @@ -411,7 +393,7 @@ impl Runner { tx_event_reader.send(false)?; } - app::MsgOut::CallSilently(cmd) => { + CallSilently(cmd) => { tx_event_reader.send(true)?; app.write_pipes()?; @@ -448,7 +430,7 @@ impl Runner { tx_event_reader.send(false)?; } - app::MsgOut::CallLua(func) => { + CallLua(func) => { execute!(terminal.backend_mut(), event::DisableMouseCapture) .unwrap_or_default(); @@ -494,7 +476,7 @@ impl Runner { } } - app::MsgOut::Call(cmd) => { + Call(cmd) => { execute!(terminal.backend_mut(), event::DisableMouseCapture) .unwrap_or_default();