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

This commit is contained in:
Chester Liu 2021-04-13 11:27:49 +08:00
commit 8f0e4ccfdd
59 changed files with 517 additions and 182 deletions

86
Cargo.lock generated
View File

@ -23,24 +23,24 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "byteorder"
version = "1.3.4"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.61"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "datetime"
@ -79,10 +79,20 @@ dependencies = [
]
[[package]]
name = "git2"
version = "0.13.11"
name = "form_urlencoded"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e094214efbc7fdbbdee952147e493b00e99a4e52817492277e98967ae918165"
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
dependencies = [
"matches",
"percent-encoding",
]
[[package]]
name = "git2"
version = "0.13.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d250f5f82326884bd39c2853577e70a121775db76818ffa452ed1e80de12986"
dependencies = [
"bitflags",
"libc",
@ -100,18 +110,18 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "hermit-abi"
version = "0.1.17"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
dependencies = [
"libc",
]
[[package]]
name = "idna"
version = "0.2.0"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21"
dependencies = [
"matches",
"unicode-bidi",
@ -135,15 +145,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.79"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
[[package]]
name = "libgit2-sys"
version = "0.12.14+1.1.0"
version = "0.12.18+1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f25af58e6495f7caf2919d08f212de550cfa3ed2f5e744988938ea292b9f549"
checksum = "3da6a42da88fc37ee1ecda212ffa254c25713532980005d5f7c0b0fbe7e6e885"
dependencies = [
"cc",
"libc",
@ -174,9 +184,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.11"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
@ -211,18 +221,18 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
name = "openssl-src"
version = "111.12.0+1.1.1h"
version = "111.15.0+1.1.1k"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "858a4132194f8570a7ee9eb8629e85b23cbc4565f2d4a162e87556e5956abf61"
checksum = "b1a5f6ae2ac04393b217ea9f700cd04fa9bf3d93fae2872069f3d15d908af70a"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.58"
version = "0.9.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de"
checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f"
dependencies = [
"autocfg",
"cc",
@ -286,24 +296,33 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "0.3.4"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "unicode-bidi"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0"
dependencies = [
"matches",
]
[[package]]
name = "unicode-normalization"
version = "0.1.13"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef"
dependencies = [
"tinyvec",
]
@ -316,10 +335,11 @@ checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "url"
version = "2.1.1"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b"
dependencies = [
"form_urlencoded",
"idna",
"matches",
"percent-encoding",
@ -337,9 +357,9 @@ dependencies = [
[[package]]
name = "vcpkg"
version = "0.2.10"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
[[package]]
name = "winapi"

View File

@ -9,7 +9,7 @@ exclude = ["/devtools/*", "/Justfile", "/Vagrantfile", "/screenshots.png"]
homepage = "https://the.exa.website/"
license = "MIT"
repository = "https://github.com/ogham/exa"
version = "0.11.0-pre"
version = "0.10.1"
[[bin]]

View File

@ -300,6 +300,8 @@ touch "ignoreds/music.m4a"
mkdir "ignoreds/nested"
touch "ignoreds/nested/70s grove.mp3"
touch "ignoreds/nested/funky chicken.m4a"
mkdir "ignoreds/nested2"
touch "ignoreds/nested2/ievan polkka.mp3"
mkdir "target"
touch "target/another ignored file"

View File

@ -84,7 +84,7 @@ FILTERING AND SORTING OPTIONS
Use this twice to also show the `.` and `..` directories.
`-d`, `--list-dirs`
: List directories like regular files.
: List directories as regular files, rather than recursing and listing their contents.
`-L`, `--level=DEPTH`
: Limit the depth of recursion.
@ -183,6 +183,10 @@ These options are available when running with `--long` (`-l`):
`--git` [if exa was built with git support]
: List each files Git status, if tracked.
This adds a two-character column indicating the staged and unstaged statuses respectively. The status character can be `-` for not modified, `M` for a modified file, `N` for a new file, `D` for deleted, `R` for renamed, `T` for type-change, `I` for ignored, and `U` for conflicted.
Directories will be shown to have the status of their contents, which is how deleted is possible: if a directory contains a file that has a certain status, it will be shown to have that status.
ENVIRONMENT VARIABLES
=====================

View File

@ -242,25 +242,40 @@ impl Git {
else { self.file_status(index) }
}
/// Get the status for the file at the given path.
/// Get the user-facing status of a file.
/// We check the statuses directly applying to a file, and for the ignored
/// status we check if any of its parents directories is ignored by git.
fn file_status(&self, file: &Path) -> f::Git {
let path = reorient(file);
self.statuses.iter()
.find(|p| p.0.as_path() == path)
.map(|&(_, s)| f::Git { staged: index_status(s), unstaged: working_tree_status(s) })
.unwrap_or_default()
let s = self.statuses.iter()
.filter(|p| if p.1 == git2::Status::IGNORED {
path.starts_with(&p.0)
} else {
p.0 == path
})
.fold(git2::Status::empty(), |a, b| a | b.1);
let staged = index_status(s);
let unstaged = working_tree_status(s);
f::Git { staged, unstaged }
}
/// Get the combined status for all the files whose paths begin with the
/// path that gets passed in. This is used for getting the status of
/// directories, which dont really have an official status.
/// Get the combined, user-facing status of a directory.
/// Statuses are aggregating (for example, a directory is considered
/// modified if any file under it has the status modified), except for
/// ignored status which applies to files under (for example, a directory
/// is considered ignored if one of its parent directories is ignored).
fn dir_status(&self, dir: &Path) -> f::Git {
let path = reorient(dir);
let s = self.statuses.iter()
.filter(|p| p.0.starts_with(&path))
.fold(git2::Status::empty(), |a, b| a | b.1);
.filter(|p| if p.1 == git2::Status::IGNORED {
path.starts_with(&p.0)
} else {
p.0.starts_with(&path)
})
.fold(git2::Status::empty(), |a, b| a | b.1);
let staged = index_status(s);
let unstaged = working_tree_status(s);

View File

@ -333,10 +333,15 @@ impl<'dir> File<'dir> {
f::Size::None
}
else if self.is_char_device() || self.is_block_device() {
let dev = self.metadata.rdev();
let device_ids = self.metadata.rdev().to_be_bytes();
// In C-land, getting the major and minor device IDs is done with
// preprocessor macros called `major` and `minor` that depend on
// the size of `dev_t`, but we just take the second-to-last and
// last bytes.
f::Size::DeviceIDs(f::DeviceIDs {
major: (dev / 256) as u8,
minor: (dev % 256) as u8,
major: device_ids[6],
minor: device_ids[7],
})
}
else {

View File

@ -1,7 +1,7 @@
//! Parsing the options for `DirAction`.
use crate::options::parser::MatchedFlags;
use crate::options::{flags, OptionsError};
use crate::options::{flags, OptionsError, NumberSource};
use crate::fs::dir_action::{DirAction, RecurseOptions};
@ -55,17 +55,21 @@ impl RecurseOptions {
/// determined earlier. The maximum level should be a number, and this
/// will fail with an `Err` if it isnt.
pub fn deduce(matches: &MatchedFlags<'_>, tree: bool) -> Result<Self, OptionsError> {
let max_depth = if let Some(level) = matches.get(&flags::LEVEL)? {
match level.to_string_lossy().parse() {
Ok(l) => Some(l),
Err(e) => return Err(OptionsError::FailedParse(e)),
if let Some(level) = matches.get(&flags::LEVEL)? {
let arg_str = level.to_string_lossy();
match arg_str.parse() {
Ok(l) => {
Ok(Self { tree, max_depth: Some(l) })
}
Err(e) => {
let source = NumberSource::Arg(&flags::LEVEL);
Err(OptionsError::FailedParse(arg_str.to_string(), source, e))
}
}
}
else {
None
};
Ok(Self { tree, max_depth })
Ok(Self { tree, max_depth: None })
}
}
}

View File

@ -37,18 +37,38 @@ pub enum OptionsError {
TreeAllAll,
/// A numeric option was given that failed to be parsed as a number.
FailedParse(ParseIntError),
FailedParse(String, NumberSource, ParseIntError),
/// A glob ignore was given that failed to be parsed as a pattern.
FailedGlobPattern(String),
}
/// The source of a string that failed to be parsed as a number.
#[derive(PartialEq, Debug)]
pub enum NumberSource {
/// It came... from a command-line argument!
Arg(&'static Arg),
/// It came... from the enviroment!
Env(&'static str),
}
impl From<glob::PatternError> for OptionsError {
fn from(error: glob::PatternError) -> Self {
Self::FailedGlobPattern(error.to_string())
}
}
impl fmt::Display for NumberSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Arg(arg) => write!(f, "option {}", arg),
Self::Env(env) => write!(f, "environment variable {}", env),
}
}
}
impl fmt::Display for OptionsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::options::parser::TakesValue;
@ -71,7 +91,7 @@ impl fmt::Display for OptionsError {
Self::Useless(a, true, b) => write!(f, "Option {} is useless given option {}", a, b),
Self::Useless2(a, b1, b2) => write!(f, "Option {} is useless without options {} or {}", a, b1, b2),
Self::TreeAllAll => write!(f, "Option --tree is useless given --all --all"),
Self::FailedParse(ref e) => write!(f, "Failed to parse number: {}", e),
Self::FailedParse(s, n, e) => write!(f, "Value {:?} not valid for {}: {}", s, n, e),
Self::FailedGlobPattern(ref e) => write!(f, "Failed to parse glob pattern: {}", e),
}
}

View File

@ -1,4 +1,4 @@
use crate::options::{flags, OptionsError};
use crate::options::{flags, OptionsError, NumberSource};
use crate::options::parser::MatchedFlags;
use crate::options::vars::{self, Vars};
@ -30,8 +30,13 @@ impl ShowIcons {
}
else if let Some(columns) = vars.get(vars::EXA_ICON_SPACING).and_then(|s| s.into_string().ok()) {
match columns.parse() {
Ok(width) => Ok(Self::On(width)),
Err(e) => Err(OptionsError::FailedParse(e)),
Ok(width) => {
Ok(Self::On(width))
}
Err(e) => {
let source = NumberSource::Env(vars::EXA_ICON_SPACING);
Err(OptionsError::FailedParse(columns, source, e))
}
}
}
else {

View File

@ -27,7 +27,7 @@ DISPLAY OPTIONS
FILTERING AND SORTING OPTIONS
-a, --all show hidden and 'dot' files
-d, --list-dirs list directories like regular files
-d, --list-dirs list directories as files; don't list their contents
-L, --level DEPTH limit the depth of recursion
-r, --reverse reverse the sort order
-s, --sort SORT_FIELD which field to sort by

View File

@ -84,7 +84,7 @@ mod theme;
mod view;
mod error;
pub use self::error::OptionsError;
pub use self::error::{OptionsError, NumberSource};
mod help;
use self::help::HelpString;

View File

@ -1,5 +1,5 @@
use crate::fs::feature::xattr;
use crate::options::{flags, OptionsError, Vars};
use crate::options::{flags, OptionsError, NumberSource, Vars};
use crate::options::parser::MatchedFlags;
use crate::output::{View, Mode, TerminalWidth, grid, details};
use crate::output::grid_details::{self, RowThreshold};
@ -151,8 +151,13 @@ impl TerminalWidth {
if let Some(columns) = vars.get(vars::COLUMNS).and_then(|s| s.into_string().ok()) {
match columns.parse() {
Ok(width) => Ok(Self::Set(width)),
Err(e) => Err(OptionsError::FailedParse(e)),
Ok(width) => {
Ok(Self::Set(width))
}
Err(e) => {
let source = NumberSource::Env(vars::COLUMNS);
Err(OptionsError::FailedParse(columns, source, e))
}
}
}
else {
@ -168,8 +173,13 @@ impl RowThreshold {
if let Some(columns) = vars.get(vars::EXA_GRID_ROWS).and_then(|s| s.into_string().ok()) {
match columns.parse() {
Ok(rows) => Ok(Self::MinimumRows(rows)),
Err(e) => Err(OptionsError::FailedParse(e)),
Ok(rows) => {
Ok(Self::MinimumRows(rows))
}
Err(e) => {
let source = NumberSource::Env(vars::EXA_GRID_ROWS);
Err(OptionsError::FailedParse(columns, source, e))
}
}
}
else {

View File

@ -173,7 +173,7 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
show_icons: ShowIcons::Off,
};
let target = FileName {
let target_name = FileName {
file: target,
colours: self.colours,
target: None,
@ -181,9 +181,15 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
options: target_options,
};
for bit in target.coloured_file_name() {
for bit in target_name.coloured_file_name() {
bits.push(bit);
}
if let Classify::AddFileIndicators = self.options.classify {
if let Some(class) = self.classify_char(target) {
bits.push(Style::default().paint(class));
}
}
}
}
@ -206,7 +212,7 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
}
}
else if let Classify::AddFileIndicators = self.options.classify {
if let Some(class) = self.classify_char() {
if let Some(class) = self.classify_char(self.file) {
bits.push(Style::default().paint(class));
}
}
@ -236,20 +242,20 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
/// The character to be displayed after a file when classifying is on, if
/// the files type has one associated with it.
#[cfg(unix)]
fn classify_char(&self) -> Option<&'static str> {
if self.file.is_executable_file() {
fn classify_char(&self, file: &File<'_>) -> Option<&'static str> {
if file.is_executable_file() {
Some("*")
}
else if self.file.is_directory() {
else if file.is_directory() {
Some("/")
}
else if self.file.is_pipe() {
else if file.is_pipe() {
Some("|")
}
else if self.file.is_link() {
else if file.is_link() {
Some("@")
}
else if self.file.is_socket() {
else if file.is_socket() {
Some("=")
}
else {
@ -258,11 +264,11 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
}
#[cfg(windows)]
fn classify_char(&self) -> Option<&'static str> {
if self.file.is_directory() {
fn classify_char(&self, file: &File<'_>) -> Option<&'static str> {
if file.is_directory() {
Some("/")
}
else if self.file.is_link() {
else if file.is_link() {
Some("@")
}
else {

View File

@ -174,22 +174,21 @@ impl<'a> Render<'a> {
};
if the_grid_fits {
if column_count == file_names.len() {
return Some((grid, column_count));
} else {
last_working_grid = grid;
}
} else {
// If weve figured out how many columns can fit in the users
// terminal, and it turns out there arent enough rows to
// make it worthwhile, then just resort to the lines view.
last_working_grid = grid;
}
if !the_grid_fits || column_count == file_names.len() {
let last_column_count = if the_grid_fits { column_count } else { column_count - 1 };
// If weve figured out how many columns can fit in the users terminal,
// and it turns out there arent enough rows to make it worthwhile
// (according to EXA_GRID_ROWS), then just resort to the lines view.
if let RowThreshold::MinimumRows(thresh) = self.row_threshold {
if last_working_grid.fit_into_columns(column_count - 1).row_count() < thresh {
if last_working_grid.fit_into_columns(last_column_count).row_count() < thresh {
return None;
}
}
return Some((last_working_grid, column_count - 1));
return Some((last_working_grid, last_column_count));
}
}

View File

@ -128,7 +128,7 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"class" => '\u{e256}', // 
"clj" => '\u{e768}', // 
"cljs" => '\u{e76a}', // 
"cls" => '\u{e600}', // 
"cls" => '\u{f034}', // 
"cmd" => '\u{e70f}', // 
"coffee" => '\u{f0f4}', // 
"conf" => '\u{e615}', // 
@ -209,7 +209,7 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"json" => '\u{e60b}', // 
"jsx" => '\u{e7ba}', // 
"ksh" => '\u{f489}', // 
"latex" => '\u{e600}', // 
"latex" => '\u{f034}', // 
"less" => '\u{e758}', // 
"lhs" => '\u{e777}', // 
"license" => '\u{f718}', // 
@ -297,7 +297,7 @@ pub fn icon_for_file(file: &File<'_>) -> char {
"taz" => '\u{f410}', // 
"tbz" => '\u{f410}', // 
"tbz2" => '\u{f410}', // 
"tex" => '\u{e600}', // 
"tex" => '\u{f034}', // 
"tiff" => '\u{f1c5}', // 
"toml" => '\u{e615}', // 
"ts" => '\u{e628}', // 

View File

@ -36,20 +36,20 @@ impl f::Size {
};
let (prefix, n) = match result {
NumberPrefix::Standalone(b) => return TextCell::paint(colours.size(None), b.to_string()),
NumberPrefix::Standalone(b) => return TextCell::paint(colours.size(None), numerics.format_int(b)),
NumberPrefix::Prefixed(p, n) => (p, n),
};
let symbol = prefix.symbol();
let decimal_to_diplay = if n < 10_f64 { 1 } else { 0 };
let number = numerics.format_float(n, decimal_to_diplay);
let number = if n < 10_f64 {
numerics.format_float(n, 1)
} else {
numerics.format_int(n.round() as isize)
};
// The numbers and symbols are guaranteed to be written in ASCII, so
// we can skip the display width calculation.
let width = DisplayWidth::from(number.len() + symbol.len());
TextCell {
width,
// symbol is guaranteed to be ASCII since unit prefixes are hardcoded.
width: DisplayWidth::from(&*number) + symbol.len(),
contents: vec![
colours.size(Some(prefix)).paint(number),
colours.unit(Some(prefix)).paint(symbol),

View File

@ -2,7 +2,7 @@
use std::time::{SystemTime, UNIX_EPOCH};
use datetime::{LocalDateTime, TimeZone, DatePiece, TimePiece, Month};
use datetime::{LocalDateTime, TimeZone, DatePiece, TimePiece};
use datetime::fmt::DateFormat;
use lazy_static::lazy_static;
@ -75,40 +75,25 @@ impl TimeFormat {
#[allow(trivial_numeric_casts)]
fn default_local(time: SystemTime) -> String {
let date = LocalDateTime::at(systemtime_epoch(time));
if date.year() == *CURRENT_YEAR {
format!("{:2} {} {:02}:{:02}",
date.day(), month_to_abbrev(date.month()),
date.hour(), date.minute())
}
else {
let date_format = match *MAXIMUM_MONTH_WIDTH {
4 => &*FOUR_WIDE_DATE_TIME,
5 => &*FIVE_WIDE_DATE_TIME,
_ => &*OTHER_WIDE_DATE_TIME,
};
date_format.format(&date, &*LOCALE)
}
let date_format = get_dateformat(&date);
date_format.format(&date, &*LOCALE)
}
#[allow(trivial_numeric_casts)]
fn default_zoned(time: SystemTime, zone: &TimeZone) -> String {
let date = zone.to_zoned(LocalDateTime::at(systemtime_epoch(time)));
let date_format = get_dateformat(&date);
date_format.format(&date, &*LOCALE)
}
if date.year() == *CURRENT_YEAR {
format!("{:2} {} {:02}:{:02}",
date.day(), month_to_abbrev(date.month()),
date.hour(), date.minute())
}
else {
let date_format = match *MAXIMUM_MONTH_WIDTH {
4 => &*FOUR_WIDE_DATE_YEAR,
5 => &*FIVE_WIDE_DATE_YEAR,
_ => &*OTHER_WIDE_DATE_YEAR,
};
date_format.format(&date, &*LOCALE)
fn get_dateformat(date: &LocalDateTime) -> &'static DateFormat<'static> {
match (is_recent(&date), *MAXIMUM_MONTH_WIDTH) {
(true, 4) => &FOUR_WIDE_DATE_TIME,
(true, 5) => &FIVE_WIDE_DATE_TIME,
(true, _) => &OTHER_WIDE_DATE_TIME,
(false, 4) => &FOUR_WIDE_DATE_YEAR,
(false, 5) => &FIVE_WIDE_DATE_YEAR,
(false, _) => &OTHER_WIDE_DATE_YEAR,
}
}
@ -153,7 +138,7 @@ fn full_zoned(time: SystemTime, zone: &TimeZone) -> String {
fn iso_local(time: SystemTime) -> String {
let date = LocalDateTime::at(systemtime_epoch(time));
if is_recent(date) {
if is_recent(&date) {
format!("{:02}-{:02} {:02}:{:02}",
date.month() as usize, date.day(),
date.hour(), date.minute())
@ -168,7 +153,7 @@ fn iso_local(time: SystemTime) -> String {
fn iso_zoned(time: SystemTime, zone: &TimeZone) -> String {
let date = zone.to_zoned(LocalDateTime::at(systemtime_epoch(time)));
if is_recent(date) {
if is_recent(&date) {
format!("{:02}-{:02} {:02}:{:02}",
date.month() as usize, date.day(),
date.hour(), date.minute())
@ -206,27 +191,10 @@ fn systemtime_nanos(time: SystemTime) -> u32 {
})
}
fn is_recent(date: LocalDateTime) -> bool {
fn is_recent(date: &LocalDateTime) -> bool {
date.year() == *CURRENT_YEAR
}
fn month_to_abbrev(month: Month) -> &'static str {
match month {
Month::January => "Jan",
Month::February => "Feb",
Month::March => "Mar",
Month::April => "Apr",
Month::May => "May",
Month::June => "Jun",
Month::July => "Jul",
Month::August => "Aug",
Month::September => "Sep",
Month::October => "Oct",
Month::November => "Nov",
Month::December => "Dec",
}
}
lazy_static! {
@ -250,15 +218,15 @@ lazy_static! {
};
static ref FOUR_WIDE_DATE_TIME: DateFormat<'static> = DateFormat::parse(
"{2>:D} {4<:M} {2>:h}:{02>:m}"
"{2>:D} {4<:M} {02>:h}:{02>:m}"
).unwrap();
static ref FIVE_WIDE_DATE_TIME: DateFormat<'static> = DateFormat::parse(
"{2>:D} {5<:M} {2>:h}:{02>:m}"
"{2>:D} {5<:M} {02>:h}:{02>:m}"
).unwrap();
static ref OTHER_WIDE_DATE_TIME: DateFormat<'static> = DateFormat::parse(
"{2>:D} {:M} {2>:h}:{02>:m}"
"{2>:D} {:M} {02>:h}:{02>:m}"
).unwrap();
static ref FOUR_WIDE_DATE_YEAR: DateFormat<'static> = DateFormat::parse(

View File

@ -68,7 +68,7 @@ tags = [ 'long', 'time-style' ]
[[cmd]]
name = "exa -l using a locale with 4-character-long month abbreviations (ja_JP) sizes the date column correctly"
shell = "exa -l /testcases/dates"
environment = { LC_ALL = "ja_JP.UTF-8", LANG = "ja_JP.UTF-8" }
environment = { LC_TIME = "ja_JP.UTF-8", LANG = "ja_JP.UTF-8" }
stdout = { file = "outputs/dates_long_localejp.ansitxt" }
stderr = { empty = true }
status = 0
@ -77,8 +77,17 @@ tags = [ 'long', 'locales' ]
[[cmd]]
name = "exa -l using a locale with 5-character-long month abbreviations (fr_FR) sizes the date column correctly"
shell = "exa -l /testcases/dates"
environment = { LC_ALL = "fr_FR.UTF-8", LANG = "fr_FR.UTF-8" }
environment = { LC_TIME = "fr_FR.UTF-8", LANG = "fr_FR.UTF-8" }
stdout = { file = "outputs/dates_long_localefr.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'locales' ]
[[cmd]]
name = "exa -l using a locale (fr_FR) display dates of the current year with localized month name"
shell = "exa -l /testcases/files"
environment = { LC_TIME = "fr_FR.UTF-8", LANG = "fr_FR.UTF-8" }
stdout = { file = "outputs/dates_long_currentyear_localefr.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'locales' ]

View File

@ -61,3 +61,14 @@ stdout = { file = "outputs/files_long_colourscale_bytes.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'colour-scale', 'bytes' ]
[[cmd]]
name = "exa -l produces a details table with major and minor device IDs"
shell = "cd /dev; exa -l mem null port zero full random urandom --sort=none --no-time"
stdout = { file = "outputs/dev_long.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'dev' ]
# these particular device IDs should be fixed:
# https://raw.githubusercontent.com/torvalds/linux/master/Documentation/admin-guide/devices.txt

View File

@ -43,3 +43,11 @@ stdout = { file = "outputs/specials_long_classify.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'classify' ]
[[cmd]]
name = "exa -lF handles and classifies symlink kinds"
shell = "exa -lF --no-time /testcases/links"
stdout = { file = "outputs/links_long_classify.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'classify' ]

View File

@ -1,3 +1,22 @@
# Command-line errors
[[cmd]]
name = "exa --aoeu displays an error"
shell = "exa --aoeu"
stdout = { empty = true }
stderr = { file = "outputs/error_invalid_option.ansitxt" }
status = 3
tags = [ 'error' ]
[[cmd]]
name = "exa -Taa displays an error"
shell = "exa -Taa"
stdout = { empty = true }
stderr = { file = "outputs/error_tree_all_all.ansitxt" }
status = 3
tags = [ 'error' ]
# Error suggestions
[[cmd]]
@ -15,3 +34,85 @@ stdout = { empty = true }
stderr = { string = "To sort newest files last, try \"--sort newest\", or just \"-snew\""}
status = 3
tags = [ 'error', 'long', 'sort' ]
# Invalid values for $COLUMNS
[[cmd]]
name = "COLUMNS=999... exa shows an error about the number size"
shell = "exa"
environment = { "COLUMNS" = "99999999999999999999999" }
stdout = { empty = true }
stderr = { file = "outputs/error_columns_nines.ansitxt" }
status = 3
tags = [ 'error', 'env' ]
[[cmd]]
name = "COLUMNS=abcdef exa shows an error about invalid digits"
shell = "exa"
environment = { "COLUMNS" = "abcdef" }
stdout = { empty = true }
stderr = { file = "outputs/error_columns_invalid.ansitxt" }
status = 3
tags = [ 'error', 'env' ]
# Invalid values for $EXA_GRID_ROWS
[[cmd]]
name = "EXA_GRID_ROWS=999... exa -lG shows an error about the number size"
shell = "exa -lG"
environment = { "EXA_GRID_ROWS" = "99999999999999999999999" }
stdout = { empty = true }
stderr = { file = "outputs/error_grid_rows_nines.ansitxt" }
status = 3
tags = [ 'error', 'env' ]
[[cmd]]
name = "EXA_GRID_ROWS=abcdef exa -lG shows an error about invalid digits"
shell = "exa -lG"
environment = { "EXA_GRID_ROWS" = "abcdef" }
stdout = { empty = true }
stderr = { file = "outputs/error_grid_rows_invalid.ansitxt" }
status = 3
tags = [ 'error', 'env' ]
# Invalid values for $EXA_ICON_SPACING
[[cmd]]
name = "EXA_ICON_SPACING=999... exa --icons shows an error about the number size"
shell = "exa --icons"
environment = { "EXA_ICON_SPACING" = "99999999999999999999999" }
stdout = { empty = true }
stderr = { file = "outputs/error_icon_spacing_nines.ansitxt" }
status = 3
tags = [ 'error', 'env', 'icons' ]
[[cmd]]
name = "EXA_ICON_SPACING=abcdef exa --icons shows an error about invalid digits"
shell = "exa --icons"
environment = { "EXA_ICON_SPACING" = "abcdef" }
stdout = { empty = true }
stderr = { file = "outputs/error_icon_spacing_invalid.ansitxt" }
status = 3
tags = [ 'error', 'env', 'icons' ]
# Invalid values for --level (-L)
[[cmd]]
name = "exa -TL999... shows an error about the number size"
shell = "exa -TL99999999999999999999999"
stdout = { empty = true }
stderr = { file = "outputs/error_level_nines.ansitxt" }
status = 3
tags = [ 'error', 'tree', 'level' ]
[[cmd]]
name = "exa -TLabcdef shows an error about invalid digits"
shell = "exa -TLabcdef"
stdout = { empty = true }
stderr = { file = "outputs/error_level_invalid.ansitxt" }
status = 3
tags = [ 'error', 'tree', 'level' ]

View File

@ -101,13 +101,21 @@ status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l with an ignored directory argument does not flag the contents as ignored"
name = "exa --git -l with an ignored directory argument flags the contents as ignored"
shell = "exa --git -l /testcases/git2/target"
stdout = { file = "outputs/git2_long_ignoreddir.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l --list-dirs with a directory argument doesnt flag it as ignored if only the content is"
shell = "exa --git -l --list-dirs /testcases/git2/ignoreds/nested2"
stdout = { file = "outputs/git2_long_ignoredcontent.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l with a nested repository argument uses the sub-repository rules"
shell = "exa --git -l /testcases/git2/deeply/nested/repository"
@ -155,7 +163,7 @@ status = 0
tags = [ 'long', 'git' ]
[[cmd]]
name = "exa --git -l shows a Git status column for multiple repositories across multiple directories"
name = "exa --git -l shows a Git status column for multiple repositories across multiple directories 2"
shell = "exa --git -l /testcases/{git2/deeply/nested/directory,git/edits,git2/target,git2/deeply,git}"
stdout = { file = "outputs/git1+2_long_nested.ansitxt" }
stderr = { empty = true }

View File

@ -81,19 +81,49 @@ tags = [ 'env', 'long', 'grid' ]
# check if exa is using the minimum number of columns with headers
[[cmd]]
name = "COLUMN=200 exa -lGh with one file dont produce extra columns even if there place for more"
name = "COLUMNS=200 exa -lGh with one file dont produce extra columns even if there place for more"
shell = "exa -lGh /testcases/files/10_bytes"
environment = { COLUMNS = "200" }
stdout = { file = "outputs/files_paths_long_grid_header_1file.ansitxt" }
stdout = { file = "outputs/files_long_grid_header_1file.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
[[cmd]]
name = "COLUMN=200 exa -lGh with several files dont produce extra columns even if there place for more"
name = "COLUMNS=200 exa -lGh with several files dont produce extra columns even if there place for more"
shell = "exa -lGh /testcases/files/10_{bytes,KiB}"
environment = { COLUMNS = "200" }
stdout = { file = "outputs/files_paths_long_grid_header_2files.ansitxt" }
stdout = { file = "outputs/files_long_grid_header_2files.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
# check if EXA_GRID_ROWS is working
[[cmd]]
name = "COLUMNS=200 EXA_GRID_ROWS=2 exa -lG with three files produces a grid details of 1 column"
shell = "exa -lG /testcases/files/1_*"
environment = { COLUMNS = "200", EXA_GRID_ROWS = "2" }
stdout = { file = "outputs/files_long_grid_exa_grid_rows_2_3files.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
[[cmd]]
name = "COLUMNS=200 EXA_GRID_ROWS=5 exa -lG with 15 files produces a grid details of 3 columns"
shell = "exa -lG /testcases/files/1*"
environment = { COLUMNS = "200", EXA_GRID_ROWS = "5" }
stdout = { file = "outputs/files_long_grid_exa_grid_rows_5_15files.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]
[[cmd]]
name = "COLUMNS=200 EXA_GRID_ROWS=6 exa -lG with 15 files produces a grid details of 1 column"
shell = "exa -lG /testcases/files/1*"
environment = { COLUMNS = "200", EXA_GRID_ROWS = "6" }
stdout = { file = "outputs/files_long_grid_exa_grid_rows_6_15files.ansitxt" }
stderr = { empty = true }
status = 0
tags = [ 'env', 'long', 'grid' ]

View File

@ -0,0 +1,39 @@
.rw-r--r-- 1 cassowary  1 janv. 12:34 1_bytes
.rw-r--r-- 1,0k cassowary  1 janv. 12:34 1_KiB
.rw-r--r-- 1,0M cassowary  1 janv. 12:34 1_MiB
.rw-r--r-- 2 cassowary  1 janv. 12:34 2_bytes
.rw-r--r-- 2,0k cassowary  1 janv. 12:34 2_KiB
.rw-r--r-- 2,1M cassowary  1 janv. 12:34 2_MiB
.rw-r--r-- 3 cassowary  1 janv. 12:34 3_bytes
.rw-r--r-- 3,1k cassowary  1 janv. 12:34 3_KiB
.rw-r--r-- 3,1M cassowary  1 janv. 12:34 3_MiB
.rw-r--r-- 4 cassowary  1 janv. 12:34 4_bytes
.rw-r--r-- 4,1k cassowary  1 janv. 12:34 4_KiB
.rw-r--r-- 4,2M cassowary  1 janv. 12:34 4_MiB
.rw-r--r-- 5 cassowary  1 janv. 12:34 5_bytes
.rw-r--r-- 5,1k cassowary  1 janv. 12:34 5_KiB
.rw-r--r-- 5,2M cassowary  1 janv. 12:34 5_MiB
.rw-r--r-- 6 cassowary  1 janv. 12:34 6_bytes
.rw-r--r-- 6,1k cassowary  1 janv. 12:34 6_KiB
.rw-r--r-- 6,3M cassowary  1 janv. 12:34 6_MiB
.rw-r--r-- 7 cassowary  1 janv. 12:34 7_bytes
.rw-r--r-- 7,2k cassowary  1 janv. 12:34 7_KiB
.rw-r--r-- 7,3M cassowary  1 janv. 12:34 7_MiB
.rw-r--r-- 8 cassowary  1 janv. 12:34 8_bytes
.rw-r--r-- 8,2k cassowary  1 janv. 12:34 8_KiB
.rw-r--r-- 8,4M cassowary  1 janv. 12:34 8_MiB
.rw-r--r-- 9 cassowary  1 janv. 12:34 9_bytes
.rw-r--r-- 9,2k cassowary  1 janv. 12:34 9_KiB
.rw-r--r-- 9,4M cassowary  1 janv. 12:34 9_MiB
.rw-r--r-- 10 cassowary  1 janv. 12:34 10_bytes
.rw-r--r-- 10k cassowary  1 janv. 12:34 10_KiB
.rw-r--r-- 10M cassowary  1 janv. 12:34 10_MiB
.rw-r--r-- 11 cassowary  1 janv. 12:34 11_bytes
.rw-r--r-- 11k cassowary  1 janv. 12:34 11_KiB
.rw-r--r-- 12M cassowary  1 janv. 12:34 11_MiB
.rw-r--r-- 12 cassowary  1 janv. 12:34 12_bytes
.rw-r--r-- 12k cassowary  1 janv. 12:34 12_KiB
.rw-r--r-- 13M cassowary  1 janv. 12:34 12_MiB
.rw-r--r-- 13 cassowary  1 janv. 12:34 13_bytes
.rw-r--r-- 13k cassowary  1 janv. 12:34 13_KiB
.rw-r--r-- 14M cassowary  1 janv. 12:34 13_MiB

View File

@ -0,0 +1,7 @@
crw-r----- 1,1 root mem
crw-rw-rw- 1,3 root null
crw-r----- 1,4 root port
crw-rw-rw- 1,5 root zero
crw-rw-rw- 1,7 root full
crw-rw-rw- 1,8 root random
crw-rw-rw- 1,9 root urandom

View File

@ -0,0 +1 @@
exa: Value "abcdef" not valid for environment variable COLUMNS: invalid digit found in string

View File

@ -0,0 +1 @@
exa: Value "99999999999999999999999" not valid for environment variable COLUMNS: number too large to fit in target type

View File

@ -0,0 +1 @@
exa: Value "abcdef" not valid for environment variable EXA_GRID_ROWS: invalid digit found in string

View File

@ -0,0 +1 @@
exa: Value "99999999999999999999999" not valid for environment variable EXA_GRID_ROWS: number too large to fit in target type

View File

@ -0,0 +1 @@
exa: Value "abcdef" not valid for environment variable EXA_ICON_SPACING: invalid digit found in string

View File

@ -0,0 +1 @@
exa: Value "99999999999999999999999" not valid for environment variable EXA_ICON_SPACING: number too large to fit in target type

View File

@ -0,0 +1 @@
exa: Unknown argument --aoeu

View File

@ -0,0 +1 @@
exa: Value "abcdef" not valid for option --level (-L): invalid digit found in string

View File

@ -0,0 +1 @@
exa: Value "99999999999999999999999" not valid for option --level (-L): number too large to fit in target type

View File

@ -0,0 +1 @@
exa: Option --tree is useless given --all --all

View File

@ -0,0 +1,3 @@
.rw-r--r-- 1 cassowary  1 Jan 12:34 /testcases/files/1_bytes
.rw-r--r-- 1.0k cassowary  1 Jan 12:34 /testcases/files/1_KiB
.rw-r--r-- 1.0M cassowary  1 Jan 12:34 /testcases/files/1_MiB

View File

@ -0,0 +1,5 @@
.rw-r--r-- 10 cassowary  1 Jan 12:34 /testcases/files/10_bytes .rw-r--r-- 12M cassowary  1 Jan 12:34 /testcases/files/11_MiB .rw-r--r-- 13k cassowary  1 Jan 12:34 /testcases/files/13_KiB
.rw-r--r-- 10k cassowary  1 Jan 12:34 /testcases/files/10_KiB .rw-r--r-- 12 cassowary  1 Jan 12:34 /testcases/files/12_bytes .rw-r--r-- 14M cassowary  1 Jan 12:34 /testcases/files/13_MiB
.rw-r--r-- 10M cassowary  1 Jan 12:34 /testcases/files/10_MiB .rw-r--r-- 12k cassowary  1 Jan 12:34 /testcases/files/12_KiB .rw-r--r-- 1 cassowary  1 Jan 12:34 /testcases/files/1_bytes
.rw-r--r-- 11 cassowary  1 Jan 12:34 /testcases/files/11_bytes .rw-r--r-- 13M cassowary  1 Jan 12:34 /testcases/files/12_MiB .rw-r--r-- 1.0k cassowary  1 Jan 12:34 /testcases/files/1_KiB
.rw-r--r-- 11k cassowary  1 Jan 12:34 /testcases/files/11_KiB .rw-r--r-- 13 cassowary  1 Jan 12:34 /testcases/files/13_bytes .rw-r--r-- 1.0M cassowary  1 Jan 12:34 /testcases/files/1_MiB

View File

@ -0,0 +1,15 @@
.rw-r--r-- 1 cassowary  1 Jan 12:34 /testcases/files/1_bytes
.rw-r--r-- 1.0k cassowary  1 Jan 12:34 /testcases/files/1_KiB
.rw-r--r-- 1.0M cassowary  1 Jan 12:34 /testcases/files/1_MiB
.rw-r--r-- 10 cassowary  1 Jan 12:34 /testcases/files/10_bytes
.rw-r--r-- 10k cassowary  1 Jan 12:34 /testcases/files/10_KiB
.rw-r--r-- 10M cassowary  1 Jan 12:34 /testcases/files/10_MiB
.rw-r--r-- 11 cassowary  1 Jan 12:34 /testcases/files/11_bytes
.rw-r--r-- 11k cassowary  1 Jan 12:34 /testcases/files/11_KiB
.rw-r--r-- 12M cassowary  1 Jan 12:34 /testcases/files/11_MiB
.rw-r--r-- 12 cassowary  1 Jan 12:34 /testcases/files/12_bytes
.rw-r--r-- 12k cassowary  1 Jan 12:34 /testcases/files/12_KiB
.rw-r--r-- 13M cassowary  1 Jan 12:34 /testcases/files/12_MiB
.rw-r--r-- 13 cassowary  1 Jan 12:34 /testcases/files/13_bytes
.rw-r--r-- 13k cassowary  1 Jan 12:34 /testcases/files/13_KiB
.rw-r--r-- 14M cassowary  1 Jan 12:34 /testcases/files/13_MiB

View File

@ -8,7 +8,7 @@
.rw-rw-r-- 20 cassowary  1 Jan 12:34 -M unstaged
/testcases/git2/target:
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -- another ignored file
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I another ignored file
/testcases/git2/deeply:
drwxrwxr-x - cassowary  1 Jan 12:34 -N nested

View File

@ -1 +1 @@
music.m4a nested
music.m4a nested nested2

View File

@ -1,2 +1,3 @@
music.m4a
nested
nested2

View File

@ -1,2 +1,3 @@
.rw-rw-r-- 0 cassowary  1 Jan 12:34 music.m4a
drwxrwxr-x - cassowary  1 Jan 12:34 nested
drwxrwxr-x - cassowary  1 Jan 12:34 nested2

View File

@ -1 +1 @@
.rw-rw-r-- 0 cassowary  1 Jan 12:34 music.m4a drwxrwxr-x - cassowary  1 Jan 12:34 nested
.rw-rw-r-- 0 cassowary  1 Jan 12:34 music.m4a drwxrwxr-x - cassowary  1 Jan 12:34 nested drwxrwxr-x - cassowary  1 Jan 12:34 nested2

View File

@ -1,5 +1,8 @@
.rw-rw-r-- 0 cassowary  1 Jan 12:34 music.m4a
drwxrwxr-x - cassowary  1 Jan 12:34 nested
drwxrwxr-x - cassowary  1 Jan 12:34 nested2
/testcases/git2/ignoreds/nested:
.rw-rw-r-- 0 cassowary  1 Jan 12:34 funky chicken.m4a
/testcases/git2/ignoreds/nested2:

View File

@ -1,4 +1,5 @@
drwxrwxr-x - cassowary  1 Jan 12:34 /testcases/git2/ignoreds
.rw-rw-r-- 0 cassowary  1 Jan 12:34 ├── music.m4a
drwxrwxr-x - cassowary  1 Jan 12:34 └── nested
.rw-rw-r-- 0 cassowary  1 Jan 12:34  └── funky chicken.m4a
drwxrwxr-x - cassowary  1 Jan 12:34 ├── nested
.rw-rw-r-- 0 cassowary  1 Jan 12:34 │ └── funky chicken.m4a
drwxrwxr-x - cassowary  1 Jan 12:34 └── nested2

View File

@ -1,4 +1,5 @@
/testcases/git2/ignoreds
├── music.m4a
└── nested
 └── funky chicken.m4a
├── nested
│ └── funky chicken.m4a
└── nested2

View File

@ -0,0 +1 @@
drwxrwxr-x - cassowary  1 Jan 12:34 -- /testcases/git2/ignoreds/nested2

View File

@ -1 +1 @@
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -- another ignored file
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I another ignored file

View File

@ -1,3 +1,4 @@
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -N music.m4a
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I music.mp3
drwxrwxr-x - cassowary  1 Jan 12:34 -N nested
drwxrwxr-x - cassowary  1 Jan 12:34 -- nested2

View File

@ -5,6 +5,7 @@
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -N music.m4a
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I music.mp3
drwxrwxr-x - cassowary  1 Jan 12:34 -N nested
drwxrwxr-x - cassowary  1 Jan 12:34 -- nested2
/testcases/git2/target:
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -- another ignored file
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I another ignored file

View File

@ -20,10 +20,14 @@
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -N music.m4a
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I music.mp3
drwxrwxr-x - cassowary  1 Jan 12:34 -N nested
drwxrwxr-x - cassowary  1 Jan 12:34 -- nested2
/testcases/git2/ignoreds/nested:
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I 70s grove.mp3
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -N funky chicken.m4a
/testcases/git2/ignoreds/nested2:
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I ievan polkka.mp3
/testcases/git2/target:
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -- another ignored file
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I another ignored file

View File

@ -18,6 +18,9 @@
/testcases/git2/ignoreds:
.rw-rw-r-- 0 cassowary  1 Jan 12:34 music.m4a
drwxrwxr-x - cassowary  1 Jan 12:34 nested
drwxrwxr-x - cassowary  1 Jan 12:34 nested2
/testcases/git2/ignoreds/nested:
.rw-rw-r-- 0 cassowary  1 Jan 12:34 funky chicken.m4a
/testcases/git2/ignoreds/nested2:

View File

@ -9,8 +9,10 @@
drwxrwxr-x - cassowary  1 Jan 12:34 -N ├── ignoreds
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -N │ ├── music.m4a
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I │ ├── music.mp3
drwxrwxr-x - cassowary  1 Jan 12:34 -N │ └── nested
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I │ ├── 70s grove.mp3
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -N │ └── funky chicken.m4a
drwxrwxr-x - cassowary  1 Jan 12:34 -N │ ├── nested
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I │ │ ├── 70s grove.mp3
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -N │ │ └── funky chicken.m4a
drwxrwxr-x - cassowary  1 Jan 12:34 -- │ └── nested2
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I │ └── ievan polkka.mp3
drwxrwxr-x - cassowary  1 Jan 12:34 -I └── target
.rw-rw-r-- 0 cassowary  1 Jan 12:34 --  └── another ignored file
.rw-rw-r-- 0 cassowary  1 Jan 12:34 -I  └── another ignored file

View File

@ -8,5 +8,6 @@
.rw-rw-r-- 0 cassowary  1 Jan 12:34 │ └── subfile
drwxrwxr-x - cassowary  1 Jan 12:34 └── ignoreds
.rw-rw-r-- 0 cassowary  1 Jan 12:34  ├── music.m4a
drwxrwxr-x - cassowary  1 Jan 12:34  └── nested
.rw-rw-r-- 0 cassowary  1 Jan 12:34  └── funky chicken.m4a
drwxrwxr-x - cassowary  1 Jan 12:34  ├── nested
.rw-rw-r-- 0 cassowary  1 Jan 12:34  │ └── funky chicken.m4a
drwxrwxr-x - cassowary  1 Jan 12:34  └── nested2

View File

@ -8,5 +8,6 @@
│ └── subfile
└── ignoreds
 ├── music.m4a
 └── nested
 └── funky chicken.m4a
 ├── nested
 │ └── funky chicken.m4a
 └── nested2

View File

@ -20,7 +20,7 @@ DISPLAY OPTIONS
FILTERING AND SORTING OPTIONS
-a, --all show hidden and 'dot' files
-d, --list-dirs list directories like regular files
-d, --list-dirs list directories as files; don't list their contents
-L, --level DEPTH limit the depth of recursion
-r, --reverse reverse the sort order
-s, --sort SORT_FIELD which field to sort by

View File

@ -0,0 +1,10 @@
lrwxrwxrwx 7 vagrant broken -> nowhere
lrwxrwxrwx 1 vagrant current_dir -> ./
lrwxrwxrwx 12 vagrant forbidden -> /proc/1/root
lrwxrwxrwx 6 vagrant itself -> itself
lrwxrwxrwx 2 vagrant parent_dir -> ../
lrwxrwxrwx 1 vagrant root -> //
.rw-rw-r-- 0 vagrant some_file
lrwxrwxrwx 26 vagrant some_file_absolute -> /testcases/links/some_file
lrwxrwxrwx 9 vagrant some_file_relative -> some_file
lrwxrwxrwx 4 vagrant usr -> /usr/