Upgrade to latest Rust nightly

This commit is contained in:
Ben S 2014-11-23 21:29:11 +00:00
parent 26f8ad08bf
commit 933f98d2c3
8 changed files with 89 additions and 86 deletions

View File

@ -19,24 +19,24 @@ pub enum Alignment {
impl Column { impl Column {
pub fn alignment(&self) -> Alignment { pub fn alignment(&self) -> Alignment {
match *self { match *self {
FileSize(_) => Right, Column::FileSize(_) => Alignment::Right,
HardLinks => Right, Column::HardLinks => Alignment::Right,
Inode => Right, Column::Inode => Alignment::Right,
Blocks => Right, Column::Blocks => Alignment::Right,
_ => Left, _ => Alignment::Left,
} }
} }
pub fn header(&self) -> &'static str { pub fn header(&self) -> &'static str {
match *self { match *self {
Permissions => "Permissions", Column::Permissions => "Permissions",
FileName => "Name", Column::FileName => "Name",
FileSize(_) => "Size", Column::FileSize(_) => "Size",
Blocks => "Blocks", Column::Blocks => "Blocks",
User => "User", Column::User => "User",
Group => "Group", Column::Group => "Group",
HardLinks => "Links", Column::HardLinks => "Links",
Inode => "inode", Column::Inode => "inode",
} }
} }
} }
@ -49,8 +49,8 @@ impl Column {
impl Alignment { impl Alignment {
pub fn pad_string(&self, string: &String, padding: uint) -> String { pub fn pad_string(&self, string: &String, padding: uint) -> String {
match *self { match *self {
Left => string.clone().append(" ".to_string().repeat(padding).as_slice()), Alignment::Left => string.clone() + " ".to_string().repeat(padding).as_slice(),
Right => " ".to_string().repeat(padding).append(string.as_slice()), Alignment::Right => " ".to_string().repeat(padding) + string.as_slice(),
} }
} }
} }

View File

@ -1,4 +1,4 @@
#![feature(phase)] #![feature(phase, globs)]
extern crate regex; extern crate regex;
#[phase(plugin)] extern crate regex_macros; #[phase(plugin)] extern crate regex_macros;
extern crate ansi_term; extern crate ansi_term;
@ -8,8 +8,9 @@ use std::os;
use file::File; use file::File;
use dir::Dir; use dir::Dir;
use column::{Column, Left}; use column::Column;
use options::{Options, Details, Lines, Grid}; use column::Alignment::Left;
use options::{Options, View};
use unix::Unix; use unix::Unix;
use ansi_term::{Paint, Plain, strip_formatting}; use ansi_term::{Paint, Plain, strip_formatting};
@ -25,7 +26,7 @@ pub mod sort;
pub mod term; pub mod term;
fn main() { fn main() {
let args = os::args(); let args: Vec<String> = os::args();
match Options::getopts(args) { match Options::getopts(args) {
Err(err) => println!("Invalid options:\n{}", err), Err(err) => println!("Invalid options:\n{}", err),
@ -58,9 +59,9 @@ fn exa(opts: &Options) {
} }
match opts.view { match opts.view {
Details(ref cols) => details_view(opts, cols, files), View::Details(ref cols) => details_view(opts, cols, files),
Lines => lines_view(files), View::Lines => lines_view(files),
Grid(across, width) => grid_view(across, width, files), View::Grid(across, width) => grid_view(across, width, files),
} }
} }
Err(e) => { Err(e) => {
@ -156,7 +157,7 @@ fn details_view(options: &Options, columns: &Vec<Column>, files: Vec<&File>) {
} }
else { else {
let padding = column_widths[num] - field_widths[num]; let padding = column_widths[num] - field_widths[num];
print!("{}", column.alignment().pad_string(row.get(num), padding)); print!("{}", column.alignment().pad_string(&row[num], padding));
} }
} }
print!("\n"); print!("\n");

View File

@ -1,17 +1,17 @@
use std::io::{fs, IoResult}; use std::io::{fs, IoResult};
use std::io; use std::io;
use unicode::str::UnicodeStrSlice;
use ansi_term::{Paint, Colour, Plain, Style, Red, Green, Yellow, Blue, Purple, Cyan, Fixed}; use ansi_term::{Paint, Colour, Plain, Style, Red, Green, Yellow, Blue, Purple, Cyan, Fixed};
use column::{Column, Permissions, FileName, FileSize, User, Group, HardLinks, Inode, Blocks}; use column::Column;
use column::Column::*;
use format::{format_metric_bytes, format_IEC_bytes}; use format::{format_metric_bytes, format_IEC_bytes};
use unix::Unix; use unix::Unix;
use sort::SortPart; use sort::SortPart;
use dir::Dir; use dir::Dir;
use filetype::HasType; use filetype::HasType;
static Grey: Colour = Fixed(244); pub static GREY: Colour = Fixed(244);
// Instead of working with Rust's Paths, we have our own File object // Instead of working with Rust's Paths, we have our own File object
// that holds the Path and various cached information. Each file is // that holds the Path and various cached information. Each file is
@ -32,7 +32,7 @@ pub struct File<'a> {
impl<'a> File<'a> { impl<'a> File<'a> {
pub fn from_path(path: &'a Path, parent: &'a Dir) -> IoResult<File<'a>> { pub fn from_path(path: &'a Path, parent: &'a Dir) -> IoResult<File<'a>> {
let v = path.filename().unwrap(); // fails if / or . or .. let v = path.filename().unwrap(); // fails if / or . or ..
let filename = String::from_utf8_lossy(v).to_string(); let filename = String::from_utf8(v.to_vec()).to_string();
// Use lstat here instead of file.stat(), as it doesn't follow // Use lstat here instead of file.stat(), as it doesn't follow
// symbolic links. Otherwise, the stat() call will fail if it // symbolic links. Otherwise, the stat() call will fail if it
@ -129,7 +129,7 @@ impl<'a> File<'a> {
Cyan.paint(self.stat.unstable.blocks.to_string().as_slice()) Cyan.paint(self.stat.unstable.blocks.to_string().as_slice())
} }
else { else {
Grey.paint("-") GREY.paint("-")
} }
}, },
@ -195,7 +195,7 @@ impl<'a> File<'a> {
// that reason anyway. // that reason anyway.
match link_target { match link_target {
Ok(file) => format!("{} {}", Grey.paint("=>"), file.file_colour().paint(filename.as_slice())), Ok(file) => format!("{} {}", GREY.paint("=>"), file.file_colour().paint(filename.as_slice())),
Err(_) => format!("{} {}", Red.paint("=>"), Red.underline().paint(filename.as_slice())), Err(_) => format!("{} {}", Red.paint("=>"), Red.underline().paint(filename.as_slice())),
} }
} }
@ -204,7 +204,7 @@ impl<'a> File<'a> {
// Don't report file sizes for directories. I've never looked // Don't report file sizes for directories. I've never looked
// at one of those numbers and gained any information from it. // at one of those numbers and gained any information from it.
if self.stat.kind == io::TypeDirectory { if self.stat.kind == io::TypeDirectory {
Grey.paint("-") GREY.paint("-")
} else { } else {
let (size, suffix) = if use_iec_prefixes { let (size, suffix) = if use_iec_prefixes {
format_IEC_bytes(self.stat.size) format_IEC_bytes(self.stat.size)
@ -242,15 +242,15 @@ impl<'a> File<'a> {
// The first three are bold because they're the ones used // The first three are bold because they're the ones used
// most often. // most often.
File::permission_bit(bits, io::UserRead, "r", Yellow.bold()), File::permission_bit(bits, io::USER_READ, "r", Yellow.bold()),
File::permission_bit(bits, io::UserWrite, "w", Red.bold()), File::permission_bit(bits, io::USER_WRITE, "w", Red.bold()),
File::permission_bit(bits, io::UserExecute, "x", Green.bold().underline()), File::permission_bit(bits, io::USER_EXECUTE, "x", Green.bold().underline()),
File::permission_bit(bits, io::GroupRead, "r", Yellow.normal()), File::permission_bit(bits, io::GROUP_READ, "r", Yellow.normal()),
File::permission_bit(bits, io::GroupWrite, "w", Red.normal()), File::permission_bit(bits, io::GROUP_WRITE, "w", Red.normal()),
File::permission_bit(bits, io::GroupExecute, "x", Green.normal()), File::permission_bit(bits, io::GROUP_EXECUTE, "x", Green.normal()),
File::permission_bit(bits, io::OtherRead, "r", Yellow.normal()), File::permission_bit(bits, io::OTHER_READ, "r", Yellow.normal()),
File::permission_bit(bits, io::OtherWrite, "w", Red.normal()), File::permission_bit(bits, io::OTHER_WRITE, "w", Red.normal()),
File::permission_bit(bits, io::OtherExecute, "x", Green.normal()), File::permission_bit(bits, io::OTHER_EXECUTE, "x", Green.normal()),
); );
} }
@ -258,7 +258,7 @@ impl<'a> File<'a> {
if bits.contains(bit) { if bits.contains(bit) {
style.paint(character.as_slice()) style.paint(character.as_slice())
} else { } else {
Grey.paint("-".as_slice()) GREY.paint("-".as_slice())
} }
} }
} }

