Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up #441

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
283 changes: 169 additions & 114 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions Cargo.toml
Expand Up @@ -25,17 +25,19 @@ dirs = "3.0.*"
libc = "0.2.*"
human-sort = "0.2.2"
term_grid = "0.1.*"
terminal_size = "0.1.*"
chrono = "0.4.*"
chrono-humanize = "0.1.*"
unicode-width = "0.1.*"
lscolors = "0.7"
lscolors = "0.7.*"
wild = "2.0.*"
globset = "0.4.*"
xdg = "2.1.*"
yaml-rust = "0.4.*"
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8"
serde = { version = "1.0.*", features = ["derive"] }
serde_yaml = "0.8.*"
fxhash = "0.2.*"
termize = "0.1.*"
simple-counter = "0.1.0"

[target.'cfg(unix)'.dependencies]
users = "0.11.*"
Expand Down
136 changes: 62 additions & 74 deletions src/color.rs
@@ -1,6 +1,8 @@
use crate::hashmap;
use ansi_term::{ANSIString, Colour, Style};
use fxhash::FxHashMap;
use lscolors::{Indicator, LsColors};
use std::collections::HashMap;
use std::fs::Metadata;
use std::path::Path;

#[allow(dead_code)]
Expand Down Expand Up @@ -73,7 +75,7 @@ pub enum Theme {
}

pub struct Colors {
colors: Option<HashMap<Elem, Colour>>,
colors: Option<FxHashMap<Elem, Colour>>,
lscolors: Option<LsColors>,
}

Expand Down Expand Up @@ -102,32 +104,30 @@ impl Colors {
input: String,
path: &Path,
elem: &Elem,
meta: &Metadata,
) -> ColoredString<'a> {
let style_from_path = self.style_from_path(path);
match style_from_path {
Some(style_from_path) => style_from_path.paint(input),
match self.style_from_path(path, meta) {
Some(style) => style.paint(input),
None => self.colorize(input, elem),
}
}

