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:
Darren Schroeder
2022-12-27 12:46:23 -06:00
committed by GitHub
parent 568927349d
commit db06edc5d3
4 changed files with 47 additions and 7 deletions

View File

@ -62,6 +62,7 @@ impl Command for Ls {
"List the specified directory itself instead of its contents",
Some('D'),
)
.switch("mime-type", "Show mime-type in type column", Some('m'))
.category(Category::FileSystem)
}
@ -78,6 +79,7 @@ impl Command for Ls {
let full_paths = call.has_flag("full-paths");
let du = call.has_flag("du");
let directory = call.has_flag("directory");
let use_mime_type = call.has_flag("mime-type");
let ctrl_c = engine_state.ctrlc.clone();
let call_span = call.head;
let cwd = current_dir(engine_state, stack)?;
@ -250,6 +252,7 @@ impl Command for Ls {
long,
du,
ctrl_c.clone(),
use_mime_type,
);
match entry {
Ok(value) => Some(value),
@ -365,7 +368,7 @@ use std::os::unix::fs::FileTypeExt;
use std::path::Path;
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 mut file_type = "unknown";
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)]
pub(crate) fn dir_entry_dict(
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>,
span: Span,
long: bool,
du: bool,
ctrl_c: Option<Arc<AtomicBool>>,
use_mime_type: bool,
) -> Result<Value, ShellError> {
#[cfg(windows)]
if metadata.is_none() {
@ -408,7 +425,7 @@ pub(crate) fn dir_entry_dict(
let mut cols = vec![];
let mut vals = vec![];
let mut file_type = "unknown";
let mut file_type = "unknown".to_string();
cols.push("name".into());
vals.push(Value::String {
@ -417,10 +434,10 @@ pub(crate) fn dir_entry_dict(
});
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());
vals.push(Value::String {
val: file_type.to_string(),
val: file_type.clone(),
span,
});
} else {