View File

@ -1,10 +1,10 @@
use file::File; use file::{File, GREY};
use self::FileType::*;
use std::io; use std::io;
use std::ascii::StrAsciiExt; use std::ascii::AsciiExt;
use ansi_term::{Paint, Colour, Plain, Style, Red, Green, Yellow, Blue, Cyan, Fixed}; use ansi_term::{Paint, Plain, Style, Red, Green, Yellow, Blue, Cyan, Fixed};
static Grey: Colour = Fixed(244);
pub enum FileType { pub enum FileType {
Normal, Directory, Executable, Immediate, Compiled, Symlink, Special, Normal, Directory, Executable, Immediate, Compiled, Symlink, Special,
@ -64,7 +64,7 @@ impl FileType {
Crypto => Fixed(109).normal(), Crypto => Fixed(109).normal(),
Document => Fixed(105).normal(), Document => Fixed(105).normal(),
Compressed => Red.normal(), Compressed => Red.normal(),
Temp => Grey.normal(), Temp => GREY.normal(),
Immediate => Yellow.bold().underline(), Immediate => Yellow.bold().underline(),
Compiled => Fixed(137).normal(), Compiled => Fixed(137).normal(),
} }
@ -87,14 +87,14 @@ impl<'a> HasType for File<'a> {
else if self.stat.kind == io::TypeBlockSpecial || self.stat.kind == io::TypeNamedPipe || self.stat.kind == io::TypeUnknown { else if self.stat.kind == io::TypeBlockSpecial || self.stat.kind == io::TypeNamedPipe || self.stat.kind == io::TypeUnknown {
return Special; return Special;
} }
else if self.stat.perm.contains(io::UserExecute) { else if self.stat.perm.contains(io::USER_EXECUTE) {
return Executable; return Executable;
} }
else if name.starts_with("README") || BUILD_TYPES.iter().any(|&s| s == name) { else if name.starts_with("README") || BUILD_TYPES.iter().any(|&s| s == name) {
return Immediate; return Immediate;
} }
else if self.ext.is_some() { else if self.ext.is_some() {
let e = self.ext.clone().unwrap().as_slice().to_ascii_lower(); let e = self.ext.clone().unwrap().to_ascii_lower();
let ext = e.as_slice(); let ext = e.as_slice();
if IMAGE_TYPES.iter().any(|&s| s == ext) { if IMAGE_TYPES.iter().any(|&s| s == ext) {
return Image; return Image;

View File

@ -1,9 +1,11 @@
extern crate getopts; extern crate getopts;
use file::File; use file::File;
use column::{Column, Permissions, FileName, FileSize, User, Group, HardLinks, Inode, Blocks}; use column::Column;
use std::ascii::StrAsciiExt; use column::Column::*;
use term; use term::dimensions;
use std::ascii::AsciiExt;
pub enum SortField { pub enum SortField {
Unsorted, Name, Extension, Size, FileInode Unsorted, Name, Extension, Size, FileInode
@ -12,12 +14,12 @@ pub enum SortField {
impl SortField { impl SortField {
fn from_word(word: String) -> SortField { fn from_word(word: String) -> SortField {
match word.as_slice() { match word.as_slice() {
"name" => Name, "name" => SortField::Name,
"size" => Size, "size" => SortField::Size,
"ext" => Extension, "ext" => SortField::Extension,
"none" => Unsorted, "none" => SortField::Unsorted,
"inode" => FileInode, "inode" => SortField::FileInode,
_ => fail!("Invalid sorting order"), _ => panic!("Invalid sorting order"),
} }
} }
} }
@ -40,7 +42,7 @@ pub struct Options {
impl Options { impl Options {
pub fn getopts(args: Vec<String>) -> Result<Options, getopts::Fail_> { pub fn getopts(args: Vec<String>) -> Result<Options, getopts::Fail_> {
let opts = [ let opts = &[
getopts::optflag("1", "oneline", "display one entry per line"), getopts::optflag("1", "oneline", "display one entry per line"),
getopts::optflag("a", "all", "show dot-files"), getopts::optflag("a", "all", "show dot-files"),
getopts::optflag("b", "binary", "use binary prefixes in file sizes"), getopts::optflag("b", "binary", "use binary prefixes in file sizes"),
@ -61,7 +63,7 @@ impl Options {
show_invisibles: matches.opt_present("all"), show_invisibles: matches.opt_present("all"),
reverse: matches.opt_present("reverse"), reverse: matches.opt_present("reverse"),
header: matches.opt_present("header"), header: matches.opt_present("header"),
sort_field: matches.opt_str("sort").map(|word| SortField::from_word(word)).unwrap_or(Name), sort_field: matches.opt_str("sort").map(|word| SortField::from_word(word)).unwrap_or(SortField::Name),
dirs: if matches.free.is_empty() { vec![ ".".to_string() ] } else { matches.free.clone() }, dirs: if matches.free.is_empty() { vec![ ".".to_string() ] } else { matches.free.clone() },
view: Options::view(matches), view: Options::view(matches),
}) })
@ -70,15 +72,15 @@ impl Options {
fn view(matches: getopts::Matches) -> View { fn view(matches: getopts::Matches) -> View {
if matches.opt_present("long") { if matches.opt_present("long") {
Details(Options::columns(matches)) View::Details(Options::columns(matches))
} }
else if matches.opt_present("oneline") { else if matches.opt_present("oneline") {
Lines View::Lines
} }
else { else {
match term::dimensions() { match dimensions() {
None => Lines, None => View::Lines,
Some((width, _)) => Grid(matches.opt_present("across"), width), Some((width, _)) => View::Grid(matches.opt_present("across"), width),
} }
} }
} }
@ -127,13 +129,13 @@ impl Options {
.collect(); .collect();
match self.sort_field { match self.sort_field {
Unsorted => {}, SortField::Unsorted => {},
Name => files.sort_by(|a, b| a.parts.cmp(&b.parts)), SortField::Name => files.sort_by(|a, b| a.parts.cmp(&b.parts)),
Size => files.sort_by(|a, b| a.stat.size.cmp(&b.stat.size)), SortField::Size => files.sort_by(|a, b| a.stat.size.cmp(&b.stat.size)),
FileInode => files.sort_by(|a, b| a.stat.unstable.inode.cmp(&b.stat.unstable.inode)), SortField::FileInode => files.sort_by(|a, b| a.stat.unstable.inode.cmp(&b.stat.unstable.inode)),
Extension => files.sort_by(|a, b| { SortField::Extension => files.sort_by(|a, b| {
let exts = a.ext.clone().map(|e| e.as_slice().to_ascii_lower()).cmp(&b.ext.clone().map(|e| e.as_slice().to_ascii_lower())); let exts = a.ext.clone().map(|e| e.to_ascii_lower()).cmp(&b.ext.clone().map(|e| e.to_ascii_lower()));
let names = a.name.as_slice().to_ascii_lower().cmp(&b.name.as_slice().to_ascii_lower()); let names = a.name.to_ascii_lower().cmp(&b.name.to_ascii_lower());
exts.cmp(&names) exts.cmp(&names)
}), }),
} }

View File

@ -1,4 +1,5 @@
use std::ascii::StrAsciiExt; use self::SortPart::*;
use std::ascii::AsciiExt;
// This is an implementation of "natural sort order". See // This is an implementation of "natural sort order". See
// http://blog.codinghorror.com/sorting-for-humans-natural-sort-order/ // http://blog.codinghorror.com/sorting-for-humans-natural-sort-order/
@ -20,11 +21,11 @@ impl SortPart {
if is_digit { if is_digit {
// numbers too big for a u64 fall back into strings. // numbers too big for a u64 fall back into strings.
match from_str::<u64>(slice) { match from_str::<u64>(slice) {
Some(num) => Numeric(num), Some(num) => SortPart::Numeric(num),
None => Stringular(slice.to_string()), None => SortPart::Stringular(slice.to_string()),
} }
} else { } else {
Stringular(slice.to_ascii_lower()) SortPart::Stringular(slice.to_ascii_lower())
} }
} }
@ -38,11 +39,11 @@ impl SortPart {
return parts return parts
} }
let mut is_digit = input.as_slice().char_at(0).is_digit(); let mut is_digit = input.as_slice().char_at(0).is_digit(10);
let mut start = 0; let mut start = 0;
for (i, c) in input.as_slice().char_indices() { for (i, c) in input.as_slice().char_indices() {
if is_digit != c.is_digit() { if is_digit != c.is_digit(10) {
parts.push(SortPart::from_string(is_digit, input.as_slice().slice(start, i))); parts.push(SortPart::from_string(is_digit, input.as_slice().slice(start, i)));
is_digit = !is_digit; is_digit = !is_digit;
start = i; start = i;

View File

@ -21,12 +21,11 @@ mod c {
// Unfortunately the actual command is not standardised... // Unfortunately the actual command is not standardised...
#[cfg(target_os = "linux")] #[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(target_os = "android")]
static TIOCGWINSZ: c_ulong = 0x5413; static TIOCGWINSZ: c_ulong = 0x5413;
#[cfg(target_os = "freebsd")] #[cfg(any(target_os = "macos", target_os = "ios"))]
#[cfg(target_os = "macos")]
static TIOCGWINSZ: c_ulong = 0x40087468; static TIOCGWINSZ: c_ulong = 0x40087468;
extern { extern {

View File

@ -1,6 +1,6 @@
use std::string::raw::from_buf; use std::string::raw::from_buf;
use std::ptr::read; use std::ptr::read;
use std::collections::hashmap::HashMap; use std::collections::HashMap;
mod c { mod c {
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
@ -127,13 +127,13 @@ impl Unix {
pub fn load_group(&mut self, gid: u32) { pub fn load_group(&mut self, gid: u32) {
match unsafe { c::getgrgid(gid).as_ref() } { match unsafe { c::getgrgid(gid).as_ref() } {
None => { None => {
self.group_names.find_or_insert(gid, None); self.group_names.insert(gid, None);
self.groups.find_or_insert(gid, false); self.groups.insert(gid, false);
}, },
Some(r) => { Some(r) => {
let group_name = unsafe { Some(from_buf(r.gr_name as *const u8)) }; let group_name = unsafe { Some(from_buf(r.gr_name as *const u8)) };
self.groups.find_or_insert(gid, Unix::group_membership(r.gr_mem, &self.username)); self.groups.insert(gid, Unix::group_membership(r.gr_mem, &self.username));
self.group_names.find_or_insert(gid, group_name); self.group_names.insert(gid, group_name);
} }
} }