Change the way columns are created

You can now have different columns per directory. So now, the Git column only appears when there's a Git repository in the current directory.
This commit is contained in:
Ben S 2015-01-28 22:02:25 +00:00
parent 947087567c
commit b0cdd17b97
3 changed files with 65 additions and 41 deletions

View File

@ -56,7 +56,7 @@ fn exa(options: &Options) {
let mut first = files.is_empty();
if !files.is_empty() {
options.view(files);
options.view(None, files);
}
for dir_name in dirs.iter() {
@ -68,7 +68,7 @@ fn exa(options: &Options) {
}
match Dir::readdir(Path::new(dir_name.clone())) {
Ok(dir) => {
Ok(ref dir) => {
let unsorted_files = dir.files();
let files: Vec<File> = options.transform_files(unsorted_files);
@ -76,7 +76,7 @@ fn exa(options: &Options) {
println!("{}:", dir_name);
}
options.view(files);
options.view(Some(dir), files);
}
Err(e) => {
println!("{}: {}", dir_name, e);

View File

@ -1,6 +1,7 @@
extern crate getopts;
extern crate natord;
use dir::Dir;
use file::File;
use column::{Column, SizeFormat};
use column::Column::*;
@ -78,8 +79,8 @@ impl Options {
}
/// Display the files using this Option's View.
pub fn view(&self, files: Vec<File>) {
self.view.view(files)
pub fn view(&self, dir: Option<&Dir>, files: Vec<File>) {
self.view.view(dir, files)
}
/// Transform the files (sorting, reversing, filtering) before listing them.
@ -187,7 +188,7 @@ fn view(matches: &getopts::Matches) -> Result<View, Misfire> {
Err(Misfire::Useless("oneline", true, "long"))
}
else {
Ok(View::Details(try!(columns(matches)), matches.opt_present("header")))
Ok(View::Details(try!(Columns::new(matches)), matches.opt_present("header")))
}
}
else if matches.opt_present("binary") {
@ -237,40 +238,62 @@ fn file_size(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
}
}
/// Turns the Getopts results object into a list of columns for the columns
/// view, depending on the passed-in command-line arguments.
fn columns(matches: &getopts::Matches) -> Result<Vec<Column>, Misfire> {
let mut columns = vec![];
#[derive(PartialEq, Copy, Debug)]
pub struct Columns {
size_format: SizeFormat,
inode: bool,
links: bool,
blocks: bool,
group: bool,
}
if matches.opt_present("inode") {
columns.push(Inode);
impl Columns {
pub fn new(matches: &getopts::Matches) -> Result<Columns, Misfire> {
Ok(Columns {
size_format: try!(file_size(matches)),
inode: matches.opt_present("inode"),
links: matches.opt_present("links"),
blocks: matches.opt_present("blocks"),
group: matches.opt_present("group"),
})
}
columns.push(Permissions);
pub fn for_dir(&self, dir: Option<&Dir>) -> Vec<Column> {
let mut columns = vec![];
if matches.opt_present("links") {
columns.push(HardLinks);
if self.inode {
columns.push(Inode);
}
columns.push(Permissions);
if self.links {
columns.push(HardLinks);
}
columns.push(FileSize(self.size_format));
if self.blocks {
columns.push(Blocks);
}
columns.push(User);
if self.group {
columns.push(Group);
}
if cfg!(feature="git") {
if let Some(d) = dir {
if d.has_git_repo() {
columns.push(GitStatus);
}
}
}
columns.push(FileName);
columns
}
// Fail early here if two file size flags are given
columns.push(FileSize(try!(file_size(matches))));
if matches.opt_present("blocks") {
columns.push(Blocks);
}
columns.push(User);
if matches.opt_present("group") {
columns.push(Group);
}
if cfg!(feature="git") {
columns.push(GitStatus);
}
columns.push(FileName);
Ok(columns)
}
#[cfg(test)]
@ -373,5 +396,4 @@ mod test {
let opts = Options::getopts(&[ "--blocks".to_string() ]);
assert_eq!(opts.unwrap_err(), Misfire::Useless("blocks", false, "long"))
}
}

View File

@ -3,23 +3,25 @@ use std::iter::{AdditiveIterator, repeat};
use column::{Column, Cell};
use column::Alignment::Left;
use dir::Dir;
use file::File;
use options::Columns;
use users::OSUsers;
use ansi_term::Style::Plain;
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Copy, Debug)]
pub enum View {
Details(Vec<Column>, bool),
Details(Columns, bool),
Lines,
Grid(bool, usize),
}
impl View {
pub fn view(&self, files: Vec<File>) {
pub fn view(&self, dir: Option<&Dir>, files: Vec<File>) {
match *self {
View::Grid(across, width) => grid_view(across, width, files),
View::Details(ref cols, header) => details_view(cols, files, header),
View::Details(ref cols, header) => details_view(&*cols.for_dir(dir), files, header),
View::Lines => lines_view(files),
}
}
@ -120,7 +122,7 @@ fn grid_view(across: bool, console_width: usize, files: Vec<File>) {
}
}
fn details_view(columns: &Vec<Column>, files: Vec<File>, header: bool) {
fn details_view(columns: &[Column], files: Vec<File>, header: bool) {
// The output gets formatted into columns, which looks nicer. To
// do this, we have to write the results into a table, instead of
// displaying each file immediately, then calculating the maximum