fn style_from_path(&self, path: &Path) -> Option<Style> {
fn style_from_path(&self, path: &Path, meta: &Metadata) -> Option<Style> {
match &self.lscolors {
Some(lscolors) => lscolors
.style_for_path(path)
.map(lscolors::Style::to_ansi_term_style),
.style_for_path_with_metadata(path, Some(meta))
.map(|s| s.to_ansi_term_style()),
None => None,
}
}

fn style(&self, elem: &Elem) -> Style {
match &self.lscolors {
Some(lscolors) => match self.get_indicator_from_elem(elem) {
Some(style) => {
let style = lscolors.style_for_indicator(style);
style
.map(lscolors::Style::to_ansi_term_style)
.unwrap_or_default()
}
Some(style) => lscolors
.style_for_indicator(style)
.map(|s| s.to_ansi_term_style())
.unwrap_or_default(),
None => self.style_default(elem),
},
None => self.style_default(elem),
Expand Down Expand Up @@ -187,77 +187,65 @@ impl Colors {
// You can find the table for each color, code, and display at:
//
//https://jonasjacek.github.io/colors/
fn get_light_theme_colour_map() -> HashMap<Elem, Colour> {
let mut m = HashMap::new();
// User / Group
m.insert(Elem::User, Colour::Fixed(230)); // Cornsilk1
m.insert(Elem::Group, Colour::Fixed(187)); // LightYellow3

// Permissions
m.insert(Elem::Read, Colour::Green);
m.insert(Elem::Write, Colour::Yellow);
m.insert(Elem::Exec, Colour::Red);
m.insert(Elem::ExecSticky, Colour::Purple);
m.insert(Elem::NoAccess, Colour::Fixed(245)); // Grey

// File Types
m.insert(
fn get_light_theme_colour_map() -> FxHashMap<Elem, Colour> {
hashmap! {
// User / Group
Elem::User => Colour::Fixed(230), // Cornsilk1
Elem::Group => Colour::Fixed(187), // LightYellow3

// Permissions
Elem::Read => Colour::Green,
Elem::Write => Colour::Yellow,
Elem::Exec => Colour::Red,
Elem::ExecSticky => Colour::Purple,
Elem::NoAccess => Colour::Fixed(245), // Grey

// File Types
Elem::File {
exec: false,
uid: false,
},
Colour::Fixed(184),
); // Yellow3
m.insert(
} => Colour::Fixed(184), // Yellow3
Elem::File {
exec: false,
uid: true,
},
Colour::Fixed(184),
); // Yellow3
m.insert(
} => Colour::Fixed(184), // Yellow3
Elem::File {
exec: true,
uid: false,
},
Colour::Fixed(40),
); // Green3
m.insert(
} => Colour::Fixed(40), // Green3
Elem::File {
exec: true,
uid: true,
},
Colour::Fixed(40),
); // Green3
m.insert(Elem::Dir { uid: true }, Colour::Fixed(33)); // DodgerBlue1
m.insert(Elem::Dir { uid: false }, Colour::Fixed(33)); // DodgerBlue1
m.insert(Elem::Pipe, Colour::Fixed(44)); // DarkTurquoise
m.insert(Elem::SymLink, Colour::Fixed(44)); // DarkTurquoise
m.insert(Elem::BrokenSymLink, Colour::Fixed(124)); // Red3
m.insert(Elem::BlockDevice, Colour::Fixed(44)); // DarkTurquoise
m.insert(Elem::CharDevice, Colour::Fixed(172)); // Orange3
m.insert(Elem::Socket, Colour::Fixed(44)); // DarkTurquoise
m.insert(Elem::Special, Colour::Fixed(44)); // DarkTurquoise

// Last Time Modified
m.insert(Elem::HourOld, Colour::Fixed(40)); // Green3
m.insert(Elem::DayOld, Colour::Fixed(42)); // SpringGreen2
m.insert(Elem::Older, Colour::Fixed(36)); // DarkCyan

// Last Time Modified
m.insert(Elem::NonFile, Colour::Fixed(245)); // Grey
m.insert(Elem::FileSmall, Colour::Fixed(229)); // Wheat1
m.insert(Elem::FileMedium, Colour::Fixed(216)); // LightSalmon1
m.insert(Elem::FileLarge, Colour::Fixed(172)); // Orange3

// INode
m.insert(Elem::INode { valid: true }, Colour::Fixed(13)); // Pink
m.insert(Elem::INode { valid: false }, Colour::Fixed(245)); // Grey
m.insert(Elem::Links { valid: true }, Colour::Fixed(13));
m.insert(Elem::Links { valid: false }, Colour::Fixed(245));

// TODO add this after we can use file to configure theme
// m.insert(Elem::TreeEdge, Colour::Fixed(44)); // DarkTurquoise
m
} => Colour::Fixed(40), // Green3
Elem::Dir { uid: true } => Colour::Fixed(33), // DodgerBlue1
Elem::Dir { uid: false } => Colour::Fixed(33), // DodgerBlue1
Elem::Pipe => Colour::Fixed(44), // DarkTurquoise
Elem::SymLink => Colour::Fixed(44), // DarkTurquoise
Elem::BrokenSymLink => Colour::Fixed(124), // Red3
Elem::BlockDevice => Colour::Fixed(44), // DarkTurquoise
Elem::CharDevice => Colour::Fixed(172), // Orange3
Elem::Socket => Colour::Fixed(44), // DarkTurquoise
Elem::Special => Colour::Fixed(44), // DarkTurquoise

// Last Time Modified
Elem::HourOld => Colour::Fixed(40), // Green3
Elem::DayOld => Colour::Fixed(42), // SpringGreen2
Elem::Older => Colour::Fixed(36), // DarkCyan

// Last Time Modified
Elem::NonFile => Colour::Fixed(245), // Grey
Elem::FileSmall => Colour::Fixed(229), // Wheat1
Elem::FileMedium => Colour::Fixed(216), // LightSalmon1
Elem::FileLarge => Colour::Fixed(172), // Orange3

// INode
Elem::INode { valid: true } => Colour::Fixed(13), // Pink
Elem::INode { valid: false } => Colour::Fixed(245), // Grey
Elem::Links { valid: true } => Colour::Fixed(13),
Elem::Links { valid: false } => Colour::Fixed(245),

// TODO add this after we can use file to configure theme
// Elem::TreeEdge => Colour::Fixed(44), // DarkTurquoise
}
}
}
67 changes: 17 additions & 50 deletions src/core.rs
Expand Up @@ -6,37 +6,22 @@ use crate::meta::Meta;
use crate::{print_error, print_output, sort};
use std::path::PathBuf;

