lsd/src/core.rs

144 lines
4.6 KiB
Rust
Raw Normal View History

2019-02-09 11:41:42 +01:00
use crate::color::{self, Colors};
use crate::display;
use crate::flags::{ColorOption, Display, Flags, IconOption, IconTheme, Layout, SortOrder};
2019-02-09 11:41:42 +01:00
use crate::icon::{self, Icons};
use crate::meta::Meta;
use crate::{print_error, print_output, sort};
2019-01-20 11:22:14 +01:00
use std::path::PathBuf;
2019-06-18 17:24:40 +10:00
#[cfg(not(target_os = "windows"))]
use std::io;
2019-06-18 17:24:40 +10:00
#[cfg(not(target_os = "windows"))]
use std::os::unix::io::AsRawFd;
2019-06-18 17:24:40 +10:00
#[cfg(target_os = "windows")]
use terminal_size::terminal_size;
pub struct Core {
flags: Flags,
2018-12-08 19:52:56 +01:00
icons: Icons,
2019-01-20 11:22:14 +01:00
//display: Display,
colors: Colors,
sorters: Vec<(SortOrder, sort::SortFn)>,
}
impl Core {
2018-12-13 16:50:47 +01:00
pub fn new(flags: Flags) -> Self {
// Check through libc if stdout is a tty. Unix specific so not on windows.
// Determine color output availability (and initialize color output (for Windows 10))
#[cfg(not(target_os = "windows"))]
let tty_available = unsafe { libc::isatty(io::stdout().as_raw_fd()) == 1 };
2019-06-18 17:24:40 +10:00
2019-05-07 12:57:01 -05:00
#[cfg(not(target_os = "windows"))]
let console_color_ok = true;
#[cfg(target_os = "windows")]
let tty_available = terminal_size().is_some(); // terminal_size allows us to know if the stdout is a tty or not.
2019-05-07 12:57:01 -05:00
#[cfg(target_os = "windows")]
let console_color_ok = ansi_term::enable_ansi_support().is_ok();
let mut inner_flags = flags.clone();
let color_theme = match (tty_available && console_color_ok, flags.color.when) {
(_, ColorOption::Never) | (false, ColorOption::Auto) => color::Theme::NoColor,
2019-01-29 18:16:55 +01:00
_ => color::Theme::Default,
2018-12-13 14:51:31 +01:00
};
let icon_theme = match (tty_available, flags.icons.when, flags.icons.theme) {
(_, IconOption::Never, _) | (false, IconOption::Auto, _) => icon::Theme::NoIcon,
2019-01-29 18:16:55 +01:00
(_, _, IconTheme::Fancy) => icon::Theme::Fancy,
(_, _, IconTheme::Unicode) => icon::Theme::Unicode,
2018-12-08 14:21:32 +01:00
};
if !tty_available {
// The output is not a tty, this means the command is piped. (ex: lsd -l | less)
//
// Most of the programs does not handle correctly the ansi colors
// or require a raw output (like the `wc` command).
inner_flags.layout = Layout::OneLine;
};
let sorters = sort::assemble_sorters(&flags);
2019-09-13 18:29:11 +10:00
2018-12-13 16:50:47 +01:00
Self {
flags,
2019-01-20 11:22:14 +01:00
//display: Display::new(inner_flags),
2018-12-13 14:51:31 +01:00
colors: Colors::new(color_theme),
icons: Icons::new(icon_theme),
sorters,
2018-12-04 14:54:56 +01:00
}
}
2018-12-04 14:54:56 +01:00
pub fn run(self, paths: Vec<PathBuf>) {
2019-01-20 11:22:14 +01:00
let mut meta_list = self.fetch(paths);
self.sort(&mut meta_list);
2019-10-23 17:26:39 +02:00
self.display(&meta_list)
2018-12-04 14:54:56 +01:00
}
2018-12-02 17:22:51 +01:00
2019-01-20 11:22:14 +01:00
fn fetch(&self, paths: Vec<PathBuf>) -> Vec<Meta> {
let mut meta_list = Vec::with_capacity(paths.len());
let depth = match self.flags.layout {
Layout::Tree { .. } => self.flags.recursion.depth,
_ if self.flags.recursion.enabled => self.flags.recursion.depth,
_ => 1,
2019-01-20 11:22:14 +01:00
};
2018-12-04 13:29:54 +01:00
for path in paths {
let mut meta = match Meta::from_path(&path, self.flags.dereference.0) {
Ok(meta) => meta,
Err(err) => {
print_error!("lsd: {}: {}\n", path.display(), err);
continue;
}
2019-01-20 11:22:14 +01:00
};
match self.flags.display {
Display::DirectoryItself => {
meta_list.push(meta);
}
_ => {
2020-08-22 00:46:59 +05:30
match meta.recurse_into(depth, &self.flags) {
2019-05-24 15:30:36 +02:00
Ok(content) => {
meta.content = content;
meta_list.push(meta);
}
Err(err) => {
print_error!("lsd: {}: {}\n", path.display(), err);
continue;
}
};
}
};
2018-12-02 17:22:51 +01:00
}
if self.flags.total_size.0 {
for meta in &mut meta_list.iter_mut() {
meta.calculate_total_size();
}
}
2018-12-02 15:05:27 +01:00
meta_list
2018-11-24 17:42:39 +01:00
}
2019-01-20 11:22:14 +01:00
fn sort(&self, metas: &mut Vec<Meta>) {
metas.sort_unstable_by(|a, b| sort::by_meta(&self.sorters, a, b));
2019-01-20 11:22:14 +01:00
for meta in metas {
if let Some(ref mut content) = meta.content {
self.sort(content);
2018-12-04 14:54:56 +01:00
}
}
}
2019-10-23 17:26:39 +02:00
fn display(&self, metas: &[Meta]) {
2019-10-24 17:18:42 +02:00
let output = if self.flags.layout == Layout::Tree {
display::tree(&metas, &self.flags, &self.colors, &self.icons)
} else {
display::grid(&metas, &self.flags, &self.colors, &self.icons)
2018-11-24 12:02:39 +01:00
};
2019-10-24 17:18:42 +02:00
print_output!("{}", output);
}
}