Skip to content

Commit

Permalink
LS support for other number formatting (#2650)
Browse files Browse the repository at this point in the history
* make sort-by fail gracefully if mismatched types are compared

* Added a test to check if sorted-by with invalid types exists gracefully

* Linter changes

* removed redundant pattern matching

* Changed the error message

* Added a comma after every argument

* Changed the test to accomodate the new err messages

* Err message for sort-by invalid types now shows the mismatched types

* Lints problems

* Changed unwrap to expect

* Added the -f flag to rm command

Now when you a use rm -f there will be no error message, even if the
file doesnt actually exist

* Lint problems

* Fixed the wrong line

* Removed println

* Spelling mistake

* Fix problems when you mv a file into itself

* Lint mistakes

* Remove unecessary filtering in most cases

* Allow the removal of sockets

* Conditional compilations to systems without socket

* Add a size-format option to ls command

* Added kib and mib formating

* Make patterns lowercase

* New subcommand to format, filesize

* Forgot the linter once more

* Remove the ls changes since its no longer needed

* CI mistakes

* Lint stuff

* Fix lint

* Added formatting for bytes

* fix lint

* Changed the usage comment
  • Loading branch information
luccasmmg committed Oct 16, 2020
1 parent 791e076 commit e626522
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 1 deletion.
1 change: 1 addition & 0 deletions crates/nu-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ pub fn create_default_context(interactive: bool) -> Result<EvaluationContext, Bo
whole_stream_command(Nth),
whole_stream_command(Drop),
whole_stream_command(Format),
whole_stream_command(FileSize),
whole_stream_command(Where),
whole_stream_command(If),
whole_stream_command(Compact),
Expand Down
2 changes: 1 addition & 1 deletion crates/nu-cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ pub(crate) use exec::Exec;
pub(crate) use exit::Exit;
pub(crate) use first::First;
pub(crate) use flatten::Command as Flatten;
pub(crate) use format::Format;
pub(crate) use format::{FileSize, Format};
pub(crate) use from::From;
pub(crate) use from_csv::FromCSV;
pub(crate) use from_eml::FromEML;
Expand Down
File renamed without changes.
194 changes: 194 additions & 0 deletions crates/nu-cli/src/commands/format/format_filesize.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
use crate::prelude::*;
use nu_errors::ShellError;

use crate::commands::WholeStreamCommand;
use nu_protocol::{
ColumnPath, Primitive::Filesize, ReturnSuccess, Signature, SyntaxShape, UntaggedValue,
UntaggedValue::Primitive, Value,
};
use nu_source::Tagged;
use nu_value_ext::get_data_by_column_path;

use num_format::{Locale, ToFormattedString};

pub struct FileSize;

#[derive(Deserialize)]
pub struct Arguments {
field: ColumnPath,
format: Tagged<String>,
}

#[async_trait]
impl WholeStreamCommand for FileSize {
fn name(&self) -> &str {
"format filesize"
}

fn signature(&self) -> Signature {
Signature::build("format filesize")
.required(
"field",
SyntaxShape::ColumnPath,
"the name of the column to update",
)
.required(
"format value",
SyntaxShape::String,
"the format into which convert the filesizes",
)
}

fn usage(&self) -> &str {
"Converts a column of filesizes to some specified format"
}

async fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
filesize(args, registry).await
}

fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Convert the size row to KB",
example: "ls | format filesize size KB",
result: None,
},
Example {
description: "Convert the apparent row to B",
example: "du | format filesize apparent B",
result: None,
},
]
}
}

async fn process_row(
input: Value,
format: Tagged<String>,
field: Arc<ColumnPath>,
) -> Result<OutputStream, ShellError> {
Ok({
let replace_for = get_data_by_column_path(&input, &field, move |_, _, error| error);
match replace_for {
Ok(s) => match convert_bytes_to_string_using_format(s, format) {
Ok(b) => OutputStream::one(ReturnSuccess::value(
input.replace_data_at_column_path(&field, b).expect("Given that the existance check was already done, this souldn't trigger never"),
)),
Err(e) => OutputStream::one(Err(e)),
},
Err(e) => OutputStream::one(Err(e)),
}
})
}

async fn filesize(
raw_args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let (Arguments { field, format }, input) = raw_args.process(&registry).await?;
let field = Arc::new(field);

Ok(input
.then(move |input| {
let format = format.clone();
let field = field.clone();

async {
match process_row(input, format, field).await {
Ok(s) => s,
Err(e) => OutputStream::one(Err(e)),
}
}
})
.flatten()
.to_output_stream())
}

fn convert_bytes_to_string_using_format(
bytes: Value,
format: Tagged<String>,
) -> Result<Value, ShellError> {
match bytes.value {
Primitive(Filesize(b)) => {
let byte = byte_unit::Byte::from_bytes(b as u128);
let value = match format.item().to_lowercase().as_str() {
"b" => Ok(UntaggedValue::string(b.to_formatted_string(&Locale::en))),
"kb" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::KB).to_string(),
)),
"kib" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::KiB).to_string(),
)),
"mb" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::MB).to_string(),
)),
"mib" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::MiB).to_string(),
)),
"gb" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::GB).to_string(),
)),
"gib" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::GiB).to_string(),
)),
"tb" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::TB).to_string(),
)),
"tib" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::TiB).to_string(),
)),
"pb" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::PB).to_string(),
)),
"pib" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::PiB).to_string(),
)),
"eb" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::EB).to_string(),
)),
"eib" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::EiB).to_string(),
)),
"zb" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::ZB).to_string(),
)),
"zib" => Ok(UntaggedValue::string(
byte.get_adjusted_unit(byte_unit::ByteUnit::ZiB).to_string(),
)),
_ => Err(ShellError::labeled_error(
format!("Invalid format code: {:}", format.item()),
"invalid format",
format.tag(),
)),
};
match value {
Ok(b) => Ok(Value { value: b, ..bytes }),
Err(e) => Err(e),
}
}
_ => Err(ShellError::labeled_error(
"the data in this row is not of the type filesize",
"invalid row type",
bytes.tag(),
)),
}
}

#[cfg(test)]
mod tests {
use super::FileSize;
use super::ShellError;

#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
use crate::examples::test as test_examples;

Ok(test_examples(FileSize {})?)
}
}
5 changes: 5 additions & 0 deletions crates/nu-cli/src/commands/format/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod command;
pub mod format_filesize;

pub use command::Format;
pub use format_filesize::FileSize;
25 changes: 25 additions & 0 deletions crates/nu-cli/tests/commands/format.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use nu_test_support::fs::Stub::EmptyFile;
use nu_test_support::playground::Playground;
use nu_test_support::{nu, pipeline};

#[test]
Expand Down Expand Up @@ -42,3 +44,26 @@ fn can_use_variables() {

assert_eq!(actual.out, "nu is a new type of shell");
}

#[test]
fn format_filesize_works() {
Playground::setup("format_filesize_test_1", |dirs, sandbox| {
sandbox.with_files(vec![
EmptyFile("yehuda.txt"),
EmptyFile("jonathan.txt"),
EmptyFile("andres.txt"),
]);

let actual = nu!(
cwd: dirs.test(), pipeline(
r#"
ls
| format filesize size KB
| get size
| first
"#
));

assert_eq!(actual.out, "0.01 KB");
})
}

0 comments on commit e626522

Please sign in to comment.