mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-17 01:35:12 +00:00
Merge branch 'file-namers'
This creates a new type that holds file extensions in preparation for #116. It doesn’t do anything yet, but it will!
This commit is contained in:
commit
f54bc41792
10
src/exa.rs
10
src/exa.rs
@ -168,13 +168,13 @@ impl<'w, W: Write + 'w> Exa<'w, W> {
|
|||||||
/// printing differently...
|
/// printing differently...
|
||||||
fn print_files(&mut self, dir: Option<&Dir>, files: Vec<File>) -> IOResult<()> {
|
fn print_files(&mut self, dir: Option<&Dir>, files: Vec<File>) -> IOResult<()> {
|
||||||
if !files.is_empty() {
|
if !files.is_empty() {
|
||||||
let View { ref mode, ref colours, classify } = self.options.view;
|
let View { ref mode, ref colours, ref style } = self.options.view;
|
||||||
|
|
||||||
match *mode {
|
match *mode {
|
||||||
Mode::Lines => lines::Render { files, colours, classify }.render(self.writer),
|
Mode::Lines => lines::Render { files, colours, style }.render(self.writer),
|
||||||
Mode::Grid(ref opts) => grid::Render { files, colours, classify, opts }.render(self.writer),
|
Mode::Grid(ref opts) => grid::Render { files, colours, style, opts }.render(self.writer),
|
||||||
Mode::Details(ref opts) => details::Render { dir, files, colours, classify, opts, filter: &self.options.filter, recurse: self.options.dir_action.recurse_options() }.render(self.writer),
|
Mode::Details(ref opts) => details::Render { dir, files, colours, style, opts, filter: &self.options.filter, recurse: self.options.dir_action.recurse_options() }.render(self.writer),
|
||||||
Mode::GridDetails(ref grid, ref details) => grid_details::Render { dir, files, colours, classify, grid, details, filter: &self.options.filter }.render(self.writer),
|
Mode::GridDetails(ref grid, ref details) => grid_details::Render { dir, files, colours, style, grid, details, filter: &self.options.filter }.render(self.writer),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -7,21 +7,24 @@
|
|||||||
use fs::File;
|
use fs::File;
|
||||||
|
|
||||||
|
|
||||||
impl<'a> File<'a> {
|
#[derive(Debug)]
|
||||||
|
pub struct FileExtensions;
|
||||||
|
|
||||||
|
impl FileExtensions {
|
||||||
|
|
||||||
/// An “immediate” file is something that can be run or activated somehow
|
/// An “immediate” file is something that can be run or activated somehow
|
||||||
/// in order to kick off the build of a project. It’s usually only present
|
/// in order to kick off the build of a project. It’s usually only present
|
||||||
/// in directories full of source code.
|
/// in directories full of source code.
|
||||||
pub fn is_immediate(&self) -> bool {
|
pub fn is_immediate(&self, file: &File) -> bool {
|
||||||
self.name.starts_with("README") || self.name_is_one_of( &[
|
file.name.starts_with("README") || file.name_is_one_of( &[
|
||||||
"Makefile", "Cargo.toml", "SConstruct", "CMakeLists.txt",
|
"Makefile", "Cargo.toml", "SConstruct", "CMakeLists.txt",
|
||||||
"build.gradle", "Rakefile", "Gruntfile.js",
|
"build.gradle", "Rakefile", "Gruntfile.js",
|
||||||
"Gruntfile.coffee",
|
"Gruntfile.coffee",
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_image(&self) -> bool {
|
pub fn is_image(&self, file: &File) -> bool {
|
||||||
self.extension_is_one_of( &[
|
file.extension_is_one_of( &[
|
||||||
"png", "jpeg", "jpg", "gif", "bmp", "tiff", "tif",
|
"png", "jpeg", "jpg", "gif", "bmp", "tiff", "tif",
|
||||||
"ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw",
|
"ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw",
|
||||||
"svg", "stl", "eps", "dvi", "ps", "cbr",
|
"svg", "stl", "eps", "dvi", "ps", "cbr",
|
||||||
@ -29,92 +32,62 @@ impl<'a> File<'a> {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_video(&self) -> bool {
|
pub fn is_video(&self, file: &File) -> bool {
|
||||||
self.extension_is_one_of( &[
|
file.extension_is_one_of( &[
|
||||||
"avi", "flv", "m2v", "mkv", "mov", "mp4", "mpeg",
|
"avi", "flv", "m2v", "mkv", "mov", "mp4", "mpeg",
|
||||||
"mpg", "ogm", "ogv", "vob", "wmv",
|
"mpg", "ogm", "ogv", "vob", "wmv",
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_music(&self) -> bool {
|
pub fn is_music(&self, file: &File) -> bool {
|
||||||
self.extension_is_one_of( &[
|
file.extension_is_one_of( &[
|
||||||
"aac", "m4a", "mp3", "ogg", "wma",
|
"aac", "m4a", "mp3", "ogg", "wma",
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lossless music, rather than any other kind of data...
|
// Lossless music, rather than any other kind of data...
|
||||||
pub fn is_lossless(&self) -> bool {
|
pub fn is_lossless(&self, file: &File) -> bool {
|
||||||
self.extension_is_one_of( &[
|
file.extension_is_one_of( &[
|
||||||
"alac", "ape", "flac", "wav",
|
"alac", "ape", "flac", "wav",
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_crypto(&self) -> bool {
|
pub fn is_crypto(&self, file: &File) -> bool {
|
||||||
self.extension_is_one_of( &[
|
file.extension_is_one_of( &[
|
||||||
"asc", "enc", "gpg", "pgp", "sig", "signature", "pfx", "p12",
|
"asc", "enc", "gpg", "pgp", "sig", "signature", "pfx", "p12",
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_document(&self) -> bool {
|
pub fn is_document(&self, file: &File) -> bool {
|
||||||
self.extension_is_one_of( &[
|
file.extension_is_one_of( &[
|
||||||
"djvu", "doc", "docx", "dvi", "eml", "eps", "fotd",
|
"djvu", "doc", "docx", "dvi", "eml", "eps", "fotd",
|
||||||
"odp", "odt", "pdf", "ppt", "pptx", "rtf",
|
"odp", "odt", "pdf", "ppt", "pptx", "rtf",
|
||||||
"xls", "xlsx",
|
"xls", "xlsx",
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_compressed(&self) -> bool {
|
pub fn is_compressed(&self, file: &File) -> bool {
|
||||||
self.extension_is_one_of( &[
|
file.extension_is_one_of( &[
|
||||||
"zip", "tar", "Z", "gz", "bz2", "a", "ar", "7z",
|
"zip", "tar", "Z", "gz", "bz2", "a", "ar", "7z",
|
||||||
"iso", "dmg", "tc", "rar", "par", "tgz",
|
"iso", "dmg", "tc", "rar", "par", "tgz",
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_temp(&self) -> bool {
|
pub fn is_temp(&self, file: &File) -> bool {
|
||||||
self.name.ends_with('~')
|
file.name.ends_with('~')
|
||||||
|| (self.name.starts_with('#') && self.name.ends_with('#'))
|
|| (file.name.starts_with('#') && file.name.ends_with('#'))
|
||||||
|| self.extension_is_one_of( &[ "tmp", "swp", "swo", "swn", "bak" ])
|
|| file.extension_is_one_of( &[ "tmp", "swp", "swo", "swn", "bak" ])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_compiled(&self) -> bool {
|
pub fn is_compiled(&self, file: &File) -> bool {
|
||||||
if self.extension_is_one_of( &[ "class", "elc", "hi", "o", "pyc" ]) {
|
if file.extension_is_one_of( &[ "class", "elc", "hi", "o", "pyc" ]) {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else if let Some(dir) = self.parent_dir {
|
else if let Some(dir) = file.parent_dir {
|
||||||
self.get_source_files().iter().any(|path| dir.contains(path))
|
file.get_source_files().iter().any(|path| dir.contains(path))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(broken_test)]
|
|
||||||
mod test {
|
|
||||||
use file::test::{dummy_stat, new_file};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn lowercase() {
|
|
||||||
let file = new_file(dummy_stat(), "/barracks.wav");
|
|
||||||
assert_eq!(FileType::Lossless, file.get_type())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn uppercase() {
|
|
||||||
let file = new_file(dummy_stat(), "/BARRACKS.WAV");
|
|
||||||
assert_eq!(FileType::Lossless, file.get_type())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn cargo() {
|
|
||||||
let file = new_file(dummy_stat(), "/Cargo.toml");
|
|
||||||
assert_eq!(FileType::Immediate, file.get_type())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn not_cargo() {
|
|
||||||
let file = new_file(dummy_stat(), "/cargo.toml");
|
|
||||||
assert_eq!(FileType::Normal, file.get_type())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! The "info" module contains routines that aren't about probing the
|
//! The “info” module contains routines that aren’t about probing the
|
||||||
//! filesystem nor displaying output to the user, but are internal "business
|
//! filesystem nor displaying output to the user, but are internal “business
|
||||||
//! logic” routines that are performed on a file’s already-read metadata.
|
//! logic” routines that are performed on a file’s already-read metadata.
|
||||||
//! (This counts the file name as metadata.)
|
//! (This counts the file name as metadata.)
|
||||||
|
|
||||||
mod filetype;
|
pub mod filetype;
|
||||||
mod sources;
|
mod sources;
|
||||||
|
@ -2,10 +2,11 @@ use std::env::var_os;
|
|||||||
|
|
||||||
use getopts;
|
use getopts;
|
||||||
|
|
||||||
|
use info::filetype::FileExtensions;
|
||||||
use output::Colours;
|
use output::Colours;
|
||||||
use output::{grid, details};
|
use output::{grid, details};
|
||||||
use output::table::{TimeTypes, Environment, SizeFormat, Options as TableOptions};
|
use output::table::{TimeTypes, Environment, SizeFormat, Options as TableOptions};
|
||||||
use output::file_name::Classify;
|
use output::file_name::{Classify, FileStyle};
|
||||||
use output::time::TimeFormat;
|
use output::time::TimeFormat;
|
||||||
use options::Misfire;
|
use options::Misfire;
|
||||||
use fs::feature::xattr;
|
use fs::feature::xattr;
|
||||||
@ -16,17 +17,17 @@ use fs::feature::xattr;
|
|||||||
pub struct View {
|
pub struct View {
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
pub colours: Colours,
|
pub colours: Colours,
|
||||||
pub classify: Classify,
|
pub style: FileStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View {
|
impl View {
|
||||||
|
|
||||||
/// Determine which view to use and all of that view’s arguments.
|
/// Determine which view to use and all of that view’s arguments.
|
||||||
pub fn deduce(matches: &getopts::Matches) -> Result<View, Misfire> {
|
pub fn deduce(matches: &getopts::Matches) -> Result<View, Misfire> {
|
||||||
let mode = Mode::deduce(matches)?;
|
let mode = Mode::deduce(matches)?;
|
||||||
let colours = Colours::deduce(matches)?;
|
let colours = Colours::deduce(matches)?;
|
||||||
let classify = Classify::deduce(matches);
|
let style = FileStyle::deduce(matches);
|
||||||
Ok(View { mode, colours, classify })
|
Ok(View { mode, colours, style })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,6 +371,15 @@ impl Colours {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
impl FileStyle {
|
||||||
|
fn deduce(matches: &getopts::Matches) -> FileStyle {
|
||||||
|
let classify = Classify::deduce(matches);
|
||||||
|
let exts = FileExtensions;
|
||||||
|
FileStyle { classify, exts }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
impl Classify {
|
impl Classify {
|
||||||
fn deduce(matches: &getopts::Matches) -> Classify {
|
fn deduce(matches: &getopts::Matches) -> Classify {
|
||||||
if matches.opt_present("classify") { Classify::AddFileIndicators }
|
if matches.opt_present("classify") { Classify::AddFileIndicators }
|
||||||
|
@ -70,7 +70,7 @@ use options::{FileFilter, RecurseOptions};
|
|||||||
use output::colours::Colours;
|
use output::colours::Colours;
|
||||||
use output::cell::TextCell;
|
use output::cell::TextCell;
|
||||||
use output::tree::{TreeTrunk, TreeParams, TreeDepth};
|
use output::tree::{TreeTrunk, TreeParams, TreeDepth};
|
||||||
use output::file_name::{FileName, LinkStyle, Classify};
|
use output::file_name::FileStyle;
|
||||||
use output::table::{Table, Options as TableOptions, Row as TableRow};
|
use output::table::{Table, Options as TableOptions, Row as TableRow};
|
||||||
|
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ pub struct Render<'a> {
|
|||||||
pub dir: Option<&'a Dir>,
|
pub dir: Option<&'a Dir>,
|
||||||
pub files: Vec<File<'a>>,
|
pub files: Vec<File<'a>>,
|
||||||
pub colours: &'a Colours,
|
pub colours: &'a Colours,
|
||||||
pub classify: Classify,
|
pub style: &'a FileStyle,
|
||||||
pub opts: &'a Options,
|
pub opts: &'a Options,
|
||||||
|
|
||||||
/// Whether to recurse through directories with a tree view, and if so,
|
/// Whether to recurse through directories with a tree view, and if so,
|
||||||
@ -233,7 +233,9 @@ impl<'a> Render<'a> {
|
|||||||
let row = Row {
|
let row = Row {
|
||||||
tree: tree_params,
|
tree: tree_params,
|
||||||
cells: egg.table_row,
|
cells: egg.table_row,
|
||||||
name: FileName::new(&egg.file, LinkStyle::FullLinkPaths, self.classify, self.colours).paint().promote(),
|
name: self.style.for_file(&egg.file, self.colours)
|
||||||
|
.with_link_paths()
|
||||||
|
.paint().promote(),
|
||||||
};
|
};
|
||||||
|
|
||||||
rows.push(row);
|
rows.push(row);
|
||||||
|
@ -3,11 +3,76 @@ use std::path::Path;
|
|||||||
use ansi_term::{ANSIString, Style};
|
use ansi_term::{ANSIString, Style};
|
||||||
|
|
||||||
use fs::{File, FileTarget};
|
use fs::{File, FileTarget};
|
||||||
|
use info::filetype::FileExtensions;
|
||||||
use output::Colours;
|
use output::Colours;
|
||||||
use output::escape;
|
use output::escape;
|
||||||
use output::cell::TextCellContents;
|
use output::cell::TextCellContents;
|
||||||
|
|
||||||
|
|
||||||
|
/// Basically a file name factory.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FileStyle {
|
||||||
|
|
||||||
|
/// Whether to append file class characters to file names.
|
||||||
|
pub classify: Classify,
|
||||||
|
|
||||||
|
/// Mapping of file extensions to colours, to highlight regular files.
|
||||||
|
pub exts: FileExtensions,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileStyle {
|
||||||
|
|
||||||
|
/// Create a new `FileName` that prints the given file’s name, painting it
|
||||||
|
/// with the remaining arguments.
|
||||||
|
pub fn for_file<'a, 'dir>(&'a self, file: &'a File<'dir>, colours: &'a Colours) -> FileName<'a, 'dir> {
|
||||||
|
FileName {
|
||||||
|
file, colours,
|
||||||
|
link_style: LinkStyle::JustFilenames,
|
||||||
|
exts: &self.exts,
|
||||||
|
classify: self.classify,
|
||||||
|
target: if file.is_link() { Some(file.link_target()) }
|
||||||
|
else { None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// When displaying a file name, there needs to be some way to handle broken
|
||||||
|
/// links, depending on how long the resulting Cell can be.
|
||||||
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
|
enum LinkStyle {
|
||||||
|
|
||||||
|
/// Just display the file names, but colour them differently if they’re
|
||||||
|
/// a broken link or can’t be followed.
|
||||||
|
JustFilenames,
|
||||||
|
|
||||||
|
/// Display all files in their usual style, but follow each link with an
|
||||||
|
/// arrow pointing to their path, colouring the path differently if it’s
|
||||||
|
/// a broken link, and doing nothing if it can’t be followed.
|
||||||
|
FullLinkPaths,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Whether to append file class characters to the file names.
|
||||||
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
|
pub enum Classify {
|
||||||
|
|
||||||
|
/// Just display the file names, without any characters.
|
||||||
|
JustFilenames,
|
||||||
|
|
||||||
|
/// Add a character after the file name depending on what class of file
|
||||||
|
/// it is.
|
||||||
|
AddFileIndicators,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Classify {
|
||||||
|
fn default() -> Classify {
|
||||||
|
Classify::JustFilenames
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// A **file name** holds all the information necessary to display the name
|
/// A **file name** holds all the information necessary to display the name
|
||||||
/// of the given file. This is used in all of the views.
|
/// of the given file. This is used in all of the views.
|
||||||
pub struct FileName<'a, 'dir: 'a> {
|
pub struct FileName<'a, 'dir: 'a> {
|
||||||
@ -26,20 +91,21 @@ pub struct FileName<'a, 'dir: 'a> {
|
|||||||
|
|
||||||
/// Whether to append file class characters to file names.
|
/// Whether to append file class characters to file names.
|
||||||
classify: Classify,
|
classify: Classify,
|
||||||
|
|
||||||
|
/// Mapping of file extensions to colours, to highlight regular files.
|
||||||
|
exts: &'a FileExtensions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a, 'dir> FileName<'a, 'dir> {
|
impl<'a, 'dir> FileName<'a, 'dir> {
|
||||||
|
|
||||||
/// Create a new `FileName` that prints the given file’s name, painting it
|
/// Sets the flag on this file name to display link targets with an
|
||||||
/// with the remaining arguments.
|
/// arrow followed by their path.
|
||||||
pub fn new(file: &'a File<'dir>, link_style: LinkStyle, classify: Classify, colours: &'a Colours) -> FileName<'a, 'dir> {
|
pub fn with_link_paths(mut self) -> Self {
|
||||||
let target = if file.is_link() { Some(file.link_target()) }
|
self.link_style = LinkStyle::FullLinkPaths;
|
||||||
else { None };
|
self
|
||||||
FileName { file, colours, target, link_style, classify }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Paints the name of the file using the colours, resulting in a vector
|
/// Paints the name of the file using the colours, resulting in a vector
|
||||||
/// of coloured cells that can be printed to the terminal.
|
/// of coloured cells that can be printed to the terminal.
|
||||||
///
|
///
|
||||||
@ -73,7 +139,15 @@ impl<'a, 'dir> FileName<'a, 'dir> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !target.name.is_empty() {
|
if !target.name.is_empty() {
|
||||||
let target = FileName::new(target, LinkStyle::FullLinkPaths, Classify::JustFilenames, self.colours);
|
let target = FileName {
|
||||||
|
file: target,
|
||||||
|
colours: self.colours,
|
||||||
|
target: None,
|
||||||
|
link_style: LinkStyle::FullLinkPaths,
|
||||||
|
classify: Classify::JustFilenames,
|
||||||
|
exts: self.exts,
|
||||||
|
};
|
||||||
|
|
||||||
for bit in target.coloured_file_name() {
|
for bit in target.coloured_file_name() {
|
||||||
bits.push(bit);
|
bits.push(bit);
|
||||||
}
|
}
|
||||||
@ -181,52 +255,18 @@ impl<'a, 'dir> FileName<'a, 'dir> {
|
|||||||
| f.is_block_device() => self.colours.filetypes.device,
|
| f.is_block_device() => self.colours.filetypes.device,
|
||||||
f if f.is_socket() => self.colours.filetypes.socket,
|
f if f.is_socket() => self.colours.filetypes.socket,
|
||||||
f if !f.is_file() => self.colours.filetypes.special,
|
f if !f.is_file() => self.colours.filetypes.special,
|
||||||
f if f.is_immediate() => self.colours.filetypes.immediate,
|
|
||||||
f if f.is_image() => self.colours.filetypes.image,
|
f if self.exts.is_immediate(f) => self.colours.filetypes.immediate,
|
||||||
f if f.is_video() => self.colours.filetypes.video,
|
f if self.exts.is_image(f) => self.colours.filetypes.image,
|
||||||
f if f.is_music() => self.colours.filetypes.music,
|
f if self.exts.is_video(f) => self.colours.filetypes.video,
|
||||||
f if f.is_lossless() => self.colours.filetypes.lossless,
|
f if self.exts.is_music(f) => self.colours.filetypes.music,
|
||||||
f if f.is_crypto() => self.colours.filetypes.crypto,
|
f if self.exts.is_lossless(f) => self.colours.filetypes.lossless,
|
||||||
f if f.is_document() => self.colours.filetypes.document,
|
f if self.exts.is_crypto(f) => self.colours.filetypes.crypto,
|
||||||
f if f.is_compressed() => self.colours.filetypes.compressed,
|
f if self.exts.is_document(f) => self.colours.filetypes.document,
|
||||||
f if f.is_temp() => self.colours.filetypes.temp,
|
f if self.exts.is_compressed(f) => self.colours.filetypes.compressed,
|
||||||
f if f.is_compiled() => self.colours.filetypes.compiled,
|
f if self.exts.is_temp(f) => self.colours.filetypes.temp,
|
||||||
_ => self.colours.filetypes.normal,
|
f if self.exts.is_compiled(f) => self.colours.filetypes.compiled,
|
||||||
|
_ => self.colours.filetypes.normal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// When displaying a file name, there needs to be some way to handle broken
|
|
||||||
/// links, depending on how long the resulting Cell can be.
|
|
||||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
|
||||||
pub enum LinkStyle {
|
|
||||||
|
|
||||||
/// Just display the file names, but colour them differently if they’re
|
|
||||||
/// a broken link or can’t be followed.
|
|
||||||
JustFilenames,
|
|
||||||
|
|
||||||
/// Display all files in their usual style, but follow each link with an
|
|
||||||
/// arrow pointing to their path, colouring the path differently if it’s
|
|
||||||
/// a broken link, and doing nothing if it can’t be followed.
|
|
||||||
FullLinkPaths,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Whether to append file class characters to the file names.
|
|
||||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
|
||||||
pub enum Classify {
|
|
||||||
|
|
||||||
/// Just display the file names, without any characters.
|
|
||||||
JustFilenames,
|
|
||||||
|
|
||||||
/// Add a character after the file name depending on what class of file
|
|
||||||
/// it is.
|
|
||||||
AddFileIndicators,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Classify {
|
|
||||||
fn default() -> Classify {
|
|
||||||
Classify::JustFilenames
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,7 +4,7 @@ use term_grid as tg;
|
|||||||
|
|
||||||
use fs::File;
|
use fs::File;
|
||||||
use output::colours::Colours;
|
use output::colours::Colours;
|
||||||
use output::file_name::{FileName, LinkStyle, Classify};
|
use output::file_name::FileStyle;
|
||||||
|
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
@ -24,7 +24,7 @@ impl Options {
|
|||||||
pub struct Render<'a> {
|
pub struct Render<'a> {
|
||||||
pub files: Vec<File<'a>>,
|
pub files: Vec<File<'a>>,
|
||||||
pub colours: &'a Colours,
|
pub colours: &'a Colours,
|
||||||
pub classify: Classify,
|
pub style: &'a FileStyle,
|
||||||
pub opts: &'a Options,
|
pub opts: &'a Options,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ impl<'a> Render<'a> {
|
|||||||
grid.reserve(self.files.len());
|
grid.reserve(self.files.len());
|
||||||
|
|
||||||
for file in self.files.iter() {
|
for file in self.files.iter() {
|
||||||
let filename = FileName::new(file, LinkStyle::JustFilenames, self.classify, self.colours).paint();
|
let filename = self.style.for_file(file, self.colours).paint();
|
||||||
let width = filename.width();
|
let width = filename.width();
|
||||||
|
|
||||||
grid.add(tg::Cell {
|
grid.add(tg::Cell {
|
||||||
@ -52,8 +52,10 @@ impl<'a> Render<'a> {
|
|||||||
}
|
}
|
||||||
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!
|
||||||
|
// This isn’t *quite* the same as the lines view, which also
|
||||||
|
// displays full link paths.
|
||||||
for file in self.files.iter() {
|
for file in self.files.iter() {
|
||||||
let name_cell = FileName::new(file, LinkStyle::JustFilenames, self.classify, self.colours).paint();
|
let name_cell = self.style.for_file(file, self.colours).paint();
|
||||||
writeln!(w, "{}", name_cell.strings())?;
|
writeln!(w, "{}", name_cell.strings())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -11,7 +11,7 @@ use output::cell::TextCell;
|
|||||||
use output::colours::Colours;
|
use output::colours::Colours;
|
||||||
use output::details::{Options as DetailsOptions, Row as DetailsRow, Render as DetailsRender};
|
use output::details::{Options as DetailsOptions, Row as DetailsRow, Render as DetailsRender};
|
||||||
use output::grid::Options as GridOptions;
|
use output::grid::Options as GridOptions;
|
||||||
use output::file_name::{FileName, LinkStyle, Classify};
|
use output::file_name::FileStyle;
|
||||||
use output::table::{Table, Row as TableRow, Options as TableOptions};
|
use output::table::{Table, Row as TableRow, Options as TableOptions};
|
||||||
use output::tree::{TreeParams, TreeDepth};
|
use output::tree::{TreeParams, TreeDepth};
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ pub struct Render<'a> {
|
|||||||
pub dir: Option<&'a Dir>,
|
pub dir: Option<&'a Dir>,
|
||||||
pub files: Vec<File<'a>>,
|
pub files: Vec<File<'a>>,
|
||||||
pub colours: &'a Colours,
|
pub colours: &'a Colours,
|
||||||
pub classify: Classify,
|
pub style: &'a FileStyle,
|
||||||
pub grid: &'a GridOptions,
|
pub grid: &'a GridOptions,
|
||||||
pub details: &'a DetailsOptions,
|
pub details: &'a DetailsOptions,
|
||||||
pub filter: &'a FileFilter,
|
pub filter: &'a FileFilter,
|
||||||
@ -32,7 +32,7 @@ impl<'a> Render<'a> {
|
|||||||
dir: self.dir.clone(),
|
dir: self.dir.clone(),
|
||||||
files: Vec::new(),
|
files: Vec::new(),
|
||||||
colours: self.colours,
|
colours: self.colours,
|
||||||
classify: self.classify,
|
style: self.style,
|
||||||
opts: self.details,
|
opts: self.details,
|
||||||
recurse: None,
|
recurse: None,
|
||||||
filter: self.filter,
|
filter: self.filter,
|
||||||
@ -52,7 +52,7 @@ impl<'a> Render<'a> {
|
|||||||
.collect::<Vec<TableRow>>();
|
.collect::<Vec<TableRow>>();
|
||||||
|
|
||||||
let file_names = self.files.iter()
|
let file_names = self.files.iter()
|
||||||
.map(|file| FileName::new(file, LinkStyle::JustFilenames, self.classify, self.colours).paint().promote())
|
.map(|file| self.style.for_file(file, self.colours).paint().promote())
|
||||||
.collect::<Vec<TextCell>>();
|
.collect::<Vec<TextCell>>();
|
||||||
|
|
||||||
let mut last_working_table = self.make_grid(1, options, &file_names, rows.clone(), &drender);
|
let mut last_working_table = self.make_grid(1, options, &file_names, rows.clone(), &drender);
|
||||||
|
@ -4,7 +4,7 @@ use ansi_term::ANSIStrings;
|
|||||||
|
|
||||||
use fs::File;
|
use fs::File;
|
||||||
|
|
||||||
use output::file_name::{FileName, LinkStyle, Classify};
|
use output::file_name::{FileName, FileStyle};
|
||||||
use super::colours::Colours;
|
use super::colours::Colours;
|
||||||
|
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ use super::colours::Colours;
|
|||||||
pub struct Render<'a> {
|
pub struct Render<'a> {
|
||||||
pub files: Vec<File<'a>>,
|
pub files: Vec<File<'a>>,
|
||||||
pub colours: &'a Colours,
|
pub colours: &'a Colours,
|
||||||
pub classify: Classify,
|
pub style: &'a FileStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Render<'a> {
|
impl<'a> Render<'a> {
|
||||||
@ -26,6 +26,6 @@ impl<'a> Render<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render_file<'f>(&self, file: &'f File<'a>) -> FileName<'f, 'a> {
|
fn render_file<'f>(&self, file: &'f File<'a>) -> FileName<'f, 'a> {
|
||||||
FileName::new(file, LinkStyle::FullLinkPaths, self.classify, self.colours)
|
self.style.for_file(file, self.colours).with_link_paths()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user