Merge branch 'master' into chesterliu/dev/win-support

This commit is contained in:
Chester Liu 2021-03-30 11:58:39 +08:00
commit 78a3bc9838
26 changed files with 428 additions and 203 deletions

View File

@ -47,6 +47,7 @@ exas options are almost, but not quite, entirely unlike `ls`s.
- **--colo[u]r**: when to use terminal colours
- **--colo[u]r-scale**: highlight levels of file sizes distinctly
- **--icons**: display icons
- **--no-icons**: don't display icons (always overrides --icons)
### Filtering options
@ -82,6 +83,7 @@ These options are available when running with `--long` (`-l`):
- **--git**: list each files Git status, if tracked or ignored
- **--time-style**: how to format timestamps
- **--no-permissions**: suppress the permissions field
- **--octal-permissions**: list each file's permission in octal format
- **--no-filesize**: suppress the filesize field
- **--no-user**: suppress the user field
- **--no-time**: suppress the time field

View File

@ -15,6 +15,7 @@ complete -c exa -l 'colour' -d "When to use terminal colours"
complete -c exa -l 'color-scale' -d "Highlight levels of file sizes distinctly"
complete -c exa -l 'colour-scale' -d "Highlight levels of file sizes distinctly"
complete -c exa -l 'icons' -d "Display icons"
complete -c exa -l 'no-icons' -d "Don't display icons"
# Filtering and sorting options
complete -c exa -l 'group-directories-first' -d "Sort directories before other files"
@ -75,6 +76,7 @@ complete -c exa -l 'time-style' -x -d "How to format timestamps" -a "
full-iso\t'Display full ISO timestamps, up to the nanosecond'
"
complete -c exa -l 'no-permissions' -d "Suppress the permissions field"
complete -c exa -l 'octal-permissions' -d "List each file's permission in octal format"
complete -c exa -l 'no-filesize' -d "Suppress the filesize field"
complete -c exa -l 'no-user' -d "Suppress the user field"
complete -c exa -l 'no-time' -d "Suppress the time field"

View File

@ -22,6 +22,7 @@ __exa() {
--colo{,u}r"[When to use terminal colours]" \
--colo{,u}r-scale"[Highlight levels of file sizes distinctly]" \
--icons"[Display icons]" \
--no-icons"[Hide icons]" \
--group-directories-first"[Sort directories before other files]" \
--git-ignore"[Ignore files mentioned in '.gitignore']" \
{-a,--all}"[Show hidden and 'dot' files]" \
@ -43,6 +44,7 @@ __exa() {
{-t,--time}="[Which time field to show]:(time field):(accessed changed created modified)" \
--time-style="[How to format timestamps]:(time style):(default iso long-iso full-iso)" \
--no-permissions"[Suppress the permissions field]" \
--octal-permissions"[List each file's permission in octal format]" \
--no-filesize"[Suppress the filesize field]" \
--no-user"[Suppress the user field]" \
--no-time"[Suppress the time field]" \

View File

@ -72,6 +72,9 @@ Valid settings are `always`, `automatic`, and `never`.
`--icons`
: Display icons next to file names.
`--no-icons`
: Don't display icons. (Always overrides --icons)
FILTERING AND SORTING OPTIONS
=============================
@ -101,7 +104,7 @@ Sort fields starting with a capital letter will sort uppercase before lowercase:
`-I`, `--ignore-glob=GLOBS`
: Glob patterns, pipe-separated, of files to ignore.
`--git-ignore`
`--git-ignore` [if exa was built with git support]
: Do not list files that are ignored by Git.
`--group-directories-first`
@ -174,7 +177,7 @@ These options are available when running with `--long` (`-l`):
`-@`, `--extended`
: List each files extended attributes and sizes.
`--git`
`--git` [if exa was built with git support]
: List each files Git status, if tracked.

View File

@ -27,7 +27,7 @@ pub mod git {
}
pub fn get(&self, _index: &Path, _prefix_lookup: bool) -> f::Git {
panic!("Tried to query a Git cache, but Git support is disabled")
unreachable!();
}
}
}

View File

