mirror of
https://github.com/nushell/nushell.git
synced 2025-05-08 12:04:25 +02:00
Rename/deprecate range
to slice
(#14825)
# Description As the `range` command has an ambiguous name (does it construct a range type?, does it iterate a range like `seq`) replace it with a more descriptive verb of what it does: `slice` Closes #14130 # User-Facing Changes `range` is now deprecated and replaced in whole by `slice` with the same behavior. `range` will be removed in `0.103.0` # Tests + Formatting Tests have been updated to use `slice` # After submitting - [ ] prepare PR for `nu_scripts` (several usages of `range` to be fixed) - [ ] update documentation usages of `range` after release
This commit is contained in:
parent
089c5221cc
commit
4dcaf2a201
@ -79,6 +79,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
|||||||
Skip,
|
Skip,
|
||||||
SkipUntil,
|
SkipUntil,
|
||||||
SkipWhile,
|
SkipWhile,
|
||||||
|
Slice,
|
||||||
Sort,
|
Sort,
|
||||||
SortBy,
|
SortBy,
|
||||||
SplitList,
|
SplitList,
|
||||||
|
@ -40,6 +40,7 @@ mod select;
|
|||||||
#[cfg(feature = "rand")]
|
#[cfg(feature = "rand")]
|
||||||
mod shuffle;
|
mod shuffle;
|
||||||
mod skip;
|
mod skip;
|
||||||
|
mod slice;
|
||||||
mod sort;
|
mod sort;
|
||||||
mod sort_by;
|
mod sort_by;
|
||||||
mod take;
|
mod take;
|
||||||
@ -99,6 +100,7 @@ pub use select::Select;
|
|||||||
#[cfg(feature = "rand")]
|
#[cfg(feature = "rand")]
|
||||||
pub use shuffle::Shuffle;
|
pub use shuffle::Shuffle;
|
||||||
pub use skip::*;
|
pub use skip::*;
|
||||||
|
pub use slice::Slice;
|
||||||
pub use sort::Sort;
|
pub use sort::Sort;
|
||||||
pub use sort_by::SortBy;
|
pub use sort_by::SortBy;
|
||||||
pub use take::*;
|
pub use take::*;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
use nu_protocol::Range as NumRange;
|
use nu_protocol::{report_parse_warning, ParseWarning};
|
||||||
use std::ops::Bound;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Range;
|
pub struct Range;
|
||||||
@ -17,7 +16,7 @@ impl Command for Range {
|
|||||||
Type::List(Box::new(Type::Any)),
|
Type::List(Box::new(Type::Any)),
|
||||||
)])
|
)])
|
||||||
.required("rows", SyntaxShape::Range, "Range of rows to return.")
|
.required("rows", SyntaxShape::Range, "Range of rows to return.")
|
||||||
.category(Category::Filters)
|
.category(Category::Deprecated)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
@ -65,69 +64,16 @@ impl Command for Range {
|
|||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let head = call.head;
|
let head = call.head;
|
||||||
let metadata = input.metadata();
|
report_parse_warning(
|
||||||
let rows: Spanned<NumRange> = call.req(engine_state, stack, 0)?;
|
&StateWorkingSet::new(engine_state),
|
||||||
|
&ParseWarning::DeprecatedWarning {
|
||||||
match rows.item {
|
old_command: "range".into(),
|
||||||
NumRange::IntRange(range) => {
|
new_suggestion: "use `slice`".into(),
|
||||||
let start = range.start();
|
span: head,
|
||||||
let end = match range.end() {
|
url: "`help slice`".into(),
|
||||||
Bound::Included(end) => end,
|
},
|
||||||
Bound::Excluded(end) => end - 1,
|
);
|
||||||
Bound::Unbounded => {
|
super::Slice::run(&super::Slice, engine_state, stack, call, input)
|
||||||
if range.step() < 0 {
|
|
||||||
i64::MIN
|
|
||||||
} else {
|
|
||||||
i64::MAX
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// only collect the input if we have any negative indices
|
|
||||||
if start < 0 || end < 0 {
|
|
||||||
let v: Vec<_> = input.into_iter().collect();
|
|
||||||
let vlen: i64 = v.len() as i64;
|
|
||||||
|
|
||||||
let from = if start < 0 {
|
|
||||||
(vlen + start) as usize
|
|
||||||
} else {
|
|
||||||
start as usize
|
|
||||||
};
|
|
||||||
|
|
||||||
let to = if end < 0 {
|
|
||||||
(vlen + end) as usize
|
|
||||||
} else if end > v.len() as i64 {
|
|
||||||
v.len()
|
|
||||||
} else {
|
|
||||||
end as usize
|
|
||||||
};
|
|
||||||
|
|
||||||
if from > to {
|
|
||||||
Ok(PipelineData::Value(Value::nothing(head), None))
|
|
||||||
} else {
|
|
||||||
let iter = v.into_iter().skip(from).take(to - from + 1);
|
|
||||||
Ok(iter.into_pipeline_data(head, engine_state.signals().clone()))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let from = start as usize;
|
|
||||||
let to = end as usize;
|
|
||||||
|
|
||||||
if from > to {
|
|
||||||
Ok(PipelineData::Value(Value::nothing(head), None))
|
|
||||||
} else {
|
|
||||||
let iter = input.into_iter().skip(from).take(to - from + 1);
|
|
||||||
Ok(iter.into_pipeline_data(head, engine_state.signals().clone()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.map(|x| x.set_metadata(metadata))
|
|
||||||
}
|
|
||||||
NumRange::FloatRange(_) => Err(ShellError::UnsupportedInput {
|
|
||||||
msg: "float range".into(),
|
|
||||||
input: "value originates from here".into(),
|
|
||||||
msg_span: call.head,
|
|
||||||
input_span: rows.span,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
144
crates/nu-command/src/filters/slice.rs
Normal file
144
crates/nu-command/src/filters/slice.rs
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
use nu_engine::command_prelude::*;
|
||||||
|
use nu_protocol::Range;
|
||||||
|
use std::ops::Bound;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Slice;
|
||||||
|
|
||||||
|
impl Command for Slice {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"slice"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("slice")
|
||||||
|
.input_output_types(vec![(
|
||||||
|
Type::List(Box::new(Type::Any)),
|
||||||
|
Type::List(Box::new(Type::Any)),
|
||||||
|
)])
|
||||||
|
.required("rows", SyntaxShape::Range, "Range of rows to return.")
|
||||||
|
.category(Category::Filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
"Return only the selected rows."
|
||||||
|
}
|
||||||
|
|
||||||
|
fn search_terms(&self) -> Vec<&str> {
|
||||||
|
vec!["filter", "head", "tail", "range"]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
vec![
|
||||||
|
Example {
|
||||||
|
example: "[0,1,2,3,4,5] | slice 4..5",
|
||||||
|
description: "Get the last 2 items",
|
||||||
|
result: Some(Value::list(
|
||||||
|
vec![Value::test_int(4), Value::test_int(5)],
|
||||||
|
Span::test_data(),
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
example: "[0,1,2,3,4,5] | slice (-2)..",
|
||||||
|
description: "Get the last 2 items",
|
||||||
|
result: Some(Value::list(
|
||||||
|
vec![Value::test_int(4), Value::test_int(5)],
|
||||||
|
Span::test_data(),
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
Example {
|
||||||
|
example: "[0,1,2,3,4,5] | slice (-3)..-2",
|
||||||
|
description: "Get the next to last 2 items",
|
||||||
|
result: Some(Value::list(
|
||||||
|
vec![Value::test_int(3), Value::test_int(4)],
|
||||||
|
Span::test_data(),
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
stack: &mut Stack,
|
||||||
|
call: &Call,
|
||||||
|
input: PipelineData,
|
||||||
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
let head = call.head;
|
||||||
|
let metadata = input.metadata();
|
||||||
|
let rows: Spanned<Range> = call.req(engine_state, stack, 0)?;
|
||||||
|
|
||||||
|
match rows.item {
|
||||||
|
Range::IntRange(range) => {
|
||||||
|
let start = range.start();
|
||||||
|
let end = match range.end() {
|
||||||
|
Bound::Included(end) => end,
|
||||||
|
Bound::Excluded(end) => end - 1,
|
||||||
|
Bound::Unbounded => {
|
||||||
|
if range.step() < 0 {
|
||||||
|
i64::MIN
|
||||||
|
} else {
|
||||||
|
i64::MAX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// only collect the input if we have any negative indices
|
||||||
|
if start < 0 || end < 0 {
|
||||||
|
let v: Vec<_> = input.into_iter().collect();
|
||||||
|
let vlen: i64 = v.len() as i64;
|
||||||
|
|
||||||
|
let from = if start < 0 {
|
||||||
|
(vlen + start) as usize
|
||||||
|
} else {
|
||||||
|
start as usize
|
||||||
|
};
|
||||||
|
|
||||||
|
let to = if end < 0 {
|
||||||
|
(vlen + end) as usize
|
||||||
|
} else if end > v.len() as i64 {
|
||||||
|
v.len()
|
||||||
|
} else {
|
||||||
|
end as usize
|
||||||
|
};
|
||||||
|
|
||||||
|
if from > to {
|
||||||
|
Ok(PipelineData::Value(Value::nothing(head), None))
|
||||||
|
} else {
|
||||||
|
let iter = v.into_iter().skip(from).take(to - from + 1);
|
||||||
|
Ok(iter.into_pipeline_data(head, engine_state.signals().clone()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let from = start as usize;
|
||||||
|
let to = end as usize;
|
||||||
|
|
||||||
|
if from > to {
|
||||||
|
Ok(PipelineData::Value(Value::nothing(head), None))
|
||||||
|
} else {
|
||||||
|
let iter = input.into_iter().skip(from).take(to - from + 1);
|
||||||
|
Ok(iter.into_pipeline_data(head, engine_state.signals().clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.map(|x| x.set_metadata(metadata))
|
||||||
|
}
|
||||||
|
Range::FloatRange(_) => Err(ShellError::UnsupportedInput {
|
||||||
|
msg: "float range".into(),
|
||||||
|
input: "value originates from here".into(),
|
||||||
|
msg_span: call.head,
|
||||||
|
input_span: rows.span,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_examples() {
|
||||||
|
use crate::test_examples;
|
||||||
|
|
||||||
|
test_examples(Slice {})
|
||||||
|
}
|
||||||
|
}
|
@ -82,7 +82,6 @@ mod print;
|
|||||||
#[cfg(feature = "sqlite")]
|
#[cfg(feature = "sqlite")]
|
||||||
mod query;
|
mod query;
|
||||||
mod random;
|
mod random;
|
||||||
mod range;
|
|
||||||
mod redirection;
|
mod redirection;
|
||||||
mod reduce;
|
mod reduce;
|
||||||
mod reject;
|
mod reject;
|
||||||
@ -100,6 +99,7 @@ mod seq;
|
|||||||
mod seq_char;
|
mod seq_char;
|
||||||
mod seq_date;
|
mod seq_date;
|
||||||
mod skip;
|
mod skip;
|
||||||
|
mod slice;
|
||||||
mod sort;
|
mod sort;
|
||||||
mod sort_by;
|
mod sort_by;
|
||||||
mod source_env;
|
mod source_env;
|
||||||
|
@ -4,7 +4,7 @@ use nu_test_support::{nu, pipeline};
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn selects_a_row() {
|
fn selects_a_row() {
|
||||||
Playground::setup("range_test_1", |dirs, sandbox| {
|
Playground::setup("slice_test_1", |dirs, sandbox| {
|
||||||
sandbox.with_files(&[EmptyFile("notes.txt"), EmptyFile("tests.txt")]);
|
sandbox.with_files(&[EmptyFile("notes.txt"), EmptyFile("tests.txt")]);
|
||||||
|
|
||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
@ -12,7 +12,7 @@ fn selects_a_row() {
|
|||||||
"
|
"
|
||||||
ls
|
ls
|
||||||
| sort-by name
|
| sort-by name
|
||||||
| range 0..0
|
| slice 0..0
|
||||||
| get name.0
|
| get name.0
|
||||||
"
|
"
|
||||||
));
|
));
|
||||||
@ -23,7 +23,7 @@ fn selects_a_row() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn selects_some_rows() {
|
fn selects_some_rows() {
|
||||||
Playground::setup("range_test_2", |dirs, sandbox| {
|
Playground::setup("slice_test_2", |dirs, sandbox| {
|
||||||
sandbox.with_files(&[
|
sandbox.with_files(&[
|
||||||
EmptyFile("notes.txt"),
|
EmptyFile("notes.txt"),
|
||||||
EmptyFile("tests.txt"),
|
EmptyFile("tests.txt"),
|
||||||
@ -35,7 +35,7 @@ fn selects_some_rows() {
|
|||||||
"
|
"
|
||||||
ls
|
ls
|
||||||
| get name
|
| get name
|
||||||
| range 1..2
|
| slice 1..2
|
||||||
| length
|
| length
|
||||||
"
|
"
|
||||||
));
|
));
|
||||||
@ -46,7 +46,7 @@ fn selects_some_rows() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn negative_indices() {
|
fn negative_indices() {
|
||||||
Playground::setup("range_test_negative_indices", |dirs, sandbox| {
|
Playground::setup("slice_test_negative_indices", |dirs, sandbox| {
|
||||||
sandbox.with_files(&[
|
sandbox.with_files(&[
|
||||||
EmptyFile("notes.txt"),
|
EmptyFile("notes.txt"),
|
||||||
EmptyFile("tests.txt"),
|
EmptyFile("tests.txt"),
|
||||||
@ -58,7 +58,7 @@ fn negative_indices() {
|
|||||||
"
|
"
|
||||||
ls
|
ls
|
||||||
| get name
|
| get name
|
||||||
| range (-1..)
|
| slice (-1..)
|
||||||
| length
|
| length
|
||||||
"
|
"
|
||||||
));
|
));
|
@ -441,7 +441,7 @@ fn better_operator_spans() -> TestResult {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn range_right_exclusive() -> TestResult {
|
fn range_right_exclusive() -> TestResult {
|
||||||
run_test(r#"[1, 4, 5, 8, 9] | range 1..<3 | math sum"#, "9")
|
run_test(r#"[1, 4, 5, 8, 9] | slice 1..<3 | math sum"#, "9")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Issue #7872
|
/// Issue #7872
|
||||||
|
Loading…
Reference in New Issue
Block a user