mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-26 22:06:26 +00:00
Merge branch 'common-view-fields'
This commit is contained in:
commit
c7f18873fd
77
Cargo.lock
generated
77
Cargo.lock
generated
@ -7,10 +7,11 @@ dependencies = [
|
||||
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"locale 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"natord 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term_grid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -39,7 +40,7 @@ name = "cmake"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -48,7 +49,7 @@ version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"iso8601 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"locale 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pad 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -56,7 +57,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.50"
|
||||
version = "0.3.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -70,9 +71,9 @@ version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -87,7 +88,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -98,9 +99,14 @@ dependencies = [
|
||||
"nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.23"
|
||||
version = "0.2.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -109,20 +115,21 @@ version = "0.6.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.0.13"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -130,7 +137,7 @@ name = "locale"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -216,10 +223,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.5.1"
|
||||
version = "1.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -238,6 +245,11 @@ dependencies = [
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.9"
|
||||
@ -248,7 +260,7 @@ name = "rand"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -279,7 +291,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -289,11 +301,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "1.4.1"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -301,9 +314,14 @@ name = "users"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "zoneinfo_compiled"
|
||||
version = "0.2.1"
|
||||
@ -319,15 +337,16 @@ dependencies = [
|
||||
"checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304"
|
||||
"checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f"
|
||||
"checksum datetime 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2d425bf1f6bbd57cf833081c1e60ac294fd74e7edd66acc91c3fca2e496bcee9"
|
||||
"checksum gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)" = "5f837c392f2ea61cb1576eac188653df828c861b7137d74ea4a5caa89621f9e6"
|
||||
"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a"
|
||||
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
|
||||
"checksum git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa01936ac96555c083c0e8553f672616274408d9d3fc5b8696603fbf63ff43ee"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37"
|
||||
"checksum iso8601 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "11dc464f8c6f17595d191447c9c6559298b2d023d6f846a4a23ac7ea3c46c477"
|
||||
"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e"
|
||||
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
|
||||
"checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc"
|
||||
"checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d"
|
||||
"checksum libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e5ee912a45d686d393d5ac87fac15ba0ba18daae14e8e7543c63ebf7fb7e970c"
|
||||
"checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
|
||||
"checksum locale 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5fdbe492a9c0238da900a1165c42fc5067161ce292678a6fe80921f30fe307fd"
|
||||
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
|
||||
"checksum natord 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c"
|
||||
@ -339,17 +358,19 @@ dependencies = [
|
||||
"checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
|
||||
"checksum num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "33c881e104a26e1accc09449374c095ff2312c8e0c27fab7bbefe16eac7c776d"
|
||||
"checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6"
|
||||
"checksum num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e416ba127a4bb3ff398cb19546a8d0414f73352efe2857f4060d36f5fe5983a"
|
||||
"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"
|
||||
"checksum number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "59a14be9c211cb9c602bad35ac99f41e9a84b44d71b8cbd3040e3bd02a214902"
|
||||
"checksum pad 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d1bf3336e626b898e7263790d432a711d4277e22faea20dd9f70e0cab268fa58"
|
||||
"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
|
||||
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
|
||||
"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
|
||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
"checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a"
|
||||
"checksum term_grid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc202875496cf72a683a1ecd66f0742a830e73c202bdbd21867d73dfaac8343"
|
||||
"checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a"
|
||||
"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
|
||||
"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
|
||||
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
||||
"checksum url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2ba3456fbe5c0098cb877cf08b92b76c3e18e0be9e47c35b487220d377d24e"
|
||||
"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27"
|
||||
"checksum users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7ae8fdf783cb9652109c99886459648feb92ecc749e6b8e7930f6decba74c7c"
|
||||
"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
|
||||
"checksum zoneinfo_compiled 0.2.1 (git+https://github.com/rust-datetime/zoneinfo-compiled.git)" = "<none>"
|
||||
|
@ -16,6 +16,7 @@ ansi_term = "0.8.0"
|
||||
datetime = "0.4.3"
|
||||
getopts = "0.2.14"
|
||||
glob = "0.2"
|
||||
lazy_static = "0.2"
|
||||
libc = "0.2.9"
|
||||
locale = "0.2.1"
|
||||
natord = "1.0.7"
|
||||
|
20
src/exa.rs
20
src/exa.rs
@ -18,6 +18,10 @@ extern crate zoneinfo_compiled;
|
||||
|
||||
#[cfg(feature="git")] extern crate git2;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::io::{stderr, Write, Result as IOResult};
|
||||
use std::path::{Component, Path};
|
||||
@ -25,9 +29,9 @@ use std::path::{Component, Path};
|
||||
use ansi_term::{ANSIStrings, Style};
|
||||
|
||||
use fs::{Dir, File};
|
||||
use options::{Options, View};
|
||||
use options::{Options, View, Mode};
|
||||
pub use options::Misfire;
|
||||
use output::escape;
|
||||
use output::{escape, lines, grid, grid_details, details};
|
||||
|
||||
mod fs;
|
||||
mod info;
|
||||
@ -164,11 +168,13 @@ impl<'w, W: Write + 'w> Exa<'w, W> {
|
||||
/// printing differently...
|
||||
fn print_files(&mut self, dir: Option<&Dir>, files: Vec<File>) -> IOResult<()> {
|
||||
if !files.is_empty() {
|
||||
match self.options.view {
|
||||
View::Grid(ref g) => g.view(&files, self.writer),
|
||||
View::Details(ref d) => d.view(dir, files, self.writer),
|
||||
View::GridDetails(ref gd) => gd.view(dir, files, self.writer),
|
||||
View::Lines(ref l) => l.view(files, self.writer),
|
||||
let View { ref mode, ref colours, classify } = self.options.view;
|
||||
|
||||
match *mode {
|
||||
Mode::Lines => lines::Render { files, colours, classify }.render(self.writer),
|
||||
Mode::Grid(ref opts) => grid::Render { files, colours, classify, 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::GridDetails(ref grid, ref details) => grid_details::Render { dir, files, colours, classify, grid, details }.render(self.writer),
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -3,7 +3,7 @@ use std::ffi::OsStr;
|
||||
use getopts;
|
||||
|
||||
use fs::feature::xattr;
|
||||
use output::{Details, GridDetails};
|
||||
use output::details;
|
||||
|
||||
mod dir_action;
|
||||
pub use self::dir_action::{DirAction, RecurseOptions};
|
||||
@ -18,7 +18,7 @@ mod misfire;
|
||||
pub use self::misfire::Misfire;
|
||||
|
||||
mod view;
|
||||
pub use self::view::View;
|
||||
pub use self::view::{View, Mode};
|
||||
|
||||
|
||||
/// These **options** represent a parsed, error-checked versions of the
|
||||
@ -123,9 +123,9 @@ impl Options {
|
||||
/// status column. It’s only worth trying to discover a repository if the
|
||||
/// results will end up being displayed.
|
||||
pub fn should_scan_for_git(&self) -> bool {
|
||||
match self.view {
|
||||
View::Details(Details { columns: Some(cols), .. }) |
|
||||
View::GridDetails(GridDetails { details: Details { columns: Some(cols), .. }, .. }) => cols.should_scan_for_git(),
|
||||
match self.view.mode {
|
||||
Mode::Details(details::Options { columns: Some(cols), .. }) |
|
||||
Mode::GridDetails(_, details::Options { columns: Some(cols), .. }) => cols.should_scan_for_git(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -135,7 +135,7 @@ impl Options {
|
||||
fn deduce(matches: &getopts::Matches) -> Result<Options, Misfire> {
|
||||
let dir_action = DirAction::deduce(matches)?;
|
||||
let filter = FileFilter::deduce(matches)?;
|
||||
let view = View::deduce(matches, filter.clone(), dir_action)?;
|
||||
let view = View::deduce(matches)?;
|
||||
|
||||
Ok(Options { dir_action, view, filter })
|
||||
}
|
||||
|
@ -3,32 +3,47 @@ use std::env::var_os;
|
||||
use getopts;
|
||||
|
||||
use output::Colours;
|
||||
use output::{Grid, Details, GridDetails, Lines};
|
||||
use output::{grid, details};
|
||||
use output::column::{Columns, TimeTypes, SizeFormat};
|
||||
use output::file_name::Classify;
|
||||
use options::{FileFilter, DirAction, Misfire};
|
||||
use term::dimensions;
|
||||
use options::Misfire;
|
||||
use fs::feature::xattr;
|
||||
|
||||
|
||||
/// The **view** contains all information about how to format output.
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub enum View {
|
||||
Details(Details),
|
||||
Grid(Grid),
|
||||
GridDetails(GridDetails),
|
||||
Lines(Lines),
|
||||
pub struct View {
|
||||
pub mode: Mode,
|
||||
pub colours: Colours,
|
||||
pub classify: Classify,
|
||||
}
|
||||
|
||||
impl View {
|
||||
|
||||
/// Determine which view to use and all of that view’s arguments.
|
||||
pub fn deduce(matches: &getopts::Matches, filter: FileFilter, dir_action: DirAction) -> Result<View, Misfire> {
|
||||
use options::misfire::Misfire::*;
|
||||
pub fn deduce(matches: &getopts::Matches) -> Result<View, Misfire> {
|
||||
let mode = Mode::deduce(matches)?;
|
||||
let colours = Colours::deduce(matches)?;
|
||||
let classify = Classify::deduce(matches);
|
||||
Ok(View { mode, colours, classify })
|
||||
}
|
||||
}
|
||||
|
||||
let colour_scale = || {
|
||||
matches.opt_present("color-scale") || matches.opt_present("colour-scale")
|
||||
};
|
||||
|
||||
/// The **mode** is the “type” of output.
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub enum Mode {
|
||||
Grid(grid::Options),
|
||||
Details(details::Options),
|
||||
GridDetails(grid::Options, details::Options),
|
||||
Lines,
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
|
||||
/// Determine the mode from the command-line arguments.
|
||||
pub fn deduce(matches: &getopts::Matches) -> Result<Mode, Misfire> {
|
||||
use options::misfire::Misfire::*;
|
||||
|
||||
let long = || {
|
||||
if matches.opt_present("across") && !matches.opt_present("grid") {
|
||||
@ -38,31 +53,11 @@ impl View {
|
||||
Err(Useless("oneline", true, "long"))
|
||||
}
|
||||
else {
|
||||
let term_colours = TerminalColours::deduce(matches)?;
|
||||
let colours = match term_colours {
|
||||
TerminalColours::Always => Colours::colourful(colour_scale()),
|
||||
TerminalColours::Never => Colours::plain(),
|
||||
TerminalColours::Automatic => {
|
||||
if dimensions().is_some() {
|
||||
Colours::colourful(colour_scale())
|
||||
}
|
||||
else {
|
||||
Colours::plain()
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let details = Details {
|
||||
Ok(details::Options {
|
||||
columns: Some(Columns::deduce(matches)?),
|
||||
header: matches.opt_present("header"),
|
||||
recurse: dir_action.recurse_options(),
|
||||
filter: filter.clone(),
|
||||
xattr: xattr::ENABLED && matches.opt_present("extended"),
|
||||
colours: colours,
|
||||
classify: Classify::deduce(matches),
|
||||
};
|
||||
|
||||
Ok(details)
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
@ -88,47 +83,31 @@ impl View {
|
||||
};
|
||||
|
||||
let other_options_scan = || {
|
||||
let classify = Classify::deduce(matches);
|
||||
let term_colours = TerminalColours::deduce(matches)?;
|
||||
let term_width = TerminalWidth::deduce()?;
|
||||
|
||||
if let Some(&width) = term_width.as_ref() {
|
||||
let colours = match term_colours {
|
||||
TerminalColours::Always |
|
||||
TerminalColours::Automatic => Colours::colourful(colour_scale()),
|
||||
TerminalColours::Never => Colours::plain(),
|
||||
};
|
||||
|
||||
if let Some(width) = TerminalWidth::deduce()?.width() {
|
||||
if matches.opt_present("oneline") {
|
||||
if matches.opt_present("across") {
|
||||
Err(Useless("across", true, "oneline"))
|
||||
}
|
||||
else {
|
||||
Ok(View::Lines(Lines { colours, classify }))
|
||||
Ok(Mode::Lines)
|
||||
}
|
||||
}
|
||||
else if matches.opt_present("tree") {
|
||||
let details = Details {
|
||||
let details = details::Options {
|
||||
columns: None,
|
||||
header: false,
|
||||
recurse: dir_action.recurse_options(),
|
||||
filter: filter.clone(), // TODO: clone
|
||||
xattr: false,
|
||||
colours: colours,
|
||||
classify: classify,
|
||||
};
|
||||
|
||||
Ok(View::Details(details))
|
||||
Ok(Mode::Details(details))
|
||||
}
|
||||
else {
|
||||
let grid = Grid {
|
||||
let grid = grid::Options {
|
||||
across: matches.opt_present("across"),
|
||||
console_width: width,
|
||||
colours: colours,
|
||||
classify: classify,
|
||||
};
|
||||
|
||||
Ok(View::Grid(grid))
|
||||
Ok(Mode::Grid(grid))
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -136,42 +115,31 @@ impl View {
|
||||
// as the program’s stdout being connected to a file, then
|
||||
// fallback to the lines view.
|
||||
|
||||
let colours = match term_colours {
|
||||
TerminalColours::Always => Colours::colourful(colour_scale()),
|
||||
TerminalColours::Never | TerminalColours::Automatic => Colours::plain(),
|
||||
};
|
||||
|
||||
if matches.opt_present("tree") {
|
||||
let details = Details {
|
||||
let details = details::Options {
|
||||
columns: None,
|
||||
header: false,
|
||||
recurse: dir_action.recurse_options(),
|
||||
filter: filter.clone(),
|
||||
xattr: false,
|
||||
colours: colours,
|
||||
classify: classify,
|
||||
};
|
||||
|
||||
Ok(View::Details(details))
|
||||
Ok(Mode::Details(details))
|
||||
}
|
||||
else {
|
||||
Ok(View::Lines(Lines { colours, classify }))
|
||||
Ok(Mode::Lines)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if matches.opt_present("long") {
|
||||
let details = long()?;
|
||||
|
||||
if matches.opt_present("grid") {
|
||||
match other_options_scan() {
|
||||
Ok(View::Grid(grid)) => return Ok(View::GridDetails(GridDetails { grid, details })),
|
||||
Ok(lines) => return Ok(lines),
|
||||
Err(e) => return Err(e),
|
||||
match other_options_scan()? {
|
||||
Mode::Grid(grid) => return Ok(Mode::GridDetails(grid, details)),
|
||||
others => return Ok(others),
|
||||
};
|
||||
}
|
||||
else {
|
||||
return Ok(View::Details(details));
|
||||
return Ok(Mode::Details(details));
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,7 +176,7 @@ impl TerminalWidth {
|
||||
Err(e) => Err(Misfire::FailedParse(e)),
|
||||
}
|
||||
}
|
||||
else if let Some((width, _)) = dimensions() {
|
||||
else if let Some(width) = *TERM_WIDTH {
|
||||
Ok(TerminalWidth::Terminal(width))
|
||||
}
|
||||
else {
|
||||
@ -216,11 +184,11 @@ impl TerminalWidth {
|
||||
}
|
||||
}
|
||||
|
||||
fn as_ref(&self) -> Option<&usize> {
|
||||
fn width(&self) -> Option<usize> {
|
||||
match *self {
|
||||
TerminalWidth::Set(ref width)
|
||||
| TerminalWidth::Terminal(ref width) => Some(width),
|
||||
TerminalWidth::Unset => None,
|
||||
TerminalWidth::Set(width) |
|
||||
TerminalWidth::Terminal(width) => Some(width),
|
||||
TerminalWidth::Unset => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -359,6 +327,22 @@ impl TerminalColours {
|
||||
}
|
||||
|
||||
|
||||
impl Colours {
|
||||
fn deduce(matches: &getopts::Matches) -> Result<Colours, Misfire> {
|
||||
use self::TerminalColours::*;
|
||||
|
||||
let tc = TerminalColours::deduce(matches)?;
|
||||
if tc == Always || (tc == Automatic && TERM_WIDTH.is_some()) {
|
||||
let scale = matches.opt_present("color-scale") || matches.opt_present("colour-scale");
|
||||
Ok(Colours::colourful(scale))
|
||||
}
|
||||
else {
|
||||
Ok(Colours::plain())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl Classify {
|
||||
fn deduce(matches: &getopts::Matches) -> Classify {
|
||||
@ -366,3 +350,14 @@ impl Classify {
|
||||
else { Classify::JustFilenames }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Gets, then caches, the width of the terminal that exa is running in.
|
||||
// This gets used multiple times above, with no real guarantee of order,
|
||||
// so it’s easier to just cache it the first time it runs.
|
||||
lazy_static! {
|
||||
static ref TERM_WIDTH: Option<usize> = {
|
||||
use term::dimensions;
|
||||
dimensions().map(|t| t.0)
|
||||
};
|
||||
}
|
||||
|
@ -113,33 +113,18 @@ use output::file_name::{FileName, LinkStyle, Classify};
|
||||
/// Almost all the heavy lifting is done in a Table object, which handles the
|
||||
/// columns for each row.
|
||||
#[derive(PartialEq, Debug, Clone, Default)]
|
||||
pub struct Details {
|
||||
pub struct Options {
|
||||
|
||||
/// A Columns object that says which columns should be included in the
|
||||
/// output in the general case. Directories themselves can pick which
|
||||
/// columns are *added* to this list, such as the Git column.
|
||||
pub columns: Option<Columns>,
|
||||
|
||||
/// Whether to recurse through directories with a tree view, and if so,
|
||||
/// which options to use. This field is only relevant here if the `tree`
|
||||
/// field of the RecurseOptions is `true`.
|
||||
pub recurse: Option<RecurseOptions>,
|
||||
|
||||
/// How to sort and filter the files after getting their details.
|
||||
pub filter: FileFilter,
|
||||
|
||||
/// Whether to show a header line or not.
|
||||
pub header: bool,
|
||||
|
||||
/// Whether to show each file's extended attributes.
|
||||
pub xattr: bool,
|
||||
|
||||
/// The colours to use to display information in the table, including the
|
||||
/// colour of the tree view symbols.
|
||||
pub colours: Colours,
|
||||
|
||||
/// Whether to show a file type indiccator.
|
||||
pub classify: Classify,
|
||||
}
|
||||
|
||||
/// The **environment** struct contains any data that could change between
|
||||
@ -224,16 +209,30 @@ fn determine_time_zone() -> TZResult<TimeZone> {
|
||||
TimeZone::from_file("/etc/localtime")
|
||||
}
|
||||
|
||||
impl Details {
|
||||
|
||||
/// Print the details of the given vector of files -- all of which will
|
||||
/// have been read from the given directory, if present -- to stdout.
|
||||
pub fn view<W: Write>(&self, dir: Option<&Dir>, files: Vec<File>, w: &mut W) -> IOResult<()> {
|
||||
pub struct Render<'a> {
|
||||
pub dir: Option<&'a Dir>,
|
||||
pub files: Vec<File<'a>>,
|
||||
pub colours: &'a Colours,
|
||||
pub classify: Classify,
|
||||
pub opts: &'a Options,
|
||||
|
||||
/// Whether to recurse through directories with a tree view, and if so,
|
||||
/// which options to use. This field is only relevant here if the `tree`
|
||||
/// field of the RecurseOptions is `true`.
|
||||
pub recurse: Option<RecurseOptions>,
|
||||
|
||||
/// How to sort and filter the files after getting their details.
|
||||
pub filter: &'a FileFilter,
|
||||
}
|
||||
|
||||
impl<'a> Render<'a> {
|
||||
pub fn render<W: Write>(&self, w: &mut W) -> IOResult<()> {
|
||||
|
||||
// First, transform the Columns object into a vector of columns for
|
||||
// the current directory.
|
||||
let columns_for_dir = match self.columns {
|
||||
Some(cols) => cols.for_dir(dir),
|
||||
let columns_for_dir = match self.opts.columns {
|
||||
Some(cols) => cols.for_dir(self.dir),
|
||||
None => Vec::new(),
|
||||
};
|
||||
|
||||
@ -243,16 +242,18 @@ impl Details {
|
||||
// Build the table to put rows in.
|
||||
let mut table = Table {
|
||||
columns: &*columns_for_dir,
|
||||
opts: self,
|
||||
colours: self.colours,
|
||||
classify: self.classify,
|
||||
xattr: self.opts.xattr,
|
||||
env: env,
|
||||
rows: Vec::new(),
|
||||
};
|
||||
|
||||
// Next, add a header if the user requests it.
|
||||
if self.header { table.add_header() }
|
||||
if self.opts.header { table.add_header() }
|
||||
|
||||
// Then add files to the table and print it out.
|
||||
self.add_files_to_table(&mut table, files, 0);
|
||||
self.add_files_to_table(&mut table, &self.files, 0);
|
||||
for cell in table.print_table() {
|
||||
writeln!(w, "{}", cell.strings())?;
|
||||
}
|
||||
@ -262,7 +263,7 @@ impl Details {
|
||||
|
||||
/// Adds files to the table, possibly recursively. This is easily
|
||||
/// parallelisable, and uses a pool of threads.
|
||||
fn add_files_to_table<'dir, U: Users+Groups+Send>(&self, mut table: &mut Table<U>, src: Vec<File<'dir>>, depth: usize) {
|
||||
fn add_files_to_table<'dir, U: Users+Groups+Send>(&self, mut table: &mut Table<U>, src: &Vec<File<'dir>>, depth: usize) {
|
||||
use num_cpus;
|
||||
use scoped_threadpool::Pool;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -276,12 +277,12 @@ impl Details {
|
||||
xattrs: Vec<Attribute>,
|
||||
errors: Vec<(IOError, Option<PathBuf>)>,
|
||||
dir: Option<Dir>,
|
||||
file: File<'a>,
|
||||
file: &'a File<'a>,
|
||||
}
|
||||
|
||||
impl<'a> AsRef<File<'a>> for Egg<'a> {
|
||||
fn as_ref(&self) -> &File<'a> {
|
||||
&self.file
|
||||
self.file
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,7 +307,7 @@ impl Details {
|
||||
|
||||
let cells = table.cells_for_file(&file, !xattrs.is_empty());
|
||||
|
||||
if !table.opts.xattr {
|
||||
if !table.xattr {
|
||||
xattrs.clear();
|
||||
}
|
||||
|
||||
@ -336,7 +337,7 @@ impl Details {
|
||||
let row = Row {
|
||||
depth: depth,
|
||||
cells: Some(egg.cells),
|
||||
name: FileName::new(&egg.file, LinkStyle::FullLinkPaths, self.classify, &self.colours).paint().promote(),
|
||||
name: FileName::new(&egg.file, LinkStyle::FullLinkPaths, table.classify, table.colours).paint().promote(),
|
||||
last: index == num_eggs - 1,
|
||||
};
|
||||
|
||||
@ -361,7 +362,7 @@ impl Details {
|
||||
table.add_error(&error, depth + 1, false, path);
|
||||
}
|
||||
|
||||
self.add_files_to_table(table, files, depth + 1);
|
||||
self.add_files_to_table(table, &files, depth + 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -420,9 +421,10 @@ impl Row {
|
||||
/// directories.
|
||||
pub struct Table<'a, U: 'a> { // where U: Users+Groups
|
||||
pub rows: Vec<Row>,
|
||||
|
||||
pub columns: &'a [Column],
|
||||
pub opts: &'a Details,
|
||||
pub colours: &'a Colours,
|
||||
pub xattr: bool,
|
||||
pub classify: Classify,
|
||||
pub env: Arc<Environment<U>>,
|
||||
}
|
||||
|
||||
@ -434,8 +436,8 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> {
|
||||
pub fn add_header(&mut self) {
|
||||
let row = Row {
|
||||
depth: 0,
|
||||
cells: Some(self.columns.iter().map(|c| TextCell::paint_str(self.opts.colours.header, c.header())).collect()),
|
||||
name: TextCell::paint_str(self.opts.colours.header, "Name"),
|
||||
cells: Some(self.columns.iter().map(|c| TextCell::paint_str(self.colours.header, c.header())).collect()),
|
||||
name: TextCell::paint_str(self.colours.header, "Name"),
|
||||
last: false,
|
||||
};
|
||||
|
||||
@ -451,7 +453,7 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> {
|
||||
let row = Row {
|
||||
depth: depth,
|
||||
cells: None,
|
||||
name: TextCell::paint(self.opts.colours.broken_arrow, error_message),
|
||||
name: TextCell::paint(self.colours.broken_arrow, error_message),
|
||||
last: last,
|
||||
};
|
||||
|
||||
@ -462,15 +464,15 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> {
|
||||
let row = Row {
|
||||
depth: depth,
|
||||
cells: None,
|
||||
name: TextCell::paint(self.opts.colours.perms.attribute, format!("{} (len {})", xattr.name, xattr.size)),
|
||||
name: TextCell::paint(self.colours.perms.attribute, format!("{} (len {})", xattr.name, xattr.size)),
|
||||
last: last,
|
||||
};
|
||||
|
||||
self.rows.push(row);
|
||||
}
|
||||
|
||||
pub fn filename(&self, file: File, links: LinkStyle) -> TextCellContents {
|
||||
FileName::new(&file, links, self.opts.classify, &self.opts.colours).paint()
|
||||
pub fn filename(&self, file: &File, links: LinkStyle) -> TextCellContents {
|
||||
FileName::new(file, links, self.classify, &self.colours).paint()
|
||||
}
|
||||
|
||||
pub fn add_file_with_cells(&mut self, cells: Vec<TextCell>, name_cell: TextCell, depth: usize, last: bool) {
|
||||
@ -504,17 +506,17 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> {
|
||||
use output::column::TimeType::*;
|
||||
|
||||
match *column {
|
||||
Column::Permissions => self.permissions_plus(file, xattrs).render(&self.opts.colours),
|
||||
Column::FileSize(fmt) => file.size().render(&self.opts.colours, fmt, &self.env.numeric),
|
||||
Column::Timestamp(Modified) => file.modified_time().render(&self.opts.colours, &self.env.tz, &self.env.date_and_time, &self.env.date_and_year, &self.env.time, self.env.current_year),
|
||||
Column::Timestamp(Created) => file.created_time().render( &self.opts.colours, &self.env.tz, &self.env.date_and_time, &self.env.date_and_year, &self.env.time, self.env.current_year),
|
||||
Column::Timestamp(Accessed) => file.accessed_time().render(&self.opts.colours, &self.env.tz, &self.env.date_and_time, &self.env.date_and_year, &self.env.time, self.env.current_year),
|
||||
Column::HardLinks => file.links().render(&self.opts.colours, &self.env.numeric),
|
||||
Column::Inode => file.inode().render(&self.opts.colours),
|
||||
Column::Blocks => file.blocks().render(&self.opts.colours),
|
||||
Column::User => file.user().render(&self.opts.colours, &*self.env.lock_users()),
|
||||
Column::Group => file.group().render(&self.opts.colours, &*self.env.lock_users()),
|
||||
Column::GitStatus => file.git_status().render(&self.opts.colours),
|
||||
Column::Permissions => self.permissions_plus(file, xattrs).render(&self.colours),
|
||||
Column::FileSize(fmt) => file.size().render(&self.colours, fmt, &self.env.numeric),
|
||||
Column::Timestamp(Modified) => file.modified_time().render(&self.colours, &self.env.tz, &self.env.date_and_time, &self.env.date_and_year, &self.env.time, self.env.current_year),
|
||||
Column::Timestamp(Created) => file.created_time().render( &self.colours, &self.env.tz, &self.env.date_and_time, &self.env.date_and_year, &self.env.time, self.env.current_year),
|
||||
Column::Timestamp(Accessed) => file.accessed_time().render(&self.colours, &self.env.tz, &self.env.date_and_time, &self.env.date_and_year, &self.env.time, self.env.current_year),
|
||||
Column::HardLinks => file.links().render(&self.colours, &self.env.numeric),
|
||||
Column::Inode => file.inode().render(&self.colours),
|
||||
Column::Blocks => file.blocks().render(&self.colours),
|
||||
Column::User => file.user().render(&self.colours, &*self.env.lock_users()),
|
||||
Column::Group => file.group().render(&self.colours, &*self.env.lock_users()),
|
||||
Column::GitStatus => file.git_status().render(&self.colours),
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,7 +556,7 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> {
|
||||
let mut filename = TextCell::default();
|
||||
|
||||
for tree_part in tree_trunk.new_row(row.depth, row.last) {
|
||||
filename.push(self.opts.colours.punctuation.paint(tree_part.ascii_art()), 4);
|
||||
filename.push(self.colours.punctuation.paint(tree_part.ascii_art()), 4);
|
||||
}
|
||||
|
||||
// If any tree characters have been printed, then add an extra
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::io::{Write, Result as IOResult};
|
||||
|
||||
use term_grid as grid;
|
||||
use term_grid as tg;
|
||||
|
||||
use fs::File;
|
||||
use output::colours::Colours;
|
||||
@ -8,42 +8,52 @@ use output::file_name::{FileName, LinkStyle, Classify};
|
||||
|
||||
|
||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||
pub struct Grid {
|
||||
pub struct Options {
|
||||
pub across: bool,
|
||||
pub console_width: usize,
|
||||
pub colours: Colours,
|
||||
pub classify: Classify,
|
||||
}
|
||||
|
||||
impl Grid {
|
||||
pub fn view<W: Write>(&self, files: &[File], w: &mut W) -> IOResult<()> {
|
||||
let direction = if self.across { grid::Direction::LeftToRight }
|
||||
else { grid::Direction::TopToBottom };
|
||||
impl Options {
|
||||
pub fn direction(&self) -> tg::Direction {
|
||||
if self.across { tg::Direction::LeftToRight }
|
||||
else { tg::Direction::TopToBottom }
|
||||
}
|
||||
}
|
||||
|
||||
let mut grid = grid::Grid::new(grid::GridOptions {
|
||||
direction: direction,
|
||||
filling: grid::Filling::Spaces(2),
|
||||
|
||||
pub struct Render<'a> {
|
||||
pub files: Vec<File<'a>>,
|
||||
pub colours: &'a Colours,
|
||||
pub classify: Classify,
|
||||
pub opts: &'a Options,
|
||||
}
|
||||
|
||||
impl<'a> Render<'a> {
|
||||
pub fn render<W: Write>(&self, w: &mut W) -> IOResult<()> {
|
||||
let mut grid = tg::Grid::new(tg::GridOptions {
|
||||
direction: self.opts.direction(),
|
||||
filling: tg::Filling::Spaces(2),
|
||||
});
|
||||
|
||||
grid.reserve(files.len());
|
||||
grid.reserve(self.files.len());
|
||||
|
||||
for file in files.iter() {
|
||||
let filename = FileName::new(file, LinkStyle::JustFilenames, self.classify, &self.colours).paint();
|
||||
for file in self.files.iter() {
|
||||
let filename = FileName::new(file, LinkStyle::JustFilenames, self.classify, self.colours).paint();
|
||||
let width = filename.width();
|
||||
|
||||
grid.add(grid::Cell {
|
||||
grid.add(tg::Cell {
|
||||
contents: filename.strings().to_string(),
|
||||
width: *width,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(display) = grid.fit_into_width(self.console_width) {
|
||||
if let Some(display) = grid.fit_into_width(self.opts.console_width) {
|
||||
write!(w, "{}", display)
|
||||
}
|
||||
else {
|
||||
// File names too long for a grid - drop down to just listing them!
|
||||
for file in files.iter() {
|
||||
let name_cell = FileName::new(file, LinkStyle::JustFilenames, self.classify, &self.colours).paint();
|
||||
for file in self.files.iter() {
|
||||
let name_cell = FileName::new(file, LinkStyle::JustFilenames, self.classify, self.colours).paint();
|
||||
writeln!(w, "{}", name_cell.strings())?;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -10,29 +10,26 @@ use fs::feature::xattr::FileAttributes;
|
||||
|
||||
use output::cell::TextCell;
|
||||
use output::column::Column;
|
||||
use output::details::{Details, Table, Environment};
|
||||
use output::grid::Grid;
|
||||
use output::file_name::LinkStyle;
|
||||
use output::colours::Colours;
|
||||
use output::details::{Table, Environment, Options as DetailsOptions};
|
||||
use output::grid::Options as GridOptions;
|
||||
use output::file_name::{Classify, LinkStyle};
|
||||
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct GridDetails {
|
||||
pub grid: Grid,
|
||||
pub details: Details,
|
||||
pub struct Render<'a> {
|
||||
pub dir: Option<&'a Dir>,
|
||||
pub files: Vec<File<'a>>,
|
||||
pub colours: &'a Colours,
|
||||
pub classify: Classify,
|
||||
pub grid: &'a GridOptions,
|
||||
pub details: &'a DetailsOptions,
|
||||
}
|
||||
|
||||
fn file_has_xattrs(file: &File) -> bool {
|
||||
match file.path.attributes() {
|
||||
Ok(attrs) => !attrs.is_empty(),
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
impl<'a> Render<'a> {
|
||||
pub fn render<W: Write>(&self, w: &mut W) -> IOResult<()> {
|
||||
|
||||
impl GridDetails {
|
||||
pub fn view<W>(&self, dir: Option<&Dir>, files: Vec<File>, w: &mut W) -> IOResult<()>
|
||||
where W: Write {
|
||||
let columns_for_dir = match self.details.columns {
|
||||
Some(cols) => cols.for_dir(dir),
|
||||
Some(cols) => cols.for_dir(self.dir),
|
||||
None => Vec::new(),
|
||||
};
|
||||
|
||||
@ -40,23 +37,23 @@ impl GridDetails {
|
||||
|
||||
let (cells, file_names) = {
|
||||
|
||||
let first_table = self.make_table(env.clone(), &*columns_for_dir);
|
||||
let first_table = self.make_table(env.clone(), &*columns_for_dir, self.colours, self.classify);
|
||||
|
||||
let cells = files.iter()
|
||||
let cells = self.files.iter()
|
||||
.map(|file| first_table.cells_for_file(file, file_has_xattrs(file)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let file_names = files.into_iter()
|
||||
let file_names = self.files.iter()
|
||||
.map(|file| first_table.filename(file, LinkStyle::JustFilenames).promote())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
(cells, file_names)
|
||||
};
|
||||
|
||||
let mut last_working_table = self.make_grid(env.clone(), 1, &columns_for_dir, &file_names, cells.clone());
|
||||
let mut last_working_table = self.make_grid(env.clone(), 1, &columns_for_dir, &file_names, cells.clone(), self.colours, self.classify);
|
||||
|
||||
for column_count in 2.. {
|
||||
let grid = self.make_grid(env.clone(), column_count, &columns_for_dir, &file_names, cells.clone());
|
||||
let grid = self.make_grid(env.clone(), column_count, &columns_for_dir, &file_names, cells.clone(), self.colours, self.classify);
|
||||
|
||||
let the_grid_fits = {
|
||||
let d = grid.fit_into_columns(column_count);
|
||||
@ -74,12 +71,11 @@ impl GridDetails {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make_table<'a>(&'a self, env: Arc<Environment<UsersCache>>, columns_for_dir: &'a [Column]) -> Table<UsersCache> {
|
||||
fn make_table<'g>(&'g self, env: Arc<Environment<UsersCache>>, columns_for_dir: &'g [Column], colours: &'g Colours, classify: Classify) -> Table<UsersCache> {
|
||||
let mut table = Table {
|
||||
columns: columns_for_dir,
|
||||
opts: &self.details,
|
||||
env: env,
|
||||
|
||||
colours, classify, env,
|
||||
xattr: self.details.xattr,
|
||||
rows: Vec::new(),
|
||||
};
|
||||
|
||||
@ -87,10 +83,10 @@ impl GridDetails {
|
||||
table
|
||||
}
|
||||
|
||||
fn make_grid<'a>(&'a self, env: Arc<Environment<UsersCache>>, column_count: usize, columns_for_dir: &'a [Column], file_names: &[TextCell], cells: Vec<Vec<TextCell>>) -> grid::Grid {
|
||||
fn make_grid<'g>(&'g self, env: Arc<Environment<UsersCache>>, column_count: usize, columns_for_dir: &'g [Column], file_names: &[TextCell], cells: Vec<Vec<TextCell>>, colours: &'g Colours, classify: Classify) -> grid::Grid {
|
||||
let mut tables = Vec::new();
|
||||
for _ in 0 .. column_count {
|
||||
tables.push(self.make_table(env.clone(), columns_for_dir));
|
||||
tables.push(self.make_table(env.clone(), columns_for_dir, colours, classify));
|
||||
}
|
||||
|
||||
let mut num_cells = cells.len();
|
||||
@ -159,3 +155,11 @@ fn divide_rounding_up(a: usize, b: usize) -> usize {
|
||||
if a % b != 0 { result += 1; }
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
fn file_has_xattrs(file: &File) -> bool {
|
||||
match file.path.attributes() {
|
||||
Ok(attrs) => !attrs.is_empty(),
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
@ -8,19 +8,24 @@ use output::file_name::{FileName, LinkStyle, Classify};
|
||||
use super::colours::Colours;
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Lines {
|
||||
pub colours: Colours,
|
||||
/// The lines view literally just displays each file, line-by-line.
|
||||
pub struct Render<'a> {
|
||||
pub files: Vec<File<'a>>,
|
||||
pub colours: &'a Colours,
|
||||
pub classify: Classify,
|
||||
}
|
||||
|
||||
/// The lines view literally just displays each file, line-by-line.
|
||||
impl Lines {
|
||||
pub fn view<W: Write>(&self, files: Vec<File>, w: &mut W) -> IOResult<()> {
|
||||
for file in files {
|
||||
let name_cell = FileName::new(&file, LinkStyle::FullLinkPaths, self.classify, &self.colours).paint();
|
||||
impl<'a> Render<'a> {
|
||||
pub fn render<W: Write>(&self, w: &mut W) -> IOResult<()> {
|
||||
for file in &self.files {
|
||||
let name_cell = self.render_file(file).paint();
|
||||
writeln!(w, "{}", ANSIStrings(&name_cell))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_file<'f>(&self, file: &'f File<'a>) -> FileName<'f, 'a> {
|
||||
FileName::new(file, LinkStyle::FullLinkPaths, self.classify, self.colours)
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,16 @@
|
||||
pub use self::cell::{TextCell, TextCellContents, DisplayWidth};
|
||||
pub use self::colours::Colours;
|
||||
pub use self::details::Details;
|
||||
pub use self::grid_details::GridDetails;
|
||||
pub use self::grid::Grid;
|
||||
pub use self::lines::Lines;
|
||||
pub use self::escape::escape;
|
||||
|
||||
mod grid;
|
||||
pub mod details;
|
||||
mod lines;
|
||||
mod grid_details;
|
||||
pub mod column;
|
||||
pub mod details;
|
||||
pub mod file_name;
|
||||
pub mod grid_details;
|
||||
pub mod grid;
|
||||
pub mod lines;
|
||||
|
||||
mod cell;
|
||||
mod colours;
|
||||
mod tree;
|
||||
pub mod file_name;
|
||||
mod escape;
|
||||
mod render;
|
||||
mod tree;
|
||||
|
@ -15,7 +15,7 @@ impl f::Blocks {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use output::details::Details;
|
||||
use output::colours::Colours;
|
||||
use output::cell::TextCell;
|
||||
use fs::fields as f;
|
||||
|
||||
@ -24,21 +24,21 @@ pub mod test {
|
||||
|
||||
#[test]
|
||||
fn blocklessness() {
|
||||
let mut details = Details::default();
|
||||
details.colours.punctuation = Green.italic();
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Green.italic();
|
||||
|
||||
let blox = f::Blocks::None;
|
||||
let expected = TextCell::blank(Green.italic());
|
||||
assert_eq!(expected, blox.render(&details.colours).into());
|
||||
assert_eq!(expected, blox.render(&colours).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blockfulity() {
|
||||
let mut details = Details::default();
|
||||
details.colours.blocks = Red.blink();
|
||||
let mut colours = Colours::default();
|
||||
colours.blocks = Red.blink();
|
||||
|
||||
let blox = f::Blocks::Some(3005);
|
||||
let expected = TextCell::paint_str(Red.blink(), "3005");
|
||||
assert_eq!(expected, blox.render(&details.colours).into());
|
||||
assert_eq!(expected, blox.render(&colours).into());
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ impl f::GitStatus {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use output::details::Details;
|
||||
use output::colours::Colours;
|
||||
use output::cell::{TextCell, DisplayWidth};
|
||||
use fs::fields as f;
|
||||
|
||||
@ -42,8 +42,8 @@ pub mod test {
|
||||
|
||||
#[test]
|
||||
fn git_blank() {
|
||||
let mut details = Details::default();
|
||||
details.colours.punctuation = Fixed(44).normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Fixed(44).normal();
|
||||
|
||||
let stati = f::Git {
|
||||
staged: f::GitStatus::NotModified,
|
||||
@ -58,15 +58,15 @@ pub mod test {
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, stati.render(&details.colours).into())
|
||||
assert_eq!(expected, stati.render(&colours).into())
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn git_new_changed() {
|
||||
let mut details = Details::default();
|
||||
details.colours.git.new = Red.normal();
|
||||
details.colours.git.modified = Purple.normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.git.new = Red.normal();
|
||||
colours.git.modified = Purple.normal();
|
||||
|
||||
let stati = f::Git {
|
||||
staged: f::GitStatus::New,
|
||||
@ -81,6 +81,6 @@ pub mod test {
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, stati.render(&details.colours).into())
|
||||
assert_eq!(expected, stati.render(&colours).into())
|
||||
}
|
||||
}
|
||||
|
@ -32,10 +32,9 @@ impl f::Group {
|
||||
#[cfg(test)]
|
||||
#[allow(unused_results)]
|
||||
pub mod test {
|
||||
use output::details::Details;
|
||||
|
||||
use fs::fields as f;
|
||||
use output::cell::TextCell;
|
||||
use output::colours::Colours;
|
||||
|
||||
use users::{User, Group};
|
||||
use users::mock::MockUsers;
|
||||
@ -45,33 +44,33 @@ pub mod test {
|
||||
|
||||
#[test]
|
||||
fn named() {
|
||||
let mut details = Details::default();
|
||||
details.colours.users.group_not_yours = Fixed(101).normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.users.group_not_yours = Fixed(101).normal();
|
||||
|
||||
let mut users = MockUsers::with_current_uid(1000);
|
||||
users.add_group(Group::new(100, "folk"));
|
||||
|
||||
let group = f::Group(100);
|
||||
let expected = TextCell::paint_str(Fixed(101).normal(), "folk");
|
||||
assert_eq!(expected, group.render(&details.colours, &users))
|
||||
assert_eq!(expected, group.render(&colours, &users))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unnamed() {
|
||||
let mut details = Details::default();
|
||||
details.colours.users.group_not_yours = Fixed(87).normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.users.group_not_yours = Fixed(87).normal();
|
||||
|
||||
let users = MockUsers::with_current_uid(1000);
|
||||
|
||||
let group = f::Group(100);
|
||||
let expected = TextCell::paint_str(Fixed(87).normal(), "100");
|
||||
assert_eq!(expected, group.render(&details.colours, &users));
|
||||
assert_eq!(expected, group.render(&colours, &users));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn primary() {
|
||||
let mut details = Details::default();
|
||||
details.colours.users.group_yours = Fixed(64).normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.users.group_yours = Fixed(64).normal();
|
||||
|
||||
let mut users = MockUsers::with_current_uid(2);
|
||||
users.add_user(User::new(2, "eve", 100));
|
||||
@ -79,13 +78,13 @@ pub mod test {
|
||||
|
||||
let group = f::Group(100);
|
||||
let expected = TextCell::paint_str(Fixed(64).normal(), "folk");
|
||||
assert_eq!(expected, group.render(&details.colours, &users))
|
||||
assert_eq!(expected, group.render(&colours, &users))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn secondary() {
|
||||
let mut details = Details::default();
|
||||
details.colours.users.group_yours = Fixed(31).normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.users.group_yours = Fixed(31).normal();
|
||||
|
||||
let mut users = MockUsers::with_current_uid(2);
|
||||
users.add_user(User::new(2, "eve", 666));
|
||||
@ -95,16 +94,16 @@ pub mod test {
|
||||
|
||||
let group = f::Group(100);
|
||||
let expected = TextCell::paint_str(Fixed(31).normal(), "folk");
|
||||
assert_eq!(expected, group.render(&details.colours, &users))
|
||||
assert_eq!(expected, group.render(&colours, &users))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overflow() {
|
||||
let mut details = Details::default();
|
||||
details.colours.users.group_not_yours = Blue.underline();
|
||||
let mut colours = Colours::default();
|
||||
colours.users.group_not_yours = Blue.underline();
|
||||
|
||||
let group = f::Group(2_147_483_648);
|
||||
let expected = TextCell::paint_str(Blue.underline(), "2147483648");
|
||||
assert_eq!(expected, group.render(&details.colours, &MockUsers::with_current_uid(0)));
|
||||
assert_eq!(expected, group.render(&colours, &MockUsers::with_current_uid(0)));
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ impl f::Inode {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use output::details::Details;
|
||||
use output::colours::Colours;
|
||||
use output::cell::TextCell;
|
||||
use fs::fields as f;
|
||||
|
||||
@ -21,11 +21,11 @@ pub mod test {
|
||||
|
||||
#[test]
|
||||
fn blocklessness() {
|
||||
let mut details = Details::default();
|
||||
details.colours.inode = Cyan.underline();
|
||||
let mut colours = Colours::default();
|
||||
colours.inode = Cyan.underline();
|
||||
|
||||
let io = f::Inode(1414213);
|
||||
let expected = TextCell::paint_str(Cyan.underline(), "1414213");
|
||||
assert_eq!(expected, io.render(&details.colours).into());
|
||||
assert_eq!(expected, io.render(&colours).into());
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ impl f::Links {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use output::details::Details;
|
||||
use output::colours::Colours;
|
||||
use output::cell::{TextCell, DisplayWidth};
|
||||
use fs::fields as f;
|
||||
|
||||
@ -27,8 +27,8 @@ pub mod test {
|
||||
|
||||
#[test]
|
||||
fn regular_file() {
|
||||
let mut details = Details::default();
|
||||
details.colours.links.normal = Blue.normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.links.normal = Blue.normal();
|
||||
|
||||
let stati = f::Links {
|
||||
count: 1,
|
||||
@ -40,13 +40,13 @@ pub mod test {
|
||||
contents: vec![ Blue.paint("1") ].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, stati.render(&details.colours, &locale::Numeric::english()).into());
|
||||
assert_eq!(expected, stati.render(&colours, &locale::Numeric::english()).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regular_directory() {
|
||||
let mut details = Details::default();
|
||||
details.colours.links.normal = Blue.normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.links.normal = Blue.normal();
|
||||
|
||||
let stati = f::Links {
|
||||
count: 3005,
|
||||
@ -58,13 +58,13 @@ pub mod test {
|
||||
contents: vec![ Blue.paint("3,005") ].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, stati.render(&details.colours, &locale::Numeric::english()).into());
|
||||
assert_eq!(expected, stati.render(&colours, &locale::Numeric::english()).into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn popular_file() {
|
||||
let mut details = Details::default();
|
||||
details.colours.links.multi_link_file = Blue.on(Red);
|
||||
let mut colours = Colours::default();
|
||||
colours.links.multi_link_file = Blue.on(Red);
|
||||
|
||||
let stati = f::Links {
|
||||
count: 3005,
|
||||
@ -76,6 +76,6 @@ pub mod test {
|
||||
contents: vec![ Blue.on(Red).paint("3,005") ].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, stati.render(&details.colours, &locale::Numeric::english()).into());
|
||||
assert_eq!(expected, stati.render(&colours, &locale::Numeric::english()).into());
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ impl f::Type {
|
||||
#[cfg(test)]
|
||||
#[allow(unused_results)]
|
||||
pub mod test {
|
||||
use output::details::Details;
|
||||
use output::colours::Colours;
|
||||
use output::cell::TextCellContents;
|
||||
use fs::fields as f;
|
||||
|
||||
@ -101,8 +101,8 @@ pub mod test {
|
||||
|
||||
#[test]
|
||||
fn negate() {
|
||||
let mut details = Details::default();
|
||||
details.colours.punctuation = Fixed(11).normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Fixed(11).normal();
|
||||
|
||||
let bits = f::Permissions {
|
||||
user_read: false, user_write: false, user_execute: false, setuid: false,
|
||||
@ -116,24 +116,24 @@ pub mod test {
|
||||
Fixed(11).paint("-"), Fixed(11).paint("-"), Fixed(11).paint("-"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&details.colours, false).into())
|
||||
assert_eq!(expected, bits.render(&colours, false).into())
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn affirm() {
|
||||
let mut details = Details::default();
|
||||
details.colours.perms.user_read = Fixed(101).normal();
|
||||
details.colours.perms.user_write = Fixed(102).normal();
|
||||
details.colours.perms.user_execute_file = Fixed(103).normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.perms.user_read = Fixed(101).normal();
|
||||
colours.perms.user_write = Fixed(102).normal();
|
||||
colours.perms.user_execute_file = Fixed(103).normal();
|
||||
|
||||
details.colours.perms.group_read = Fixed(104).normal();
|
||||
details.colours.perms.group_write = Fixed(105).normal();
|
||||
details.colours.perms.group_execute = Fixed(106).normal();
|
||||
colours.perms.group_read = Fixed(104).normal();
|
||||
colours.perms.group_write = Fixed(105).normal();
|
||||
colours.perms.group_execute = Fixed(106).normal();
|
||||
|
||||
details.colours.perms.other_read = Fixed(107).normal();
|
||||
details.colours.perms.other_write = Fixed(108).normal();
|
||||
details.colours.perms.other_execute = Fixed(109).normal();
|
||||
colours.perms.other_read = Fixed(107).normal();
|
||||
colours.perms.other_write = Fixed(108).normal();
|
||||
colours.perms.other_execute = Fixed(109).normal();
|
||||
|
||||
let bits = f::Permissions {
|
||||
user_read: true, user_write: true, user_execute: true, setuid: false,
|
||||
@ -147,16 +147,16 @@ pub mod test {
|
||||
Fixed(107).paint("r"), Fixed(108).paint("w"), Fixed(109).paint("x"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&details.colours, true).into())
|
||||
assert_eq!(expected, bits.render(&colours, true).into())
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn specials() {
|
||||
let mut details = Details::default();
|
||||
details.colours.punctuation = Fixed(11).normal();
|
||||
details.colours.perms.special_user_file = Fixed(77).normal();
|
||||
details.colours.perms.special_other = Fixed(88).normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Fixed(11).normal();
|
||||
colours.perms.special_user_file = Fixed(77).normal();
|
||||
colours.perms.special_other = Fixed(88).normal();
|
||||
|
||||
let bits = f::Permissions {
|
||||
user_read: false, user_write: false, user_execute: true, setuid: true,
|
||||
@ -170,15 +170,15 @@ pub mod test {
|
||||
Fixed(11).paint("-"), Fixed(11).paint("-"), Fixed(88).paint("t"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&details.colours, true).into())
|
||||
assert_eq!(expected, bits.render(&colours, true).into())
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn extra_specials() {
|
||||
let mut details = Details::default();
|
||||
details.colours.punctuation = Fixed(11).normal();
|
||||
details.colours.perms.special_other = Fixed(88).normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Fixed(11).normal();
|
||||
colours.perms.special_other = Fixed(88).normal();
|
||||
|
||||
let bits = f::Permissions {
|
||||
user_read: false, user_write: false, user_execute: false, setuid: true,
|
||||
@ -192,6 +192,6 @@ pub mod test {
|
||||
Fixed(11).paint("-"), Fixed(11).paint("-"), Fixed(88).paint("T"),
|
||||
]);
|
||||
|
||||
assert_eq!(expected, bits.render(&details.colours, true).into())
|
||||
assert_eq!(expected, bits.render(&colours, true).into())
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ impl f::DeviceIDs {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use output::details::Details;
|
||||
use output::colours::Colours;
|
||||
use output::column::SizeFormat;
|
||||
use output::cell::{TextCell, DisplayWidth};
|
||||
use fs::fields as f;
|
||||
@ -78,20 +78,20 @@ pub mod test {
|
||||
|
||||
#[test]
|
||||
fn directory() {
|
||||
let mut details = Details::default();
|
||||
details.colours.punctuation = Green.italic();
|
||||
let mut colours = Colours::default();
|
||||
colours.punctuation = Green.italic();
|
||||
|
||||
let directory = f::Size::None;
|
||||
let expected = TextCell::blank(Green.italic());
|
||||
assert_eq!(expected, directory.render(&details.colours, SizeFormat::JustBytes, &locale::Numeric::english()))
|
||||
assert_eq!(expected, directory.render(&colours, SizeFormat::JustBytes, &locale::Numeric::english()))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn file_decimal() {
|
||||
let mut details = Details::default();
|
||||
details.colours.size.numbers = Blue.on(Red);
|
||||
details.colours.size.unit = Yellow.bold();
|
||||
let mut colours = Colours::default();
|
||||
colours.size.numbers = Blue.on(Red);
|
||||
colours.size.unit = Yellow.bold();
|
||||
|
||||
let directory = f::Size::Some(2_100_000);
|
||||
let expected = TextCell {
|
||||
@ -102,15 +102,15 @@ pub mod test {
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, directory.render(&details.colours, SizeFormat::DecimalBytes, &locale::Numeric::english()))
|
||||
assert_eq!(expected, directory.render(&colours, SizeFormat::DecimalBytes, &locale::Numeric::english()))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn file_binary() {
|
||||
let mut details = Details::default();
|
||||
details.colours.size.numbers = Blue.on(Red);
|
||||
details.colours.size.unit = Yellow.bold();
|
||||
let mut colours = Colours::default();
|
||||
colours.size.numbers = Blue.on(Red);
|
||||
colours.size.unit = Yellow.bold();
|
||||
|
||||
let directory = f::Size::Some(1_048_576);
|
||||
let expected = TextCell {
|
||||
@ -121,14 +121,14 @@ pub mod test {
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, directory.render(&details.colours, SizeFormat::BinaryBytes, &locale::Numeric::english()))
|
||||
assert_eq!(expected, directory.render(&colours, SizeFormat::BinaryBytes, &locale::Numeric::english()))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn file_bytes() {
|
||||
let mut details = Details::default();
|
||||
details.colours.size.numbers = Blue.on(Red);
|
||||
let mut colours = Colours::default();
|
||||
colours.size.numbers = Blue.on(Red);
|
||||
|
||||
let directory = f::Size::Some(1048576);
|
||||
let expected = TextCell {
|
||||
@ -138,16 +138,16 @@ pub mod test {
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, directory.render(&details.colours, SizeFormat::JustBytes, &locale::Numeric::english()))
|
||||
assert_eq!(expected, directory.render(&colours, SizeFormat::JustBytes, &locale::Numeric::english()))
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn device_ids() {
|
||||
let mut details = Details::default();
|
||||
details.colours.size.major = Blue.on(Red);
|
||||
details.colours.punctuation = Green.italic();
|
||||
details.colours.size.minor = Cyan.on(Yellow);
|
||||
let mut colours = Colours::default();
|
||||
colours.size.major = Blue.on(Red);
|
||||
colours.punctuation = Green.italic();
|
||||
colours.size.minor = Cyan.on(Yellow);
|
||||
|
||||
let directory = f::Size::DeviceIDs(f::DeviceIDs { major: 10, minor: 80 });
|
||||
let expected = TextCell {
|
||||
@ -159,6 +159,6 @@ pub mod test {
|
||||
].into(),
|
||||
};
|
||||
|
||||
assert_eq!(expected, directory.render(&details.colours, SizeFormat::JustBytes, &locale::Numeric::english()))
|
||||
assert_eq!(expected, directory.render(&colours, SizeFormat::JustBytes, &locale::Numeric::english()))
|
||||
}
|
||||
}
|
||||
|
@ -21,10 +21,9 @@ impl f::User {
|
||||
#[cfg(test)]
|
||||
#[allow(unused_results)]
|
||||
pub mod test {
|
||||
use output::details::Details;
|
||||
|
||||
use fs::fields as f;
|
||||
use output::cell::TextCell;
|
||||
use output::colours::Colours;
|
||||
|
||||
use users::User;
|
||||
use users::mock::MockUsers;
|
||||
@ -32,59 +31,59 @@ pub mod test {
|
||||
|
||||
#[test]
|
||||
fn named() {
|
||||
let mut details = Details::default();
|
||||
details.colours.users.user_you = Red.bold();
|
||||
let mut colours = Colours::default();
|
||||
colours.users.user_you = Red.bold();
|
||||
|
||||
let mut users = MockUsers::with_current_uid(1000);
|
||||
users.add_user(User::new(1000, "enoch", 100));
|
||||
|
||||
let user = f::User(1000);
|
||||
let expected = TextCell::paint_str(Red.bold(), "enoch");
|
||||
assert_eq!(expected, user.render(&details.colours, &users))
|
||||
assert_eq!(expected, user.render(&colours, &users))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unnamed() {
|
||||
let mut details = Details::default();
|
||||
details.colours.users.user_you = Cyan.bold();
|
||||
let mut colours = Colours::default();
|
||||
colours.users.user_you = Cyan.bold();
|
||||
|
||||
let users = MockUsers::with_current_uid(1000);
|
||||
|
||||
let user = f::User(1000);
|
||||
let expected = TextCell::paint_str(Cyan.bold(), "1000");
|
||||
assert_eq!(expected, user.render(&details.colours, &users));
|
||||
assert_eq!(expected, user.render(&colours, &users));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn different_named() {
|
||||
let mut details = Details::default();
|
||||
details.colours.users.user_someone_else = Green.bold();
|
||||
let mut colours = Colours::default();
|
||||
colours.users.user_someone_else = Green.bold();
|
||||
|
||||
let mut users = MockUsers::with_current_uid(0);
|
||||
users.add_user(User::new(1000, "enoch", 100));
|
||||
|
||||
let user = f::User(1000);
|
||||
let expected = TextCell::paint_str(Green.bold(), "enoch");
|
||||
assert_eq!(expected, user.render(&details.colours, &users));
|
||||
assert_eq!(expected, user.render(&colours, &users));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn different_unnamed() {
|
||||
let mut details = Details::default();
|
||||
details.colours.users.user_someone_else = Red.normal();
|
||||
let mut colours = Colours::default();
|
||||
colours.users.user_someone_else = Red.normal();
|
||||
|
||||
let user = f::User(1000);
|
||||
let expected = TextCell::paint_str(Red.normal(), "1000");
|
||||
assert_eq!(expected, user.render(&details.colours, &MockUsers::with_current_uid(0)));
|
||||
assert_eq!(expected, user.render(&colours, &MockUsers::with_current_uid(0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overflow() {
|
||||
let mut details = Details::default();
|
||||
details.colours.users.user_someone_else = Blue.underline();
|
||||
let mut colours = Colours::default();
|
||||
colours.users.user_someone_else = Blue.underline();
|
||||
|
||||
let user = f::User(2_147_483_648);
|
||||
let expected = TextCell::paint_str(Blue.underline(), "2147483648");
|
||||
assert_eq!(expected, user.render(&details.colours, &MockUsers::with_current_uid(0)));
|
||||
assert_eq!(expected, user.render(&colours, &MockUsers::with_current_uid(0)));
|
||||
}
|
||||
}
|
||||
|
39
xtests/files_l_bw
Normal file
39
xtests/files_l_bw
Normal file
@ -0,0 +1,39 @@
|
||||
.rw-r--r-- 1.0k cassowary 1 Jan 12:34 1_KiB
|
||||
.rw-r--r-- 1.0M cassowary 1 Jan 12:34 1_MiB
|
||||
.rw-r--r-- 1 cassowary 1 Jan 12:34 1_bytes
|
||||
.rw-r--r-- 2.0k cassowary 1 Jan 12:34 2_KiB
|
||||
.rw-r--r-- 2.1M cassowary 1 Jan 12:34 2_MiB
|
||||
.rw-r--r-- 2 cassowary 1 Jan 12:34 2_bytes
|
||||
.rw-r--r-- 3.1k cassowary 1 Jan 12:34 3_KiB
|
||||
.rw-r--r-- 3.1M cassowary 1 Jan 12:34 3_MiB
|
||||
.rw-r--r-- 3 cassowary 1 Jan 12:34 3_bytes
|
||||
.rw-r--r-- 4.1k cassowary 1 Jan 12:34 4_KiB
|
||||
.rw-r--r-- 4.2M cassowary 1 Jan 12:34 4_MiB
|
||||
.rw-r--r-- 4 cassowary 1 Jan 12:34 4_bytes
|
||||
.rw-r--r-- 5.1k cassowary 1 Jan 12:34 5_KiB
|
||||
.rw-r--r-- 5.2M cassowary 1 Jan 12:34 5_MiB
|
||||
.rw-r--r-- 5 cassowary 1 Jan 12:34 5_bytes
|
||||
.rw-r--r-- 6.1k cassowary 1 Jan 12:34 6_KiB
|
||||
.rw-r--r-- 6.3M cassowary 1 Jan 12:34 6_MiB
|
||||
.rw-r--r-- 6 cassowary 1 Jan 12:34 6_bytes
|
||||
.rw-r--r-- 7.2k cassowary 1 Jan 12:34 7_KiB
|
||||
.rw-r--r-- 7.3M cassowary 1 Jan 12:34 7_MiB
|
||||
.rw-r--r-- 7 cassowary 1 Jan 12:34 7_bytes
|
||||
.rw-r--r-- 8.2k cassowary 1 Jan 12:34 8_KiB
|
||||
.rw-r--r-- 8.4M cassowary 1 Jan 12:34 8_MiB
|
||||
.rw-r--r-- 8 cassowary 1 Jan 12:34 8_bytes
|
||||
.rw-r--r-- 9.2k cassowary 1 Jan 12:34 9_KiB
|
||||
.rw-r--r-- 9.4M cassowary 1 Jan 12:34 9_MiB
|
||||
.rw-r--r-- 9 cassowary 1 Jan 12:34 9_bytes
|
||||
.rw-r--r-- 10k cassowary 1 Jan 12:34 10_KiB
|
||||
.rw-r--r-- 10M cassowary 1 Jan 12:34 10_MiB
|
||||
.rw-r--r-- 10 cassowary 1 Jan 12:34 10_bytes
|
||||
.rw-r--r-- 11k cassowary 1 Jan 12:34 11_KiB
|
||||
.rw-r--r-- 11M cassowary 1 Jan 12:34 11_MiB
|
||||
.rw-r--r-- 11 cassowary 1 Jan 12:34 11_bytes
|
||||
.rw-r--r-- 12k cassowary 1 Jan 12:34 12_KiB
|
||||
.rw-r--r-- 12M cassowary 1 Jan 12:34 12_MiB
|
||||
.rw-r--r-- 12 cassowary 1 Jan 12:34 12_bytes
|
||||
.rw-r--r-- 13k cassowary 1 Jan 12:34 13_KiB
|
||||
.rw-r--r-- 13M cassowary 1 Jan 12:34 13_MiB
|
||||
.rw-r--r-- 13 cassowary 1 Jan 12:34 13_bytes
|
@ -2,14 +2,17 @@
|
||||
set +xe
|
||||
|
||||
|
||||
# The exa binary we want to run
|
||||
exa="$HOME/target/debug/exa --colour=always"
|
||||
# The exa binary
|
||||
exa_binary="$HOME/target/debug/exa"
|
||||
|
||||
# The exa command that ends up being run
|
||||
exa="$exa_binary --colour=always"
|
||||
|
||||
# Directory containing our awkward testcase files
|
||||
testcases=/testcases
|
||||
testcases="/testcases"
|
||||
|
||||
# Directory containing existing test results to compare against
|
||||
results=/vagrant/xtests
|
||||
results="/vagrant/xtests"
|
||||
|
||||
|
||||
# Check that no files were created more than a year ago.
|
||||
@ -25,7 +28,7 @@ $exa $testcases/files -lhb | diff -q - $results/files_lhb || exit 1
|
||||
$exa $testcases/files -lhB | diff -q - $results/files_lhb2 || exit 1
|
||||
$exa $testcases/attributes/dirs/empty-with-attribute -lh | diff -q - $results/empty || exit 1
|
||||
|
||||
$exa $testcases/files -l --color-scale | diff -q - $results/files_l_scale || exit 1
|
||||
$exa --color-scale $testcases/files -l | diff -q - $results/files_l_scale || exit 1
|
||||
|
||||
|
||||
# Grid view tests
|
||||
@ -105,6 +108,14 @@ COLUMNS=80 $exa $testcases/links 2>&1 | diff -q - $results/links || ex
|
||||
$exa $testcases/links/* -1 | diff -q - $results/links_1_files || exit 1
|
||||
|
||||
|
||||
# Colours and terminals
|
||||
# Just because COLUMNS is present, doesn’t mean output is to a terminal
|
||||
COLUMNS=80 $exa_binary $testcases/files -l | diff -q - $results/files_l_bw || exit 1
|
||||
COLUMNS=80 $exa_binary --colour=always $testcases/files -l | diff -q - $results/files_l || exit 1
|
||||
COLUMNS=80 $exa_binary --colour=never $testcases/files -l | diff -q - $results/files_l_bw || exit 1
|
||||
COLUMNS=80 $exa_binary --colour=automatic $testcases/files -l | diff -q - $results/files_l_bw || exit 1
|
||||
|
||||
|
||||
# Git
|
||||
$exa $testcases/git/additions -l --git 2>&1 | diff -q - $results/git_additions || exit 1
|
||||
$exa $testcases/git/edits -l --git 2>&1 | diff -q - $results/git_edits || exit 1
|
||||
|
Loading…
Reference in New Issue
Block a user