diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app/app.rs | 9 | ||||
-rw-r--r-- | src/app/app_context.rs | 80 | ||||
-rw-r--r-- | src/cli/app_launch_args.rs | 22 | ||||
-rw-r--r-- | src/cli/args.rs | 200 | ||||
-rw-r--r-- | src/cli/clap_args.rs | 235 | ||||
-rw-r--r-- | src/cli/install_launch_args.rs | 19 | ||||
-rw-r--r-- | src/cli/mod.rs | 110 | ||||
-rw-r--r-- | src/print.rs | 83 | ||||
-rw-r--r-- | src/shell_install/mod.rs | 82 | ||||
-rw-r--r-- | src/tree/tree_options.rs | 55 | ||||
-rw-r--r-- | src/verb/external_execution.rs | 11 |
11 files changed, 382 insertions, 524 deletions
diff --git a/src/app/app.rs b/src/app/app.rs index 73bbc6d..7f75c11 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -2,6 +2,7 @@ use { super::*, crate::{ browser::BrowserState, + cli::TriBool, command::{Command, Sequence}, conf::Conf, display::{Areas, Screen, W}, @@ -80,8 +81,8 @@ impl App { PanelId::from(0), Box::new( BrowserState::new( - con.launch_args.root.clone(), - con.launch_args.tree_options.clone(), + con.initial_root.clone(), + con.initial_tree_options.clone(), screen, con, &Dam::unlimited(), @@ -663,10 +664,10 @@ impl App { let event_source = EventSource::new()?; let rx_events = event_source.receiver(); let mut dam = Dam::from(rx_events); - let skin = AppSkin::new(conf, con.launch_args.color == Some(false)); + let skin = AppSkin::new(conf, con.launch_args.color == TriBool::No); let mut app_state = AppState { stage: Stage::default(), - root: con.launch_args.root.clone(), + root: con.initial_root.clone(), other_panel_path: None, }; diff --git a/src/app/app_context.rs b/src/app/app_context.rs index 518bafa..d3424e3 100644 --- a/src/app/app_context.rs +++ b/src/app/app_context.rs @@ -1,19 +1,21 @@ use { super::*, crate::{ - cli::AppLaunchArgs, + cli::{Args, TriBool}, conf::Conf, - errors::ConfError, + errors::*, file_sum, icon::*, pattern::SearchModeMap, path::SpecialPath, skin::ExtColorMap, + tree::TreeOptions, verb::VerbStore, }, std::{ convert::{TryFrom, TryInto}, - path::PathBuf, + io, + path::{Path, PathBuf}, }, }; @@ -22,12 +24,18 @@ use { /// life of the App pub struct AppContext { + /// The initial tree root + pub initial_root: PathBuf, + + /// Initial tree options + pub initial_tree_options: TreeOptions, + /// where's the config file we're using /// This vec can't be empty pub config_paths: Vec<PathBuf>, /// all the arguments specified at launch - pub launch_args: AppLaunchArgs, + pub launch_args: Args, /// the verbs in use (builtins and configured ones) pub verb_store: VerbStore, @@ -82,10 +90,10 @@ pub struct AppContext { impl AppContext { pub fn from( - launch_args: AppLaunchArgs, + launch_args: Args, verb_store: VerbStore, config: &Conf, - ) -> Result<Self, ConfError> { + ) -> Result<Self, ProgramError> { let config_paths = config.files.clone(); let standard_status = StandardStatus::new(&verb_store); let true_colors = if let Some(value) = config.true_colors { @@ -105,11 +113,12 @@ impl AppContext { .map(|map| map.try_into()) .transpose()? .unwrap_or_default(); - let ext_colors = ExtColorMap::try_from(&config.ext_colors)?; + let ext_colors = ExtColorMap::try_from(&config.ext_colors) + .map_err(ConfError::from)?; let file_sum_threads_count = config.file_sum_threads_count .unwrap_or(file_sum::DEFAULT_THREAD_COUNT); if file_sum_threads_count < 1 || file_sum_threads_count > 50 { - return Err(ConfError::InvalidThreadsCount{ count: file_sum_threads_count }); + return Err(ConfError::InvalidThreadsCount{ count: file_sum_threads_count }.into()); } let max_panels_count = config.max_panels_count .unwrap_or(2) @@ -122,7 +131,21 @@ impl AppContext { let max_staged_count = config.max_staged_count .unwrap_or(10_000) .clamp(10, 100_000); + let initial_root = get_root_path(&launch_args)?; + + // tree options are built from the default_flags + // found in the config file(s) (if any) then overriden + // by the cli args + let mut initial_tree_options = TreeOptions::default(); + initial_tree_options.apply_config(config)?; + initial_tree_options.apply_launch_args(&launch_args); + if launch_args.color == TriBool::No { + initial_tree_options.show_selection_mark = true; + } + Ok(Self { + initial_root, + initial_tree_options, config_paths, launch_args, verb_store, @@ -165,3 +188,44 @@ fn are_true_colors_available() -> bool { true } } + +fn get_root_path(cli_args: &Args) -> Result<PathBuf, ProgramError> { + let mut root = cli_args + .root + .as_ref() + .map_or(std::env::current_dir()?, PathBuf::from); + if !root.exists() { + return Err(TreeBuildError::FileNotFound { + path: format!("{:?}", &root), + }.into()); + } + if !root.is_dir() { + // we try to open the parent directory if the passed file isn't one + if let Some(parent) = root.parent() { + info!("Passed path isn't a directory => opening parent instead"); + root = parent.to_path_buf(); + } else { + // let's give up + return Err(TreeBuildError::NotADirectory { + path: format!("{:?}", &root), + }.into()); + } + } + Ok(canonicalize_root(&root)?) +} + +#[cfg(not(windows))] +fn canonicalize_root(root: &Path) -> io::Result<PathBuf> { + root.canonicalize() +} + +#[cfg(windows)] +fn canonicalize_root(root: &Path) -> io::Result<PathBuf> { + Ok(if root.is_relative() { + env::current_dir()?.join(root) + } else { + root.to_path_buf() + }) +} + + diff --git a/src/cli/app_launch_args.rs b/src/cli/app_launch_args.rs deleted file mode 100644 index 03b25ae..0000000 --- a/src/cli/app_launch_args.rs +++ /dev/null @@ -1,22 +0,0 @@ -use { - crate::{ - tree::TreeOptions, - }, - std::{ - path::PathBuf, - }, -}; - - -/// the parsed program launch arguments which are kept for the -/// life of the program -pub struct AppLaunchArgs { - pub root: PathBuf, // what should be the initial root - pub file_export_path: Option<String>, // where to write the produced path (if required with --out) - deprecated - pub cmd_export_path: Option<String>, // where to write the produced command (if required with --outcmd) - pub tree_options: TreeOptions, // initial tree options - pub commands: Option<String>, // commands passed as cli argument, still unparsed - pub height: Option<u16>, // an optional height to replace the screen's one - pub color: Option<bool>, // whether to display colors and styles - pub listen: Option<String>, // if some, broot will start in serve mode on this socket -} diff --git a/src/cli/args.rs b/src/cli/args.rs new file mode 100644 index 0000000..9ad810e --- /dev/null +++ b/src/cli/args.rs @@ -0,0 +1,200 @@ +use { + std::{ + path::PathBuf, + str::FromStr, + }, +}; + +#[derive(Debug, clap::Parser)] +/// A tree explorer and a customizable launcher +/// +/// Complete documentation lives at https://dystroy.org/broot" +#[clap(author, version, about)] +pub struct Args { + + /// Show the last modified date of files and directories" + #[clap(short, long, action)] + pub dates: bool, + + /// Don't show the last modified date" + #[clap(short='D', long, action)] + pub no_dates: bool, + + #[clap(short='f', long, action)] + /// Only show folders + pub only_folders: bool, + + /// Show folders and files alike + #[clap(short='F', long, action)] + pub no_only_folders: bool, + + /// Show filesystem info on top + #[clap(long, action)] + pub show_root_fs: bool, + + /// Show git statuses on files and stats on repo + #[clap(short='g', long, action)] + pub show_git_info: bool, + + /// Don't show git statuses on files and stats on repo + #[clap(short='G', long, action)] + pub no_show_git_info: bool, + + #[clap(long, action)] + /// Only show files having an interesting git status, including hidden ones + pub git_status: bool, + + #[clap(short='h', long, action)] + /// Show hidden files + pub hidden: bool, + + #[clap(short='H', long, action)] + /// Don't show hidden files + pub no_hidden: bool, + + #[clap(short='i', long, action)] + /// Show git ignored files + pub git_ignored: bool, + + #[clap(short='I', long, action)] + /// Don't show git ignored files + pub no_git_ignored: bool, + + #[clap(short='p', long, action)] + /// Show permissions + pub permissions: bool, + + #[clap(short='P', long, action)] + /// Don't show permissions + pub no_permissions: bool, + + #[clap(short='s', long, action)] + /// Show the size of files and directories + pub sizes: bool, + + #[clap(short='S', long, action)] + /// Don't show sizes + pub no_sizes: bool, + + #[clap(long, action)] + /// Sort by count (only show one level of the tree) + pub sort_by_count: bool, + + #[clap(long, action)] + /// Sort by date (only show one level of the tree) + pub sort_by_date: bool, + + #[clap(long, action)] + /// Sort by size (only show one level of the tree) + pub sort_by_size: bool, + + /// Sort by size, show ignored and hidden files + #[clap(short, long, action)] + pub whale_spotting: bool, + + /// Don't sort + #[clap(long, action)] + pub no_sort: bool, + + /// Trim the root too and don't show a scrollbar + #[clap(short='t', long, action)] + pub trim_root: bool, + + /// Don't trim the root level, show a scrollbar + #[clap(short='T', long, action)] + pub no_trim_root: bool, + + /// Where to write the produced cmd (if any) + #[clap(long, value_parser)] + pub cmd_export_path: Option<PathBuf>, + + /// Semicolon separated commands to execute + #[clap(short, long, value_parser)] + pub commands: Option<String>, + + /// Whether to have styles and colors (auto is default and usually OK) + #[clap(long, arg_enum, value_parser, default_value="auto")] + pub color: TriBool, + + /// Semicolon separated paths to specific config files"), + #[clap(long, value_parser)] + pub conf: Option<String>, + + /// Height (if you don't want to fill the screen or for file export) + #[clap(long, value_parser)] + pub height: Option<u16>, + + /// Install or reinstall the br shell function + #[clap(long, action)] + pub install: bool, + + /// Where to write the produced cmd (if any) + #[clap(long, value_parser)] + pub set_install_state: Option<ShellInstallState>, + + /// Print to stdout the br function for a given shell + #[clap(long, value_parser)] + pub print_shell_function: Option<String>, + + /// A socket to listen to for commands + #[cfg(unix)] + #[clap(long, value_parser)] + pub listen: Option<String>, + + /// Ask for the current root of the remote broot + #[cfg(unix)] + #[clap(long, action)] + pub get_root: bool, + + /// A socket that broot sends commands to before quitting + #[cfg(unix)] + #[clap(long, value_parser)] + pub send: Option<String>, + + /// Root Directory + #[clap(value_parser, value_name="FILE")] + pub root: Option<PathBuf>, +} + +/// This is an Option<bool> but I didn't find any way to configure +/// clap to parse an Option<T> as I want +#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ArgEnum)] +pub enum TriBool { + Auto, + Yes, + No, +} +impl TriBool { + pub fn unwrap_or_else<F>(self, f: F) -> bool + where + F: FnOnce() -> bool + { + match self { + Self::Auto => f(), + Self::Yes => true, + Self::No => false, + } + } +} + +#[derive(Debug, Clone, Copy, clap::ValueEnum)] +pub enum ShellInstallState { + Undefined, // before any install, this is the initial state + Refused, + Installed, +} +impl FromStr for ShellInstallState { + type Err = String; + fn from_str(state: &str) -> Result<Self, Self::Err> { + match state { + "undefined" => Ok(Self::Undefined), + "refused" => Ok(Self::Refused), + "installed" => Ok(Self::Installed), + _ => Err( + // not supposed to happen because claps check the values + format!("unexpected install state: {:?}", state) + ), + } + } +} + diff --git a/src/cli/clap_args.rs b/src/cli/clap_args.rs deleted file mode 100644 index 0ac9524..0000000 --- a/src/cli/clap_args.rs +++ /dev/null @@ -1,235 +0,0 @@ -/// this module generate the clap App, which defines -/// launch arguments - -/// Declare the possible CLI arguments -pub fn clap_app() -> clap::Command<'static> { - let app = clap::Command::new("broot") - .version(env!("CARGO_PKG_VERSION")) - .author("dystroy <denys.seguret@gmail.com>") - .about( - "A tree explorer and a customizable launcher\n\ - Complete documentation lives at https://dystroy.org/broot" - ) - .arg(clap::Arg::new("ROOT").help("sets the root directory")) - // tree flags - .arg( - clap::Arg::new("dates") - .short('d') - .long("dates") - .help("Show the last modified date of files and directories"), - ) - .arg( - clap::Arg::new("no-dates") - .short('D') - .long("no-dates") - .help("Don't show last modified date"), - ) - .arg( - clap::Arg::new("only-folders") - .short('f') - .long("only-folders") - .help("Only show folders"), - ) - .arg( - clap::Arg::new("no-only-folders") - .short('F') - .long("no-only-folders") - .help("Show folders and files alike"), - ) - .arg( - clap::Arg::new("show-root-fs") - .long("show-root-fs") - .help("Show filesystem info on top"), - ) - .arg( - clap::Arg::new("show-git-info") - .short('g') - .long("show-git-info") - .help("Show git statuses on files and stats on repo"), - ) - .arg( - clap::Arg::new("no-show-git-info") - .short('G') - .long("no-show-git-info") - .help("Don't show git statuses on files"), - ) - .arg( - clap::Arg::new("git-status") - .long("git-status") - .help("Only show files having an interesting git status, including hidden ones"), - ) - .arg( - clap::Arg::new("hidden") - .short('h') - .long("hidden") - .help("Show hidden files"), - ) - .arg( - clap::Arg::new("no-hidden") - .short('H') - .long("no-hidden") - .help("Don't show hidden files"), - ) - .arg( - clap::Arg::new("show-gitignored") - .short('i') - .long("show-gitignored") - .help("Show files which should be ignored according to git"), - ) - .arg( - clap::Arg::new("no-show-gitignored") - .short('I') - .long("no-show-gitignored") - .help("Don't show gitignored files"), - ) - .arg( - clap::Arg::new("permissions") - .short('p') - .long("permissions") - .help("Show permissions, with owner and group"), - ) - .arg( - clap::Arg::new("no-permissions") - .short('P') - .long("no-permissions") - .help("Don't show permissions"), - ) - .arg( - clap::Arg::new("sizes") - .short('s') - .long("sizes") - .help("Show the size of files and directories"), - ) - .arg( - clap::Arg::new("no-sizes") - .short('S') - .long("no-sizes") - .help("Don't show sizes"), - ) - .arg( - clap::Arg::new("sort-by-count") - .long("sort-by-count") - .help("Sort by count (only show one level of the tree)"), - ) - .arg( - clap::Arg::new("sort-by-date") - .long("sort-by-date") - .help("Sort by date (only show one level of the tree)"), - ) - .arg( - clap::Arg::new("sort-by-size") - .long("sort-by-size") - .help("Sort by size (only show one level of the tree)"), - ) - .arg( - clap::Arg::new("whale-spotting") - .short('w') - .long("whale-spotting") - .help("Sort by size, show ignored and hidden files"), - ) - .arg( - clap::Arg::new("no-sort") - .long("no-sort") - .help("Don't sort"), - ) - .arg( - clap::Arg::new("trim-root") - .short('t') - .long("trim-root") - .help("Trim the root too and don't show a scrollbar"), - ) - .arg( - clap::Arg::new("no-trim-root") - .short('T') - .long("no-trim-root") - .help("Don't trim the root level, show a scrollbar"), - ) - // other options - .arg( - clap::Arg::new("cmd-export-path") - .long("outcmd") - .takes_value(true) - .help("Where to write the produced cmd (if any)"), - ) - .arg( - clap::Arg::new("commands") - .short('c') - .long("cmd") - .takes_value(true) - .help("Semicolon separated commands to execute"), - ) - .arg( - clap::Arg::new("color") - .long("color") - .takes_value(true) - .possible_values(&["yes", "no", "auto"]) - .default_value("auto") - .help("Whether to have styles and colors (auto is default and usually OK)"), - ) - .arg( - clap::Arg::new("conf") - .long("conf") - .takes_value(true) - .help("Semicolon separated paths to specific config files"), - ) - .arg( - clap::Arg::new("height") - .long("height") - .help("Height (if you don't want to fill the screen or for file export)") - .takes_value(true), - ) - .arg( - clap::Arg::new("file-export-path") // deprecated since broot 1.6 - .short('o') - .long("out") - .takes_value(true) - .hide(true) - .help("Where to write the produced path (if any)"), - ) - .arg( - clap::Arg::new("install") - .long("install") - .help("Install or reinstall the br shell function"), - ) - .arg( - clap::Arg::new("set-install-state") - .long("set-install-state") - .takes_value(true) - .value_name("state") - .possible_values(&["undefined", "refused", "installed"]) - .help("Set the installation state (for use in install script)"), - ) - .arg( - clap::Arg::new("print-shell-function") - .long("print-shell-function") - .takes_value(true) - .value_name("shell") - .help("Print to stdout the br function for a given shell"), - ) - .setting(clap::AppSettings::DeriveDisplayOrder); - #[cfg(unix)] - let app = app - .arg( - clap::Arg::new("listen") - .long("listen") - .takes_value(true) - .help("Listen for commands") - ) - .arg( - clap::Arg::new("get-root") - .long("get-root") - .help("Ask for the current root of the remote broot") - ) - .arg( - clap::Arg::new("send") - .long("send") - .takes_value(true) - .help("send commands to a remote broot then quits") - ); - app -} - -#[test] -fn verify_app() { - clap_app().debug_assert(); -} diff --git a/src/cli/install_launch_args.rs b/src/cli/install_launch_args.rs index c688e12..e5b1d01 100644 --- a/src/cli/install_launch_args.rs +++ b/src/cli/install_launch_args.rs @@ -3,12 +3,10 @@ use { crate::{ errors::ProgramError, - shell_install::ShellInstallState, + cli::{Args, ShellInstallState}, }, - clap::{self, ArgMatches}, std::{ env, - str::FromStr, }, }; @@ -21,7 +19,7 @@ pub struct InstallLaunchArgs { pub print_shell_function: Option<String>, // shell function to print on stdout } impl InstallLaunchArgs { - pub fn from(cli_args: &ArgMatches) -> Result<Self, ProgramError> { + pub fn from(args: &Args) -> Result<Self, ProgramError> { let mut install = None; if let Ok(s) = env::var("BR_INSTALL") { if s == "yes" { @@ -33,18 +31,13 @@ impl InstallLaunchArgs { } } // the cli arguments may override the env var value - if cli_args.is_present("install") { + if args.install { install = Some(true); - } else if cli_args.value_of("cmd-export-path").is_some() { + } else if args.cmd_export_path.is_some() { install = Some(false); } - let print_shell_function = cli_args - .value_of("print-shell-function") - .map(str::to_string); - let set_install_state = cli_args - .value_of("set-install-state") - .map(ShellInstallState::from_str) - .transpose()?; + let print_shell_function = args.print_shell_function.clone(); + let set_install_state = args.set_install_state; Ok(Self { install, set_install_state, diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 29c5152..310a7ed 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,12 +1,13 @@ //! this module manages reading and translating //! the arguments passed on launch of the application. -pub mod clap_args; -mod app_launch_args; +//mod app_launch_args; +mod args; mod install_launch_args; pub use { - app_launch_args::*, + //app_launch_args::*, + args::*, install_launch_args::*, }; @@ -15,13 +16,12 @@ use { app::{App, AppContext}, conf::Conf, display, - errors::{ProgramError, TreeBuildError}, + errors::ProgramError, launchable::Launchable, - shell_install::ShellInstall, - tree::TreeOptions, + shell_install::{ShellInstall, write_state}, verb::VerbStore, }, - clap::{self, ArgMatches}, + clap::Parser, crossterm::{ self, cursor, @@ -30,65 +30,25 @@ use { QueueableCommand, }, std::{ - env, io::{self, Write}, - path::{Path, PathBuf}, + path::PathBuf, }, }; -#[cfg(not(windows))] -fn canonicalize_root(root: &Path) -> io::Result<PathBuf> { - root.canonicalize() -} - -#[cfg(windows)] -fn canonicalize_root(root: &Path) -> io::Result<PathBuf> { - Ok(if root.is_relative() { - env::current_dir()?.join(root) - } else { - root.to_path_buf() - }) -} - -fn get_root_path(cli_args: &ArgMatches) -> Result<PathBuf, ProgramError> { - let mut root = cli_args - .value_of("ROOT") - .map_or(env::current_dir()?, PathBuf::from); - if !root.exists() { - return Err(TreeBuildError::FileNotFound { - path: format!("{:?}", &root), - }.into()); - } - if !root.is_dir() { - // we try to open the parent directory if the passed file isn't one - if let Some(parent) = root.parent() { - info!("Passed path isn't a directory => opening parent instead"); - root = parent.to_path_buf(); - } else { - // let's give up - return Err(TreeBuildError::NotADirectory { - path: format!("{:?}", &root), - }.into()); - } - } - Ok(canonicalize_root(&root)?) -} - /// run the application, and maybe return a launchable /// which must be run after broot pub fn run() -> Result<Option<Launchable>, ProgramError> { - let clap_app = clap_args::clap_app(); // parse the launch arguments we got from cli - let cli_matches = clap_app.get_matches(); + let args = Args::parse(); // read the install related arguments - let install_args = InstallLaunchArgs::from(&cli_matches)?; + let install_args = InstallLaunchArgs::from(&args)?; // execute installation things required by launch args let mut must_quit = false; if let Some(state) = install_args.set_install_state { - state.write_file()?; + write_state(state)?; must_quit = true; } if let Some(shell) = &install_args.print_shell_function { @@ -100,8 +60,8 @@ pub fn run() -> Result<Option<Launchable>, ProgramError> { } // read the list of specific config files - let specific_conf: Option<Vec<PathBuf>> = cli_matches - .value_of("conf") + let specific_conf: Option<Vec<PathBuf>> = args.conf + .as_ref() .map(|s| s.split(';').map(PathBuf::from).collect()); // if we don't run on a specific config file, we check the @@ -128,64 +88,32 @@ pub fn run() -> Result<Option<Launchable>, ProgramError> { }; debug!("config: {:#?}", &config); - // tree options are built from the default_flags - // found in the config file(s) (if any) then overriden - // by the cli args - let mut tree_options = TreeOptions::default(); - tree_options.apply_config(&config)?; - tree_options.apply_launch_args(&cli_matches); // verb store is completed from the config file(s) let verb_store = VerbStore::new(&mut config)?; - // reading the other arguments - let file_export_path = cli_matches.value_of("file-export-path").map(str::to_string); - let cmd_export_path = cli_matches.value_of("cmd-export-path").map(str::to_string); - let commands = cli_matches.value_of("commands").map(str::to_string); - let height = cli_matches.value_of("height").and_then(|s| s.parse().ok()); - let color = match cli_matches.value_of("color") { - Some("yes") => Some(true), - Some("no") => Some(false), - _ => None, - }; - - let root = get_root_path(&cli_matches)?; + let context = AppContext::from(args, verb_store, &config)?; #[cfg(unix)] - if let Some(server_name) = cli_matches.value_of("send") { + if let Some(server_name) = &context.launch_args.send { use crate::{ command::Sequence, net::{Client, Message}, }; let client = Client::new(server_name); - if let Some(seq) = &commands { + if let Some(seq) = &context.launch_args.commands { let message = Message::Sequence(Sequence::new_local(seq.to_string())); client.send(&message)?; - } else if !cli_matches.is_present("get-root") { - let message = Message::Command(format!(":focus {}", root.to_string_lossy())); + } else if !context.launch_args.get_root { + let message = Message::Command(format!(":focus {}", context.initial_root.to_string_lossy())); client.send(&message)?; }; - if cli_matches.is_present("get-root") { + if context.launch_args.get_root { client.send(&Message::GetRoot)?; } return Ok(None); } - let mut launch_args = AppLaunchArgs { - root, - file_export_path, - cmd_export_path, - tree_options, - commands, - height, - color, - listen: cli_matches.value_of("listen").map(str::to_string), - }; - if color == Some(false) { - launch_args.tree_options.show_selection_mark = true; - } - - let context = AppContext::from(launch_args, verb_store, &config)?; let mut w = display::writer(); let app = App::new(&context)?; w.queue(EnterAlternateScreen)?; diff --git a/src/print.rs b/src/print.rs index 90d38ef..d7c4af7 100644 --- a/src/print.rs +++ b/src/print.rs @@ -3,37 +3,26 @@ use { crate::{ app::*, - display::{DisplayableTree, Screen}, + display::Screen, errors::ProgramError, launchable::Launchable, - skin::{ExtColorMap, PanelSkin, StyleMap}, + skin::{PanelSkin, StyleMap}, tree::Tree, }, crossterm::tty::IsTty, pathdiff, std::{ - fs::OpenOptions, - io::{self, Write, stdout}, + io::{self, stdout}, path::Path, }, }; -fn print_string(string: String, con: &AppContext) -> io::Result<CmdResult> { +fn print_string(string: String, _con: &AppContext) -> io::Result<CmdResult> { Ok( - if let Some(ref output_path) = con.launch_args.file_export_path { - // an output path was provided, we write to it - let f = OpenOptions::new() - .create(true) - .append(true) - .open(output_path)?; - writeln!(&f, "{}", string)?; - CmdResult::Quit - } else { - // no output path provided. We write on stdout, but we must - // do it after app closing to have the desired stdout (it may - // be the normal terminal or a file, or other output) - CmdResult::from(Launchable::printer(string)) - } + // We write on stdout, but we must do it after app closing + // to have the desired stdout (it may be the normal terminal + // or a file, or other output) + CmdResult::from(Launchable::printer(string)) ) } @@ -54,7 +43,7 @@ pub fn print_paths(sel_info: &SelInfo, con: &AppContext) -> io::Result<CmdResult } fn relativize_path(path: &Path, con: &AppContext) -> io::Result<String> { - let relative_path = match pathdiff::diff_paths(path, &con.launch_args.root) { + let relative_path = match pathdiff::diff_paths(path, &con.initial_root) { None => { return Err(io::Error::new( io::ErrorKind::Other, @@ -88,53 +77,23 @@ pub fn print_relative_paths(sel_info: &SelInfo, con: &AppContext) -> io::Result< print_string(string, con) } -fn print_tree_to_file( - tree: &Tree, - screen: Screen, - file_path: &str, - ext_colors: &ExtColorMap, -) -> Result<CmdResult, ProgramError> { - let no_style_skin = StyleMap::no_term(); - let dp = DisplayableTree::out_of_app( - tree, - &no_style_skin, - ext_colors, - screen.width, - (tree.lines.len() as u16).min(screen.height), - ); - let mut f = OpenOptions::new() - .create(true) - .append(true) - .open(file_path)?; - dp.write_on(&mut f)?; - Ok(CmdResult::Quit) -} - pub fn print_tree( tree: &Tree, screen: Screen, panel_skin: &PanelSkin, con: &AppContext, ) -> Result<CmdResult, ProgramError> { - if let Some(ref output_path) = con.launch_args.file_export_path { - // an output path was provided, we write to it - print_tree_to_file(tree, screen, output_path, &con.ext_colors) + // We write on stdout, but we must do it after app closing to have the normal terminal + let show_color = con.launch_args.color.unwrap_or_else(|| stdout().is_tty()); + let styles = if show_color { + panel_skin.styles.clone() } else { - // no output path provided. We write on stdout, but we must - // do it after app closing to have the normal terminal - let show_color = con.launch |