#[cfg(not(target_os = "windows"))]
use std::io;
#[cfg(not(target_os = "windows"))]
use std::os::unix::io::AsRawFd;

#[cfg(target_os = "windows")]
use terminal_size::terminal_size;

pub struct Core {
flags: Flags,
icons: Icons,
//display: Display,
colors: Colors,
sorters: Vec<(SortOrder, sort::SortFn)>,
}

impl Core {
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 };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was used to check if lsd is outputting to a terminal or being piped to something else. This behaviour is not available with the new changes.

For example if we pipe lsd to less, we used to convert it to single line and remove the colors. But now it does not do that.

Screenshot


#[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.
// termize allows us to know if the stdout is a tty or not.
let tty_available = termize::dimensions().is_some();

#[cfg(target_os = "windows")]
#[cfg(windows)]
let console_color_ok = ansi_term::enable_ansi_support().is_ok();
#[cfg(unix)]
let console_color_ok = true;

let mut inner_flags = flags.clone();

Expand All @@ -51,8 +36,6 @@ impl Core {
(_, _, IconTheme::Unicode) => icon::Theme::Unicode,
};

let icon_separator = flags.icons.separator.0.clone();

if !tty_available {
// The output is not a tty, this means the command is piped. (ex: lsd -l | less)
//
Expand All @@ -67,26 +50,22 @@ impl Core {
flags,
//display: Display::new(inner_flags),
colors: Colors::new(color_theme),
icons: Icons::new(icon_theme, icon_separator),
icons: Icons::new(icon_theme),
sorters,
}
}

pub fn run(self, paths: Vec<PathBuf>) {
let mut meta_list = self.fetch(paths);

self.sort(&mut meta_list);
self.display(&meta_list)
}

fn fetch(&self, paths: Vec<PathBuf>) -> Vec<Meta> {
pub fn run(self, paths: &[PathBuf]) {
let mut meta_list = Vec::with_capacity(paths.len());

// if -R or --tree, get depth
let depth = match self.flags.layout {
Layout::Tree { .. } => self.flags.recursion.depth,
_ if self.flags.recursion.enabled => self.flags.recursion.depth,
_ => 1,
};

// fetch metas
for path in paths {
let mut meta = match Meta::from_path(&path, self.flags.dereference.0) {
Ok(meta) => meta,
Expand All @@ -102,6 +81,9 @@ impl Core {
match meta.recurse_into(depth, &self.flags) {
Ok(content) => {
meta.content = content;
if let Some(ref mut inner) = meta.content {
inner.sort_unstable_by(|a, b| sort::by_meta(&self.sorters, a, b));
}
meta_list.push(meta);
}
Err(err) => {
Expand All @@ -113,30 +95,15 @@ impl Core {
meta_list.push(meta);
};
}
if self.flags.total_size.0 {
for meta in &mut meta_list.iter_mut() {
meta.calculate_total_size();
}
}

meta_list
}

fn sort(&self, metas: &mut Vec<Meta>) {
metas.sort_unstable_by(|a, b| sort::by_meta(&self.sorters, a, b));

for meta in metas {
if let Some(ref mut content) = meta.content {
self.sort(content);
}
if self.flags.total_size.0 {
meta_list.iter_mut().for_each(Meta::calculate_total_size)
}
}

fn display(&self, metas: &[Meta]) {
let output = if self.flags.layout == Layout::Tree {
display::tree(&metas, &self.flags, &self.colors, &self.icons)
display::tree(&meta_list, &self.flags, &self.colors, &self.icons)
} else {
display::grid(&metas, &self.flags, &self.colors, &self.icons)
display::grid(&mut meta_list, &self.flags, &self.colors, &self.icons)
};

print_output!("{}", output);
Expand Down