forked from extern/nushell
add format filesize (#5498)
* add format filesize * add comment * add comment * remove comment
This commit is contained in:
parent
e4959d2f9f
commit
8030f7e9f0
@ -162,6 +162,7 @@ pub fn create_default_context(cwd: impl AsRef<Path>) -> EngineState {
|
||||
Decode,
|
||||
DetectColumns,
|
||||
Format,
|
||||
FileSize,
|
||||
Parse,
|
||||
Size,
|
||||
Split,
|
||||
|
144
crates/nu-command/src/strings/format/filesize.rs
Normal file
144
crates/nu-command/src/strings/format/filesize.rs
Normal file
@ -0,0 +1,144 @@
|
||||
use nu_engine::CallExt;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
format_filesize, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature,
|
||||
Span, SyntaxShape, Value,
|
||||
};
|
||||
use std::iter;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FileSize;
|
||||
|
||||
impl Command for FileSize {
|
||||
fn name(&self) -> &str {
|
||||
"format filesize"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("format filesize")
|
||||
.required(
|
||||
"field",
|
||||
SyntaxShape::String,
|
||||
"the name of the column to update",
|
||||
)
|
||||
.required(
|
||||
"format value",
|
||||
SyntaxShape::String,
|
||||
"the format into which convert the filesizes",
|
||||
)
|
||||
.category(Category::Strings)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Converts a column of filesizes to some specified format"
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let field = call.req::<Value>(engine_state, stack, 0)?.as_string()?;
|
||||
let format_value = call
|
||||
.req::<Value>(engine_state, stack, 1)?
|
||||
.as_string()?
|
||||
.to_ascii_lowercase();
|
||||
let span = call.head;
|
||||
let data_as_value = input.into_value(span);
|
||||
|
||||
// Something need to consider:
|
||||
// 1. what if input data type is not table? For now just output nothing.
|
||||
// 2. what if value is not a FileSize type? For now just return nothing too for the value.
|
||||
match data_as_value {
|
||||
Value::List { vals, span } => format_impl(vals, field, format_value, span),
|
||||
_ => Ok(Value::Nothing { span }.into_pipeline_data()),
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
fn format_impl(
|
||||
vals: Vec<Value>,
|
||||
field: String,
|
||||
format_value: String,
|
||||
input_span: Span,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let records: Vec<Value> = vals
|
||||
.into_iter()
|
||||
.map(|rec| {
|
||||
let record_span = rec.span();
|
||||
match rec {
|
||||
Value::Record { cols, vals, span } => {
|
||||
let mut new_cols = vec![];
|
||||
let mut new_vals = vec![];
|
||||
for (c, v) in iter::zip(cols, vals) {
|
||||
// find column to format, try format the value.
|
||||
if c == field {
|
||||
new_vals.push(format_value_impl(v, &format_value, span));
|
||||
} else {
|
||||
new_vals.push(v);
|
||||
}
|
||||
new_cols.push(c);
|
||||
}
|
||||
Value::Record {
|
||||
cols: new_cols,
|
||||
vals: new_vals,
|
||||
span,
|
||||
}
|
||||
}
|
||||
_ => Value::Nothing {
|
||||
span: match record_span {
|
||||
Ok(s) => s,
|
||||
Err(_) => input_span,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(Value::List {
|
||||
vals: records,
|
||||
span: input_span,
|
||||
}
|
||||
.into_pipeline_data())
|
||||
}
|
||||
|
||||
fn format_value_impl(val: Value, format_value: &str, span: Span) -> Value {
|
||||
match val {
|
||||
Value::Filesize { val, span } => Value::String {
|
||||
// don't need to concern about metric, we just format units by what user input.
|
||||
val: format_filesize(val, format_value, false),
|
||||
span,
|
||||
},
|
||||
_ => Value::Nothing { span },
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
|
||||
test_examples(FileSize)
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
pub mod command;
|
||||
mod filesize;
|
||||
|
||||
pub use self::filesize::FileSize;
|
||||
pub use command::Format;
|
||||
|
@ -46,8 +46,6 @@ fn can_use_variables() {
|
||||
assert_eq!(actual.out, "nu is a new type of shell");
|
||||
}
|
||||
|
||||
// FIXME: jt: needs more work
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn format_filesize_works() {
|
||||
Playground::setup("format_filesize_test_1", |dirs, sandbox| {
|
||||
@ -71,8 +69,6 @@ fn format_filesize_works() {
|
||||
})
|
||||
}
|
||||
|
||||
// FIXME: jt: needs more work
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn format_filesize_works_with_nonempty_files() {
|
||||
Playground::setup(
|
||||
|
@ -458,7 +458,7 @@ impl Value {
|
||||
Value::Bool { val, .. } => val.to_string(),
|
||||
Value::Int { val, .. } => val.to_string(),
|
||||
Value::Float { val, .. } => val.to_string(),
|
||||
Value::Filesize { val, .. } => format_filesize(*val, config),
|
||||
Value::Filesize { val, .. } => format_filesize_from_conf(*val, config),
|
||||
Value::Duration { val, .. } => format_duration(*val),
|
||||
Value::Date { val, .. } => format!("{} ({})", val.to_rfc2822(), HumanTime::from(*val)),
|
||||
Value::Range { val, .. } => {
|
||||
@ -499,7 +499,7 @@ impl Value {
|
||||
Value::Bool { val, .. } => val.to_string(),
|
||||
Value::Int { val, .. } => val.to_string(),
|
||||
Value::Float { val, .. } => val.to_string(),
|
||||
Value::Filesize { val, .. } => format_filesize(*val, config),
|
||||
Value::Filesize { val, .. } => format_filesize_from_conf(*val, config),
|
||||
Value::Duration { val, .. } => format_duration(*val),
|
||||
Value::Date { val, .. } => HumanTime::from(*val).to_string(),
|
||||
Value::Range { val, .. } => {
|
||||
@ -547,7 +547,7 @@ impl Value {
|
||||
Value::Bool { val, .. } => val.to_string(),
|
||||
Value::Int { val, .. } => val.to_string(),
|
||||
Value::Float { val, .. } => val.to_string(),
|
||||
Value::Filesize { val, .. } => format_filesize(*val, config),
|
||||
Value::Filesize { val, .. } => format_filesize_from_conf(*val, config),
|
||||
Value::Duration { val, .. } => format_duration(*val),
|
||||
Value::Date { val, .. } => format!("{:?}", val),
|
||||
Value::Range { val, .. } => {
|
||||
@ -2325,14 +2325,24 @@ pub fn format_duration(duration: i64) -> String {
|
||||
)
|
||||
}
|
||||
|
||||
fn format_filesize(num_bytes: i64, config: &Config) -> String {
|
||||
fn format_filesize_from_conf(num_bytes: i64, config: &Config) -> String {
|
||||
// We need to take into account config.filesize_metric so, if someone asks for KB
|
||||
// filesize_metric is true, return KiB
|
||||
format_filesize(
|
||||
num_bytes,
|
||||
config.filesize_format.as_str(),
|
||||
config.filesize_metric,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn format_filesize(num_bytes: i64, format_value: &str, filesize_metric: bool) -> String {
|
||||
// Allow the user to specify how they want their numbers formatted
|
||||
let filesize_format_var = get_config_filesize_format(config);
|
||||
let filesize_format_var = get_filesize_format(format_value, filesize_metric);
|
||||
|
||||
let byte = byte_unit::Byte::from_bytes(num_bytes as u128);
|
||||
let adj_byte =
|
||||
if filesize_format_var.0 == byte_unit::ByteUnit::B && filesize_format_var.1 == "auto" {
|
||||
byte.get_appropriate_unit(!config.filesize_metric)
|
||||
byte.get_appropriate_unit(!filesize_metric)
|
||||
} else {
|
||||
byte.get_adjusted_unit(filesize_format_var.0)
|
||||
};
|
||||
@ -2371,13 +2381,11 @@ fn format_filesize(num_bytes: i64, config: &Config) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_config_filesize_format(config: &Config) -> (ByteUnit, &str) {
|
||||
// We need to take into account config.filesize_metric so, if someone asks for KB
|
||||
// filesize_metric is true, return KiB
|
||||
let filesize_format = match config.filesize_format.as_str() {
|
||||
fn get_filesize_format(format_value: &str, filesize_metric: bool) -> (ByteUnit, &str) {
|
||||
match format_value {
|
||||
"b" => (byte_unit::ByteUnit::B, ""),
|
||||
"kb" => {
|
||||
if config.filesize_metric {
|
||||
if filesize_metric {
|
||||
(byte_unit::ByteUnit::KiB, "")
|
||||
} else {
|
||||
(byte_unit::ByteUnit::KB, "")
|
||||
@ -2385,7 +2393,7 @@ fn get_config_filesize_format(config: &Config) -> (ByteUnit, &str) {
|
||||
}
|
||||
"kib" => (byte_unit::ByteUnit::KiB, ""),
|
||||
"mb" => {
|
||||
if config.filesize_metric {
|
||||
if filesize_metric {
|
||||
(byte_unit::ByteUnit::MiB, "")
|
||||
} else {
|
||||
(byte_unit::ByteUnit::MB, "")
|
||||
@ -2393,7 +2401,7 @@ fn get_config_filesize_format(config: &Config) -> (ByteUnit, &str) {
|
||||
}
|
||||
"mib" => (byte_unit::ByteUnit::MiB, ""),
|
||||
"gb" => {
|
||||
if config.filesize_metric {
|
||||
if filesize_metric {
|
||||
(byte_unit::ByteUnit::GiB, "")
|
||||
} else {
|
||||
(byte_unit::ByteUnit::GB, "")
|
||||
@ -2401,7 +2409,7 @@ fn get_config_filesize_format(config: &Config) -> (ByteUnit, &str) {
|
||||
}
|
||||
"gib" => (byte_unit::ByteUnit::GiB, ""),
|
||||
"tb" => {
|
||||
if config.filesize_metric {
|
||||
if filesize_metric {
|
||||
(byte_unit::ByteUnit::TiB, "")
|
||||
} else {
|
||||
(byte_unit::ByteUnit::TB, "")
|
||||
@ -2409,7 +2417,7 @@ fn get_config_filesize_format(config: &Config) -> (ByteUnit, &str) {
|
||||
}
|
||||
"tib" => (byte_unit::ByteUnit::TiB, ""),
|
||||
"pb" => {
|
||||
if config.filesize_metric {
|
||||
if filesize_metric {
|
||||
(byte_unit::ByteUnit::PiB, "")
|
||||
} else {
|
||||
(byte_unit::ByteUnit::PB, "")
|
||||
@ -2417,7 +2425,7 @@ fn get_config_filesize_format(config: &Config) -> (ByteUnit, &str) {
|
||||
}
|
||||
"pib" => (byte_unit::ByteUnit::PiB, ""),
|
||||
"eb" => {
|
||||
if config.filesize_metric {
|
||||
if filesize_metric {
|
||||
(byte_unit::ByteUnit::EiB, "")
|
||||
} else {
|
||||
(byte_unit::ByteUnit::EB, "")
|
||||
@ -2425,7 +2433,7 @@ fn get_config_filesize_format(config: &Config) -> (ByteUnit, &str) {
|
||||
}
|
||||
"eib" => (byte_unit::ByteUnit::EiB, ""),
|
||||
"zb" => {
|
||||
if config.filesize_metric {
|
||||
if filesize_metric {
|
||||
(byte_unit::ByteUnit::ZiB, "")
|
||||
} else {
|
||||
(byte_unit::ByteUnit::ZB, "")
|
||||
@ -2433,9 +2441,7 @@ fn get_config_filesize_format(config: &Config) -> (ByteUnit, &str) {
|
||||
}
|
||||
"zib" => (byte_unit::ByteUnit::ZiB, ""),
|
||||
_ => (byte_unit::ByteUnit::B, "auto"),
|
||||
};
|
||||
|
||||
filesize_format
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
Loading…
Reference in New Issue
Block a user