mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-17 17:55:11 +00:00
2d1f462bfa
This commit removes the dependency on the ‘getopts’ crate entirely, and re-writes all its uses to use the new options parser instead. As expected there are casualties galore: - We now need to collect the options into a vector at the start, so we can use references to them, knowing they’ll be stored *somewhere*. - Because OsString isn’t Display, its Debug impl gets used instead. (This is hopefully temporary) - Options that take values (such as ‘sort’ or ‘time-style’) now parse those values with ‘to_string_lossy’. The ‘lossy’ part means “I’m at a loss for what to do here” - Error messages got a lot worse, but “--tree --all --all” is now a special case of error rather than just another Misfire::Useless. - Some tests had to be re-written to deal with the fact that the parser works with references. - ParseError loses its lifetime and owns its contents, to avoid having to attach <'a> to Misfire. - The parser now takes an iterator instead of a slice. - OsStrings can’t be ‘match’ patterns, so the code devolves to using long Eq chains instead. - Make a change to the xtest that assumed an input argument with invalid UTF-8 in was always an error to stderr, when that now in fact works! - Fix a bug in Vagrant where ‘exa’ and ‘rexa’ didn’t properly escape filenames with spaces in.
123 lines
3.6 KiB
Rust
123 lines
3.6 KiB
Rust
use glob;
|
||
|
||
use fs::DotFilter;
|
||
use fs::filter::{FileFilter, SortField, SortCase, IgnorePatterns};
|
||
|
||
use options::{flags, Misfire};
|
||
use options::parser::Matches;
|
||
|
||
|
||
impl FileFilter {
|
||
|
||
/// Determines the set of file filter options to use, based on the user’s
|
||
/// command-line arguments.
|
||
pub fn deduce(matches: &Matches) -> Result<FileFilter, Misfire> {
|
||
Ok(FileFilter {
|
||
list_dirs_first: matches.has(&flags::DIRS_FIRST),
|
||
reverse: matches.has(&flags::REVERSE),
|
||
sort_field: SortField::deduce(matches)?,
|
||
dot_filter: DotFilter::deduce(matches)?,
|
||
ignore_patterns: IgnorePatterns::deduce(matches)?,
|
||
})
|
||
}
|
||
}
|
||
|
||
|
||
|
||
impl Default for SortField {
|
||
fn default() -> SortField {
|
||
SortField::Name(SortCase::Sensitive)
|
||
}
|
||
}
|
||
|
||
impl SortField {
|
||
|
||
/// Determine the sort field to use, based on the presence of a “sort”
|
||
/// argument. This will return `Err` if the option is there, but does not
|
||
/// correspond to a valid field.
|
||
fn deduce(matches: &Matches) -> Result<SortField, Misfire> {
|
||
|
||
const SORTS: &[&str] = &[ "name", "Name", "size", "extension",
|
||
"Extension", "modified", "accessed",
|
||
"created", "inode", "type", "none" ];
|
||
|
||
let word = match matches.get(&flags::SORT) {
|
||
Some(w) => w,
|
||
None => return Ok(SortField::default()),
|
||
};
|
||
|
||
if word == "name" || word == "filename" {
|
||
Ok(SortField::Name(SortCase::Sensitive))
|
||
}
|
||
else if word == "Name" || word == "Filename" {
|
||
Ok(SortField::Name(SortCase::Insensitive))
|
||
}
|
||
else if word == "size" || word == "filesize" {
|
||
Ok(SortField::Size)
|
||
}
|
||
else if word == "ext" || word == "extension" {
|
||
Ok(SortField::Extension(SortCase::Sensitive))
|
||
}
|
||
else if word == "Ext" || word == "Extension" {
|
||
Ok(SortField::Extension(SortCase::Insensitive))
|
||
}
|
||
else if word == "mod" || word == "modified" {
|
||
Ok(SortField::ModifiedDate)
|
||
}
|
||
else if word == "acc" || word == "accessed" {
|
||
Ok(SortField::AccessedDate)
|
||
}
|
||
else if word == "cr" || word == "created" {
|
||
Ok(SortField::CreatedDate)
|
||
}
|
||
else if word == "inode" {
|
||
Ok(SortField::FileInode)
|
||
}
|
||
else if word == "type" {
|
||
Ok(SortField::FileType)
|
||
}
|
||
else if word == "none" {
|
||
Ok(SortField::Unsorted)
|
||
}
|
||
else {
|
||
Err(Misfire::bad_argument(&flags::SORT, word, SORTS))
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
impl DotFilter {
|
||
pub fn deduce(matches: &Matches) -> Result<DotFilter, Misfire> {
|
||
let dots = match matches.count(&flags::ALL) {
|
||
0 => return Ok(DotFilter::JustFiles),
|
||
1 => DotFilter::Dotfiles,
|
||
_ => DotFilter::DotfilesAndDots,
|
||
};
|
||
|
||
if matches.has(&flags::TREE) {
|
||
Err(Misfire::TreeAllAll)
|
||
}
|
||
else {
|
||
Ok(dots)
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
impl IgnorePatterns {
|
||
|
||
/// Determines the set of file filter options to use, based on the user’s
|
||
/// command-line arguments.
|
||
pub fn deduce(matches: &Matches) -> Result<IgnorePatterns, Misfire> {
|
||
let patterns = match matches.get(&flags::IGNORE_GLOB) {
|
||
None => Ok(Vec::new()),
|
||
Some(is) => is.to_string_lossy().split('|').map(|a| glob::Pattern::new(a)).collect(),
|
||
}?;
|
||
|
||
// TODO: is to_string_lossy really the best way to handle
|
||
// invalid UTF-8 there?
|
||
|
||
Ok(IgnorePatterns { patterns })
|
||
}
|
||
}
|