forked from extern/nushell
add --mime-type(-m)
to ls
in the type
column (#7616)
# Description This PR adds the `mime-type` to the `type` column if you add the `--mime-type(-m)` flag to `ls`. <img width="853" alt="Screenshot 2022-12-27 at 11 43 20 AM" src="https://user-images.githubusercontent.com/343840/209705499-27fe40fe-0356-4d9d-97f2-4b2dc52e0963.png"> <img width="781" alt="Screenshot 2022-12-27 at 11 45 53 AM" src="https://user-images.githubusercontent.com/343840/209705509-4d677389-fd68-401e-a7af-3fc6052743b6.png"> # User-Facing Changes If you specify the `-m` flag, you get the "guessed at" mime type. The guess is based on the file name and uses this crate https://docs.rs/mime_guess/latest/mime_guess/ for the guessing. Part of issue #7612 and and #7524 There's some debate on if the `mime-type` should be added to the `type` column or if there should be a separate `mime` column. I tend to lean on the side of `type` since it's technically a type and it's only in that column if you ask it to be there. Also, I'd prefer to reuse a column rather than having a list of sprawling columns. Also, as @KodiCraft suggested, there is precedence as with `ls -d` where the summed size is in the size column. I could go either way and if someone wants to create a `mime` column, we'd probably accept it. # Tests + Formatting Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass # After Submitting If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date.
This commit is contained in:
parent
568927349d
commit
db06edc5d3
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -2271,6 +2271,16 @@ version = "0.3.16"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime_guess"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
|
||||||
|
dependencies = [
|
||||||
|
"mime",
|
||||||
|
"unicase",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@ -2620,6 +2630,7 @@ dependencies = [
|
|||||||
"md-5",
|
"md-5",
|
||||||
"meval",
|
"meval",
|
||||||
"mime",
|
"mime",
|
||||||
|
"mime_guess",
|
||||||
"notify",
|
"notify",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
"nu-color-config",
|
"nu-color-config",
|
||||||
@ -5241,6 +5252,15 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
|
@ -459,7 +459,7 @@ fn flag_completions() {
|
|||||||
// Test completions for the 'ls' flags
|
// Test completions for the 'ls' flags
|
||||||
let suggestions = completer.complete("ls -", 4);
|
let suggestions = completer.complete("ls -", 4);
|
||||||
|
|
||||||
assert_eq!(14, suggestions.len());
|
assert_eq!(16, suggestions.len());
|
||||||
|
|
||||||
let expected: Vec<String> = vec![
|
let expected: Vec<String> = vec![
|
||||||
"--all".into(),
|
"--all".into(),
|
||||||
@ -468,6 +468,7 @@ fn flag_completions() {
|
|||||||
"--full-paths".into(),
|
"--full-paths".into(),
|
||||||
"--help".into(),
|
"--help".into(),
|
||||||
"--long".into(),
|
"--long".into(),
|
||||||
|
"--mime-type".into(),
|
||||||
"--short-names".into(),
|
"--short-names".into(),
|
||||||
"-D".into(),
|
"-D".into(),
|
||||||
"-a".into(),
|
"-a".into(),
|
||||||
@ -475,6 +476,7 @@ fn flag_completions() {
|
|||||||
"-f".into(),
|
"-f".into(),
|
||||||
"-h".into(),
|
"-h".into(),
|
||||||
"-l".into(),
|
"-l".into(),
|
||||||
|
"-m".into(),
|
||||||
"-s".into(),
|
"-s".into(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ lscolors = { version = "0.12.0", features = ["crossterm"], default-features = fa
|
|||||||
md5 = { package = "md-5", version = "0.10.0" }
|
md5 = { package = "md-5", version = "0.10.0" }
|
||||||
meval = "0.2.0"
|
meval = "0.2.0"
|
||||||
mime = "0.3.16"
|
mime = "0.3.16"
|
||||||
|
mime_guess = "2.0.4"
|
||||||
notify = "4.0.17"
|
notify = "4.0.17"
|
||||||
num = { version = "0.4.0", optional = true }
|
num = { version = "0.4.0", optional = true }
|
||||||
num-traits = "0.2.14"
|
num-traits = "0.2.14"
|
||||||
|
@ -62,6 +62,7 @@ impl Command for Ls {
|
|||||||
"List the specified directory itself instead of its contents",
|
"List the specified directory itself instead of its contents",
|
||||||
Some('D'),
|
Some('D'),
|
||||||
)
|
)
|
||||||
|
.switch("mime-type", "Show mime-type in type column", Some('m'))
|
||||||
.category(Category::FileSystem)
|
.category(Category::FileSystem)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +79,7 @@ impl Command for Ls {
|
|||||||
let full_paths = call.has_flag("full-paths");
|
let full_paths = call.has_flag("full-paths");
|
||||||
let du = call.has_flag("du");
|
let du = call.has_flag("du");
|
||||||
let directory = call.has_flag("directory");
|
let directory = call.has_flag("directory");
|
||||||
|
let use_mime_type = call.has_flag("mime-type");
|
||||||
let ctrl_c = engine_state.ctrlc.clone();
|
let ctrl_c = engine_state.ctrlc.clone();
|
||||||
let call_span = call.head;
|
let call_span = call.head;
|
||||||
let cwd = current_dir(engine_state, stack)?;
|
let cwd = current_dir(engine_state, stack)?;
|
||||||
@ -250,6 +252,7 @@ impl Command for Ls {
|
|||||||
long,
|
long,
|
||||||
du,
|
du,
|
||||||
ctrl_c.clone(),
|
ctrl_c.clone(),
|
||||||
|
use_mime_type,
|
||||||
);
|
);
|
||||||
match entry {
|
match entry {
|
||||||
Ok(value) => Some(value),
|
Ok(value) => Some(value),
|
||||||
@ -365,7 +368,7 @@ use std::os::unix::fs::FileTypeExt;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
pub fn get_file_type(md: &std::fs::Metadata) -> &str {
|
pub fn get_file_type(md: &std::fs::Metadata, display_name: &str, use_mime_type: bool) -> String {
|
||||||
let ft = md.file_type();
|
let ft = md.file_type();
|
||||||
let mut file_type = "unknown";
|
let mut file_type = "unknown";
|
||||||
if ft.is_dir() {
|
if ft.is_dir() {
|
||||||
@ -388,18 +391,32 @@ pub fn get_file_type(md: &std::fs::Metadata) -> &str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_type
|
if use_mime_type {
|
||||||
|
let guess = mime_guess::from_path(display_name);
|
||||||
|
let mime_guess = match guess.first() {
|
||||||
|
Some(mime_type) => mime_type.essence_str().to_string(),
|
||||||
|
None => "unknown".to_string(),
|
||||||
|
};
|
||||||
|
if file_type == "file" {
|
||||||
|
mime_guess
|
||||||
|
} else {
|
||||||
|
file_type.to_string()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
file_type.to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) fn dir_entry_dict(
|
pub(crate) fn dir_entry_dict(
|
||||||
filename: &std::path::Path, // absolute path
|
filename: &std::path::Path, // absolute path
|
||||||
display_name: &str, // gile name to be displayed
|
display_name: &str, // file name to be displayed
|
||||||
metadata: Option<&std::fs::Metadata>,
|
metadata: Option<&std::fs::Metadata>,
|
||||||
span: Span,
|
span: Span,
|
||||||
long: bool,
|
long: bool,
|
||||||
du: bool,
|
du: bool,
|
||||||
ctrl_c: Option<Arc<AtomicBool>>,
|
ctrl_c: Option<Arc<AtomicBool>>,
|
||||||
|
use_mime_type: bool,
|
||||||
) -> Result<Value, ShellError> {
|
) -> Result<Value, ShellError> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
if metadata.is_none() {
|
if metadata.is_none() {
|
||||||
@ -408,7 +425,7 @@ pub(crate) fn dir_entry_dict(
|
|||||||
|
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
let mut vals = vec![];
|
let mut vals = vec![];
|
||||||
let mut file_type = "unknown";
|
let mut file_type = "unknown".to_string();
|
||||||
|
|
||||||
cols.push("name".into());
|
cols.push("name".into());
|
||||||
vals.push(Value::String {
|
vals.push(Value::String {
|
||||||
@ -417,10 +434,10 @@ pub(crate) fn dir_entry_dict(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if let Some(md) = metadata {
|
if let Some(md) = metadata {
|
||||||
file_type = get_file_type(md);
|
file_type = get_file_type(md, display_name, use_mime_type);
|
||||||
cols.push("type".into());
|
cols.push("type".into());
|
||||||
vals.push(Value::String {
|
vals.push(Value::String {
|
||||||
val: file_type.to_string(),
|
val: file_type.clone(),
|
||||||
span,
|
span,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user