mirror of
https://github.com/nushell/nushell.git
synced 2025-06-30 22:50:14 +02:00
Move Value to helpers, separate span call (#10121)
# Description As part of the refactor to split spans off of Value, this moves to using helper functions to create values, and using `.span()` instead of matching span out of Value directly. Hoping to get a few more helping hands to finish this, as there are a lot of commands to update :) # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # 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` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use std testing; testing run-tests --path crates/nu-std"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # 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. --> --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com> Co-authored-by: WindSoilder <windsoilder@outlook.com>
This commit is contained in:
@ -63,8 +63,8 @@ impl Command for DetectColumns {
|
||||
Example {
|
||||
description: "Splits string across multiple columns",
|
||||
example: "'a b c' | detect columns -n",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec![
|
||||
"column0".to_string(),
|
||||
"column1".to_string(),
|
||||
@ -77,7 +77,7 @@ impl Command for DetectColumns {
|
||||
],
|
||||
})],
|
||||
span,
|
||||
}),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "",
|
||||
@ -150,10 +150,7 @@ fn detect_columns(
|
||||
if headers.len() == row.len() {
|
||||
for (header, val) in headers.iter().zip(row.iter()) {
|
||||
cols.push(header.item.clone());
|
||||
vals.push(Value::String {
|
||||
val: val.item.clone(),
|
||||
span: name_span,
|
||||
});
|
||||
vals.push(Value::string(val.item.clone(), name_span));
|
||||
}
|
||||
} else {
|
||||
let mut pre_output = vec![];
|
||||
@ -217,10 +214,7 @@ fn detect_columns(
|
||||
}
|
||||
Err(processing_error) => {
|
||||
let err = processing_error("could not find range index", name_span);
|
||||
return Value::Error {
|
||||
error: Box::new(err),
|
||||
span: name_span,
|
||||
};
|
||||
return Value::error(err, name_span);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -90,8 +90,8 @@ fn action(
|
||||
"binhex" => GeneralPurpose::new(&alphabet::BIN_HEX, NO_PAD),
|
||||
"crypt" => GeneralPurpose::new(&alphabet::CRYPT, NO_PAD),
|
||||
"mutf7" => GeneralPurpose::new(&alphabet::IMAP_MUTF7, NO_PAD),
|
||||
not_valid => return Value::Error { error:
|
||||
Box::new(ShellError::GenericError(
|
||||
not_valid => return Value::error (
|
||||
ShellError::GenericError(
|
||||
"value is not an accepted character set".to_string(),
|
||||
format!(
|
||||
"{not_valid} is not a valid character-set.\nPlease use `help encode base64` to see a list of valid character sets."
|
||||
@ -99,48 +99,46 @@ fn action(
|
||||
Some(config_character_set.span),
|
||||
None,
|
||||
Vec::new(),
|
||||
)), span:config_character_set.span}
|
||||
), config_character_set.span)
|
||||
};
|
||||
let value_span = input.span();
|
||||
match input {
|
||||
// Propagate existing errors.
|
||||
Value::Error { .. } => input.clone(),
|
||||
Value::Binary { val, span } => match base64_config.action_type {
|
||||
Value::Binary { val, .. } => match base64_config.action_type {
|
||||
ActionType::Encode => {
|
||||
let mut enc_vec = Vec::new();
|
||||
enc_vec.resize(val.len() * 4 / 3 + 4, 0);
|
||||
let bytes_written = match base64_engine.encode_slice(val, &mut enc_vec) {
|
||||
Ok(bytes_written) => bytes_written,
|
||||
Err(err) => {
|
||||
return Value::Error {
|
||||
error: Box::new(ShellError::GenericError(
|
||||
return Value::error(
|
||||
ShellError::GenericError(
|
||||
"Error encoding data".into(),
|
||||
err.to_string(),
|
||||
Some(*span),
|
||||
Some(value_span),
|
||||
None,
|
||||
Vec::new(),
|
||||
)),
|
||||
span: *span,
|
||||
}
|
||||
),
|
||||
value_span,
|
||||
)
|
||||
}
|
||||
};
|
||||
enc_vec.truncate(bytes_written);
|
||||
Value::string(std::str::from_utf8(&enc_vec).unwrap_or(""), command_span)
|
||||
}
|
||||
ActionType::Decode => Value::Error {
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
ActionType::Decode => Value::error(
|
||||
ShellError::UnsupportedInput(
|
||||
"Binary data can only be encoded".to_string(),
|
||||
"value originates from here".into(),
|
||||
command_span,
|
||||
// This line requires the Value::Error {} match above.
|
||||
input.span(),
|
||||
)),
|
||||
span: command_span,
|
||||
},
|
||||
),
|
||||
command_span,
|
||||
),
|
||||
},
|
||||
Value::String {
|
||||
val,
|
||||
span: value_span,
|
||||
} => {
|
||||
Value::String { val, .. } => {
|
||||
match base64_config.action_type {
|
||||
ActionType::Encode => {
|
||||
let mut enc_str = String::new();
|
||||
@ -160,22 +158,22 @@ fn action(
|
||||
} else {
|
||||
match String::from_utf8(decoded_value) {
|
||||
Ok(string_value) => Value::string(string_value, command_span),
|
||||
Err(e) => Value::Error {
|
||||
error: Box::new(ShellError::GenericError(
|
||||
Err(e) => Value::error(
|
||||
ShellError::GenericError(
|
||||
"base64 payload isn't a valid utf-8 sequence"
|
||||
.to_owned(),
|
||||
e.to_string(),
|
||||
Some(*value_span),
|
||||
Some(value_span),
|
||||
Some("consider using the `--binary` flag".to_owned()),
|
||||
Vec::new(),
|
||||
)),
|
||||
span: *value_span,
|
||||
},
|
||||
),
|
||||
value_span,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => Value::Error {
|
||||
error: Box::new(ShellError::GenericError(
|
||||
Err(_) => Value::error(
|
||||
ShellError::GenericError(
|
||||
"value could not be base64 decoded".to_string(),
|
||||
format!(
|
||||
"invalid base64 input for character set {}",
|
||||
@ -184,20 +182,20 @@ fn action(
|
||||
Some(command_span),
|
||||
None,
|
||||
Vec::new(),
|
||||
)),
|
||||
span: command_span,
|
||||
},
|
||||
),
|
||||
command_span,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
other => Value::Error {
|
||||
error: Box::new(ShellError::TypeMismatch {
|
||||
other => Value::error(
|
||||
ShellError::TypeMismatch {
|
||||
err_message: format!("string or binary, not {}", other.get_type()),
|
||||
span: other.span(),
|
||||
}),
|
||||
span: other.span(),
|
||||
},
|
||||
},
|
||||
other.span(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,10 +321,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn base64_encode_binary() {
|
||||
let word = Value::Binary {
|
||||
val: vec![77, 97, 110],
|
||||
span: Span::test_data(),
|
||||
};
|
||||
let word = Value::binary(vec![77, 97, 110], Span::test_data());
|
||||
let expected = Value::test_string("TWFu");
|
||||
|
||||
let actual = action(
|
||||
@ -349,10 +344,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn base64_decode_binary_expect_error() {
|
||||
let word = Value::Binary {
|
||||
val: vec![77, 97, 110],
|
||||
span: Span::test_data(),
|
||||
};
|
||||
let word = Value::binary(vec![77, 97, 110], Span::test_data());
|
||||
|
||||
let actual = action(
|
||||
&word,
|
||||
|
@ -47,10 +47,7 @@ documentation link at https://docs.rs/encoding_rs/latest/encoding_rs/#statics"#
|
||||
Example {
|
||||
description: "Decode an UTF-16 string into nushell UTF-8 string",
|
||||
example: r#"0x[00 53 00 6F 00 6D 00 65 00 20 00 44 00 61 00 74 00 61] | decode utf-16be"#,
|
||||
result: Some(Value::String {
|
||||
val: "Some Data".to_owned(),
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
result: Some(Value::string("Some Data".to_owned(), Span::test_data())),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -77,29 +74,29 @@ documentation link at https://docs.rs/encoding_rs/latest/encoding_rs/#statics"#
|
||||
Some(encoding_name) => super::encoding::decode(head, encoding_name, &bytes),
|
||||
None => super::encoding::detect_encoding_name(head, input_span, &bytes)
|
||||
.map(|encoding| encoding.decode(&bytes).0.into_owned())
|
||||
.map(|s| Value::String { val: s, span: head }),
|
||||
.map(|s| Value::string(s, head)),
|
||||
}
|
||||
.map(|val| val.into_pipeline_data())
|
||||
}
|
||||
PipelineData::Value(v, ..) => match v {
|
||||
Value::Binary {
|
||||
val: bytes,
|
||||
span: input_span,
|
||||
} => match encoding {
|
||||
Some(encoding_name) => super::encoding::decode(head, encoding_name, &bytes),
|
||||
None => super::encoding::detect_encoding_name(head, input_span, &bytes)
|
||||
.map(|encoding| encoding.decode(&bytes).0.into_owned())
|
||||
.map(|s| Value::String { val: s, span: head }),
|
||||
PipelineData::Value(v, ..) => {
|
||||
let input_span = v.span();
|
||||
match v {
|
||||
Value::Binary { val: bytes, .. } => match encoding {
|
||||
Some(encoding_name) => super::encoding::decode(head, encoding_name, &bytes),
|
||||
None => super::encoding::detect_encoding_name(head, input_span, &bytes)
|
||||
.map(|encoding| encoding.decode(&bytes).0.into_owned())
|
||||
.map(|s| Value::string(s, head)),
|
||||
}
|
||||
.map(|val| val.into_pipeline_data()),
|
||||
Value::Error { error, .. } => Err(*error),
|
||||
_ => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: v.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: v.span(),
|
||||
}),
|
||||
}
|
||||
.map(|val| val.into_pipeline_data()),
|
||||
Value::Error { error, .. } => Err(*error),
|
||||
_ => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "binary".into(),
|
||||
wrong_type: v.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: v.span(),
|
||||
}),
|
||||
},
|
||||
}
|
||||
// This should be more precise, but due to difficulties in getting spans
|
||||
// from PipelineData::ListData, this is as it is.
|
||||
_ => Err(ShellError::UnsupportedInput(
|
||||
|
@ -53,23 +53,23 @@ documentation link at https://docs.rs/encoding_rs/latest/encoding_rs/#statics"#
|
||||
Example {
|
||||
description: "Encode an UTF-8 string into Shift-JIS",
|
||||
example: r#""負けると知って戦うのが、遥かに美しいのだ" | encode shift-jis"#,
|
||||
result: Some(Value::Binary {
|
||||
val: vec![
|
||||
result: Some(Value::binary(
|
||||
vec![
|
||||
0x95, 0x89, 0x82, 0xaf, 0x82, 0xe9, 0x82, 0xc6, 0x92, 0x6d, 0x82, 0xc1,
|
||||
0x82, 0xc4, 0x90, 0xed, 0x82, 0xa4, 0x82, 0xcc, 0x82, 0xaa, 0x81, 0x41,
|
||||
0x97, 0x79, 0x82, 0xa9, 0x82, 0xc9, 0x94, 0xfc, 0x82, 0xb5, 0x82, 0xa2,
|
||||
0x82, 0xcc, 0x82, 0xbe,
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Replace characters with HTML entities if they can't be encoded",
|
||||
example: r#""🎈" | encode -i shift-jis"#,
|
||||
result: Some(Value::Binary {
|
||||
val: vec![0x26, 0x23, 0x31, 0x32, 0x37, 0x38, 0x38, 0x30, 0x3b],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
result: Some(Value::binary(
|
||||
vec![0x26, 0x23, 0x31, 0x32, 0x37, 0x38, 0x38, 0x30, 0x3b],
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -95,19 +95,22 @@ documentation link at https://docs.rs/encoding_rs/latest/encoding_rs/#statics"#
|
||||
super::encoding::encode(head, encoding, &s.item, s.span, ignore_errors)
|
||||
.map(|val| val.into_pipeline_data())
|
||||
}
|
||||
PipelineData::Value(v, ..) => match v {
|
||||
Value::String { val: s, span } => {
|
||||
super::encoding::encode(head, encoding, &s, span, ignore_errors)
|
||||
.map(|val| val.into_pipeline_data())
|
||||
PipelineData::Value(v, ..) => {
|
||||
let span = v.span();
|
||||
match v {
|
||||
Value::String { val: s, .. } => {
|
||||
super::encoding::encode(head, encoding, &s, span, ignore_errors)
|
||||
.map(|val| val.into_pipeline_data())
|
||||
}
|
||||
Value::Error { error, .. } => Err(*error),
|
||||
_ => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: v.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: v.span(),
|
||||
}),
|
||||
}
|
||||
Value::Error { error, .. } => Err(*error),
|
||||
_ => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: v.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: v.span(),
|
||||
}),
|
||||
},
|
||||
}
|
||||
// This should be more precise, but due to difficulties in getting spans
|
||||
// from PipelineData::ListStream, this is as it is.
|
||||
_ => Err(ShellError::UnsupportedInput(
|
||||
|
@ -34,10 +34,7 @@ pub fn decode(
|
||||
parse_encoding(encoding_name.span, &encoding_name.item)
|
||||
}?;
|
||||
let (result, ..) = encoding.decode(bytes);
|
||||
Ok(Value::String {
|
||||
val: result.into_owned(),
|
||||
span: head,
|
||||
})
|
||||
Ok(Value::string(result.into_owned(), head))
|
||||
}
|
||||
|
||||
pub fn encode(
|
||||
@ -66,10 +63,7 @@ pub fn encode(
|
||||
vec![],
|
||||
))
|
||||
} else {
|
||||
Ok(Value::Binary {
|
||||
val: result.into_owned(),
|
||||
span: head,
|
||||
})
|
||||
Ok(Value::binary(result.into_owned(), head))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,19 +79,19 @@ impl Command for FormatDate {
|
||||
Example {
|
||||
description: "Format a given date-time using the default format (RFC 2822).",
|
||||
example: r#"'2021-10-22 20:00:12 +01:00' | into datetime | format date"#,
|
||||
result: Some(Value::String {
|
||||
val: "Fri, 22 Oct 2021 20:00:12 +0100".to_string(),
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
result: Some(Value::string(
|
||||
"Fri, 22 Oct 2021 20:00:12 +0100".to_string(),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description:
|
||||
"Format a given date-time as a string using the default format (RFC 2822).",
|
||||
example: r#""2021-10-22 20:00:12 +01:00" | format date"#,
|
||||
result: Some(Value::String {
|
||||
val: "Fri, 22 Oct 2021 20:00:12 +0100".to_string(),
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
result: Some(Value::string(
|
||||
"Fri, 22 Oct 2021 20:00:12 +0100".to_string(),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Format the current date-time using a given format string.",
|
||||
@ -126,17 +126,14 @@ where
|
||||
let format = date_time.format_localized(formatter, locale);
|
||||
|
||||
match formatter_buf.write_fmt(format_args!("{format}")) {
|
||||
Ok(_) => Value::String {
|
||||
val: formatter_buf,
|
||||
span,
|
||||
},
|
||||
Err(_) => Value::Error {
|
||||
error: Box::new(ShellError::TypeMismatch {
|
||||
Ok(_) => Value::string(formatter_buf, span),
|
||||
Err(_) => Value::error(
|
||||
ShellError::TypeMismatch {
|
||||
err_message: "invalid format".to_string(),
|
||||
span,
|
||||
}),
|
||||
},
|
||||
span,
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,39 +148,28 @@ fn format_helper(value: Value, formatter: &str, formatter_span: Span, head_span:
|
||||
Err(e) => e,
|
||||
}
|
||||
}
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::DatetimeParseError(
|
||||
value.debug_value(),
|
||||
head_span,
|
||||
)),
|
||||
span: head_span,
|
||||
},
|
||||
_ => Value::error(
|
||||
ShellError::DatetimeParseError(value.debug_value(), head_span),
|
||||
head_span,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn format_helper_rfc2822(value: Value, span: Span) -> Value {
|
||||
let val_span = value.span();
|
||||
match value {
|
||||
Value::Date { val, span: _ } => Value::String {
|
||||
val: val.to_rfc2822(),
|
||||
span,
|
||||
},
|
||||
Value::String {
|
||||
val,
|
||||
span: val_span,
|
||||
} => {
|
||||
Value::Date { val, .. } => Value::string(val.to_rfc2822(), span),
|
||||
Value::String { val, .. } => {
|
||||
let dt = parse_date_from_string(&val, val_span);
|
||||
match dt {
|
||||
Ok(x) => Value::String {
|
||||
val: x.to_rfc2822(),
|
||||
span,
|
||||
},
|
||||
Ok(x) => Value::string(x.to_rfc2822(), span),
|
||||
Err(e) => e,
|
||||
}
|
||||
}
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::DatetimeParseError(value.debug_value(), span)),
|
||||
_ => Value::error(
|
||||
ShellError::DatetimeParseError(value.debug_value(), span),
|
||||
span,
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,14 +111,12 @@ impl Command for FormatDuration {
|
||||
}
|
||||
|
||||
fn format_value_impl(val: &Value, arg: &Arguments, span: Span) -> Value {
|
||||
let inner_span = val.span();
|
||||
match val {
|
||||
Value::Duration {
|
||||
val: inner,
|
||||
span: inner_span,
|
||||
} => {
|
||||
Value::Duration { val: inner, .. } => {
|
||||
let duration = *inner;
|
||||
let float_precision = arg.float_precision;
|
||||
match convert_inner_to_unit(duration, &arg.format_value, span, *inner_span) {
|
||||
match convert_inner_to_unit(duration, &arg.format_value, span, inner_span) {
|
||||
Ok(d) => {
|
||||
let unit = if &arg.format_value == "us" {
|
||||
"µs"
|
||||
@ -126,33 +124,24 @@ fn format_value_impl(val: &Value, arg: &Arguments, span: Span) -> Value {
|
||||
&arg.format_value
|
||||
};
|
||||
if d.fract() == 0.0 {
|
||||
Value::String {
|
||||
val: format!("{} {}", d, unit),
|
||||
span: *inner_span,
|
||||
}
|
||||
Value::string(format!("{} {}", d, unit), inner_span)
|
||||
} else {
|
||||
Value::String {
|
||||
val: format!("{:.float_precision$} {}", d, unit),
|
||||
span: *inner_span,
|
||||
}
|
||||
Value::string(format!("{:.float_precision$} {}", d, unit), inner_span)
|
||||
}
|
||||
}
|
||||
Err(e) => Value::Error {
|
||||
error: Box::new(e),
|
||||
span: *inner_span,
|
||||
},
|
||||
Err(e) => Value::error(e, inner_span),
|
||||
}
|
||||
}
|
||||
Value::Error { .. } => val.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "filesize".into(),
|
||||
wrong_type: val.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: val.span(),
|
||||
}),
|
||||
},
|
||||
span,
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,22 +103,23 @@ impl Command for FormatFilesize {
|
||||
}
|
||||
|
||||
fn format_value_impl(val: &Value, arg: &Arguments, span: Span) -> Value {
|
||||
let value_span = val.span();
|
||||
match val {
|
||||
Value::Filesize { val, span } => Value::String {
|
||||
Value::Filesize { val, .. } => Value::string(
|
||||
// don't need to concern about metric, we just format units by what user input.
|
||||
val: format_filesize(*val, &arg.format_value, None),
|
||||
span: *span,
|
||||
},
|
||||
format_filesize(*val, &arg.format_value, None),
|
||||
span,
|
||||
),
|
||||
Value::Error { .. } => val.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "filesize".into(),
|
||||
wrong_type: val.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: val.span(),
|
||||
}),
|
||||
src_span: value_span,
|
||||
},
|
||||
span,
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,13 +43,13 @@ impl Command for Parse {
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
let result = Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
let result = Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec!["foo".to_string(), "bar".to_string()],
|
||||
vals: vec![Value::test_string("hi"), Value::test_string("there")],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
};
|
||||
Span::test_data(),
|
||||
);
|
||||
|
||||
vec![
|
||||
Example {
|
||||
@ -65,19 +65,19 @@ impl Command for Parse {
|
||||
Example {
|
||||
description: "Parse a string using fancy-regex named capture group pattern",
|
||||
example: "\"foo bar.\" | parse -r '\\s*(?<name>\\w+)(?=\\.)'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec!["name".to_string()],
|
||||
vals: vec![Value::test_string("bar")],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Parse a string using fancy-regex capture group pattern",
|
||||
example: "\"foo! bar.\" | parse -r '(\\w+)(?=\\.)|(\\w+)(?=!)'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_record(Record {
|
||||
cols: vec!["capture0".to_string(), "capture1".to_string()],
|
||||
vals: vec![Value::test_string(""), Value::test_string("foo")],
|
||||
@ -87,34 +87,34 @@ impl Command for Parse {
|
||||
vals: vec![Value::test_string("bar"), Value::test_string("")],
|
||||
}),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Parse a string using fancy-regex look behind pattern",
|
||||
example:
|
||||
"\" @another(foo bar) \" | parse -r '\\s*(?<=[() ])(@\\w+)(\\([^)]*\\))?\\s*'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec!["capture0".to_string(), "capture1".to_string()],
|
||||
vals: vec![
|
||||
Value::test_string("@another"),
|
||||
Value::test_string("(foo bar)"),
|
||||
],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Parse a string using fancy-regex look ahead atomic group pattern",
|
||||
example: "\"abcd\" | parse -r '^a(bc(?=d)|b)cd$'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec!["capture0".to_string()],
|
||||
vals: vec![Value::test_string("b")],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -342,14 +342,14 @@ impl Iterator for ParseStreamer {
|
||||
let Some(v) = self.stream.next() else { return None };
|
||||
|
||||
let Ok(s) = v.as_string() else {
|
||||
return Some(Value::Error {
|
||||
error: Box::new(ShellError::PipelineMismatch {
|
||||
return Some(Value::error (
|
||||
ShellError::PipelineMismatch {
|
||||
exp_input_type: "string".into(),
|
||||
dst_span: self.span,
|
||||
src_span: v.span(),
|
||||
}),
|
||||
span: v.span(),
|
||||
})
|
||||
},
|
||||
v.span(),
|
||||
))
|
||||
};
|
||||
|
||||
let parsed = stream_helper(
|
||||
@ -401,24 +401,19 @@ impl Iterator for ParseStreamerExternal {
|
||||
|
||||
let chunk = match chunk {
|
||||
Some(Ok(chunk)) => chunk,
|
||||
Some(Err(err)) => {
|
||||
return Some(Value::Error {
|
||||
error: Box::new(err),
|
||||
span: self.span,
|
||||
})
|
||||
}
|
||||
Some(Err(err)) => return Some(Value::error(err, self.span)),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let Ok(chunk) = String::from_utf8(chunk) else {
|
||||
return Some(Value::Error {
|
||||
error: Box::new(ShellError::PipelineMismatch {
|
||||
return Some(Value::error(
|
||||
ShellError::PipelineMismatch {
|
||||
exp_input_type: "string".into(),
|
||||
dst_span: self.span,
|
||||
src_span: self.span,
|
||||
}),
|
||||
span: self.span,
|
||||
})
|
||||
},
|
||||
self.span,
|
||||
))
|
||||
};
|
||||
|
||||
stream_helper(
|
||||
@ -444,16 +439,16 @@ fn stream_helper(
|
||||
let captures = match c {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
return Some(Value::Error {
|
||||
error: Box::new(ShellError::GenericError(
|
||||
return Some(Value::error(
|
||||
ShellError::GenericError(
|
||||
"Error with regular expression captures".into(),
|
||||
e.to_string(),
|
||||
Some(span),
|
||||
Some(e.to_string()),
|
||||
Vec::new(),
|
||||
)),
|
||||
),
|
||||
span,
|
||||
})
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -121,27 +121,22 @@ fn size(
|
||||
}
|
||||
input.map(
|
||||
move |v| {
|
||||
let value_span = v.span();
|
||||
// First, obtain the span. If this fails, propagate the error that results.
|
||||
let value_span = match &v {
|
||||
Value::Error { error, span } => {
|
||||
return Value::Error {
|
||||
error: error.clone(),
|
||||
span: *span,
|
||||
}
|
||||
}
|
||||
v => v.span(),
|
||||
};
|
||||
if let Value::Error { error, .. } = v {
|
||||
return Value::error(*error, span);
|
||||
}
|
||||
// Now, check if it's a string.
|
||||
match v.as_string() {
|
||||
Ok(s) => counter(&s, span),
|
||||
Err(_) => Value::Error {
|
||||
error: Box::new(ShellError::PipelineMismatch {
|
||||
Err(_) => Value::error(
|
||||
ShellError::PipelineMismatch {
|
||||
exp_input_type: "string".into(),
|
||||
dst_span: span,
|
||||
src_span: value_span,
|
||||
}),
|
||||
},
|
||||
span,
|
||||
},
|
||||
),
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
|
@ -46,28 +46,28 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Split the string into a list of characters",
|
||||
example: "'hello' | split chars",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("h"),
|
||||
Value::test_string("e"),
|
||||
Value::test_string("l"),
|
||||
Value::test_string("l"),
|
||||
Value::test_string("o"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split on grapheme clusters",
|
||||
example: "'🇯🇵ほげ' | split chars -g",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("🇯🇵"),
|
||||
Value::test_string("ほ"),
|
||||
Value::test_string("げ"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split multiple strings into lists of characters",
|
||||
@ -118,16 +118,14 @@ fn split_chars(
|
||||
}
|
||||
|
||||
fn split_chars_helper(v: &Value, name: Span, graphemes: bool) -> Value {
|
||||
let span = v.span();
|
||||
match v {
|
||||
Value::Error { error, span } => Value::Error {
|
||||
error: error.clone(),
|
||||
span: *span,
|
||||
},
|
||||
Value::Error { error, .. } => Value::error(*error.clone(), span),
|
||||
v => {
|
||||
let v_span = v.span();
|
||||
if let Ok(s) = v.as_string() {
|
||||
Value::List {
|
||||
vals: if graphemes {
|
||||
Value::list(
|
||||
if graphemes {
|
||||
s.graphemes(true)
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
@ -140,17 +138,17 @@ fn split_chars_helper(v: &Value, name: Span, graphemes: bool) -> Value {
|
||||
.map(move |x| Value::string(x, v_span))
|
||||
.collect()
|
||||
},
|
||||
span: v_span,
|
||||
}
|
||||
v_span,
|
||||
)
|
||||
} else {
|
||||
Value::Error {
|
||||
error: Box::new(ShellError::PipelineMismatch {
|
||||
Value::error(
|
||||
ShellError::PipelineMismatch {
|
||||
exp_input_type: "string".into(),
|
||||
dst_span: name,
|
||||
src_span: v_span,
|
||||
}),
|
||||
span: name,
|
||||
}
|
||||
},
|
||||
name,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Split a string into columns by the specified separator",
|
||||
example: "'a--b--c' | split column '--'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec![
|
||||
"column1".to_string(),
|
||||
"column2".to_string(),
|
||||
@ -76,14 +76,14 @@ impl Command for SubCommand {
|
||||
Value::test_string("c"),
|
||||
],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split a string into columns of char and remove the empty columns",
|
||||
example: "'abc' | split column -c ''",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec![
|
||||
"column1".to_string(),
|
||||
"column2".to_string(),
|
||||
@ -95,14 +95,14 @@ impl Command for SubCommand {
|
||||
Value::test_string("c"),
|
||||
],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split a list of strings into a table",
|
||||
example: "['a-b' 'c-d'] | split column -",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_record(Record {
|
||||
cols: vec!["column1".to_string(), "column2".to_string()],
|
||||
vals: vec![Value::test_string("a"), Value::test_string("b")],
|
||||
@ -112,14 +112,14 @@ impl Command for SubCommand {
|
||||
vals: vec![Value::test_string("c"), Value::test_string("d")],
|
||||
}),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split a list of strings into a table, ignoring padding",
|
||||
example: r"['a - b' 'c - d'] | split column -r '\s*-\s*'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_record(Record {
|
||||
cols: vec!["column1".to_string(), "column2".to_string()],
|
||||
vals: vec![Value::test_string("a"), Value::test_string("b")],
|
||||
@ -129,8 +129,8 @@ impl Command for SubCommand {
|
||||
vals: vec![Value::test_string("c"), Value::test_string("d")],
|
||||
}),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -203,21 +203,18 @@ fn split_column_helper(
|
||||
} else {
|
||||
match v {
|
||||
Value::Error { error, .. } => {
|
||||
vec![Value::Error {
|
||||
error: Box::new(*error.clone()),
|
||||
span: head,
|
||||
}]
|
||||
vec![Value::error(*error.clone(), head)]
|
||||
}
|
||||
v => {
|
||||
let span = v.span();
|
||||
vec![Value::Error {
|
||||
error: Box::new(ShellError::PipelineMismatch {
|
||||
vec![Value::error(
|
||||
ShellError::PipelineMismatch {
|
||||
exp_input_type: "string".into(),
|
||||
dst_span: head,
|
||||
src_span: span,
|
||||
}),
|
||||
},
|
||||
span,
|
||||
}]
|
||||
)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,16 +34,16 @@ impl Command for SplitCommand {
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
Ok(Value::String {
|
||||
val: get_full_help(
|
||||
Ok(Value::string(
|
||||
get_full_help(
|
||||
&SplitCommand.signature(),
|
||||
&SplitCommand.examples(),
|
||||
engine_state,
|
||||
stack,
|
||||
self.is_parser_keyword(),
|
||||
),
|
||||
span: call.head,
|
||||
}
|
||||
call.head,
|
||||
)
|
||||
.into_pipeline_data())
|
||||
}
|
||||
}
|
||||
|
@ -56,100 +56,97 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Split a list of chars into two lists",
|
||||
example: "[a, b, c, d, e, f, g] | split list d",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::list(
|
||||
vec![
|
||||
Value::test_string("a"),
|
||||
Value::test_string("b"),
|
||||
Value::test_string("c"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::List {
|
||||
vals: vec![
|
||||
Span::test_data(),
|
||||
),
|
||||
Value::list(
|
||||
vec![
|
||||
Value::test_string("e"),
|
||||
Value::test_string("f"),
|
||||
Value::test_string("g"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Span::test_data(),
|
||||
),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split a list of lists into two lists of lists",
|
||||
example: "[[1,2], [2,3], [3,4]] | split list [2,3]",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::List {
|
||||
vals: vec![Value::List {
|
||||
vals: vec![Value::test_int(1), Value::test_int(2)],
|
||||
span: Span::test_data(),
|
||||
}],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::List {
|
||||
vals: vec![Value::List {
|
||||
vals: vec![Value::test_int(3), Value::test_int(4)],
|
||||
span: Span::test_data(),
|
||||
}],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::list(
|
||||
vec![Value::list(
|
||||
vec![Value::test_int(1), Value::test_int(2)],
|
||||
Span::test_data(),
|
||||
)],
|
||||
Span::test_data(),
|
||||
),
|
||||
Value::list(
|
||||
vec![Value::list(
|
||||
vec![Value::test_int(3), Value::test_int(4)],
|
||||
Span::test_data(),
|
||||
)],
|
||||
Span::test_data(),
|
||||
),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split a list of chars into two lists",
|
||||
example: "[a, b, c, d, a, e, f, g] | split list a",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::list(
|
||||
vec![
|
||||
Value::test_string("b"),
|
||||
Value::test_string("c"),
|
||||
Value::test_string("d"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::List {
|
||||
vals: vec![
|
||||
Span::test_data(),
|
||||
),
|
||||
Value::list(
|
||||
vec![
|
||||
Value::test_string("e"),
|
||||
Value::test_string("f"),
|
||||
Value::test_string("g"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Span::test_data(),
|
||||
),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split a list of chars into lists based on multiple characters",
|
||||
example: r"[a, b, c, d, a, e, f, g] | split list -r '(b|e)'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
Value::List {
|
||||
vals: vec![Value::test_string("a")],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::list(vec![Value::test_string("a")], Span::test_data()),
|
||||
Value::list(
|
||||
vec![
|
||||
Value::test_string("c"),
|
||||
Value::test_string("d"),
|
||||
Value::test_string("a"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::List {
|
||||
vals: vec![Value::test_string("f"), Value::test_string("g")],
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Span::test_data(),
|
||||
),
|
||||
Value::list(
|
||||
vec![Value::test_string("f"), Value::test_string("g")],
|
||||
Span::test_data(),
|
||||
),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -211,10 +208,7 @@ fn split_list(
|
||||
for val in iter {
|
||||
if matcher.compare(&val)? {
|
||||
if !temp_list.is_empty() {
|
||||
returned_list.push(Value::List {
|
||||
vals: temp_list.clone(),
|
||||
span: call.head,
|
||||
});
|
||||
returned_list.push(Value::list(temp_list.clone(), call.head));
|
||||
temp_list = Vec::new();
|
||||
}
|
||||
} else {
|
||||
@ -222,16 +216,9 @@ fn split_list(
|
||||
}
|
||||
}
|
||||
if !temp_list.is_empty() {
|
||||
returned_list.push(Value::List {
|
||||
vals: temp_list.clone(),
|
||||
span: call.head,
|
||||
});
|
||||
returned_list.push(Value::list(temp_list.clone(), call.head));
|
||||
}
|
||||
Ok(Value::List {
|
||||
vals: returned_list,
|
||||
span: call.head,
|
||||
}
|
||||
.into_pipeline_data())
|
||||
Ok(Value::list(returned_list, call.head).into_pipeline_data())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -62,54 +62,54 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Split a string into rows of char",
|
||||
example: "'abc' | split row ''",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string(""),
|
||||
Value::test_string("a"),
|
||||
Value::test_string("b"),
|
||||
Value::test_string("c"),
|
||||
Value::test_string(""),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split a string into rows by the specified separator",
|
||||
example: "'a--b--c' | split row '--'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("a"),
|
||||
Value::test_string("b"),
|
||||
Value::test_string("c"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split a string by '-'",
|
||||
example: "'-a-b-c-' | split row '-'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string(""),
|
||||
Value::test_string("a"),
|
||||
Value::test_string("b"),
|
||||
Value::test_string("c"),
|
||||
Value::test_string(""),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Split a string by regex",
|
||||
example: r"'a b c' | split row -r '\s+'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("a"),
|
||||
Value::test_string("b"),
|
||||
Value::test_string("c"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -146,12 +146,10 @@ fn split_row(
|
||||
}
|
||||
|
||||
fn split_row_helper(v: &Value, regex: &Regex, max_split: Option<usize>, name: Span) -> Vec<Value> {
|
||||
let span = v.span();
|
||||
match v {
|
||||
Value::Error { error, span } => {
|
||||
vec![Value::Error {
|
||||
error: Box::new(*error.clone()),
|
||||
span: *span,
|
||||
}]
|
||||
Value::Error { error, .. } => {
|
||||
vec![Value::error(*error.clone(), span)]
|
||||
}
|
||||
v => {
|
||||
let v_span = v.span();
|
||||
@ -168,14 +166,14 @@ fn split_row_helper(v: &Value, regex: &Regex, max_split: Option<usize>, name: Sp
|
||||
.collect(),
|
||||
}
|
||||
} else {
|
||||
vec![Value::Error {
|
||||
error: Box::new(ShellError::PipelineMismatch {
|
||||
vec![Value::error(
|
||||
ShellError::PipelineMismatch {
|
||||
exp_input_type: "string".into(),
|
||||
dst_span: name,
|
||||
src_span: v_span,
|
||||
}),
|
||||
span: name,
|
||||
}]
|
||||
},
|
||||
name,
|
||||
)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,23 +73,23 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Split the string's words into separate rows",
|
||||
example: "'hello world' | split words",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_string("hello"), Value::test_string("world")],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_string("hello"), Value::test_string("world")],
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description:
|
||||
"Split the string's words, of at least 3 characters, into separate rows",
|
||||
example: "'hello to the world' | split words -l 3",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("hello"),
|
||||
Value::test_string("the"),
|
||||
Value::test_string("world"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description:
|
||||
@ -152,12 +152,10 @@ fn split_words_helper(v: &Value, word_length: Option<usize>, span: Span, graphem
|
||||
// [^\p{L}\'] = do not match any unicode uppercase or lowercase letters or apostrophes
|
||||
// Let's go with the unicode one in hopes that it works on more than just ascii characters
|
||||
let regex_replace = Regex::new(r"[^\p{L}\']").expect("regular expression error");
|
||||
let v_span = v.span();
|
||||
|
||||
match v {
|
||||
Value::Error { error, span } => Value::Error {
|
||||
error: Box::new(*error.clone()),
|
||||
span: *span,
|
||||
},
|
||||
Value::Error { error, .. } => Value::error(*error.clone(), v_span),
|
||||
v => {
|
||||
let v_span = v.span();
|
||||
if let Ok(s) = v.as_string() {
|
||||
@ -189,19 +187,16 @@ fn split_words_helper(v: &Value, word_length: Option<usize>, span: Span, graphem
|
||||
}
|
||||
})
|
||||
.collect::<Vec<Value>>();
|
||||
Value::List {
|
||||
vals: words,
|
||||
span: v_span,
|
||||
}
|
||||
Value::list(words, v_span)
|
||||
} else {
|
||||
Value::Error {
|
||||
error: Box::new(ShellError::PipelineMismatch {
|
||||
Value::error(
|
||||
ShellError::PipelineMismatch {
|
||||
exp_input_type: "string".into(),
|
||||
dst_span: span,
|
||||
src_span: v_span,
|
||||
}),
|
||||
span,
|
||||
}
|
||||
},
|
||||
v_span,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,13 +68,13 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Capitalize a column in a table",
|
||||
example: "[[lang, gems]; [nu_test, 100]] | str capitalize lang",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec!["lang".to_string(), "gems".to_string()],
|
||||
vals: vec![Value::test_string("Nu_test"), Value::test_int(100)],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -98,10 +98,7 @@ fn operate(
|
||||
let r =
|
||||
ret.update_cell_path(&path.members, Box::new(move |old| action(old, head)));
|
||||
if let Err(error) = r {
|
||||
return Value::Error {
|
||||
error: Box::new(error),
|
||||
span: head,
|
||||
};
|
||||
return Value::error(error, head);
|
||||
}
|
||||
}
|
||||
ret
|
||||
@ -113,20 +110,17 @@ fn operate(
|
||||
|
||||
fn action(input: &Value, head: Span) -> Value {
|
||||
match input {
|
||||
Value::String { val, .. } => Value::String {
|
||||
val: uppercase_helper(val),
|
||||
span: head,
|
||||
},
|
||||
Value::String { val, .. } => Value::string(uppercase_helper(val), head),
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,24 +68,24 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Downcase contents",
|
||||
example: "[[ColA ColB]; [Test ABC]] | str downcase ColA",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec!["ColA".to_string(), "ColB".to_string()],
|
||||
vals: vec![Value::test_string("test"), Value::test_string("ABC")],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Downcase contents",
|
||||
example: "[[ColA ColB]; [Test ABC]] | str downcase ColA ColB",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec!["ColA".to_string(), "ColB".to_string()],
|
||||
vals: vec![Value::test_string("test"), Value::test_string("abc")],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -109,10 +109,7 @@ fn operate(
|
||||
let r =
|
||||
ret.update_cell_path(&path.members, Box::new(move |old| action(old, head)));
|
||||
if let Err(error) = r {
|
||||
return Value::Error {
|
||||
error: Box::new(error),
|
||||
span: head,
|
||||
};
|
||||
return Value::error(error, head);
|
||||
}
|
||||
}
|
||||
ret
|
||||
@ -124,20 +121,17 @@ fn operate(
|
||||
|
||||
fn action(input: &Value, head: Span) -> Value {
|
||||
match input {
|
||||
Value::String { val, .. } => Value::String {
|
||||
val: val.to_ascii_lowercase(),
|
||||
span: head,
|
||||
},
|
||||
Value::String { val, .. } => Value::string(val.to_ascii_lowercase(), head),
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,19 +51,16 @@ where
|
||||
{
|
||||
let case_operation = args.case_operation;
|
||||
match input {
|
||||
Value::String { val, .. } => Value::String {
|
||||
val: case_operation(val),
|
||||
span: head,
|
||||
},
|
||||
Value::String { val, .. } => Value::string(case_operation(val), head),
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -34,16 +34,16 @@ impl Command for Str {
|
||||
call: &Call,
|
||||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
Ok(Value::String {
|
||||
val: get_full_help(
|
||||
Ok(Value::string(
|
||||
get_full_help(
|
||||
&Str.signature(),
|
||||
&Str.examples(),
|
||||
engine_state,
|
||||
stack,
|
||||
self.is_parser_keyword(),
|
||||
),
|
||||
span: call.head,
|
||||
}
|
||||
call.head,
|
||||
)
|
||||
.into_pipeline_data())
|
||||
}
|
||||
}
|
||||
|
@ -78,10 +78,7 @@ fn operate(
|
||||
let r =
|
||||
ret.update_cell_path(&path.members, Box::new(move |old| action(old, head)));
|
||||
if let Err(error) = r {
|
||||
return Value::Error {
|
||||
error: Box::new(error),
|
||||
span: head,
|
||||
};
|
||||
return Value::error(error, head);
|
||||
}
|
||||
}
|
||||
ret
|
||||
@ -93,20 +90,17 @@ fn operate(
|
||||
|
||||
fn action(input: &Value, head: Span) -> Value {
|
||||
match input {
|
||||
Value::String { val: s, .. } => Value::String {
|
||||
val: s.to_uppercase(),
|
||||
span: head,
|
||||
},
|
||||
Value::String { val: s, .. } => Value::string(s.to_uppercase(), head),
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,24 +97,24 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Check if input contains string in a table",
|
||||
example: " [[ColA ColB]; [test 100]] | str contains -i 'E' ColA",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec!["ColA".to_string(), "ColB".to_string()],
|
||||
vals: vec![Value::test_bool(true), Value::test_int(100)],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Check if input contains string in a table",
|
||||
example: " [[ColA ColB]; [test hello]] | str contains 'e' ColA ColB",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec!["ColA".to_string(), "ColB".to_string()],
|
||||
vals: vec![Value::test_bool(true), Value::test_bool(true)],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Check if input string contains 'banana'",
|
||||
@ -124,26 +124,26 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Check if list contains string",
|
||||
example: "[one two three] | str contains o",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_bool(true),
|
||||
Value::test_bool(true),
|
||||
Value::test_bool(false),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Check if list does not contain string",
|
||||
example: "[one two three] | str contains -n o",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_bool(false),
|
||||
Value::test_bool(false),
|
||||
Value::test_bool(true),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -182,15 +182,15 @@ fn action(
|
||||
head,
|
||||
),
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,15 +80,15 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Compute edit distance between strings in table and another string, using cell paths",
|
||||
example: "[{a: 'nutshell' b: 'numetal'}] | str distance 'nushell' 'a' 'b'",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list (
|
||||
vec![
|
||||
Value::test_record(Record {
|
||||
cols: vec!["a".to_string(), "b".to_string()],
|
||||
vals: vec![Value::test_int(1), Value::test_int(4)],
|
||||
})
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Compute edit distance between strings in record and another string, using cell paths",
|
||||
@ -111,15 +111,15 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
Value::int(distance as i64, head)
|
||||
}
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,15 +105,15 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
Value::bool(ends_with, head)
|
||||
}
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,142 +43,142 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Define a range inside braces to produce a list of string.",
|
||||
example: "\"{3..5}\" | str expand",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("3"),
|
||||
Value::test_string("4"),
|
||||
Value::test_string("5")
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
},
|
||||
|
||||
Example {
|
||||
description: "Ignore the next character after the backslash ('\\')",
|
||||
example: "'A{B\\,,C}' | str expand",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("AB,"),
|
||||
Value::test_string("AC"),
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
},
|
||||
|
||||
Example {
|
||||
description: "Commas that are not inside any braces need to be skipped.",
|
||||
example: "'Welcome\\, {home,mon ami}!' | str expand",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("Welcome, home!"),
|
||||
Value::test_string("Welcome, mon ami!"),
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
},
|
||||
|
||||
Example {
|
||||
description: "Use double backslashes to add a backslash.",
|
||||
example: "'A{B\\\\,C}' | str expand",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("AB\\"),
|
||||
Value::test_string("AC"),
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
},
|
||||
|
||||
Example {
|
||||
description: "Export comma separated values inside braces (`{}`) to a string list.",
|
||||
example: "\"{apple,banana,cherry}\" | str expand",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("apple"),
|
||||
Value::test_string("banana"),
|
||||
Value::test_string("cherry")
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
},
|
||||
|
||||
Example {
|
||||
description: "If the piped data is path, you may want to use --path flag, or else manually replace the backslashes with double backslashes.",
|
||||
example: "'C:\\{Users,Windows}' | str expand --path",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("C:\\Users"),
|
||||
Value::test_string("C:\\Windows"),
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
},
|
||||
|
||||
Example {
|
||||
description: "Brace expressions can be used one after another.",
|
||||
example: "\"A{b,c}D{e,f}G\" | str expand",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("AbDeG"),
|
||||
Value::test_string("AbDfG"),
|
||||
Value::test_string("AcDeG"),
|
||||
Value::test_string("AcDfG"),
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
},
|
||||
|
||||
Example {
|
||||
description: "Collection may include an empty item. It can be put at the start of the list.",
|
||||
example: "\"A{,B,C}\" | str expand",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("A"),
|
||||
Value::test_string("AB"),
|
||||
Value::test_string("AC"),
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
},
|
||||
|
||||
Example {
|
||||
description: "Empty item can be at the end of the collection.",
|
||||
example: "\"A{B,C,}\" | str expand",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("AB"),
|
||||
Value::test_string("AC"),
|
||||
Value::test_string("A"),
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
},
|
||||
|
||||
Example {
|
||||
description: "Empty item can be in the middle of the collection.",
|
||||
example: "\"A{B,,C}\" | str expand",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("AB"),
|
||||
Value::test_string("A"),
|
||||
Value::test_string("AC"),
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
},
|
||||
|
||||
Example {
|
||||
description: "Also, it is possible to use one inside another. Here is a real-world example, that creates files:",
|
||||
example: "\"A{B{1,3},C{2,5}}D\" | str expand",
|
||||
result: Some(Value::List{
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("AB1D"),
|
||||
Value::test_string("AB3D"),
|
||||
Value::test_string("AC2D"),
|
||||
Value::test_string("AC5D"),
|
||||
],
|
||||
span: Span::test_data()
|
||||
},)
|
||||
Span::test_data()
|
||||
)),
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -203,14 +203,14 @@ impl Command for SubCommand {
|
||||
let contents = if is_path { s.replace('\\', "\\\\") } else { s };
|
||||
str_expand(&contents, span, v.span())
|
||||
}
|
||||
Err(_) => Value::Error {
|
||||
error: Box::new(ShellError::PipelineMismatch {
|
||||
Err(_) => Value::error(
|
||||
ShellError::PipelineMismatch {
|
||||
exp_input_type: "string".into(),
|
||||
dst_span: span,
|
||||
src_span: value_span,
|
||||
}),
|
||||
},
|
||||
span,
|
||||
},
|
||||
),
|
||||
}
|
||||
},
|
||||
engine_state.ctrlc.clone(),
|
||||
@ -230,17 +230,17 @@ fn str_expand(contents: &str, span: Span, value_span: Span) -> Value {
|
||||
Ok(node) => {
|
||||
match expand(&node) {
|
||||
Ok(possibilities) => {
|
||||
Value::List { vals: possibilities.iter().map(|e| Value::string(e,span)).collect::<Vec<Value>>(), span }
|
||||
Value::list(possibilities.iter().map(|e| Value::string(e,span)).collect::<Vec<Value>>(), span)
|
||||
},
|
||||
Err(e) => match e {
|
||||
bracoxide::ExpansionError::NumConversionFailed(s) => Value::Error { error:
|
||||
Box::new(ShellError::GenericError("Number Conversion Failed".to_owned(), format!("Number conversion failed at {s}."), Some(value_span), Some("Expected number, found text. Range format is `{M..N}`, where M and N are numeric values representing the starting and ending limits.".to_owned()), vec![])),
|
||||
bracoxide::ExpansionError::NumConversionFailed(s) => Value::error(
|
||||
ShellError::GenericError("Number Conversion Failed".to_owned(), format!("Number conversion failed at {s}."), Some(value_span), Some("Expected number, found text. Range format is `{M..N}`, where M and N are numeric values representing the starting and ending limits.".to_owned()), vec![]),
|
||||
span,
|
||||
},
|
||||
),
|
||||
},
|
||||
}
|
||||
},
|
||||
Err(e) => Value::Error { error: Box::new(
|
||||
Err(e) => Value::error(
|
||||
match e {
|
||||
ParsingError::NoTokens => ShellError::PipelineEmpty { dst_span: value_span },
|
||||
ParsingError::OBraExpected(s) => ShellError::GenericError("Opening Brace Expected".to_owned(), format!("Opening brace is expected at {s}."), Some(value_span), Some("In brace syntax, we use equal amount of opening (`{`) and closing (`}`). Please, take a look at the examples.".to_owned()), vec![]),
|
||||
@ -255,31 +255,31 @@ fn str_expand(contents: &str, span: Span, value_span: Span) -> Value {
|
||||
ParsingError::ExtraOBra(s) => ShellError::GenericError("Extra Opening Brace".to_owned(), format!("Used extra opening brace at {s}."), Some(value_span), Some("To escape opening brace use backslash, e.g. `\\{`".to_owned()), vec![]),
|
||||
ParsingError::NothingInBraces(s) => ShellError::GenericError("Nothing In Braces".to_owned(), format!("Nothing found inside braces at {s}."), Some(value_span), Some("Please provide valid content within the braces. Additionally, you can safely remove it, not needed.".to_owned()), vec![]),
|
||||
}
|
||||
),
|
||||
,
|
||||
span,
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
Err(e) => match e {
|
||||
TokenizationError::EmptyContent => Value::Error {
|
||||
error: Box::new(ShellError::PipelineEmpty { dst_span: value_span }),
|
||||
span: value_span,
|
||||
},
|
||||
TokenizationError::FormatNotSupported => Value::Error {
|
||||
error: Box::new(
|
||||
TokenizationError::EmptyContent => Value::error(
|
||||
ShellError::PipelineEmpty { dst_span: value_span },
|
||||
value_span,
|
||||
),
|
||||
TokenizationError::FormatNotSupported => Value::error(
|
||||
|
||||
ShellError::GenericError(
|
||||
"Format Not Supported".to_owned(),
|
||||
"Usage of only `{` or `}`. Brace Expansion syntax, needs to have equal amount of opening (`{`) and closing (`}`)".to_owned(),
|
||||
Some(value_span),
|
||||
Some("In brace expansion syntax, it is important to have an equal number of opening (`{`) and closing (`}`) braces. Please ensure that you provide a balanced pair of braces in your brace expansion pattern.".to_owned()),
|
||||
vec![]
|
||||
)),
|
||||
span: value_span,
|
||||
},
|
||||
TokenizationError::NoBraces => Value::Error {
|
||||
error: Box::new(ShellError::GenericError("No Braces".to_owned(), "At least one `{}` brace expansion expected.".to_owned(), Some(value_span), Some("Please, examine the examples.".to_owned()), vec![])),
|
||||
span: value_span,
|
||||
}
|
||||
),
|
||||
value_span,
|
||||
),
|
||||
TokenizationError::NoBraces => Value::error(
|
||||
ShellError::GenericError("No Braces".to_owned(), "At least one `{}` brace expansion expected.".to_owned(), Some(value_span), Some("Please, examine the examples.".to_owned()), vec![]),
|
||||
value_span,
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -292,51 +292,33 @@ mod tests {
|
||||
fn dots() {
|
||||
assert_eq!(
|
||||
str_expand("{a.b.c,d}", Span::test_data(), Span::test_data()),
|
||||
Value::List {
|
||||
vals: vec![
|
||||
Value::String {
|
||||
val: String::from("a.b.c"),
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::String {
|
||||
val: String::from("d"),
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::list(
|
||||
vec![
|
||||
Value::string(String::from("a.b.c"), Span::test_data(),),
|
||||
Value::string(String::from("d"), Span::test_data(),)
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}
|
||||
Span::test_data(),
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
str_expand("{1.2.3,a}", Span::test_data(), Span::test_data()),
|
||||
Value::List {
|
||||
vals: vec![
|
||||
Value::String {
|
||||
val: String::from("1.2.3"),
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::String {
|
||||
val: String::from("a"),
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::list(
|
||||
vec![
|
||||
Value::string(String::from("1.2.3"), Span::test_data(),),
|
||||
Value::string(String::from("a"), Span::test_data(),)
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}
|
||||
Span::test_data(),
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
str_expand("{a-1.2,b}", Span::test_data(), Span::test_data()),
|
||||
Value::List {
|
||||
vals: vec![
|
||||
Value::String {
|
||||
val: String::from("a-1.2"),
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::String {
|
||||
val: String::from("b"),
|
||||
span: Span::test_data(),
|
||||
},
|
||||
Value::list(
|
||||
vec![
|
||||
Value::string(String::from("a-1.2"), Span::test_data(),),
|
||||
Value::string(String::from("b"), Span::test_data(),)
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}
|
||||
Span::test_data(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -161,10 +161,7 @@ fn action(
|
||||
}
|
||||
Err(processing_error) => {
|
||||
let err = processing_error("could not find `index-of`", head);
|
||||
return Value::Error {
|
||||
error: Box::new(err),
|
||||
span: head,
|
||||
};
|
||||
return Value::error(err, head);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -198,15 +195,15 @@ fn action(
|
||||
}
|
||||
}
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,17 +259,9 @@ mod tests {
|
||||
fn returns_index_of_next_substring() {
|
||||
let word = Value::test_string("Cargo.Cargo");
|
||||
let range = Range {
|
||||
from: Value::Int {
|
||||
val: 1,
|
||||
span: Span::test_data(),
|
||||
},
|
||||
incr: Value::Int {
|
||||
val: 1,
|
||||
span: Span::test_data(),
|
||||
},
|
||||
to: Value::Nothing {
|
||||
span: Span::test_data(),
|
||||
},
|
||||
from: Value::int(1, Span::test_data()),
|
||||
incr: Value::int(1, Span::test_data()),
|
||||
to: Value::nothing(Span::test_data()),
|
||||
inclusion: RangeInclusion::Inclusive,
|
||||
};
|
||||
|
||||
@ -293,18 +282,10 @@ mod tests {
|
||||
fn index_does_not_exist_due_to_end_index() {
|
||||
let word = Value::test_string("Cargo.Banana");
|
||||
let range = Range {
|
||||
from: Value::Nothing {
|
||||
span: Span::test_data(),
|
||||
},
|
||||
from: Value::nothing(Span::test_data()),
|
||||
inclusion: RangeInclusion::Inclusive,
|
||||
incr: Value::Int {
|
||||
val: 1,
|
||||
span: Span::test_data(),
|
||||
},
|
||||
to: Value::Int {
|
||||
val: 5,
|
||||
span: Span::test_data(),
|
||||
},
|
||||
incr: Value::int(1, Span::test_data()),
|
||||
to: Value::int(5, Span::test_data()),
|
||||
};
|
||||
|
||||
let options = Arguments {
|
||||
@ -324,18 +305,9 @@ mod tests {
|
||||
fn returns_index_of_nums_in_middle_due_to_index_limit_from_both_ends() {
|
||||
let word = Value::test_string("123123123");
|
||||
let range = Range {
|
||||
from: Value::Int {
|
||||
val: 2,
|
||||
span: Span::test_data(),
|
||||
},
|
||||
incr: Value::Int {
|
||||
val: 1,
|
||||
span: Span::test_data(),
|
||||
},
|
||||
to: Value::Int {
|
||||
val: 6,
|
||||
span: Span::test_data(),
|
||||
},
|
||||
from: Value::int(2, Span::test_data()),
|
||||
incr: Value::int(1, Span::test_data()),
|
||||
to: Value::int(6, Span::test_data()),
|
||||
inclusion: RangeInclusion::Inclusive,
|
||||
};
|
||||
|
||||
@ -356,18 +328,9 @@ mod tests {
|
||||
fn index_does_not_exists_due_to_strict_bounds() {
|
||||
let word = Value::test_string("123456");
|
||||
let range = Range {
|
||||
from: Value::Int {
|
||||
val: 2,
|
||||
span: Span::test_data(),
|
||||
},
|
||||
incr: Value::Int {
|
||||
val: 1,
|
||||
span: Span::test_data(),
|
||||
},
|
||||
to: Value::Int {
|
||||
val: 5,
|
||||
span: Span::test_data(),
|
||||
},
|
||||
from: Value::int(2, Span::test_data()),
|
||||
incr: Value::int(1, Span::test_data()),
|
||||
to: Value::int(5, Span::test_data()),
|
||||
inclusion: RangeInclusion::RightExclusive,
|
||||
};
|
||||
|
||||
@ -386,10 +349,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn use_utf8_bytes() {
|
||||
let word = Value::String {
|
||||
val: String::from("🇯🇵ほげ ふが ぴよ"),
|
||||
span: Span::test_data(),
|
||||
};
|
||||
let word = Value::string(String::from("🇯🇵ほげ ふが ぴよ"), Span::test_data());
|
||||
|
||||
let options = Arguments {
|
||||
substring: String::from("ふが"),
|
||||
|
@ -70,11 +70,7 @@ impl Command for StrJoin {
|
||||
strings.join("")
|
||||
};
|
||||
|
||||
Ok(Value::String {
|
||||
val: output,
|
||||
span: call.head,
|
||||
}
|
||||
.into_pipeline_data())
|
||||
Ok(Value::string(output, call.head).into_pipeline_data())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
|
@ -102,10 +102,10 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Return the lengths of multiple strings",
|
||||
example: "['hi' 'there'] | str length",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_int(2), Value::test_int(5)],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
result: Some(Value::list(
|
||||
vec![Value::test_int(2), Value::test_int(5)],
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -135,15 +135,15 @@ fn action(input: &Value, arg: &Arguments, head: Span) -> Value {
|
||||
head,
|
||||
),
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,10 +153,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn use_utf8_bytes() {
|
||||
let word = Value::String {
|
||||
val: String::from("🇯🇵ほげ ふが ぴよ"),
|
||||
span: Span::test_data(),
|
||||
};
|
||||
let word = Value::string(String::from("🇯🇵ほげ ふが ぴよ"), Span::test_data());
|
||||
|
||||
let options = Arguments {
|
||||
cell_paths: None,
|
||||
|
@ -149,8 +149,8 @@ impl Command for SubCommand {
|
||||
description: "Find and replace all occurrences of find string in table using regular expression",
|
||||
example:
|
||||
"[[ColA ColB ColC]; [abc abc ads]] | str replace -ar 'b' 'z' ColA ColC",
|
||||
result: Some(Value::List {
|
||||
vals: vec![Value::test_record(Record {
|
||||
result: Some(Value::list (
|
||||
vec![Value::test_record(Record {
|
||||
cols: vec!["ColA".to_string(), "ColB".to_string(), "ColC".to_string()],
|
||||
vals: vec![
|
||||
Value::test_string("azc"),
|
||||
@ -158,8 +158,8 @@ impl Command for SubCommand {
|
||||
Value::test_string("ads"),
|
||||
],
|
||||
})],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Find and replace all occurrences of find string in record using regular expression",
|
||||
@ -225,15 +225,9 @@ fn action(
|
||||
if *no_regex {
|
||||
// just use regular string replacement vs regular expressions
|
||||
if *all {
|
||||
Value::String {
|
||||
val: val.replace(find_str, replace_str),
|
||||
span: head,
|
||||
}
|
||||
Value::string(val.replace(find_str, replace_str), head)
|
||||
} else {
|
||||
Value::String {
|
||||
val: val.replacen(find_str, replace_str, 1),
|
||||
span: head,
|
||||
}
|
||||
Value::string(val.replacen(find_str, replace_str, 1), head)
|
||||
}
|
||||
} else {
|
||||
// use regular expressions to replace strings
|
||||
@ -247,50 +241,50 @@ fn action(
|
||||
match regex {
|
||||
Ok(re) => {
|
||||
if *all {
|
||||
Value::String {
|
||||
val: {
|
||||
Value::string(
|
||||
{
|
||||
if *literal_replace {
|
||||
re.replace_all(val, NoExpand(replace_str)).to_string()
|
||||
} else {
|
||||
re.replace_all(val, replace_str).to_string()
|
||||
}
|
||||
},
|
||||
span: head,
|
||||
}
|
||||
head,
|
||||
)
|
||||
} else {
|
||||
Value::String {
|
||||
val: {
|
||||
Value::string(
|
||||
{
|
||||
if *literal_replace {
|
||||
re.replace(val, NoExpand(replace_str)).to_string()
|
||||
} else {
|
||||
re.replace(val, replace_str).to_string()
|
||||
}
|
||||
},
|
||||
span: head,
|
||||
}
|
||||
head,
|
||||
)
|
||||
}
|
||||
}
|
||||
Err(e) => Value::Error {
|
||||
error: Box::new(ShellError::IncorrectValue {
|
||||
Err(e) => Value::error(
|
||||
ShellError::IncorrectValue {
|
||||
msg: format!("Regex error: {e}"),
|
||||
val_span: find.span,
|
||||
call_span: head,
|
||||
}),
|
||||
span: find.span,
|
||||
},
|
||||
},
|
||||
find.span,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,14 +64,14 @@ impl Command for SubCommand {
|
||||
Example {
|
||||
description: "Reverse multiple strings in a list",
|
||||
example: "['Nushell' 'is' 'cool'] | str reverse",
|
||||
result: Some(Value::List {
|
||||
vals: vec![
|
||||
result: Some(Value::list(
|
||||
vec![
|
||||
Value::test_string("llehsuN"),
|
||||
Value::test_string("si"),
|
||||
Value::test_string("looc"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
}),
|
||||
Span::test_data(),
|
||||
)),
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -79,20 +79,17 @@ impl Command for SubCommand {
|
||||
|
||||
fn action(input: &Value, _arg: &CellPathOnlyArgs, head: Span) -> Value {
|
||||
match input {
|
||||
Value::String { val, .. } => Value::String {
|
||||
val: val.chars().rev().collect::<String>(),
|
||||
span: head,
|
||||
},
|
||||
Value::String { val, .. } => Value::string(val.chars().rev().collect::<String>(), head),
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,15 +118,15 @@ fn action(
|
||||
Value::bool(starts_with, head)
|
||||
}
|
||||
Value::Error { .. } => input.clone(),
|
||||
_ => Value::Error {
|
||||
error: Box::new(ShellError::OnlySupportsThisInputType {
|
||||
_ => Value::error(
|
||||
ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "string".into(),
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span(),
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,15 +144,15 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
if start < len && end >= 0 {
|
||||
match start.cmp(&end) {
|
||||
Ordering::Equal => Value::string("", head),
|
||||
Ordering::Greater => Value::Error {
|
||||
error: Box::new(ShellError::TypeMismatch {
|
||||
Ordering::Greater => Value::error(
|
||||
ShellError::TypeMismatch {
|
||||
err_message: "End must be greater than or equal to Start".to_string(),
|
||||
span: head,
|
||||
}),
|
||||
span: head,
|
||||
},
|
||||
Ordering::Less => Value::String {
|
||||
val: {
|
||||
},
|
||||
head,
|
||||
),
|
||||
Ordering::Less => Value::string(
|
||||
{
|
||||
if end == isize::max_value() {
|
||||
if args.graphemes {
|
||||
s.graphemes(true)
|
||||
@ -181,8 +181,8 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
.to_string()
|
||||
}
|
||||
},
|
||||
span: head,
|
||||
},
|
||||
head,
|
||||
),
|
||||
}
|
||||
} else {
|
||||
Value::string("", head)
|
||||
@ -190,16 +190,16 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
|
||||
}
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => input.clone(),
|
||||
other => Value::Error {
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
other => Value::error(
|
||||
ShellError::UnsupportedInput(
|
||||
"Only string values are supported".into(),
|
||||
format!("input type: {:?}", other.get_type()),
|
||||
head,
|
||||
// This line requires the Value::Error match above.
|
||||
other.span(),
|
||||
)),
|
||||
span: head,
|
||||
},
|
||||
),
|
||||
head,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,10 +279,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn use_utf8_bytes() {
|
||||
let word = Value::String {
|
||||
val: String::from("🇯🇵ほげ ふが ぴよ"),
|
||||
span: Span::test_data(),
|
||||
};
|
||||
let word = Value::string(String::from("🇯🇵ほげ ふが ぴよ"), Span::test_data());
|
||||
|
||||
let options = Arguments {
|
||||
cell_paths: None,
|
||||
|
@ -172,48 +172,46 @@ fn action(input: &Value, arg: &Arguments, head: Span) -> Value {
|
||||
let trim_side = &arg.trim_side;
|
||||
let mode = &arg.mode;
|
||||
match input {
|
||||
Value::String { val: s, .. } => Value::String {
|
||||
val: trim(s, char_, trim_side),
|
||||
span: head,
|
||||
},
|
||||
Value::String { val: s, .. } => Value::string(trim(s, char_, trim_side), head),
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { .. } => input.clone(),
|
||||
other => match mode {
|
||||
ActionMode::Global => match other {
|
||||
Value::Record { val: record, span } => {
|
||||
let new_vals = record.vals.iter().map(|v| action(v, arg, head)).collect();
|
||||
other => {
|
||||
let span = other.span();
|
||||
|
||||
Value::record(
|
||||
Record {
|
||||
cols: record.cols.to_vec(),
|
||||
vals: new_vals,
|
||||
},
|
||||
*span,
|
||||
match mode {
|
||||
ActionMode::Global => match other {
|
||||
Value::Record { val: record, .. } => {
|
||||
let new_vals = record.vals.iter().map(|v| action(v, arg, head)).collect();
|
||||
|
||||
Value::record(
|
||||
Record {
|
||||
cols: record.cols.to_vec(),
|
||||
vals: new_vals,
|
||||
},
|
||||
span,
|
||||
)
|
||||
}
|
||||
Value::List { vals, .. } => {
|
||||
let new_vals = vals.iter().map(|v| action(v, arg, head)).collect();
|
||||
|
||||
Value::list(new_vals, span)
|
||||
}
|
||||
_ => input.clone(),
|
||||
},
|
||||
ActionMode::Local => {
|
||||
Value::error(
|
||||
ShellError::UnsupportedInput(
|
||||
"Only string values are supported".into(),
|
||||
format!("input type: {:?}", other.get_type()),
|
||||
head,
|
||||
// This line requires the Value::Error match above.
|
||||
other.span(),
|
||||
),
|
||||
head,
|
||||
)
|
||||
}
|
||||
Value::List { vals, span } => {
|
||||
let new_vals = vals.iter().map(|v| action(v, arg, head)).collect();
|
||||
|
||||
Value::List {
|
||||
vals: new_vals,
|
||||
span: *span,
|
||||
}
|
||||
}
|
||||
_ => input.clone(),
|
||||
},
|
||||
ActionMode::Local => {
|
||||
Value::Error {
|
||||
error: Box::new(ShellError::UnsupportedInput(
|
||||
"Only string values are supported".into(),
|
||||
format!("input type: {:?}", other.get_type()),
|
||||
head,
|
||||
// This line requires the Value::Error match above.
|
||||
other.span(),
|
||||
)),
|
||||
span: head,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,13 +259,12 @@ mod tests {
|
||||
}
|
||||
|
||||
fn make_list(vals: Vec<&str>) -> Value {
|
||||
Value::List {
|
||||
vals: vals
|
||||
.iter()
|
||||
Value::list(
|
||||
vals.iter()
|
||||
.map(|x| Value::test_string(x.to_string()))
|
||||
.collect(),
|
||||
span: Span::test_data(),
|
||||
}
|
||||
Span::test_data(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -422,22 +419,22 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn global_trim_left_table() {
|
||||
let row = Value::List {
|
||||
vals: vec![
|
||||
let row = Value::list(
|
||||
vec![
|
||||
Value::test_string(" a "),
|
||||
Value::test_int(65),
|
||||
Value::test_string(" d"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
};
|
||||
let expected = Value::List {
|
||||
vals: vec![
|
||||
Span::test_data(),
|
||||
);
|
||||
let expected = Value::list(
|
||||
vec![
|
||||
Value::test_string("a "),
|
||||
Value::test_int(65),
|
||||
Value::test_string("d"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
};
|
||||
Span::test_data(),
|
||||
);
|
||||
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
@ -522,22 +519,22 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn global_trim_right_table() {
|
||||
let row = Value::List {
|
||||
vals: vec![
|
||||
let row = Value::list(
|
||||
vec![
|
||||
Value::test_string(" a "),
|
||||
Value::test_int(65),
|
||||
Value::test_string(" d"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
};
|
||||
let expected = Value::List {
|
||||
vals: vec![
|
||||
Span::test_data(),
|
||||
);
|
||||
let expected = Value::list(
|
||||
vec![
|
||||
Value::test_string(" a"),
|
||||
Value::test_int(65),
|
||||
Value::test_string(" d"),
|
||||
],
|
||||
span: Span::test_data(),
|
||||
};
|
||||
Span::test_data(),
|
||||
);
|
||||
let args = Arguments {
|
||||
to_trim: None,
|
||||
trim_side: TrimSide::Right,
|
||||
|
Reference in New Issue
Block a user