1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 12:37:49 +00:00

ls: Process OsStrings instead of Strings

This commit is contained in:
Jan Verbeek 2021-08-31 12:57:39 +02:00
parent 4d6faae555
commit 483a5fd1d4
2 changed files with 19 additions and 17 deletions

View file

@ -21,6 +21,7 @@ use lscolors::LsColors;
use number_prefix::NumberPrefix;
use once_cell::unsync::OnceCell;
use quoting_style::{escape_name, QuotingStyle};
use std::ffi::OsString;
#[cfg(windows)]
use std::os::windows::fs::MetadataExt;
use std::{
@ -1173,7 +1174,7 @@ struct PathData {
md: OnceCell<Option<Metadata>>,
ft: OnceCell<Option<FileType>>,
// Name of the file - will be empty for . or ..
display_name: String,
display_name: OsString,
// PathBuf that all above data corresponds to
p_buf: PathBuf,
must_dereference: bool,
@ -1183,7 +1184,7 @@ impl PathData {
fn new(
p_buf: PathBuf,
file_type: Option<std::io::Result<FileType>>,
file_name: Option<String>,
file_name: Option<OsString>,
config: &Config,
command_line: bool,
) -> Self {
@ -1191,16 +1192,13 @@ impl PathData {
// For '..', the filename is None
let display_name = if let Some(name) = file_name {
name
} else if command_line {
p_buf.clone().into()
} else {
let display_os_str = if command_line {
p_buf.as_os_str()
} else {
p_buf
.file_name()
.unwrap_or_else(|| p_buf.iter().next_back().unwrap())
};
display_os_str.to_string_lossy().into_owned()
p_buf
.file_name()
.unwrap_or_else(|| p_buf.iter().next_back().unwrap())
.to_owned()
};
let must_dereference = match &config.dereference {
Dereference::All => true,

View file

@ -1,4 +1,5 @@
use std::char::from_digit;
use std::ffi::OsStr;
// These are characters with special meaning in the shell (e.g. bash).
// The first const contains characters that only have a special meaning when they appear at the beginning of a name.
@ -255,19 +256,21 @@ fn shell_with_escape(name: &str, quotes: Quotes) -> (String, bool) {
(escaped_str, must_quote)
}
pub(super) fn escape_name(name: &str, style: &QuotingStyle) -> String {
pub(super) fn escape_name(name: &OsStr, style: &QuotingStyle) -> String {
match style {
QuotingStyle::Literal { show_control } => {
if !show_control {
name.chars()
name.to_string_lossy()
.chars()
.flat_map(|c| EscapedChar::new_literal(c).hide_control())
.collect()
} else {
name.into()
name.to_string_lossy().into_owned()
}
}
QuotingStyle::C { quotes } => {
let escaped_str: String = name
.to_string_lossy()
.chars()
.flat_map(|c| EscapedChar::new_c(c, *quotes))
.collect();
@ -283,6 +286,7 @@ pub(super) fn escape_name(name: &str, style: &QuotingStyle) -> String {
always_quote,
show_control,
} => {
let name = name.to_string_lossy();
let (quotes, must_quote) = if name.contains('"') {
(Quotes::Single, true)
} else if name.contains('\'') {
@ -294,9 +298,9 @@ pub(super) fn escape_name(name: &str, style: &QuotingStyle) -> String {
};
let (escaped_str, contains_quote_chars) = if *escape {
shell_with_escape(name, quotes)
shell_with_escape(&name, quotes)
} else {
shell_without_escape(name, quotes, *show_control)
shell_without_escape(&name, quotes, *show_control)
};
match (must_quote | contains_quote_chars, quotes) {
@ -362,7 +366,7 @@ mod tests {
fn check_names(name: &str, map: Vec<(&str, &str)>) {
assert_eq!(
map.iter()
.map(|(_, style)| escape_name(name, &get_style(style)))
.map(|(_, style)| escape_name(name.as_ref(), &get_style(style)))
.collect::<Vec<String>>(),
map.iter()
.map(|(correct, _)| correct.to_string())