summaryrefslogtreecommitdiffstats
path: root/src/launchable.rs
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2020-04-14 16:41:19 +0200
committerCanop <cano.petrole@gmail.com>2020-04-14 16:41:19 +0200
commitf9c5b49358ec1654cceed5aacc8620bf060acb4d (patch)
tree698a638651cfb2a99e2d19afd3b8ec2609b26edf /src/launchable.rs
parent2e9fb3295d7ee797d01c1f573c15c9a7e915d9ae (diff)
refactor: separate Launchable and print functions
Diffstat (limited to 'src/launchable.rs')
-rw-r--r--src/launchable.rs123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/launchable.rs b/src/launchable.rs
new file mode 100644
index 0000000..13ae530
--- /dev/null
+++ b/src/launchable.rs
@@ -0,0 +1,123 @@
+use {
+ crate::{
+ displayable_tree::DisplayableTree,
+ errors::ProgramError,
+ flat_tree::Tree,
+ screens::Screen,
+ skin::Skin,
+ },
+ open,
+ std::{
+ env,
+ io,
+ path::PathBuf,
+ process::Command,
+ },
+};
+
+/// description of a possible launch of an external program
+/// A launchable can only be executed on end of life of broot.
+#[derive(Debug)]
+pub enum Launchable {
+ Printer {
+ // just print something on stdout on end of broot
+ to_print: String,
+ },
+ TreePrinter {
+ // print the tree on end of broot
+ tree: Box<Tree>,
+ skin: Box<Skin>,
+ width: u16,
+ },
+ Program {
+ // execute an external program
+ exe: String,
+ args: Vec<String>,
+ },
+ SystemOpen {
+ // open a path
+ path: PathBuf,
+ },
+}
+
+/// If a part starts with a '$', replace it by the environment variable of the same name.
+/// This part is splitted too (because of https://github.com/Canop/broot/issues/114)
+fn resolve_env_variables(parts: Vec<String>) -> Vec<String> {
+ let mut resolved = Vec::new();
+ for part in parts.into_iter() {
+ if part.starts_with('$') {
+ if let Ok(val) = env::var(&part[1..]) {
+ resolved.extend(val.split(' ').map(|s| s.to_string()));
+ continue;
+ }
+ }
+ resolved.push(part);
+ }
+ resolved
+}
+
+impl Launchable {
+ pub fn opener(path: PathBuf) -> Launchable {
+ Launchable::SystemOpen { path }
+ }
+ pub fn printer(to_print: String) -> Launchable {
+ Launchable::Printer { to_print }
+ }
+ pub fn tree_printer(
+ tree: &Tree,
+ screen: &Screen,
+ no_style: bool,
+ ) -> Launchable {
+ Launchable::TreePrinter {
+ tree: Box::new(tree.clone()),
+ skin: Box::new(
+ if no_style {
+ Skin::no_term()
+ } else {
+ screen.skin.clone()
+ }
+ ),
+ width: screen.width,
+ }
+ }
+
+ pub fn program(parts: Vec<String>) -> io::Result<Launchable> {
+ let mut parts = resolve_env_variables(parts).into_iter();
+ match parts.next() {
+ Some(exe) => Ok(Launchable::Program {
+ exe,
+ args: parts.collect(),
+ }),
+ None => Err(io::Error::new(io::ErrorKind::Other, "Empty launch string")),
+ }
+ }
+
+ pub fn execute(&self) -> Result<(), ProgramError> {
+ match self {
+ Launchable::Printer { to_print } => {
+ println!("{}", to_print);
+ Ok(())
+ }
+ Launchable::TreePrinter { tree, skin, width } => {
+ let dp = DisplayableTree::out_of_app(&tree, &skin, *width);
+ dp.write_on(&mut std::io::stdout())
+ }
+ Launchable::Program { exe, args } => {
+ Command::new(&exe)
+ .args(args.iter())
+ .spawn()
+ .and_then(|mut p| p.wait())
+ .map_err(|source| ProgramError::LaunchError {
+ program: exe.clone(),
+ source,
+ })?;
+ Ok(())
+ }
+ Launchable::SystemOpen { path } => {
+ open::that(&path)?;
+ Ok(())
+ }
+ }
+ }
+}
+