@ -7,9 +7,7 @@ use std::io;
use std::path::Path;
pub const ENABLED: bool =
cfg!(feature="git") &&
cfg!(any(target_os = "macos", target_os = "linux"));
pub const ENABLED: bool = cfg!(any(target_os = "macos", target_os = "linux"));
pub trait FileAttributes {

View File

@ -264,13 +264,15 @@ impl<'args> Exa<'args> {
match (mode, self.console_width) {
(Mode::Grid(ref opts), Some(console_width)) => {
let r = grid::Render { files, theme, file_style, opts, console_width };
let filter = &self.options.filter;
let r = grid::Render { files, theme, file_style, opts, console_width, filter };
r.render(&mut self.writer)
}
(Mode::Grid(_), None) |
(Mode::Lines, _) => {
let r = lines::Render { files, theme, file_style };
let filter = &self.options.filter;
let r = lines::Render { files, theme, file_style, filter };
r.render(&mut self.writer)
}

View File

@ -16,7 +16,7 @@ pub enum OptionsError {
/// The user supplied an illegal choice to an Argument.
BadArgument(&'static Arg, OsString),
/// The user supplied a set of options
/// The user supplied a set of options that are unsupported
Unsupported(String),
/// An option was given twice or more in strict mode.

View File

@ -25,7 +25,7 @@ impl Classify {
impl ShowIcons {
pub fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
if ! matches.has(&flags::ICONS)? {
if matches.has(&flags::NO_ICONS)? || !matches.has(&flags::ICONS)? {
Ok(Self::Off)
}
else if let Some(columns) = vars.get(vars::EXA_ICON_SPACING).and_then(|s| s.into_string().ok()) {

View File

@ -58,6 +58,7 @@ pub static NO_PERMISSIONS: Arg = Arg { short: None, long: "no-permissions", take
pub static NO_FILESIZE: Arg = Arg { short: None, long: "no-filesize", takes_value: TakesValue::Forbidden };
pub static NO_USER: Arg = Arg { short: None, long: "no-user", takes_value: TakesValue::Forbidden };
pub static NO_TIME: Arg = Arg { short: None, long: "no-time", takes_value: TakesValue::Forbidden };
pub static NO_ICONS: Arg = Arg { short: None, long: "no-icons", takes_value: TakesValue::Forbidden };
// optional feature options
pub static GIT: Arg = Arg { short: None, long: "git", takes_value: TakesValue::Forbidden };
@ -76,7 +77,7 @@ pub static ALL_ARGS: Args = Args(&[
&BINARY, &BYTES, &GROUP, &HEADER, &ICONS, &INODE, &LINKS, &MODIFIED, &CHANGED,
&BLOCKS, &TIME, &ACCESSED, &CREATED, &TIME_STYLE,
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME,
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME, &NO_ICONS,
&GIT, &EXTENDED, &OCTAL
]);

View File

@ -5,7 +5,7 @@ use crate::options::flags;
use crate::options::parser::MatchedFlags;
static USAGE: &str = r##"Usage:
static USAGE_PART1: &str = "Usage:
exa [options] [files...]
META OPTIONS
@ -23,6 +23,7 @@ DISPLAY OPTIONS
--colo[u]r=WHEN when to use terminal colours (always, auto, never)
--colo[u]r-scale highlight levels of file sizes distinctly
--icons display icons
--no-icons don't display icons (always overrides --icons)
FILTERING AND SORTING OPTIONS
-a, --all show hidden and 'dot' files
@ -32,8 +33,9 @@ FILTERING AND SORTING OPTIONS
-s, --sort SORT_FIELD which field to sort by
--group-directories-first list directories before other files
-D, --only-dirs list only directories
-I, --ignore-glob GLOBS glob patterns (pipe-separated) of files to ignore
--git-ignore ignore files mentioned in '.gitignore'
-I, --ignore-glob GLOBS glob patterns (pipe-separated) of files to ignore";
static USAGE_PART2: &str = " \
Valid sort fields: name, Name, extension, Extension, size, type,
modified, accessed, created, inode, and none.
date, time, old, and new all refer to modified.
@ -56,10 +58,11 @@ LONG VIEW OPTIONS
--octal-permissions list each file's permission in octal format
--no-filesize suppress the filesize field
--no-user suppress the user field
--no-time suppress the time field"##;
--no-time suppress the time field";
static GIT_HELP: &str = r##" --git list each file's Git status, if tracked or ignored"##;
static EXTENDED_HELP: &str = r##" -@, --extended list each file's extended attributes and sizes"##;
static GIT_FILTER_HELP: &str = " --git-ignore ignore files mentioned in '.gitignore'";
static GIT_VIEW_HELP: &str = " --git list each file's Git status, if tracked or ignored";
static EXTENDED_HELP: &str = " -@, --extended list each file's extended attributes and sizes";
/// All the information needed to display the help text, which depends
@ -92,14 +95,20 @@ impl fmt::Display for HelpString {
/// Format this help options into an actual string of help
/// text to be displayed to the user.
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
writeln!(f, "{}", USAGE)?;
write!(f, "{}", USAGE_PART1)?;
if cfg!(feature="git") {
writeln!(f, "{}", GIT_HELP)?;
if cfg!(feature = "git") {
write!(f, "\n{}", GIT_FILTER_HELP)?;
}
write!(f, "\n{}", USAGE_PART2)?;
if cfg!(feature = "git") {
write!(f, "\n{}", GIT_VIEW_HELP)?;
}
if xattr::ENABLED {
writeln!(f, "{}", EXTENDED_HELP)?;
write!(f, "\n{}", EXTENDED_HELP)?;
}
Ok(())

View File

@ -176,6 +176,13 @@ impl Options {
/// Determines the complete set of options based on the given command-line
/// arguments, after theyve been parsed.
fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
if cfg!(not(feature = "git")) &&
matches.has_where_any(|f| f.matches(&flags::GIT) || f.matches(&flags::GIT_IGNORE)).is_some() {
return Err(OptionsError::Unsupported(format!(
"Options --git and --git-ignore can't be used because `git` feature was disabled in this build of exa"
)));
}
let view = View::deduce(matches, vars)?;
let dir_action = DirAction::deduce(matches, matches!(view.mode, Mode::Details(_)))?;
let filter = FileFilter::deduce(matches)?;

View File

@ -31,7 +31,11 @@ impl VersionString {
impl fmt::Display for VersionString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
writeln!(f, "{}", include!(concat!(env!("OUT_DIR"), "/version_string.txt")))
writeln!(
f,
"{} (git support: {})",
include!(concat!(env!("OUT_DIR"), "/version_string.txt")),
if cfg!(feature = "git") { "enabled" } else { "disabled" })
}
}

View File

@ -91,7 +91,7 @@ impl Mode {
}
}
if cfg!(feature = "git") && matches.has(&flags::GIT)? {
if matches.has(&flags::GIT)? {
return Err(OptionsError::Useless(&flags::GIT, false, &flags::LONG));
}
else if matches.has(&flags::LEVEL)? && ! matches.has(&flags::RECURSE)? && ! matches.has(&flags::TREE)? {
@ -192,7 +192,7 @@ impl TableOptions {
impl Columns {
fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
let time_types = TimeTypes::deduce(matches)?;
let git = cfg!(feature = "git") && matches.has(&flags::GIT)?;
let git = matches.has(&flags::GIT)?;
let blocks = matches.has(&flags::BLOCKS)?;
let group = matches.has(&flags::GROUP)?;

View File

@ -132,9 +132,9 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
bits.push(style.paint(file_icon));
match spaces_count {
1 => bits.push(Style::default().paint(" ")),
2 => bits.push(Style::default().paint(" ")),
n => bits.push(Style::default().paint(spaces(n))),
1 => bits.push(style.paint(" ")),
2 => bits.push(style.paint(" ")),
n => bits.push(style.paint(spaces(n))),
}
}

View File

@ -3,6 +3,7 @@ use std::io::{self, Write};
use term_grid as tg;
use crate::fs::File;
use crate::fs::filter::FileFilter;
use crate::output::file_name::Options as FileStyle;
use crate::theme::Theme;
@ -26,10 +27,11 @@ pub struct Render<'a> {
pub file_style: &'a FileStyle,
pub opts: &'a Options,
pub console_width: usize,
pub filter: &'a FileFilter,
}
impl<'a> Render<'a> {
pub fn render<W: Write>(&self, w: &mut W) -> io::Result<()> {
pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> {
let mut grid = tg::Grid::new(tg::GridOptions {
direction: self.opts.direction(),
filling: tg::Filling::Spaces(2),
@ -37,6 +39,7 @@ impl<'a> Render<'a> {
grid.reserve(self.files.len());
self.filter.sort_files(&mut self.files);
for file in &self.files {
let filename = self.file_style.for_file(file, self.theme).paint();

View File

@ -2,6 +2,8 @@ use ansi_term::Style;
use crate::fs::File;
use crate::info::filetype::FileExtensions;
use lazy_static::lazy_static;
use std::collections::HashMap;
pub trait FileIcon {
@ -42,156 +44,293 @@ pub fn iconify_style<'a>(style: Style) -> Style {
}
lazy_static! {
static ref MAP_BY_NAME: HashMap<&'static str, char> = {
let mut m = HashMap::new();
m.insert(".Trash", '\u{f1f8}'); // 
m.insert(".atom", '\u{e764}'); // 
m.insert(".bashprofile", '\u{e615}'); // 
m.insert(".bashrc", '\u{f489}'); // 
m.insert(".git", '\u{f1d3}'); // 
m.insert(".gitattributes", '\u{f1d3}'); // 
m.insert(".gitconfig", '\u{f1d3}'); // 
m.insert(".github", '\u{f408}'); // 
m.insert(".gitignore", '\u{f1d3}'); // 
m.insert(".gitmodules", '\u{f1d3}'); // 
m.insert(".rvm", '\u{e21e}'); // 
m.insert(".vimrc", '\u{e62b}'); // 
m.insert(".vscode", '\u{e70c}'); // 
m.insert(".zshrc", '\u{f489}'); // 
m.insert("Cargo.lock", '\u{e7a8}'); // 
m.insert("bin", '\u{e5fc}'); // 
m.insert("config", '\u{e5fc}'); // 
m.insert("docker-compose.yml", '\u{f308}'); // 
m.insert("Dockerfile", '\u{f308}'); // 
m.insert("ds_store", '\u{f179}'); // 
m.insert("gitignore_global", '\u{f1d3}'); // 
m.insert("gradle", '\u{e70e}'); // 
m.insert("gruntfile.coffee", '\u{e611}'); // 
m.insert("gruntfile.js", '\u{e611}'); // 
m.insert("gruntfile.ls", '\u{e611}'); // 
m.insert("gulpfile.coffee", '\u{e610}'); // 
m.insert("gulpfile.js", '\u{e610}'); // 
m.insert("gulpfile.ls", '\u{e610}'); // 
m.insert("hidden", '\u{f023}'); // 
m.insert("include", '\u{e5fc}'); // 
m.insert("lib", '\u{f121}'); // 
m.insert("localized", '\u{f179}'); // 
m.insert("Makefile", '\u{e779}'); // 
m.insert("node_modules", '\u{e718}'); // 
m.insert("npmignore", '\u{e71e}'); // 
m.insert("rubydoc", '\u{e73b}'); // 
m.insert("yarn.lock", '\u{e718}'); // 
m
};
}
pub fn icon_for_file(file: &File<'_>) -> char {
let extensions = Box::new(FileExtensions);
if file.points_to_directory() {
'\u{f115}'
}
else if let Some(icon) = extensions.icon_file(file) {
icon
if let Some(icon) = MAP_BY_NAME.get(file.name.as_str()) { *icon }
else if file.points_to_directory() {
match file.name.as_str() {
"bin" => '\u{e5fc}', // 
".git" => '\u{f1d3}', // 
".idea" => '\u{e7b5}', // 
_ => '\u{f115}' // 
}
}
else if let Some(icon) = extensions.icon_file(file) { icon }
else if let Some(ext) = file.ext.as_ref() {
match ext.as_str() {
"ai" => '\u{e7b4}',
"android" => '\u{e70e}',
"apple" => '\u{f179}',
"avro" => '\u{e60b}',
"clj" => '\u{e768}',
"coffee" => '\u{f0f4}',
"cpp" => '\u{e61d}',
"hpp" => '\u{e61d}',
"c" => '\u{e61e}',
"h" => '\u{e61e}',
"cs" => '\u{f81a}',
"css" => '\u{e749}',
"d" => '\u{e7af}',
"dart" => '\u{e798}',
"db" => '\u{f1c0}',
"diff" => '\u{f440}',
"patch" => '\u{f440}',
"rtf" => '\u{f1c2}',
"doc" => '\u{f1c2}',
"docx" => '\u{f1c2}',
"odt" => '\u{f1c2}',
"ebook" => '\u{e28b}',
"env" => '\u{f462}',
"epub" => '\u{e28a}',
"erl" => '\u{e7b1}',
"font" => '\u{f031}',
"gform" => '\u{f298}',
"git" => '\u{f1d3}',
"go" => '\u{e626}',
"hs" => '\u{e777}',
"htm" => '\u{f13b}',
"html" => '\u{f13b}',
"xhtml" => '\u{f13b}',
"iml" => '\u{e7b5}',
"java" => '\u{e204}',
"js" => '\u{e74e}',
"mjs" => '\u{e74e}',
"json" => '\u{e60b}',
"jsx" => '\u{e7ba}',
"vue" => '\u{fd42}',
"node" => '\u{f898}',
"less" => '\u{e758}',
"log" => '\u{f18d}',
"lua" => '\u{e620}',
"md" => '\u{f48a}',
"markdown" => '\u{f48a}',
"mustache" => '\u{e60f}',
"npmignore" => '\u{e71e}',
"pdf" => '\u{f1c1}',
"djvu" => '\u{f02d}',
"mobi" => '\u{f02d}',
"php" => '\u{e73d}',
"pl" => '\u{e769}',
"ppt" => '\u{f1c4}',
"pptx" => '\u{f1c4}',
"odp" => '\u{f1c4}',
"psd" => '\u{e7b8}',
"py" => '\u{e606}',
"r" => '\u{f25d}',
"rb" => '\u{e21e}',
"ru" => '\u{e21e}',
"erb" => '\u{e21e}',
"gem" => '\u{e21e}',
"rdb" => '\u{e76d}',
"rs" => '\u{e7a8}',
"rss" => '\u{f09e}',
"rubydoc" => '\u{e73b}',
"sass" => '\u{e74b}',
"stylus" => '\u{e759}',
"scala" => '\u{e737}',
"shell" => '\u{f489}',
"sqlite3" => '\u{e7c4}',
"styl" => '\u{e600}',
"latex" => '\u{e600}',
"tex" => '\u{e600}',
"ts" => '\u{e628}',
"tsx" => '\u{e628}',
"twig" => '\u{e61c}',
"txt" => '\u{f15c}',
"video" => '\u{f03d}',
"vim" => '\u{e62b}',
"xml" => '\u{e619}',
"yml" => '\u{f481}',
"yaml" => '\u{f481}',
"rar" => '\u{f410}',
"zip" => '\u{f410}',
"bz" => '\u{f410}',
"bz2" => '\u{f410}',
"xz" => '\u{f410}',
"taz" => '\u{f410}',
"tbz" => '\u{f410}',
"tbz2" => '\u{f410}',
"tz" => '\u{f410}',
"tar" => '\u{f410}',
"tzo" => '\u{f410}',
"lz" => '\u{f410}',
"lzh" => '\u{f410}',
"lzma" => '\u{f410}',
"lzo" => '\u{f410}',
"gz" => '\u{f410}',
"deb" => '\u{e77d}',
"rpm" => '\u{e7bb}',
"exe" => '\u{e70f}',
"msi" => '\u{e70f}',
"dll" => '\u{e70f}',
"cab" => '\u{e70f}',
"bat" => '\u{e70f}',
"cmd" => '\u{e70f}',
"sh" => '\u{f489}',
"bash" => '\u{f489}',
"zsh" => '\u{f489}',
"fish" => '\u{f489}',
"csh" => '\u{f489}',
"ini" => '\u{e615}',
"toml" => '\u{e615}',
"cfg" => '\u{e615}',
"conf" => '\u{e615}',
"apk" => '\u{e70e}',
"ttf" => '\u{f031}',
"woff" => '\u{f031}',
"woff2" => '\u{f031}',
"otf" => '\u{f031}',
"csv" => '\u{f1c3}',
"tsv" => '\u{f1c3}',
"xls" => '\u{f1c3}',
"xlsx" => '\u{f1c3}',
"ods" => '\u{f1c3}',
"so" => '\u{f17c}',
"sql" => '\u{f1c0}',
"jar" => '\u{e256}',
"jad" => '\u{e256}',
"class" => '\u{e256}',
"war" => '\u{e256}',
"groovy" => '\u{e775}',
"iso" => '\u{e271}',
"lock" => '\u{f023}',
"swift" => '\u{e755}',
"nix" => '\u{f313}',
_ => '\u{f016}'
"ai" => '\u{e7b4}', // 
"android" => '\u{e70e}', // 
"apk" => '\u{e70e}', // 
"apple" => '\u{f179}', // 
"avi" => '\u{f03d}', // 
"avro" => '\u{e60b}', // 
"awk" => '\u{f489}', // 
"bash" => '\u{f489}', // 
"bash_history" => '\u{f489}', // 
"bash_profile" => '\u{f489}', // 
"bashrc" => '\u{f489}', // 
"bat" => '\u{f17a}', // 
"bmp" => '\u{f1c5}', // 
"bz" => '\u{f410}', // 
"bz2" => '\u{f410}', // 
"c" => '\u{e61e}', // 
"c++" => '\u{e61d}', // 
"cab" => '\u{e70f}', // 
"cc" => '\u{e61d}', // 
"cfg" => '\u{e615}', // 
"class" => '\u{e256}', // 
"clj" => '\u{e768}', // 
"cljs" => '\u{e76a}', // 
"cls" => '\u{e600}', // 
"cmd" => '\u{e70f}', // 
"coffee" => '\u{f0f4}', // 
"conf" => '\u{e615}', // 
"cp" => '\u{e61d}', // 
"cpp" => '\u{e61d}', // 
"cs" => '\u{f81a}', // 
"csh" => '\u{f489}', // 
"cshtml" => '\u{f1fa}', // 
"csproj" => '\u{f81a}', // 
"css" => '\u{e749}', // 
"csv" => '\u{f1c3}', // 
"csx" => '\u{f81a}', // 
"cxx" => '\u{e61d}', // 
"d" => '\u{e7af}', // 
"dart" => '\u{e798}', // 
"db" => '\u{f1c0}', // 
"deb" => '\u{e77d}', // 
"diff" => '\u{f440}', // 
"djvu" => '\u{f02d}', // 
"dll" => '\u{e70f}', // 
"doc" => '\u{f1c2}', // 
"docx" => '\u{f1c2}', // 
"ds_store" => '\u{f179}', // 
"DS_store" => '\u{f179}', // 
"dump" => '\u{f1c0}', // 
"ebook" => '\u{e28b}', // 
"editorconfig" => '\u{e615}', // 
"ejs" => '\u{e618}', // 
"elm" => '\u{e62c}', // 
"env" => '\u{f462}', // 
"eot" => '\u{f031}', // 
"epub" => '\u{e28a}', // 
"erb" => '\u{e73b}', // 
"erl" => '\u{e7b1}', // 
"ex" => '\u{e62d}', // 
"exe" => '\u{f17a}', // 
"exs" => '\u{e62d}', // 
"fish" => '\u{f489}', // 
"flac" => '\u{f001}', // 
"flv" => '\u{f03d}', // 
"font" => '\u{f031}', // 
"gdoc" => '\u{f1c2}', // 
"gem" => '\u{e21e}', // 
"gemfile" => '\u{e21e}', // 
"gemspec" => '\u{e21e}', // 
"gform" => '\u{f298}', // 
"gif" => '\u{f1c5}', // 
"git" => '\u{f1d3}', // 
"gitattributes" => '\u{f1d3}', // 
"gitignore" => '\u{f1d3}', // 
"gitmodules" => '\u{f1d3}', // 
"go" => '\u{e626}', // 
"gradle" => '\u{e70e}', // 
"groovy" => '\u{e775}', // 
"gsheet" => '\u{f1c3}', // 
"gslides" => '\u{f1c4}', // 
"guardfile" => '\u{e21e}', // 
"gz" => '\u{f410}', // 
"h" => '\u{f0fd}', // 
"hbs" => '\u{e60f}', // 
"hpp" => '\u{f0fd}', // 
"hs" => '\u{e777}', // 
"htm" => '\u{f13b}', // 
"html" => '\u{f13b}', // 
"hxx" => '\u{f0fd}', // 
"ico" => '\u{f1c5}', // 
"image" => '\u{f1c5}', // 
"iml" => '\u{e7b5}', // 
"ini" => '\u{f17a}', // 
"ipynb" => '\u{e606}', // 
"iso" => '\u{e271}', // 
"jad" => '\u{e256}', // 
"jar" => '\u{e204}', // 
"java" => '\u{e204}', // 
"jpeg" => '\u{f1c5}', // 
"jpg" => '\u{f1c5}', // 
"js" => '\u{e74e}', // 
"json" => '\u{e60b}', // 
"jsx" => '\u{e7ba}', // 
"ksh" => '\u{f489}', // 
"latex" => '\u{e600}', // 
"less" => '\u{e758}', // 
"lhs" => '\u{e777}', // 
"license" => '\u{f718}', // 
"localized" => '\u{f179}', // 
"lock" => '\u{f023}', // 
"log" => '\u{f18d}', // 
"lua" => '\u{e620}', // 
"lz" => '\u{f410}', // 
"lzh" => '\u{f410}', // 
"lzma" => '\u{f410}', // 
"lzo" => '\u{f410}', // 
"m" => '\u{e61e}', // 
"mm" => '\u{e61d}', // 
"m4a" => '\u{f001}', // 
"markdown" => '\u{f48a}', // 
"md" => '\u{f48a}', // 
"mjs" => '\u{e74e}', // 
"mkd" => '\u{f48a}', // 
"mkv" => '\u{f03d}', // 
"mobi" => '\u{e28b}', // 
"mov" => '\u{f03d}', // 
"mp3" => '\u{f001}', // 
"mp4" => '\u{f03d}', // 
"msi" => '\u{e70f}', // 
"mustache" => '\u{e60f}', // 
"nix" => '\u{f313}', // 
"node" => '\u{f898}', // 
"npmignore" => '\u{e71e}', // 
"odp" => '\u{f1c4}', // 
"ods" => '\u{f1c3}', // 
"odt" => '\u{f1c2}', // 
"ogg" => '\u{f001}', // 
"ogv" => '\u{f03d}', // 
"otf" => '\u{f031}', // 
"patch" => '\u{f440}', // 
"pdf" => '\u{f1c1}', // 
"php" => '\u{e73d}', // 
"pl" => '\u{e769}', // 
"png" => '\u{f1c5}', // 
"ppt" => '\u{f1c4}', // 
"pptx" => '\u{f1c4}', // 
"procfile" => '\u{e21e}', // 
"properties" => '\u{e60b}', // 
"ps1" => '\u{f489}', // 
"psd" => '\u{e7b8}', // 
"pxm" => '\u{f1c5}', // 
"py" => '\u{e606}', // 
"pyc" => '\u{e606}', // 
"r" => '\u{f25d}', // 
"rakefile" => '\u{e21e}', // 
"rar" => '\u{f410}', // 
"razor" => '\u{f1fa}', // 
"rb" => '\u{e21e}', // 
"rdata" => '\u{f25d}', // 
"rdb" => '\u{e76d}', // 
"rdoc" => '\u{f48a}', // 
"rds" => '\u{f25d}', // 
"readme" => '\u{f48a}', // 
"rlib" => '\u{e7a8}', // 
"rmd" => '\u{f48a}', // 
"rpm" => '\u{e7bb}', // 
"rs" => '\u{e7a8}', // 
"rspec" => '\u{e21e}', // 
"rspec_parallel"=> '\u{e21e}', // 
"rspec_status" => '\u{e21e}', // 
"rss" => '\u{f09e}', // 
"rtf" => '\u{f718}', // 
"ru" => '\u{e21e}', // 
"rubydoc" => '\u{e73b}', // 
"sass" => '\u{e603}', // 
"scala" => '\u{e737}', // 
"scss" => '\u{e749}', // 
"sh" => '\u{f489}', // 
"shell" => '\u{f489}', // 
"slim" => '\u{e73b}', // 
"sln" => '\u{e70c}', // 
"so" => '\u{f17c}', // 
"sql" => '\u{f1c0}', // 
"sqlite3" => '\u{e7c4}', // 
"styl" => '\u{e600}', // 
"stylus" => '\u{e600}', // 
"svg" => '\u{f1c5}', // 
"swift" => '\u{e755}', // 
"tar" => '\u{f410}', // 
"taz" => '\u{f410}', // 
"tbz" => '\u{f410}', // 
"tbz2" => '\u{f410}', // 
"tex" => '\u{e600}', // 
"tiff" => '\u{f1c5}', // 
"toml" => '\u{e615}', // 
"ts" => '\u{e628}', // 
"tsv" => '\u{f1c3}', // 
"tsx" => '\u{e7ba}', // 
"ttf" => '\u{f031}', // 
"twig" => '\u{e61c}', // 
"txt" => '\u{f15c}', // 
"tz" => '\u{f410}', // 
"tzo" => '\u{f410}', // 
"video" => '\u{f03d}', // 
"vim" => '\u{e62b}', // 
"vue" => '\u{fd42}', // ﵂
"war" => '\u{e256}', // 
"wav" => '\u{f001}', // 
"webm" => '\u{f03d}', // 
"webp" => '\u{f1c5}', // 
"windows" => '\u{f17a}', // 
"woff" => '\u{f031}', // 
"woff2" => '\u{f031}', // 
"xhtml" => '\u{f13b}', // 
"xls" => '\u{f1c3}', // 
"xlsx" => '\u{f1c3}', // 
"xml" => '\u{fabf}', // 謹
"xul" => '\u{fabf}', // 謹
"xz" => '\u{f410}', // 
"yaml" => '\u{f481}', // 
"yml" => '\u{f481}', // 
"zip" => '\u{f410}', // 
"zsh" => '\u{f489}', // 
"zsh-theme" => '\u{f489}', // 
"zshrc" => '\u{f489}', // 
_ => '\u{f15b}' // 
}
}
else {

View File

@ -3,6 +3,7 @@ use std::io::{self, Write};
use ansi_term::ANSIStrings;
use crate::fs::File;
use crate::fs::filter::FileFilter;
use crate::output::cell::TextCellContents;
use crate::output::file_name::{Options as FileStyle};
use crate::theme::Theme;
@ -13,10 +14,12 @@ pub struct Render<'a> {
pub files: Vec<File<'a>>,
pub theme: &'a Theme,
pub file_style: &'a FileStyle,
pub filter: &'a FileFilter,
}
impl<'a> Render<'a> {
pub fn render<W: Write>(&self, w: &mut W) -> io::Result<()> {
pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> {
self.filter.sort_files(&mut self.files);
for file in &self.files {
let name_cell = self.render_file(file);
writeln!(w, "{}", ANSIStrings(&name_cell))?;

View File

@ -107,7 +107,7 @@ impl Columns {
columns.push(Column::Timestamp(TimeType::Accessed));
}
if cfg!(feature = "git") && self.git && actually_enable_git {
if self.git && actually_enable_git {
columns.push(Column::GitStatus);
}

View File

@ -102,8 +102,7 @@ tags = [ 'env', 'grid' ]
# columns and width tests with files
# (these rely on bashs glob sort order)
# (some of the output files also have trailing whitespace)
# (warning: some of the output files have trailing whitespace)
[[cmd]]
name = "COLUMNS=100 exa with file arguments produces a grid of 3 columns, with full paths"

View File

@ -0,0 +1,6 @@
video.wmv lossless.flac crypto.signature compressed.tar.gz backup~
VIDEO.AVI image.svg crypto.asc compressed.deb #SAVEFILE#
MUSIC.OGG IMAGE.PNG COMPRESSED.ZIP compiled.o
music.mp3 file.tmp compressed.txz compiled.js
Makefile DOCUMENT.XLSX compressed.tgz compiled.coffee
lossless.wav document.pdf compressed.tar.xz compiled.class

View File

@ -0,0 +1,26 @@
video.wmv
VIDEO.AVI
MUSIC.OGG
music.mp3
Makefile
lossless.wav
lossless.flac
image.svg
IMAGE.PNG
file.tmp
DOCUMENT.XLSX
document.pdf
crypto.signature
crypto.asc
COMPRESSED.ZIP
compressed.txz
compressed.tgz
compressed.tar.xz
compressed.tar.gz
compressed.deb
compiled.o
compiled.js
compiled.coffee
compiled.class
backup~
#SAVEFILE#

View File

@ -1,13 +1,13 @@
/testcases/files/10_bytes /testcases/files/1_KiB /testcases/files/5_MiB
/testcases/files/10_KiB /testcases/files/1_MiB /testcases/files/6_bytes
/testcases/files/10_MiB /testcases/files/2_bytes /testcases/files/6_KiB
/testcases/files/11_bytes /testcases/files/2_KiB /testcases/files/6_MiB
/testcases/files/11_KiB /testcases/files/2_MiB /testcases/files/7_bytes
/testcases/files/11_MiB /testcases/files/3_bytes /testcases/files/7_KiB
/testcases/files/12_bytes /testcases/files/3_KiB /testcases/files/7_MiB
/testcases/files/12_KiB /testcases/files/3_MiB /testcases/files/8_bytes
/testcases/files/12_MiB /testcases/files/4_bytes /testcases/files/8_KiB
/testcases/files/13_bytes /testcases/files/4_KiB /testcases/files/8_MiB
/testcases/files/13_KiB /testcases/files/4_MiB /testcases/files/9_bytes
/testcases/files/13_MiB /testcases/files/5_bytes /testcases/files/9_KiB
/testcases/files/1_bytes /testcases/files/5_KiB /testcases/files/9_MiB
/testcases/files/1_bytes /testcases/files/5_KiB /testcases/files/9_MiB
/testcases/files/1_KiB /testcases/files/5_MiB /testcases/files/10_bytes
/testcases/files/1_MiB /testcases/files/6_bytes /testcases/files/10_KiB
/testcases/files/2_bytes /testcases/files/6_KiB /testcases/files/10_MiB
/testcases/files/2_KiB /testcases/files/6_MiB /testcases/files/11_bytes
/testcases/files/2_MiB /testcases/files/7_bytes /testcases/files/11_KiB
/testcases/files/3_bytes /testcases/files/7_KiB /testcases/files/11_MiB
/testcases/files/3_KiB /testcases/files/7_MiB /testcases/files/12_bytes
/testcases/files/3_MiB /testcases/files/8_bytes /testcases/files/12_KiB
/testcases/files/4_bytes /testcases/files/8_KiB /testcases/files/12_MiB
/testcases/files/4_KiB /testcases/files/8_MiB /testcases/files/13_bytes
/testcases/files/4_MiB /testcases/files/9_bytes /testcases/files/13_KiB
/testcases/files/5_bytes /testcases/files/9_KiB /testcases/files/13_MiB

View File

@ -1,8 +1,8 @@
/testcases/files/10_bytes /testcases/files/12_MiB /testcases/files/2_KiB /testcases/files/5_bytes /testcases/files/7_MiB
/testcases/files/10_KiB /testcases/files/13_bytes /testcases/files/2_MiB /testcases/files/5_KiB /testcases/files/8_bytes
/testcases/files/10_MiB /testcases/files/13_KiB /testcases/files/3_bytes /testcases/files/5_MiB /testcases/files/8_KiB
/testcases/files/11_bytes /testcases/files/13_MiB /testcases/files/3_KiB /testcases/files/6_bytes /testcases/files/8_MiB
/testcases/files/11_KiB /testcases/files/1_bytes /testcases/files/3_MiB /testcases/files/6_KiB /testcases/files/9_bytes
/testcases/files/11_MiB /testcases/files/1_KiB /testcases/files/4_bytes /testcases/files/6_MiB /testcases/files/9_KiB
/testcases/files/12_bytes /testcases/files/1_MiB /testcases/files/4_KiB /testcases/files/7_bytes /testcases/files/9_MiB
/testcases/files/12_KiB /testcases/files/2_bytes /testcases/files/4_MiB /testcases/files/7_KiB
/testcases/files/1_bytes /testcases/files/3_MiB /testcases/files/6_KiB /testcases/files/9_bytes /testcases/files/11_MiB
/testcases/files/1_KiB /testcases/files/4_bytes /testcases/files/6_MiB /testcases/files/9_KiB /testcases/files/12_bytes
/testcases/files/1_MiB /testcases/files/4_KiB /testcases/files/7_bytes /testcases/files/9_MiB /testcases/files/12_KiB
/testcases/files/2_bytes /testcases/files/4_MiB /testcases/files/7_KiB /testcases/files/10_bytes /testcases/files/12_MiB
/testcases/files/2_KiB /testcases/files/5_bytes /testcases/files/7_MiB /testcases/files/10_KiB /testcases/files/13_bytes
/testcases/files/2_MiB /testcases/files/5_KiB /testcases/files/8_bytes /testcases/files/10_MiB /testcases/files/13_KiB
/testcases/files/3_bytes /testcases/files/5_MiB /testcases/files/8_KiB /testcases/files/11_bytes /testcases/files/13_MiB
/testcases/files/3_KiB /testcases/files/6_bytes /testcases/files/8_MiB /testcases/files/11_KiB

View File

@ -1,6 +1,6 @@
/testcases/files/10_bytes /testcases/files/12_bytes /testcases/files/1_bytes /testcases/files/3_bytes /testcases/files/5_bytes /testcases/files/7_bytes /testcases/files/9_bytes
/testcases/files/10_KiB /testcases/files/12_KiB /testcases/files/1_KiB /testcases/files/3_KiB /testcases/files/5_KiB /testcases/files/7_KiB /testcases/files/9_KiB
/testcases/files/10_MiB /testcases/files/12_MiB /testcases/files/1_MiB /testcases/files/3_MiB /testcases/files/5_MiB /testcases/files/7_MiB /testcases/files/9_MiB
/testcases/files/11_bytes /testcases/files/13_bytes /testcases/files/2_bytes /testcases/files/4_bytes /testcases/files/6_bytes /testcases/files/8_bytes
/testcases/files/11_KiB /testcases/files/13_KiB /testcases/files/2_KiB /testcases/files/4_KiB /testcases/files/6_KiB /testcases/files/8_KiB
/testcases/files/11_MiB /testcases/files/13_MiB /testcases/files/2_MiB /testcases/files/4_MiB /testcases/files/6_MiB /testcases/files/8_MiB
/testcases/files/1_bytes /testcases/files/3_bytes /testcases/files/5_bytes /testcases/files/7_bytes /testcases/files/9_bytes /testcases/files/11_bytes /testcases/files/13_bytes
/testcases/files/1_KiB /testcases/files/3_KiB /testcases/files/5_KiB /testcases/files/7_KiB /testcases/files/9_KiB /testcases/files/11_KiB /testcases/files/13_KiB
/testcases/files/1_MiB /testcases/files/3_MiB /testcases/files/5_MiB /testcases/files/7_MiB /testcases/files/9_MiB /testcases/files/11_MiB /testcases/files/13_MiB
/testcases/files/2_bytes /testcases/files/4_bytes /testcases/files/6_bytes /testcases/files/8_bytes /testcases/files/10_bytes /testcases/files/12_bytes
/testcases/files/2_KiB /testcases/files/4_KiB /testcases/files/6_KiB /testcases/files/8_KiB /testcases/files/10_KiB /testcases/files/12_KiB
/testcases/files/2_MiB /testcases/files/4_MiB /testcases/files/6_MiB /testcases/files/8_MiB /testcases/files/10_MiB /testcases/files/12_MiB

View File

@ -136,3 +136,22 @@ stdout = { string = "plum\npear\npeach" }
stderr = { empty = true }
status = 0
tags = [ 'oneline', 'sort', 'dates' ]
# sorting with arguments specified
[[cmd]]
name = "exa -G --sort=name -r with file arguments sorts by file name in reverse order"
shell = "cd /testcases/file-names-exts; exa -G --sort=name -r *"
environment = { COLUMNS = "80" }
stdout = { file = "outputs/exts_grid_sort_name_reverse.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'grid', 'sort', 'reverse' ]
[[cmd]]
name = "exa -1 --sort=name -r with file arguments sorts by file name in reverse order"
shell = "cd /testcases/file-names-exts; exa -1 --sort=name -r *"
stdout = { file = "outputs/exts_oneline_sort_name_reverse.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'oneline', 'sort', 'reverse' ]