mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-26 22:06:26 +00:00
Implement -F/--classify option
This commit is contained in:
parent
3087565c01
commit
e81b83b4ac
@ -7,6 +7,7 @@ DISPLAY OPTIONS
|
|||||||
-R, --recurse recurse into directories
|
-R, --recurse recurse into directories
|
||||||
-T, --tree recurse into subdirectories in a tree view
|
-T, --tree recurse into subdirectories in a tree view
|
||||||
-x, --across sort multi-column view entries across
|
-x, --across sort multi-column view entries across
|
||||||
|
-F, --classify show file type indicator (one of */=@|)
|
||||||
|
|
||||||
--color=WHEN, --colour=WHEN when to colourise the output (always, auto, never)
|
--color=WHEN, --colour=WHEN when to colourise the output (always, auto, never)
|
||||||
--color-scale, --colour-scale colour file sizes according to their magnitude
|
--color-scale, --colour-scale colour file sizes according to their magnitude
|
||||||
|
@ -55,6 +55,7 @@ impl Options {
|
|||||||
opts.optflag("R", "recurse", "recurse into directories");
|
opts.optflag("R", "recurse", "recurse into directories");
|
||||||
opts.optflag("T", "tree", "recurse into subdirectories in a tree view");
|
opts.optflag("T", "tree", "recurse into subdirectories in a tree view");
|
||||||
opts.optflag("x", "across", "sort multi-column view entries across");
|
opts.optflag("x", "across", "sort multi-column view entries across");
|
||||||
|
opts.optflag("F", "classify", "show file type indicator (one of */=@|)");
|
||||||
opts.optopt ("", "color", "when to show anything in colours", "WHEN");
|
opts.optopt ("", "color", "when to show anything in colours", "WHEN");
|
||||||
opts.optopt ("", "colour", "when to show anything in colours (alternate spelling)", "WHEN");
|
opts.optopt ("", "colour", "when to show anything in colours (alternate spelling)", "WHEN");
|
||||||
opts.optflag("", "color-scale", "use a colour scale when displaying file sizes (alternate spelling)");
|
opts.optflag("", "color-scale", "use a colour scale when displaying file sizes (alternate spelling)");
|
||||||
|
@ -58,6 +58,7 @@ impl View {
|
|||||||
filter: filter.clone(),
|
filter: filter.clone(),
|
||||||
xattr: xattr::ENABLED && matches.opt_present("extended"),
|
xattr: xattr::ENABLED && matches.opt_present("extended"),
|
||||||
colours: colours,
|
colours: colours,
|
||||||
|
classify: matches.opt_present("classify"),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(details)
|
Ok(details)
|
||||||
@ -86,6 +87,8 @@ impl View {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let other_options_scan = || {
|
let other_options_scan = || {
|
||||||
|
let classify = matches.opt_present("classify");
|
||||||
|
|
||||||
let term_colours = TerminalColours::deduce(matches)?;
|
let term_colours = TerminalColours::deduce(matches)?;
|
||||||
let term_width = TerminalWidth::deduce()?;
|
let term_width = TerminalWidth::deduce()?;
|
||||||
|
|
||||||
@ -103,6 +106,7 @@ impl View {
|
|||||||
else {
|
else {
|
||||||
let lines = Lines {
|
let lines = Lines {
|
||||||
colours: colours,
|
colours: colours,
|
||||||
|
classify: classify,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(View::Lines(lines))
|
Ok(View::Lines(lines))
|
||||||
@ -116,6 +120,7 @@ impl View {
|
|||||||
filter: filter.clone(), // TODO: clone
|
filter: filter.clone(), // TODO: clone
|
||||||
xattr: false,
|
xattr: false,
|
||||||
colours: colours,
|
colours: colours,
|
||||||
|
classify: classify,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(View::Details(details))
|
Ok(View::Details(details))
|
||||||
@ -125,6 +130,7 @@ impl View {
|
|||||||
across: matches.opt_present("across"),
|
across: matches.opt_present("across"),
|
||||||
console_width: width,
|
console_width: width,
|
||||||
colours: colours,
|
colours: colours,
|
||||||
|
classify: classify,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(View::Grid(grid))
|
Ok(View::Grid(grid))
|
||||||
@ -148,6 +154,7 @@ impl View {
|
|||||||
filter: filter.clone(),
|
filter: filter.clone(),
|
||||||
xattr: false,
|
xattr: false,
|
||||||
colours: colours,
|
colours: colours,
|
||||||
|
classify: classify,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(View::Details(details))
|
Ok(View::Details(details))
|
||||||
@ -155,6 +162,7 @@ impl View {
|
|||||||
else {
|
else {
|
||||||
let lines = Lines {
|
let lines = Lines {
|
||||||
colours: colours,
|
colours: colours,
|
||||||
|
classify: classify,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(View::Lines(lines))
|
Ok(View::Lines(lines))
|
||||||
|
@ -5,6 +5,8 @@ use std::ops::{Add, Deref, DerefMut};
|
|||||||
use ansi_term::{Style, ANSIString, ANSIStrings};
|
use ansi_term::{Style, ANSIString, ANSIStrings};
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
|
use fs::File;
|
||||||
|
|
||||||
|
|
||||||
/// An individual cell that holds text in a table, used in the details and
|
/// An individual cell that holds text in a table, used in the details and
|
||||||
/// lines views to store ANSI-terminal-formatted data before it is printed.
|
/// lines views to store ANSI-terminal-formatted data before it is printed.
|
||||||
@ -178,6 +180,19 @@ impl TextCellContents {
|
|||||||
#[derive(PartialEq, Debug, Clone, Copy, Default)]
|
#[derive(PartialEq, Debug, Clone, Copy, Default)]
|
||||||
pub struct DisplayWidth(usize);
|
pub struct DisplayWidth(usize);
|
||||||
|
|
||||||
|
impl DisplayWidth {
|
||||||
|
pub fn from_file(file: &File, classify: bool) -> DisplayWidth {
|
||||||
|
let name_width = *DisplayWidth::from(&*file.name);
|
||||||
|
if classify {
|
||||||
|
if file.is_executable_file() || file.is_directory() ||
|
||||||
|
file.is_pipe() || file.is_link() || file.is_socket() {
|
||||||
|
return DisplayWidth(name_width + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DisplayWidth(name_width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a str> for DisplayWidth {
|
impl<'a> From<&'a str> for DisplayWidth {
|
||||||
fn from(input: &'a str) -> DisplayWidth {
|
fn from(input: &'a str) -> DisplayWidth {
|
||||||
DisplayWidth(UnicodeWidthStr::width(input))
|
DisplayWidth(UnicodeWidthStr::width(input))
|
||||||
|
@ -140,6 +140,9 @@ pub struct Details {
|
|||||||
/// The colours to use to display information in the table, including the
|
/// The colours to use to display information in the table, including the
|
||||||
/// colour of the tree view symbols.
|
/// colour of the tree view symbols.
|
||||||
pub colours: Colours,
|
pub colours: Colours,
|
||||||
|
|
||||||
|
/// Whether to show a file type indiccator.
|
||||||
|
pub classify: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The **environment** struct contains any data that could change between
|
/// The **environment** struct contains any data that could change between
|
||||||
@ -303,7 +306,7 @@ impl Details {
|
|||||||
for (index, egg) in file_eggs.into_iter().enumerate() {
|
for (index, egg) in file_eggs.into_iter().enumerate() {
|
||||||
let mut files = Vec::new();
|
let mut files = Vec::new();
|
||||||
let mut errors = egg.errors;
|
let mut errors = egg.errors;
|
||||||
let mut width = DisplayWidth::from(&*egg.file.name);
|
let mut width = DisplayWidth::from_file(&egg.file, self.classify);
|
||||||
|
|
||||||
if egg.file.dir.is_none() {
|
if egg.file.dir.is_none() {
|
||||||
if let Some(parent) = egg.file.path.parent() {
|
if let Some(parent) = egg.file.path.parent() {
|
||||||
@ -312,7 +315,7 @@ impl Details {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let name = TextCell {
|
let name = TextCell {
|
||||||
contents: filename(&egg.file, &self.colours, true),
|
contents: filename(&egg.file, &self.colours, true, self.classify),
|
||||||
width: width,
|
width: width,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -453,7 +456,7 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn filename_cell(&self, file: File, links: bool) -> TextCell {
|
pub fn filename_cell(&self, file: File, links: bool) -> TextCell {
|
||||||
let mut width = DisplayWidth::from(&*file.name);
|
let mut width = DisplayWidth::from_file(&file, self.opts.classify);
|
||||||
|
|
||||||
if file.dir.is_none() {
|
if file.dir.is_none() {
|
||||||
if let Some(parent) = file.path.parent() {
|
if let Some(parent) = file.path.parent() {
|
||||||
@ -462,7 +465,7 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextCell {
|
TextCell {
|
||||||
contents: filename(&file, &self.opts.colours, links),
|
contents: filename(&file, &self.opts.colours, links, self.opts.classify),
|
||||||
width: width,
|
width: width,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ pub struct Grid {
|
|||||||
pub across: bool,
|
pub across: bool,
|
||||||
pub console_width: usize,
|
pub console_width: usize,
|
||||||
pub colours: Colours,
|
pub colours: Colours,
|
||||||
|
pub classify: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Grid {
|
impl Grid {
|
||||||
@ -28,7 +29,7 @@ impl Grid {
|
|||||||
grid.reserve(files.len());
|
grid.reserve(files.len());
|
||||||
|
|
||||||
for file in files.iter() {
|
for file in files.iter() {
|
||||||
let mut width = DisplayWidth::from(&*file.name);
|
let mut width = DisplayWidth::from_file(file, self.classify);
|
||||||
|
|
||||||
if file.dir.is_none() {
|
if file.dir.is_none() {
|
||||||
if let Some(parent) = file.path.parent() {
|
if let Some(parent) = file.path.parent() {
|
||||||
@ -37,7 +38,7 @@ impl Grid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
grid.add(grid::Cell {
|
grid.add(grid::Cell {
|
||||||
contents: filename(file, &self.colours, false).strings().to_string(),
|
contents: filename(file, &self.colours, false, self.classify).strings().to_string(),
|
||||||
width: *width,
|
width: *width,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -48,7 +49,7 @@ impl Grid {
|
|||||||
else {
|
else {
|
||||||
// File names too long for a grid - drop down to just listing them!
|
// File names too long for a grid - drop down to just listing them!
|
||||||
for file in files.iter() {
|
for file in files.iter() {
|
||||||
writeln!(w, "{}", filename(file, &self.colours, false).strings())?;
|
writeln!(w, "{}", filename(file, &self.colours, false, self.classify).strings())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,14 @@ use super::colours::Colours;
|
|||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct Lines {
|
pub struct Lines {
|
||||||
pub colours: Colours,
|
pub colours: Colours,
|
||||||
|
pub classify: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The lines view literally just displays each file, line-by-line.
|
/// The lines view literally just displays each file, line-by-line.
|
||||||
impl Lines {
|
impl Lines {
|
||||||
pub fn view<W: Write>(&self, files: Vec<File>, w: &mut W) -> IOResult<()> {
|
pub fn view<W: Write>(&self, files: Vec<File>, w: &mut W) -> IOResult<()> {
|
||||||
for file in files {
|
for file in files {
|
||||||
writeln!(w, "{}", ANSIStrings(&filename(&file, &self.colours, true)))?;
|
writeln!(w, "{}", ANSIStrings(&filename(&file, &self.colours, true, self.classify)))?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ mod colours;
|
|||||||
mod tree;
|
mod tree;
|
||||||
|
|
||||||
|
|
||||||
pub fn filename(file: &File, colours: &Colours, links: bool) -> TextCellContents {
|
pub fn filename(file: &File, colours: &Colours, links: bool, classify: bool) -> TextCellContents {
|
||||||
let mut bits = Vec::new();
|
let mut bits = Vec::new();
|
||||||
|
|
||||||
if file.dir.is_none() {
|
if file.dir.is_none() {
|
||||||
@ -78,6 +78,18 @@ pub fn filename(file: &File, colours: &Colours, links: bool) -> TextCellContents
|
|||||||
// Do nothing -- the error gets displayed on the next line
|
// Do nothing -- the error gets displayed on the next line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if classify {
|
||||||
|
if file.is_executable_file() {
|
||||||
|
bits.push(Style::default().paint("*"));
|
||||||
|
} else if file.is_directory() {
|
||||||
|
bits.push(Style::default().paint("/"));
|
||||||
|
} else if file.is_pipe() {
|
||||||
|
bits.push(Style::default().paint("|"));
|
||||||
|
} else if file.is_link() {
|
||||||
|
bits.push(Style::default().paint("@"));
|
||||||
|
} else if file.is_socket() {
|
||||||
|
bits.push(Style::default().paint("="));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bits.into()
|
bits.into()
|
||||||
|
Loading…
Reference in New Issue
Block a user