mirror of
https://github.com/nushell/nushell.git
synced 2025-08-15 04:42:35 +02:00
feat(get,select,reject): add --ignore-case
which interprets cell-paths case insensitively, analogous to --optional
(#16401)
# Description Follow up to #16007 Also added some examples for existing flags which were previously missing. After the deprecation period of `--ignore-errors (-i)`, `-i` will be used as the short form of this flag. # User-Facing Changes `get`, `select`, `reject` commands now have a `--ignore-case` flag, which makes the commands interpret all cell-path arguments as completely case insensitive. # Tests + Formatting +1 # After Submitting Set a reminder for the `--ignore-errors` deprecation and using `-i` as the short flag. Maybe we can make PRs in advance for future versions and mark them with GitHub's milestones.
This commit is contained in:
@ -45,6 +45,11 @@ If multiple cell paths are given, this will produce a list of values."#
|
|||||||
"make all cell path members optional (returns `null` for missing values)",
|
"make all cell path members optional (returns `null` for missing values)",
|
||||||
Some('o'),
|
Some('o'),
|
||||||
)
|
)
|
||||||
|
.switch(
|
||||||
|
"ignore-case",
|
||||||
|
"make all cell path members case insensitive",
|
||||||
|
None,
|
||||||
|
)
|
||||||
.switch(
|
.switch(
|
||||||
"ignore-errors",
|
"ignore-errors",
|
||||||
"ignore missing data (make all cell path members optional) (deprecated)",
|
"ignore missing data (make all cell path members optional) (deprecated)",
|
||||||
@ -74,6 +79,30 @@ If multiple cell paths are given, this will produce a list of values."#
|
|||||||
Span::test_data(),
|
Span::test_data(),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
|
Example {
|
||||||
|
description: "Get a column from a table where some rows don't have that column, using optional cell-path syntax",
|
||||||
|
example: "[{A: A0, B: B0}, {B: B1}, {A: A2, B: B2}] | get A?",
|
||||||
|
result: Some(Value::list(
|
||||||
|
vec![
|
||||||
|
Value::test_string("A0"),
|
||||||
|
Value::test_nothing(),
|
||||||
|
Value::test_string("A2"),
|
||||||
|
],
|
||||||
|
Span::test_data(),
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Get a column from a table where some rows don't have that column, using the optional flag",
|
||||||
|
example: "[{A: A0, B: B0}, {B: B1}, {A: A2, B: B2}] | get -o A",
|
||||||
|
result: Some(Value::list(
|
||||||
|
vec![
|
||||||
|
Value::test_string("A0"),
|
||||||
|
Value::test_nothing(),
|
||||||
|
Value::test_string("A2"),
|
||||||
|
],
|
||||||
|
Span::test_data(),
|
||||||
|
)),
|
||||||
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Get a cell from a table",
|
description: "Get a cell from a table",
|
||||||
example: "[{A: A0}] | get 0.A",
|
example: "[{A: A0}] | get 0.A",
|
||||||
@ -90,8 +119,13 @@ If multiple cell paths are given, this will produce a list of values."#
|
|||||||
result: None,
|
result: None,
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Getting Path/PATH in a case insensitive way",
|
description: "Getting environment variables in a case insensitive way, using case insensitive cell-path syntax",
|
||||||
example: "$env | get paTH!",
|
example: "$env | get home! path!",
|
||||||
|
result: None,
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
description: "Getting environment variables in a case insensitive way, using the '--ignore-case' flag",
|
||||||
|
example: "$env | get --ignore-case home path",
|
||||||
result: None,
|
result: None,
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
@ -116,12 +150,14 @@ If multiple cell paths are given, this will produce a list of values."#
|
|||||||
let rest: Vec<CellPath> = call.rest_const(working_set, 1)?;
|
let rest: Vec<CellPath> = call.rest_const(working_set, 1)?;
|
||||||
let optional = call.has_flag_const(working_set, "optional")?
|
let optional = call.has_flag_const(working_set, "optional")?
|
||||||
|| call.has_flag_const(working_set, "ignore-errors")?;
|
|| call.has_flag_const(working_set, "ignore-errors")?;
|
||||||
|
let ignore_case = call.has_flag_const(working_set, "ignore-case")?;
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
action(
|
action(
|
||||||
input,
|
input,
|
||||||
cell_path,
|
cell_path,
|
||||||
rest,
|
rest,
|
||||||
optional,
|
optional,
|
||||||
|
ignore_case,
|
||||||
working_set.permanent().signals().clone(),
|
working_set.permanent().signals().clone(),
|
||||||
call.head,
|
call.head,
|
||||||
)
|
)
|
||||||
@ -139,12 +175,14 @@ If multiple cell paths are given, this will produce a list of values."#
|
|||||||
let rest: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
let rest: Vec<CellPath> = call.rest(engine_state, stack, 1)?;
|
||||||
let optional = call.has_flag(engine_state, stack, "optional")?
|
let optional = call.has_flag(engine_state, stack, "optional")?
|
||||||
|| call.has_flag(engine_state, stack, "ignore-errors")?;
|
|| call.has_flag(engine_state, stack, "ignore-errors")?;
|
||||||
|
let ignore_case = call.has_flag(engine_state, stack, "ignore-case")?;
|
||||||
let metadata = input.metadata();
|
let metadata = input.metadata();
|
||||||
action(
|
action(
|
||||||
input,
|
input,
|
||||||
cell_path,
|
cell_path,
|
||||||
rest,
|
rest,
|
||||||
optional,
|
optional,
|
||||||
|
ignore_case,
|
||||||
engine_state.signals().clone(),
|
engine_state.signals().clone(),
|
||||||
call.head,
|
call.head,
|
||||||
)
|
)
|
||||||
@ -176,6 +214,7 @@ fn action(
|
|||||||
mut cell_path: CellPath,
|
mut cell_path: CellPath,
|
||||||
mut rest: Vec<CellPath>,
|
mut rest: Vec<CellPath>,
|
||||||
optional: bool,
|
optional: bool,
|
||||||
|
ignore_case: bool,
|
||||||
signals: Signals,
|
signals: Signals,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
@ -186,6 +225,13 @@ fn action(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ignore_case {
|
||||||
|
cell_path.make_insensitive();
|
||||||
|
for path in &mut rest {
|
||||||
|
path.make_insensitive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let PipelineData::Empty = input {
|
if let PipelineData::Empty = input {
|
||||||
return Err(ShellError::PipelineEmpty { dst_span: span });
|
return Err(ShellError::PipelineEmpty { dst_span: span });
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,11 @@ impl Command for Reject {
|
|||||||
(Type::list(Type::Any), Type::list(Type::Any)),
|
(Type::list(Type::Any), Type::list(Type::Any)),
|
||||||
])
|
])
|
||||||
.switch("optional", "make all cell path members optional", Some('o'))
|
.switch("optional", "make all cell path members optional", Some('o'))
|
||||||
|
.switch(
|
||||||
|
"ignore-case",
|
||||||
|
"make all cell path members case insensitive",
|
||||||
|
None,
|
||||||
|
)
|
||||||
.switch(
|
.switch(
|
||||||
"ignore-errors",
|
"ignore-errors",
|
||||||
"ignore missing data (make all cell path members optional) (deprecated)",
|
"ignore missing data (make all cell path members optional) (deprecated)",
|
||||||
@ -93,12 +98,20 @@ impl Command for Reject {
|
|||||||
|
|
||||||
let optional = call.has_flag(engine_state, stack, "optional")?
|
let optional = call.has_flag(engine_state, stack, "optional")?
|
||||||
|| call.has_flag(engine_state, stack, "ignore-errors")?;
|
|| call.has_flag(engine_state, stack, "ignore-errors")?;
|
||||||
|
let ignore_case = call.has_flag(engine_state, stack, "ignore-case")?;
|
||||||
|
|
||||||
if optional {
|
if optional {
|
||||||
for cell_path in &mut new_columns {
|
for cell_path in &mut new_columns {
|
||||||
cell_path.make_optional();
|
cell_path.make_optional();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ignore_case {
|
||||||
|
for cell_path in &mut new_columns {
|
||||||
|
cell_path.make_insensitive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reject(engine_state, span, input, new_columns)
|
reject(engine_state, span, input, new_columns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,11 @@ impl Command for Select {
|
|||||||
"make all cell path members optional (returns `null` for missing values)",
|
"make all cell path members optional (returns `null` for missing values)",
|
||||||
Some('o'),
|
Some('o'),
|
||||||
)
|
)
|
||||||
|
.switch(
|
||||||
|
"ignore-case",
|
||||||
|
"make all cell path members case insensitive",
|
||||||
|
None,
|
||||||
|
)
|
||||||
.switch(
|
.switch(
|
||||||
"ignore-errors",
|
"ignore-errors",
|
||||||
"ignore missing data (make all cell path members optional) (deprecated)",
|
"ignore missing data (make all cell path members optional) (deprecated)",
|
||||||
@ -110,6 +115,7 @@ produce a table, a list will produce a list, and a record will produce a record.
|
|||||||
}
|
}
|
||||||
let optional = call.has_flag(engine_state, stack, "optional")?
|
let optional = call.has_flag(engine_state, stack, "optional")?
|
||||||
|| call.has_flag(engine_state, stack, "ignore-errors")?;
|
|| call.has_flag(engine_state, stack, "ignore-errors")?;
|
||||||
|
let ignore_case = call.has_flag(engine_state, stack, "ignore-case")?;
|
||||||
let span = call.head;
|
let span = call.head;
|
||||||
|
|
||||||
if optional {
|
if optional {
|
||||||
@ -118,6 +124,12 @@ produce a table, a list will produce a list, and a record will produce a record.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ignore_case {
|
||||||
|
for cell_path in &mut new_columns {
|
||||||
|
cell_path.make_insensitive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
select(engine_state, span, new_columns, input)
|
select(engine_state, span, new_columns, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +155,18 @@ produce a table, a list will produce a list, and a record will produce a record.
|
|||||||
"a" => Value::test_string("a")
|
"a" => Value::test_string("a")
|
||||||
})])),
|
})])),
|
||||||
},
|
},
|
||||||
|
Example {
|
||||||
|
description: "Select a column even if some rows are missing that column",
|
||||||
|
example: "[{a: a0 b: b0} {b: b1}] | select -o a",
|
||||||
|
result: Some(Value::test_list(vec![
|
||||||
|
Value::test_record(record! {
|
||||||
|
"a" => Value::test_string("a0")
|
||||||
|
}),
|
||||||
|
Value::test_record(record! {
|
||||||
|
"a" => Value::test_nothing()
|
||||||
|
}),
|
||||||
|
])),
|
||||||
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Select a field in a record",
|
description: "Select a field in a record",
|
||||||
example: "{a: a b: b} | select a",
|
example: "{a: a b: b} | select a",
|
||||||
|
@ -305,9 +305,38 @@ fn nullify_holes() -> TestResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_insensitive() -> TestResult {
|
fn get_with_insensitive_cellpath() -> TestResult {
|
||||||
run_test(
|
run_test(
|
||||||
r#"[[name, age]; [a, 1] [b, 2]] | get NAmE! | select 0 | get 0"#,
|
r#"[[name, age]; [a, 1] [b, 2]] | get NAmE! | select 0 | get 0"#,
|
||||||
"a",
|
"a",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ignore_case_flag() -> TestResult {
|
||||||
|
run_test(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
[Origin, Crate, Versions];
|
||||||
|
[World, {Name: "nu-cli"}, ['0.21', '0.22']]
|
||||||
|
]
|
||||||
|
| get --ignore-case crate.name.0
|
||||||
|
"#,
|
||||||
|
"nu-cli",
|
||||||
|
)?;
|
||||||
|
run_test(
|
||||||
|
r#"
|
||||||
|
[
|
||||||
|
[Origin, Crate, Versions];
|
||||||
|
[World, {Name: "nu-cli"}, ['0.21', '0.22']]
|
||||||
|
]
|
||||||
|
| select --ignore-case origin
|
||||||
|
| to nuon --raw
|
||||||
|
"#,
|
||||||
|
r#"[[origin];[World]]"#,
|
||||||
|
)?;
|
||||||
|
run_test(
|
||||||
|
r#"{A: {B: 3, C: 5}} | reject --ignore-case a.b | to nuon --raw"#,
|
||||||
|
"{A:{C:5}}",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user