Lines no longer treats a text buffer as a line (#3153)

This commit is contained in:
Jonathan Turner 2021-03-11 11:35:15 +13:00 committed by GitHub
parent ee5bd2b4b3
commit 0d305d7c3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 46 deletions

View File

@ -56,9 +56,9 @@ async fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
Ok(args Ok(args
.input .input
.chain(eos) .chain(eos)
.map(move |item| { .filter_map(move |item| {
let leftover_string = leftover_string.clone(); let leftover_string = leftover_string.clone();
async move {
match item { match item {
Value { Value {
value: UntaggedValue::Primitive(Primitive::String(st)), value: UntaggedValue::Primitive(Primitive::String(st)),
@ -66,9 +66,11 @@ async fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
} => { } => {
let mut leftover_string = leftover_string.lock(); let mut leftover_string = leftover_string.lock();
let lo_lines = (&*leftover_string).lines().map(|x| x.to_string()); let mut buffer = leftover_string.clone();
let st_lines = st.lines().map(|x| x.to_string()); buffer.push_str(&st);
let mut lines: Vec<String> = lo_lines.chain(st_lines).collect();
let mut lines: Vec<String> =
buffer.lines().map(|x| x.to_string()).collect();
leftover_string.clear(); leftover_string.clear();
@ -78,14 +80,20 @@ async fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
} }
} }
if !lines.is_empty() {
let success_lines: Vec<_> = lines let success_lines: Vec<_> = lines
.iter() .iter()
.map(|x| { .map(|x| {
ReturnSuccess::value(UntaggedValue::string(x).into_untagged_value()) ReturnSuccess::value(
UntaggedValue::string(x).into_untagged_value(),
)
}) })
.collect(); .collect();
futures::stream::iter(success_lines) Some(futures::stream::iter(success_lines))
} else {
None
}
} }
Value { Value {
value: UntaggedValue::Primitive(Primitive::EndOfStream), value: UntaggedValue::Primitive(Primitive::EndOfStream),
@ -93,22 +101,25 @@ async fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
} => { } => {
let st = (&*leftover_string).lock().clone(); let st = (&*leftover_string).lock().clone();
if !st.is_empty() { if !st.is_empty() {
futures::stream::iter(vec![ReturnSuccess::value( Some(futures::stream::iter(vec![ReturnSuccess::value(
UntaggedValue::string(st).into_untagged_value(), UntaggedValue::string(st).into_untagged_value(),
)]) )]))
} else { } else {
futures::stream::iter(vec![]) None
} }
} }
Value { Value {
tag: value_span, .. tag: value_span, ..
} => futures::stream::iter(vec![Err(ShellError::labeled_error_with_secondary( } => Some(futures::stream::iter(vec![Err(
ShellError::labeled_error_with_secondary(
"Expected a string from pipeline", "Expected a string from pipeline",
"requires string input", "requires string input",
name_span, name_span,
"value originates from here", "value originates from here",
value_span, value_span,
))]), ),
)])),
}
} }
}) })
.flatten() .flatten()

View File

@ -17,6 +17,21 @@ pub fn nonu() {
args().iter().skip(1).for_each(|arg| print!("{}", arg)); args().iter().skip(1).for_each(|arg| print!("{}", arg));
} }
pub fn repeater() {
let mut stdout = io::stdout();
let args = args();
let mut args = args.iter().skip(1);
let letter = args.next().expect("needs a character to iterate");
let count = args.next().expect("need the number of times to iterate");
let count: u64 = count.parse().expect("can't convert count to number");
for _ in 0..count {
let _ = write!(stdout, "{}", letter);
}
let _ = stdout.flush();
}
pub fn iecho() { pub fn iecho() {
// println! panics if stdout gets closed, whereas writeln gives us an error // println! panics if stdout gets closed, whereas writeln gives us an error
let mut stdout = io::stdout(); let mut stdout = io::stdout();

View File

@ -46,5 +46,5 @@ fn lines_multi_value_split() {
"# "#
)); ));
assert_eq!(actual.out, "6"); assert_eq!(actual.out, "5");
} }

View File

@ -29,7 +29,7 @@ fn main() -> Result<(), Box<dyn Error>> {
.hidden(true) .hidden(true)
.long("testbin") .long("testbin")
.value_name("TESTBIN") .value_name("TESTBIN")
.possible_values(&["cococo", "iecho", "fail", "nonu", "chop"]) .possible_values(&["cococo", "iecho", "fail", "nonu", "chop", "repeater"])
.takes_value(true), .takes_value(true),
) )
.arg( .arg(
@ -77,6 +77,7 @@ fn main() -> Result<(), Box<dyn Error>> {
"fail" => binaries::fail(), "fail" => binaries::fail(),
"nonu" => binaries::nonu(), "nonu" => binaries::nonu(),
"chop" => binaries::chop(), "chop" => binaries::chop(),
"repeater" => binaries::repeater(),
_ => unreachable!(), _ => unreachable!(),
} }

View File

@ -121,6 +121,17 @@ mod it_evaluation {
}) })
} }
#[test]
fn can_properly_buffer_lines_externally() {
let actual = nu!(
cwd: ".",
r#"
nu --testbin repeater c 8197 | lines | count
"#
);
assert_eq!(actual.out, "1");
}
#[test] #[test]
fn supports_fetching_given_a_column_path_to_it() { fn supports_fetching_given_a_column_path_to_it() {
Playground::setup("it_argument_test_3", |dirs, sandbox| { Playground::setup("it_argument_test_3", |dirs, sandbox| {