nushell/crates/nu-command/src/filters/lines.rs

90 lines
2.9 KiB
Rust
Raw Normal View History

2021-09-29 20:25:05 +02:00
use std::cell::RefCell;
use std::rc::Rc;
use nu_protocol::ast::Call;
2021-10-25 08:31:39 +02:00
use nu_protocol::engine::{Command, EngineState, EvaluationContext, Stack};
2021-10-25 06:01:02 +02:00
use nu_protocol::{IntoPipelineData, PipelineData, ShellError, Signature, Value, ValueStream};
2021-09-29 20:25:05 +02:00
2021-10-25 06:01:02 +02:00
#[derive(Clone)]
2021-09-29 20:25:05 +02:00
pub struct Lines;
const SPLIT_CHAR: char = '\n';
impl Command for Lines {
fn name(&self) -> &str {
"lines"
}
fn usage(&self) -> &str {
"Converts input to lines"
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build("lines")
}
fn run(
&self,
2021-10-25 08:31:39 +02:00
_engine_state: &EngineState,
_stack: &mut Stack,
2021-09-29 20:25:05 +02:00
call: &Call,
2021-10-25 06:01:02 +02:00
input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
let span = call.head;
2021-09-29 20:25:05 +02:00
match input {
#[allow(clippy::needless_collect)]
// Collect is needed because the string may not live long enough for
// the Rc structure to continue using it. If split could take ownership
// of the split values, then this wouldn't be needed
2021-10-25 06:01:02 +02:00
PipelineData::Value(Value::String { val, span }) => {
2021-09-29 20:25:05 +02:00
let lines = val
.split(SPLIT_CHAR)
.map(|s| s.to_string())
.collect::<Vec<String>>();
let iter = lines.into_iter().filter_map(move |s| {
if !s.is_empty() {
2021-10-20 07:58:25 +02:00
Some(Value::string(s, span))
2021-09-29 20:25:05 +02:00
} else {
None
}
});
2021-10-25 06:01:02 +02:00
Ok(iter.into_pipeline_data())
2021-09-29 20:25:05 +02:00
}
2021-10-25 06:01:02 +02:00
PipelineData::Stream(stream) => {
2021-09-29 20:25:05 +02:00
let iter = stream
.into_iter()
.filter_map(|value| {
if let Value::String { val, span } = value {
let inner = val
.split(SPLIT_CHAR)
.filter_map(|s| {
if !s.is_empty() {
Some(Value::String {
2021-10-02 23:56:11 +02:00
val: s.into(),
2021-09-29 20:25:05 +02:00
span,
})
} else {
None
}
})
.collect::<Vec<Value>>();
Some(inner)
} else {
None
}
})
.flatten();
2021-10-25 06:01:02 +02:00
Ok(iter.into_pipeline_data())
2021-09-29 20:25:05 +02:00
}
2021-10-25 06:01:02 +02:00
PipelineData::Value(val) => Err(ShellError::UnsupportedInput(
2021-09-29 20:25:05 +02:00
format!("Not supported input: {}", val.as_string()?),
call.head,
)),
}
}
}