lsd/src/core.rs

163 lines
5 KiB
Rust
Raw Normal View History

2018-12-02 14:05:27 +00:00
use batch::Batch;
use color::{Colors, Theme};
2018-12-02 16:22:51 +00:00
use display::Display;
2018-12-08 13:21:32 +00:00
use flags::{Flags, WhenFlag};
2018-12-08 18:52:56 +00:00
use icon::Icons;
2018-12-04 12:29:54 +00:00
use meta::{FileType, Meta};
use std::path::{Path, PathBuf};
use terminal_size::terminal_size;
pub struct Core {
flags: Flags,
2018-12-08 18:52:56 +00:00
icons: Icons,
display: Display,
colors: Colors,
}
impl Core {
pub fn new(flags: Flags) -> Core {
// terminal_size allows us to know if the stdout is a tty or not.
let tty_available = terminal_size().is_some();
let mut inner_flags = flags;
2018-12-08 13:21:32 +00:00
let theme = match (tty_available, flags.color) {
(true, WhenFlag::Never) => Theme::NoColor,
(false, WhenFlag::Auto) => Theme::NoColor,
(false, WhenFlag::Always) => Theme::Default,
_ => Theme::Default,
};
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.display_online = true;
};
2018-12-04 13:54:56 +00:00
Core {
flags,
display: Display::new(inner_flags),
colors: Colors::new(theme),
2018-12-08 18:52:56 +00:00
icons: Icons::new(),
2018-12-04 13:54:56 +00:00
}
}
2018-12-04 13:54:56 +00:00
pub fn run(self, paths: Vec<PathBuf>) {
self.run_inner(paths, 0);
}
2018-12-02 16:22:51 +00:00
2018-12-04 13:54:56 +00:00
fn run_inner(&self, paths: Vec<PathBuf>, depth: usize) {
let mut dirs = Vec::new();
let mut files = Vec::new();
2018-12-04 12:29:54 +00:00
for path in paths {
if path.is_dir() {
dirs.push(path);
2018-12-04 12:29:54 +00:00
} else if let Some(meta) = Meta::from_path(&path) {
files.push(meta);
}
}
2018-12-02 14:05:27 +00:00
let print_folder_name: bool = dirs.len() + files.len() > 1;
if !files.is_empty() && !self.flags.display_tree {
2018-12-02 16:22:51 +00:00
let mut file_batch = Batch::from(files);
file_batch.sort();
2018-12-04 13:54:56 +00:00
self.display
.print_outputs(self.get_batch_outputs(&file_batch));
2018-12-02 16:22:51 +00:00
}
2018-12-02 14:05:27 +00:00
dirs.sort_unstable();
for dir in dirs {
2018-12-04 12:29:54 +00:00
if let Some(folder_batch) = self.list_folder_content(dir.as_path()) {
if (print_folder_name || self.flags.recursive) && !self.flags.display_tree {
2018-12-02 14:05:27 +00:00
println!("\n{}:", dir.display())
}
2018-11-24 11:02:39 +00:00
if self.flags.display_tree {
2018-12-04 13:54:56 +00:00
self.display_as_tree(folder_batch, depth);
} else if self.flags.recursive {
2018-12-04 13:54:56 +00:00
self.display
.print_outputs(self.get_batch_outputs(&folder_batch));
2018-12-04 12:29:54 +00:00
let folder_dirs = folder_batch
.into_iter()
.filter_map(|x| {
if x.file_type == FileType::Directory {
Some(x.path)
} else {
None
}
}).collect();
2018-12-04 13:54:56 +00:00
self.run_inner(folder_dirs, depth);
} else {
self.display
.print_outputs(self.get_batch_outputs(&folder_batch));
2018-12-04 12:29:54 +00:00
}
}
2018-11-24 16:42:39 +00:00
}
}
2018-12-04 13:54:56 +00:00
pub fn display_as_tree(&self, batch: Batch, depth: usize) {
let last_idx = batch.len();
for (idx, elem) in batch.into_iter().enumerate() {
let last = idx + 1 != last_idx;
2018-12-04 13:54:56 +00:00
if elem.file_type == FileType::Directory {
self.display.print_tree_row(
2018-12-11 09:11:13 +00:00
elem.name.render(&self.colors, &self.icons).to_string(),
depth,
last,
);
2018-12-04 13:54:56 +00:00
self.run_inner(vec![elem.path], depth + 1);
} else {
self.display.print_tree_row(
2018-12-11 09:11:13 +00:00
elem.name.render(&self.colors, &self.icons).to_string(),
depth,
last,
);
2018-12-04 13:54:56 +00:00
}
}
}
2018-12-02 16:22:51 +00:00
pub fn get_batch_outputs<'b>(&self, batch: &'b Batch) -> Vec<String> {
if self.flags.display_long {
2018-12-10 17:26:34 +00:00
batch.get_long_output(&self.colors, &self.icons, self.flags)
2018-11-24 16:42:39 +00:00
} else {
2018-12-10 17:26:34 +00:00
batch.get_short_output(&self.colors, &self.icons, self.flags)
2018-11-24 16:42:39 +00:00
}
}
2018-12-02 14:05:27 +00:00
pub fn list_folder_content(&self, folder: &Path) -> Option<Batch> {
let mut metas: Vec<Meta> = Vec::new();
2018-11-24 11:02:39 +00:00
let dir = match folder.read_dir() {
Ok(dir) => dir,
Err(err) => {
println!("cannot open directory'{}': {}", folder.display(), err);
2018-12-02 14:05:27 +00:00
return None;
2018-11-24 11:02:39 +00:00
}
};
for entry in dir {
if let Ok(entry) = entry {
2018-12-04 12:29:54 +00:00
if let Some(meta) = Meta::from_path(&entry.path()) {
if !meta.name.is_hidden() || self.flags.display_all {
metas.push(meta);
}
}
}
}
2018-12-02 14:05:27 +00:00
let mut batch = Batch::from(metas);
batch.sort();
2018-12-02 14:05:27 +00:00
Some(batch)
}
}