It actually works

This commit is contained in:
Chester Liu 2021-03-26 17:47:18 +08:00
parent e9d0af0343
commit aeb4a679e8
3 changed files with 52 additions and 19 deletions

View File

@ -76,7 +76,7 @@ impl<'dir> File<'dir> {
let ext = File::ext(&path);
debug!("Statting file {:?}", &path);
let metadata = std::fs::symlink_metadata(&path)?;
let metadata = std::fs::symlink_metadata(&path)?;
let is_all_all = false;
Ok(File { path, parent_dir, metadata, ext, name, is_all_all })
@ -98,7 +98,7 @@ impl<'dir> File<'dir> {
let ext = File::ext(&path);
debug!("Statting file {:?}", &path);
let metadata = std::fs::symlink_metadata(&path)?;
let metadata = std::fs::symlink_metadata(&path)?;
let is_all_all = true;
let parent_dir = Some(parent_dir);
@ -326,10 +326,17 @@ impl<'dir> File<'dir> {
/// Block and character devices return their device IDs, because they
/// usually just have a file size of zero.
pub fn size(&self) -> f::Size {
#[cfg(windows)]
if self.is_directory() {
f::Size::None
}
else {
f::Size::Some(self.metadata.len())
}
#[cfg(unix)]
if self.is_directory() {
f::Size::None
}
else if self.is_char_device() || self.is_block_device() {
let dev = self.metadata.rdev();
f::Size::DeviceIDs(f::DeviceIDs {

View File

@ -146,8 +146,6 @@ impl Args {
pub fn parse<'args, I>(&self, inputs: I, strictness: Strictness) -> Result<Matches<'args>, ParseError>
where I: IntoIterator<Item = &'args OsStr>
{
use std::os::unix::ffi::OsStrExt;
let mut parsing = true;
// The results that get built up.
@ -159,7 +157,7 @@ impl Args {
// doesnt have one in its string so it needs the next one.
let mut inputs = inputs.into_iter();
while let Some(arg) = inputs.next() {
let bytes = arg.as_bytes();
let bytes = os_str_to_bytes(arg);
// Stop parsing if one of the arguments is the literal string “--”.
// This allows a file named “--arg” to be specified by passing in
@ -174,7 +172,7 @@ impl Args {
// If the string starts with *two* dashes then its a long argument.
else if bytes.starts_with(b"--") {
let long_arg_name = OsStr::from_bytes(&bytes[2..]);
let long_arg_name = bytes_to_os_str(&bytes[2..]);
// If theres an equals in it, then the string before the
// equals will be the flags name, and the string after it
@ -221,7 +219,7 @@ impl Args {
// If the string starts with *one* dash then its one or more
// short arguments.
else if bytes.starts_with(b"-") && arg != "-" {
let short_arg = OsStr::from_bytes(&bytes[1..]);
let short_arg = bytes_to_os_str(&bytes[1..]);
// If theres an equals in it, then the argument immediately
// before the equals was the one that has the value, with the
@ -236,7 +234,7 @@ impl Args {
// its an error if any of the first set of arguments actually
// takes a value.
if let Some((before, after)) = split_on_equals(short_arg) {
let (arg_with_value, other_args) = before.as_bytes().split_last().unwrap();
let (arg_with_value, other_args) = os_str_to_bytes(before).split_last().unwrap();
// Process the characters immediately following the dash...
for byte in other_args {
@ -291,7 +289,7 @@ impl Args {
TakesValue::Optional(values) => {
if index < bytes.len() - 1 {
let remnants = &bytes[index+1 ..];
result_flags.push((flag, Some(OsStr::from_bytes(remnants))));
result_flags.push((flag, Some(bytes_to_os_str(remnants))));
break;
}
else if let Some(next_arg) = inputs.next() {
@ -495,19 +493,42 @@ impl fmt::Display for ParseError {
}
}
#[cfg(unix)]
fn os_str_to_bytes<'b>(s: &'b OsStr) -> &'b [u8]{
use std::os::unix::ffi::OsStrExt;
return s.as_bytes()
}
#[cfg(unix)]
fn bytes_to_os_str<'b>(b: &'b [u8]) -> &'b OsStr{
use std::os::unix::ffi::OsStrExt;
return OsStr::from_bytes(b);
}
#[cfg(windows)]
fn os_str_to_bytes<'b>(s: &'b OsStr) -> &'b [u8]{
return s.to_str().unwrap().as_bytes()
}
#[cfg(windows)]
fn bytes_to_os_str<'b>(b: &'b [u8]) -> &'b OsStr{
use std::str;
return OsStr::new(str::from_utf8(b).unwrap());
}
/// Splits a string on its `=` character, returning the two substrings on
/// either side. Returns `None` if theres no equals or a string is missing.
fn split_on_equals(input: &OsStr) -> Option<(&OsStr, &OsStr)> {
use std::os::unix::ffi::OsStrExt;
if let Some(index) = input.as_bytes().iter().position(|elem| *elem == b'=') {
let (before, after) = input.as_bytes().split_at(index);
if let Some(index) = os_str_to_bytes(input).iter().position(|elem| *elem == b'=') {
let (before, after) = os_str_to_bytes(input).split_at(index);
// The after string contains the = that we need to remove.
if ! before.is_empty() && after.len() >= 2 {
return Some((OsStr::from_bytes(before),
OsStr::from_bytes(&after[1..])))
return Some((bytes_to_os_str(before),
bytes_to_os_str(&after[1..])))
}
}

View File

@ -59,11 +59,11 @@ impl Columns {
}
if self.octal {
#[cfg(unix)]
columns.push(Column::Octal);
}
if self.permissions {
#[cfg(unix)]
columns.push(Column::Permissions);
}
@ -123,7 +123,6 @@ impl Columns {
/// A table contains these.
#[derive(Debug, Copy, Clone)]
pub enum Column {
#[cfg(unix)]
Permissions,
FileSize,
#[cfg(unix)]
@ -139,6 +138,7 @@ pub enum Column {
#[cfg(unix)]
Inode,
GitStatus,
#[cfg(unix)]
Octal,
}
@ -177,7 +177,6 @@ impl Column {
/// to have a header row printed.
pub fn header(self) -> &'static str {
match self {
#[cfg(unix)]
Self::Permissions => "Permissions",
Self::FileSize => "Size",
#[cfg(unix)]
@ -193,6 +192,7 @@ impl Column {
#[cfg(unix)]
Self::Inode => "inode",
Self::GitStatus => "Git",
#[cfg(unix)]
Self::Octal => "Octal",
}
}
@ -407,6 +407,7 @@ impl<'a, 'f> Table<'a> {
}
}
#[cfg(unix)]
fn octal_permissions(&self, file: &File<'_>) -> f::OctalPermissions {
f::OctalPermissions {
permissions: file.permissions(),
@ -415,7 +416,6 @@ impl<'a, 'f> Table<'a> {
fn display(&self, file: &File<'_>, column: Column, xattrs: bool) -> TextCell {
match column {
#[cfg(unix)]
Column::Permissions => {
self.permissions_plus(file, xattrs).render(self.theme)
}
@ -445,19 +445,24 @@ impl<'a, 'f> Table<'a> {
Column::GitStatus => {
self.git_status(file).render(self.theme)
}
#[cfg(unix)]
Column::Octal => {
self.octal_permissions(file).render(self.theme.ui.octal)
}
#[cfg(unix)]
Column::Timestamp(TimeType::Modified) => {
file.modified_time().render(self.theme.ui.date, &self.env.tz, self.time_format)
}
#[cfg(unix)]
Column::Timestamp(TimeType::Changed) => {
file.changed_time().render(self.theme.ui.date, &self.env.tz, self.time_format)
}
#[cfg(unix)]
Column::Timestamp(TimeType::Created) => {
file.created_time().render(self.theme.ui.date, &self.env.tz, self.time_format)
}
#[cfg(unix)]
Column::Timestamp(TimeType::Accessed) => {
file.accessed_time().render(self.theme.ui.date, &self.env.tz, self.time_format)
}