Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/fs/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ impl FileFilter {
}

/// Sort the files in the given vector based on the sort field option.
pub fn sort_files<'a, F>(&self, files: &mut Vec<F>)
pub fn sort_files<'a, F>(&self, files: &mut Vec<F>, maybe_different_parents: bool)
where F: AsRef<File<'a>>
{
files.sort_by(|a, b| {
self.sort_field.compare_files(a.as_ref(), b.as_ref())
self.sort_field.compare_files(a.as_ref(), b.as_ref(), maybe_different_parents)
});

if self.reverse {
Expand Down Expand Up @@ -213,9 +213,16 @@ impl SortField {
/// into groups between letters and numbers, and then sorts those blocks
/// together, so `file10` will sort after `file9`, instead of before it
/// because of the `1`.
pub fn compare_files(self, a: &File<'_>, b: &File<'_>) -> Ordering {
pub fn compare_files(self, a: &File<'_>, b: &File<'_>, maybe_different_parents: bool) -> Ordering {
use self::SortCase::{ABCabc, AaBbCc};

if self != Self::Unsorted && maybe_different_parents {
match a.path.parent().cmp(&b.path.parent()) {
Ordering::Equal => {}
ord @ _ => return ord
}
}

match self {
Self::Unsorted => Ordering::Equal,

Expand Down
26 changes: 14 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ impl<'args> Exa<'args> {
let is_only_dir = dirs.len() == 1 && no_files;

self.options.filter.filter_argument_files(&mut files);
self.print_files(None, files)?;
self.print_files(None, files, true)?;

self.print_dirs(dirs, no_files, is_only_dir, exit_status)
}
Expand All @@ -204,7 +204,7 @@ impl<'args> Exa<'args> {
for dir in dir_files {

// Put a gap between directories, or between the list of files and
// the first directory.
// the first directory when recursing.
if first {
first = false;
}
Expand All @@ -226,13 +226,15 @@ impl<'args> Exa<'args> {
Err((path, e)) => writeln!(io::stderr(), "[{}: {}]", path.display(), e)?,
}
};

self.options.filter.filter_child_files(&mut children);
self.options.filter.sort_files(&mut children);
if children.is_empty() {
continue;
}

if let Some(recurse_opts) = self.options.dir_action.recurse_options() {
let depth = dir.path.components().filter(|&c| c != Component::CurDir).count() + 1;
if ! recurse_opts.tree && ! recurse_opts.is_too_deep(depth) {
self.options.filter.sort_files(&mut children, false);

let mut child_dirs = Vec::new();
for child_dir in children.iter().filter(|f| f.is_directory() && ! f.is_all_all) {
Expand All @@ -242,7 +244,7 @@ impl<'args> Exa<'args> {
}
}

self.print_files(Some(&dir), children)?;
self.print_files(Some(&dir), children, false)?;
match self.print_dirs(child_dirs, false, false, exit_status) {
Ok(_) => (),
Err(e) => return Err(e),
Expand All @@ -251,14 +253,14 @@ impl<'args> Exa<'args> {
}
}

self.print_files(Some(&dir), children)?;
self.print_files(Some(&dir), children, false)?;
}

Ok(exit_status)
}

/// Prints the list of files using whichever view is selected.
fn print_files(&mut self, dir: Option<&Dir>, files: Vec<File<'_>>) -> io::Result<()> {
fn print_files(&mut self, dir: Option<&Dir>, files: Vec<File<'_>>, maybe_different_parents: bool) -> io::Result<()> {
if files.is_empty() {
return Ok(());
}
Expand All @@ -270,14 +272,14 @@ impl<'args> Exa<'args> {
(Mode::Grid(ref opts), Some(console_width)) => {
let filter = &self.options.filter;
let r = grid::Render { files, theme, file_style, opts, console_width, filter };
r.render(&mut self.writer)
r.render(&mut self.writer, maybe_different_parents)
}

(Mode::Grid(_), None) |
(Mode::Lines, _) => {
let filter = &self.options.filter;
let r = lines::Render { files, theme, file_style, filter };
r.render(&mut self.writer)
r.render(&mut self.writer, maybe_different_parents)
}

(Mode::Details(ref opts), _) => {
Expand All @@ -287,7 +289,7 @@ impl<'args> Exa<'args> {
let git_ignoring = self.options.filter.git_ignore == GitIgnore::CheckAndIgnore;
let git = self.git.as_ref();
let r = details::Render { dir, files, theme, file_style, opts, recurse, filter, git_ignoring, git };
r.render(&mut self.writer)
r.render(&mut self.writer, maybe_different_parents)
}

(Mode::GridDetails(ref opts), Some(console_width)) => {
Expand All @@ -300,7 +302,7 @@ impl<'args> Exa<'args> {
let git = self.git.as_ref();

let r = grid_details::Render { dir, files, theme, file_style, grid, details, filter, row_threshold, git_ignoring, git, console_width };
r.render(&mut self.writer)
r.render(&mut self.writer, maybe_different_parents)
}

(Mode::GridDetails(ref opts), None) => {
Expand All @@ -311,7 +313,7 @@ impl<'args> Exa<'args> {

let git = self.git.as_ref();
let r = details::Render { dir, files, theme, file_style, opts, recurse, filter, git_ignoring, git };
r.render(&mut self.writer)
r.render(&mut self.writer, maybe_different_parents)
}
}
}
Expand Down
13 changes: 7 additions & 6 deletions src/output/details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl<'a> AsRef<File<'a>> for Egg<'a> {


impl<'a> Render<'a> {
pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> {
pub fn render<W: Write>(mut self, w: &mut W, first: bool) -> io::Result<()> {
let mut pool = Pool::new(num_cpus::get() as u32);
let mut rows = Vec::new();

Expand All @@ -168,14 +168,14 @@ impl<'a> Render<'a> {
// This is weird, but I can’t find a way around it:
// https://internals.rust-lang.org/t/should-option-mut-t-implement-copy/3715/6
let mut table = Some(table);
self.add_files_to_table(&mut pool, &mut table, &mut rows, &self.files, TreeDepth::root());
self.add_files_to_table(&mut pool, &mut table, &mut rows, &self.files, TreeDepth::root(), first);

for row in self.iterate_with_table(table.unwrap(), rows) {
writeln!(w, "{}", row.strings())?
}
}
else {
self.add_files_to_table(&mut pool, &mut None, &mut rows, &self.files, TreeDepth::root());
self.add_files_to_table(&mut pool, &mut None, &mut rows, &self.files, TreeDepth::root(), first);

for row in self.iterate(rows) {
writeln!(w, "{}", row.strings())?
Expand All @@ -187,7 +187,7 @@ impl<'a> Render<'a> {

/// Adds files to the table, possibly recursively. This is easily
/// parallelisable, and uses a pool of threads.
fn add_files_to_table<'dir>(&self, pool: &mut Pool, table: &mut Option<Table<'a>>, rows: &mut Vec<Row>, src: &[File<'dir>], depth: TreeDepth) {
fn add_files_to_table<'dir>(&self, pool: &mut Pool, table: &mut Option<Table<'a>>, rows: &mut Vec<Row>, src: &[File<'dir>], depth: TreeDepth, first: bool) {
use std::sync::{Arc, Mutex};
use log::*;
use crate::fs::feature::xattr;
Expand Down Expand Up @@ -272,7 +272,8 @@ impl<'a> Render<'a> {

// this is safe because all entries have been initialized above
let mut file_eggs = unsafe { std::mem::transmute::<_, Vec<Egg<'_>>>(file_eggs) };
self.filter.sort_files(&mut file_eggs);

self.filter.sort_files(&mut file_eggs, first);

for (tree_params, egg) in depth.iterate_over(file_eggs.into_iter()) {
let mut files = Vec::new();
Expand Down Expand Up @@ -318,7 +319,7 @@ impl<'a> Render<'a> {
rows.push(self.render_error(&error, TreeParams::new(depth.deeper(), false), path));
}

self.add_files_to_table(pool, table, rows, &files, depth.deeper());
self.add_files_to_table(pool, table, rows, &files, depth.deeper(), false);
continue;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/output/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ pub struct Render<'a> {
}

impl<'a> Render<'a> {
pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> {
pub fn render<W: Write>(mut self, w: &mut W, maybe_different_parents: bool) -> io::Result<()> {
let mut grid = tg::Grid::new(tg::GridOptions {
direction: self.opts.direction(),
filling: tg::Filling::Spaces(2),
});

grid.reserve(self.files.len());

self.filter.sort_files(&mut self.files);
self.filter.sort_files(&mut self.files, maybe_different_parents);
for file in &self.files {
let filename = self.file_style.for_file(file, self.theme).paint();

Expand Down
5 changes: 3 additions & 2 deletions src/output/grid_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,13 @@ impl<'a> Render<'a> {
// This doesn’t take an IgnoreCache even though the details one does
// because grid-details has no tree view.

pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> {
pub fn render<W: Write>(mut self, w: &mut W, maybe_different_parents: bool) -> io::Result<()> {
self.filter.sort_files(&mut self.files, maybe_different_parents);
if let Some((grid, width)) = self.find_fitting_grid() {
write!(w, "{}", grid.fit_into_columns(width))
}
else {
self.give_up().render(w)
self.give_up().render(w, maybe_different_parents)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/output/lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pub struct Render<'a> {
}

impl<'a> Render<'a> {
pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> {
self.filter.sort_files(&mut self.files);
pub fn render<W: Write>(mut self, w: &mut W, maybe_different_parents: bool) -> io::Result<()> {
self.filter.sort_files(&mut self.files, maybe_different_parents);
for file in &self.files {
let name_cell = self.render_file(file);
writeln!(w, "{}", ANSIStrings(&name_cell))?;
Expand Down