mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-29 23:23:53 +00:00
Merge branch 'recursion'
This commit is contained in:
commit
7acc1b09d5
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -2,17 +2,17 @@
|
|||||||
name = "exa"
|
name = "exa"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"getopts 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"getopts 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"git2 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"git2 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"natord 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"natord 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"number_prefix 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"number_prefix 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"users 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"users 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ansi_term"
|
name = "ansi_term"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"regex 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -26,7 +26,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getopts"
|
name = "getopts"
|
||||||
version = "0.1.4"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -55,7 +55,7 @@ name = "libressl-pnacl-sys"
|
|||||||
version = "2.1.4"
|
version = "2.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pnacl-build-helper 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pnacl-build-helper 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -83,12 +83,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "natord"
|
name = "natord"
|
||||||
version = "1.0.6"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "number_prefix"
|
name = "number_prefix"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -107,7 +107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pnacl-build-helper"
|
name = "pnacl-build-helper"
|
||||||
version = "1.3.1"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -139,6 +139,6 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "users"
|
name = "users"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ name = "exa"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ansi_term = "0.4.2"
|
ansi_term = "0.4.2"
|
||||||
getopts = "0.1.4"
|
getopts = "0.2.0"
|
||||||
natord = "1.0.6"
|
natord = "1.0.6"
|
||||||
number_prefix = "0.2.1"
|
number_prefix = "0.2.1"
|
||||||
users = "0.2.1"
|
users = "0.2.1"
|
||||||
|
@ -21,6 +21,7 @@ exa is a replacement for `ls` written in Rust.
|
|||||||
- **-i**, **--inode**: show inode number column
|
- **-i**, **--inode**: show inode number column
|
||||||
- **-l**, **--long**: display extended details and attributes
|
- **-l**, **--long**: display extended details and attributes
|
||||||
- **-r**, **--reverse**: reverse sort order
|
- **-r**, **--reverse**: reverse sort order
|
||||||
|
- **-R**, **--recurse**: recurse into subdirectories
|
||||||
- **-s**, **--sort=(field)**: field to sort by
|
- **-s**, **--sort=(field)**: field to sort by
|
||||||
- **-S**, **--blocks**: show number of file system blocks
|
- **-S**, **--blocks**: show number of file system blocks
|
||||||
- **-x**, **--across**: sort multi-column view entries across
|
- **-x**, **--across**: sort multi-column view entries across
|
||||||
|
17
src/dir.rs
17
src/dir.rs
@ -21,11 +21,11 @@ impl Dir {
|
|||||||
/// Create a new Dir object filled with all the files in the directory
|
/// Create a new Dir object filled with all the files in the directory
|
||||||
/// pointed to by the given path. Fails if the directory can't be read, or
|
/// pointed to by the given path. Fails if the directory can't be read, or
|
||||||
/// isn't actually a directory.
|
/// isn't actually a directory.
|
||||||
pub fn readdir(path: Path) -> IoResult<Dir> {
|
pub fn readdir(path: &Path) -> IoResult<Dir> {
|
||||||
fs::readdir(&path).map(|paths| Dir {
|
fs::readdir(path).map(|paths| Dir {
|
||||||
contents: paths,
|
contents: paths,
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
git: Git::scan(&path).ok(),
|
git: Git::scan(path).ok(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,12 +102,11 @@ impl Git {
|
|||||||
/// path that gets passed in. This is used for getting the status of
|
/// path that gets passed in. This is used for getting the status of
|
||||||
/// directories, which don't really have an 'official' status.
|
/// directories, which don't really have an 'official' status.
|
||||||
fn dir_status(&self, dir: &Path) -> String {
|
fn dir_status(&self, dir: &Path) -> String {
|
||||||
let status = self.statuses.iter()
|
let s = self.statuses.iter()
|
||||||
.filter(|p| p.0.starts_with(dir.as_vec()))
|
.filter(|p| p.0.starts_with(dir.as_vec()))
|
||||||
.fold(git2::Status::empty(), |a, b| a | b.1);
|
.fold(git2::Status::empty(), |a, b| a | b.1);
|
||||||
match status {
|
|
||||||
s => format!("{}{}", Git::index_status(s), Git::working_tree_status(s)),
|
format!("{}{}", Git::index_status(s), Git::working_tree_status(s))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The character to display if the file has been modified, but not staged.
|
/// The character to display if the file has been modified, but not staged.
|
||||||
|
14
src/file.rs
14
src/file.rs
@ -45,8 +45,18 @@ impl<'a> File<'a> {
|
|||||||
|
|
||||||
/// Create a new File object from the given Stat result, and other data.
|
/// Create a new File object from the given Stat result, and other data.
|
||||||
pub fn with_stat(stat: io::FileStat, path: &Path, parent: Option<&'a Dir>) -> File<'a> {
|
pub fn with_stat(stat: io::FileStat, path: &Path, parent: Option<&'a Dir>) -> File<'a> {
|
||||||
let v = path.filename().unwrap(); // fails if / or . or ..
|
|
||||||
let filename = String::from_utf8_lossy(v);
|
// The filename to display is the last component of the path. However,
|
||||||
|
// the path has no components for `.`, `..`, and `/`, so in these
|
||||||
|
// cases, the entire path is used.
|
||||||
|
let bytes = match path.components().last() {
|
||||||
|
Some(b) => b,
|
||||||
|
None => path.as_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert the string to UTF-8, replacing any invalid characters with
|
||||||
|
// replacement characters.
|
||||||
|
let filename = String::from_utf8_lossy(bytes);
|
||||||
|
|
||||||
File {
|
File {
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
|
48
src/main.rs
48
src/main.rs
@ -1,6 +1,8 @@
|
|||||||
#![feature(collections, core, io, libc, os, path, std_misc)]
|
#![feature(collections, core, io, libc, os, path, std_misc)]
|
||||||
|
|
||||||
extern crate ansi_term;
|
extern crate ansi_term;
|
||||||
|
extern crate getopts;
|
||||||
|
extern crate natord;
|
||||||
extern crate number_prefix;
|
extern crate number_prefix;
|
||||||
extern crate users;
|
extern crate users;
|
||||||
|
|
||||||
@ -12,7 +14,7 @@ use std::os::{args, set_exit_status};
|
|||||||
|
|
||||||
use dir::Dir;
|
use dir::Dir;
|
||||||
use file::File;
|
use file::File;
|
||||||
use options::Options;
|
use options::{Options, DirAction};
|
||||||
|
|
||||||
pub mod column;
|
pub mod column;
|
||||||
pub mod dir;
|
pub mod dir;
|
||||||
@ -23,7 +25,7 @@ pub mod output;
|
|||||||
pub mod term;
|
pub mod term;
|
||||||
|
|
||||||
fn exa(options: &Options) {
|
fn exa(options: &Options) {
|
||||||
let mut dirs: Vec<String> = vec![];
|
let mut dirs: Vec<Path> = vec![];
|
||||||
let mut files: Vec<File> = vec![];
|
let mut files: Vec<File> = vec![];
|
||||||
|
|
||||||
// It's only worth printing out directory names if the user supplied
|
// It's only worth printing out directory names if the user supplied
|
||||||
@ -33,16 +35,14 @@ fn exa(options: &Options) {
|
|||||||
// Separate the user-supplied paths into directories and files.
|
// Separate the user-supplied paths into directories and files.
|
||||||
// Files are shown first, and then each directory is expanded
|
// Files are shown first, and then each directory is expanded
|
||||||
// and listed second.
|
// and listed second.
|
||||||
for file in options.path_strings() {
|
for file in options.path_strs.iter() {
|
||||||
let path = Path::new(file);
|
let path = Path::new(file);
|
||||||
match fs::stat(&path) {
|
match fs::stat(&path) {
|
||||||
Ok(stat) => {
|
Ok(stat) => {
|
||||||
if !options.list_dirs && stat.kind == FileType::Directory {
|
if stat.kind == FileType::Directory && options.dir_action != DirAction::AsFile {
|
||||||
dirs.push(file.clone());
|
dirs.push(path);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// May as well reuse the stat result from earlier
|
|
||||||
// instead of just using File::from_path().
|
|
||||||
files.push(File::with_stat(stat, &path, None));
|
files.push(File::with_stat(stat, &path, None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,10 +55,19 @@ fn exa(options: &Options) {
|
|||||||
let mut first = files.is_empty();
|
let mut first = files.is_empty();
|
||||||
|
|
||||||
if !files.is_empty() {
|
if !files.is_empty() {
|
||||||
options.view(None, files);
|
options.view(None, &files[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for dir_name in dirs.iter() {
|
// Directories are put on a stack rather than just being iterated through,
|
||||||
|
// as the vector can change as more directories are added.
|
||||||
|
loop {
|
||||||
|
let dir_path = match dirs.pop() {
|
||||||
|
None => break,
|
||||||
|
Some(f) => f,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Put a gap between directories, or between the list of files and the
|
||||||
|
// first directory.
|
||||||
if first {
|
if first {
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
@ -66,19 +75,30 @@ fn exa(options: &Options) {
|
|||||||
print!("\n");
|
print!("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
match Dir::readdir(Path::new(dir_name.clone())) {
|
match Dir::readdir(&dir_path) {
|
||||||
Ok(ref dir) => {
|
Ok(ref dir) => {
|
||||||
let unsorted_files = dir.files();
|
let unsorted_files = dir.files();
|
||||||
let files: Vec<File> = options.transform_files(unsorted_files);
|
let files: Vec<File> = options.transform_files(unsorted_files);
|
||||||
|
|
||||||
if count > 1 {
|
// When recursing, add any directories to the dirs stack
|
||||||
println!("{}:", dir_name);
|
// backwards: the *last* element of the stack is used each
|
||||||
|
// time, so by inserting them backwards, they get displayed in
|
||||||
|
// the correct sort order.
|
||||||
|
if options.dir_action == DirAction::Recurse {
|
||||||
|
for dir in files.iter().filter(|f| f.stat.kind == FileType::Directory).rev() {
|
||||||
|
dirs.push(dir.path.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
options.view(Some(dir), files);
|
if count > 1 {
|
||||||
|
println!("{}:", dir_path.display());
|
||||||
|
}
|
||||||
|
count += 1;
|
||||||
|
|
||||||
|
options.view(Some(dir), &files[]);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{}: {}", dir_name, e);
|
println!("{}: {}", dir_path.display(), e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
extern crate getopts;
|
|
||||||
extern crate natord;
|
|
||||||
|
|
||||||
use dir::Dir;
|
use dir::Dir;
|
||||||
use file::File;
|
use file::File;
|
||||||
use column::{Column, SizeFormat};
|
use column::{Column, SizeFormat};
|
||||||
@ -11,7 +8,9 @@ use term::dimensions;
|
|||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::slice::Iter;
|
|
||||||
|
use getopts;
|
||||||
|
use natord;
|
||||||
|
|
||||||
use self::Misfire::*;
|
use self::Misfire::*;
|
||||||
|
|
||||||
@ -19,8 +18,8 @@ use self::Misfire::*;
|
|||||||
/// command-line options.
|
/// command-line options.
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
pub list_dirs: bool,
|
pub dir_action: DirAction,
|
||||||
path_strs: Vec<String>,
|
pub path_strs: Vec<String>,
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
show_invisibles: bool,
|
show_invisibles: bool,
|
||||||
sort_field: SortField,
|
sort_field: SortField,
|
||||||
@ -43,6 +42,7 @@ impl Options {
|
|||||||
getopts::optflag("l", "long", "display extended details and attributes"),
|
getopts::optflag("l", "long", "display extended details and attributes"),
|
||||||
getopts::optflag("i", "inode", "show each file's inode number"),
|
getopts::optflag("i", "inode", "show each file's inode number"),
|
||||||
getopts::optflag("r", "reverse", "reverse order of files"),
|
getopts::optflag("r", "reverse", "reverse order of files"),
|
||||||
|
getopts::optflag("R", "recurse", "recurse into directories"),
|
||||||
getopts::optopt ("s", "sort", "field to sort by", "WORD"),
|
getopts::optopt ("s", "sort", "field to sort by", "WORD"),
|
||||||
getopts::optflag("S", "blocks", "show number of file system blocks"),
|
getopts::optflag("S", "blocks", "show number of file system blocks"),
|
||||||
getopts::optflag("x", "across", "sort multi-column view entries across"),
|
getopts::optflag("x", "across", "sort multi-column view entries across"),
|
||||||
@ -64,7 +64,7 @@ impl Options {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(Options {
|
Ok(Options {
|
||||||
list_dirs: matches.opt_present("list-dirs"),
|
dir_action: try!(dir_action(&matches)),
|
||||||
path_strs: if matches.free.is_empty() { vec![ ".".to_string() ] } else { matches.free.clone() },
|
path_strs: if matches.free.is_empty() { vec![ ".".to_string() ] } else { matches.free.clone() },
|
||||||
reverse: matches.opt_present("reverse"),
|
reverse: matches.opt_present("reverse"),
|
||||||
show_invisibles: matches.opt_present("all"),
|
show_invisibles: matches.opt_present("all"),
|
||||||
@ -73,13 +73,8 @@ impl Options {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over the non-option arguments left oven from getopts.
|
|
||||||
pub fn path_strings(&self) -> Iter<String> {
|
|
||||||
self.path_strs.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Display the files using this Option's View.
|
/// Display the files using this Option's View.
|
||||||
pub fn view(&self, dir: Option<&Dir>, files: Vec<File>) {
|
pub fn view(&self, dir: Option<&Dir>, files: &[File]) {
|
||||||
self.view.view(dir, files)
|
self.view.view(dir, files)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +108,13 @@ impl Options {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// User-supplied field to sort by
|
/// What to do when encountering a directory?
|
||||||
|
#[derive(PartialEq, Debug, Copy)]
|
||||||
|
pub enum DirAction {
|
||||||
|
AsFile, List, Recurse
|
||||||
|
}
|
||||||
|
|
||||||
|
/// User-supplied field to sort by.
|
||||||
#[derive(PartialEq, Debug, Copy)]
|
#[derive(PartialEq, Debug, Copy)]
|
||||||
pub enum SortField {
|
pub enum SortField {
|
||||||
Unsorted, Name, Extension, Size, FileInode
|
Unsorted, Name, Extension, Size, FileInode
|
||||||
@ -228,7 +229,7 @@ fn view(matches: &getopts::Matches) -> Result<View, Misfire> {
|
|||||||
/// Finds out which file size the user has asked for.
|
/// Finds out which file size the user has asked for.
|
||||||
fn file_size(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
|
fn file_size(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
|
||||||
let binary = matches.opt_present("binary");
|
let binary = matches.opt_present("binary");
|
||||||
let bytes = matches.opt_present("bytes");
|
let bytes = matches.opt_present("bytes");
|
||||||
|
|
||||||
match (binary, bytes) {
|
match (binary, bytes) {
|
||||||
(true, true ) => Err(Misfire::Conflict("binary", "bytes")),
|
(true, true ) => Err(Misfire::Conflict("binary", "bytes")),
|
||||||
@ -238,6 +239,18 @@ fn file_size(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dir_action(matches: &getopts::Matches) -> Result<DirAction, Misfire> {
|
||||||
|
let recurse = matches.opt_present("recurse");
|
||||||
|
let list = matches.opt_present("list-dirs");
|
||||||
|
|
||||||
|
match (recurse, list) {
|
||||||
|
(true, true ) => Err(Misfire::Conflict("recurse", "list-dirs")),
|
||||||
|
(true, false) => Ok(DirAction::Recurse),
|
||||||
|
(false, true ) => Ok(DirAction::AsFile),
|
||||||
|
(false, false) => Ok(DirAction::List),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Copy, Debug)]
|
#[derive(PartialEq, Copy, Debug)]
|
||||||
pub struct Columns {
|
pub struct Columns {
|
||||||
size_format: SizeFormat,
|
size_format: SizeFormat,
|
||||||
@ -332,15 +345,15 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn files() {
|
fn files() {
|
||||||
let opts = Options::getopts(&[ "this file".to_string(), "that file".to_string() ]).unwrap();
|
let opts = Options::getopts(&[ "this file".to_string(), "that file".to_string() ]).unwrap();
|
||||||
let args: Vec<&String> = opts.path_strings().collect();
|
let args: Vec<String> = opts.path_strs;
|
||||||
assert_eq!(args, vec![ &"this file".to_string(), &"that file".to_string() ])
|
assert_eq!(args, vec![ "this file".to_string(), "that file".to_string() ])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn no_args() {
|
fn no_args() {
|
||||||
let opts = Options::getopts(&[]).unwrap();
|
let opts = Options::getopts(&[]).unwrap();
|
||||||
let args: Vec<&String> = opts.path_strings().collect();
|
let args: Vec<String> = opts.path_strs;
|
||||||
assert_eq!(args, vec![ &".".to_string() ])
|
assert_eq!(args, vec![ ".".to_string() ])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -18,7 +18,7 @@ pub enum View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl View {
|
impl View {
|
||||||
pub fn view(&self, dir: Option<&Dir>, files: Vec<File>) {
|
pub fn view(&self, dir: Option<&Dir>, files: &[File]) {
|
||||||
match *self {
|
match *self {
|
||||||
View::Grid(across, width) => grid_view(across, width, files),
|
View::Grid(across, width) => grid_view(across, width, files),
|
||||||
View::Details(ref cols, header) => details_view(&*cols.for_dir(dir), files, header),
|
View::Details(ref cols, header) => details_view(&*cols.for_dir(dir), files, header),
|
||||||
@ -28,13 +28,13 @@ impl View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The lines view literally just displays each file, line-by-line.
|
/// The lines view literally just displays each file, line-by-line.
|
||||||
fn lines_view(files: Vec<File>) {
|
fn lines_view(files: &[File]) {
|
||||||
for file in files.iter() {
|
for file in files.iter() {
|
||||||
println!("{}", file.file_name_view().text);
|
println!("{}", file.file_name_view().text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fit_into_grid(across: bool, console_width: usize, files: &Vec<File>) -> Option<(usize, Vec<usize>)> {
|
fn fit_into_grid(across: bool, console_width: usize, files: &[File]) -> Option<(usize, Vec<usize>)> {
|
||||||
// TODO: this function could almost certainly be optimised...
|
// TODO: this function could almost certainly be optimised...
|
||||||
// surely not *all* of the numbers of lines are worth searching through!
|
// surely not *all* of the numbers of lines are worth searching through!
|
||||||
|
|
||||||
@ -86,8 +86,8 @@ fn fit_into_grid(across: bool, console_width: usize, files: &Vec<File>) -> Optio
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn grid_view(across: bool, console_width: usize, files: Vec<File>) {
|
fn grid_view(across: bool, console_width: usize, files: &[File]) {
|
||||||
if let Some((num_lines, widths)) = fit_into_grid(across, console_width, &files) {
|
if let Some((num_lines, widths)) = fit_into_grid(across, console_width, files) {
|
||||||
for y in range(0, num_lines) {
|
for y in range(0, num_lines) {
|
||||||
for x in range(0, widths.len()) {
|
for x in range(0, widths.len()) {
|
||||||
let num = if across {
|
let num = if across {
|
||||||
@ -122,7 +122,7 @@ fn grid_view(across: bool, console_width: usize, files: Vec<File>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn details_view(columns: &[Column], files: Vec<File>, header: bool) {
|
fn details_view(columns: &[Column], files: &[File], header: bool) {
|
||||||
// The output gets formatted into columns, which looks nicer. To
|
// The output gets formatted into columns, which looks nicer. To
|
||||||
// do this, we have to write the results into a table, instead of
|
// do this, we have to write the results into a table, instead of
|
||||||
// displaying each file immediately, then calculating the maximum
|
// displaying each file immediately, then calculating the maximum
|
||||||
|
Loading…
Reference in New Issue
Block a user