mirror of
https://github.com/nushell/nushell
synced 2025-01-10 04:09:09 +00:00
232 lines
10 KiB
Rust
232 lines
10 KiB
Rust
use crate::commands::{RawCommandArgs, WholeStreamCommand};
|
|
use crate::prelude::*;
|
|
use futures::stream::TryStreamExt;
|
|
use nu_errors::ShellError;
|
|
use nu_parser::hir::{Expression, NamedArguments};
|
|
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
|
use std::sync::atomic::Ordering;
|
|
|
|
pub struct Autoview;
|
|
|
|
const STREAM_PAGE_SIZE: u64 = 50;
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct AutoviewArgs {}
|
|
|
|
impl WholeStreamCommand for Autoview {
|
|
fn name(&self) -> &str {
|
|
"autoview"
|
|
}
|
|
|
|
fn signature(&self) -> Signature {
|
|
Signature::build("autoview")
|
|
}
|
|
|
|
fn usage(&self) -> &str {
|
|
"View the contents of the pipeline as a table or list."
|
|
}
|
|
|
|
fn run(
|
|
&self,
|
|
args: CommandArgs,
|
|
registry: &CommandRegistry,
|
|
) -> Result<OutputStream, ShellError> {
|
|
Ok(args.process_raw(registry, autoview)?.run())
|
|
}
|
|
}
|
|
|
|
pub fn autoview(
|
|
AutoviewArgs {}: AutoviewArgs,
|
|
context: RunnableContext,
|
|
raw: RawCommandArgs,
|
|
) -> Result<OutputStream, ShellError> {
|
|
let binary = context.get_command("binaryview");
|
|
let text = context.get_command("textview");
|
|
let table = context.get_command("table");
|
|
|
|
Ok(OutputStream::new(async_stream! {
|
|
let mut output_stream: OutputStream = context.input.into();
|
|
|
|
let next = output_stream.try_next().await;
|
|
|
|
match next {
|
|
Ok(Some(x)) => {
|
|
match output_stream.try_next().await {
|
|
Ok(Some(y)) => {
|
|
let ctrl_c = context.ctrl_c.clone();
|
|
let stream = async_stream! {
|
|
yield Ok(x);
|
|
yield Ok(y);
|
|
|
|
loop {
|
|
match output_stream.try_next().await {
|
|
Ok(Some(z)) => {
|
|
if ctrl_c.load(Ordering::SeqCst) {
|
|
break;
|
|
}
|
|
yield Ok(z);
|
|
}
|
|
_ => break,
|
|
}
|
|
}
|
|
};
|
|
if let Some(table) = table {
|
|
let mut new_output_stream: OutputStream = stream.to_output_stream();
|
|
let mut finished = false;
|
|
let mut current_idx = 0;
|
|
loop {
|
|
let mut new_input = VecDeque::new();
|
|
|
|
for _ in 0..STREAM_PAGE_SIZE {
|
|
match new_output_stream.try_next().await {
|
|
|
|
Ok(Some(a)) => {
|
|
if let ReturnSuccess::Value(v) = a {
|
|
new_input.push_back(v);
|
|
}
|
|
}
|
|
_ => {
|
|
finished = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
let raw = raw.clone();
|
|
|
|
let input: Vec<Value> = new_input.into();
|
|
|
|
if input.len() > 0 && input.iter().all(|value| value.value.is_error()) {
|
|
let first = &input[0];
|
|
|
|
let mut host = context.host.clone();
|
|
let mut host = match host.lock() {
|
|
Err(err) => {
|
|
errln!("Unexpected error acquiring host lock: {:?}", err);
|
|
return;
|
|
}
|
|
Ok(val) => val
|
|
};
|
|
|
|
crate::cli::print_err(first.value.expect_error(), &*host, &context.source);
|
|
return;
|
|
}
|
|
|
|
let mut command_args = raw.with_input(input);
|
|
let mut named_args = NamedArguments::new();
|
|
named_args.insert_optional("start_number", Some(Expression::number(current_idx, Tag::unknown())));
|
|
command_args.call_info.args.named = Some(named_args);
|
|
|
|
let result = table.run(command_args, &context.commands);
|
|
result.collect::<Vec<_>>().await;
|
|
|
|
|
|
if finished {
|
|
break;
|
|
} else {
|
|
current_idx += STREAM_PAGE_SIZE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_ => {
|
|
if let ReturnSuccess::Value(x) = x {
|
|
match x {
|
|
Value {
|
|
value: UntaggedValue::Primitive(Primitive::String(ref s)),
|
|
tag: Tag { anchor, span },
|
|
} if anchor.is_some() => {
|
|
if let Some(text) = text {
|
|
let mut stream = VecDeque::new();
|
|
stream.push_back(UntaggedValue::string(s).into_value(Tag { anchor, span }));
|
|
let result = text.run(raw.with_input(stream.into()), &context.commands);
|
|
result.collect::<Vec<_>>().await;
|
|
} else {
|
|
outln!("{}", s);
|
|
}
|
|
}
|
|
Value {
|
|
value: UntaggedValue::Primitive(Primitive::String(s)),
|
|
..
|
|
} => {
|
|
outln!("{}", s);
|
|
}
|
|
Value {
|
|
value: UntaggedValue::Primitive(Primitive::Line(ref s)),
|
|
tag: Tag { anchor, span },
|
|
} if anchor.is_some() => {
|
|
if let Some(text) = text {
|
|
let mut stream = VecDeque::new();
|
|
stream.push_back(UntaggedValue::string(s).into_value(Tag { anchor, span }));
|
|
let result = text.run(raw.with_input(stream.into()), &context.commands);
|
|
result.collect::<Vec<_>>().await;
|
|
} else {
|
|
outln!("{}\n", s);
|
|
}
|
|
}
|
|
Value {
|
|
value: UntaggedValue::Primitive(Primitive::Line(s)),
|
|
..
|
|
} => {
|
|
outln!("{}\n", s);
|
|
}
|
|
Value {
|
|
value: UntaggedValue::Primitive(Primitive::Path(s)),
|
|
..
|
|
} => {
|
|
outln!("{}", s.display());
|
|
}
|
|
Value {
|
|
value: UntaggedValue::Primitive(Primitive::Int(n)),
|
|
..
|
|
} => {
|
|
outln!("{}", n);
|
|
}
|
|
Value {
|
|
value: UntaggedValue::Primitive(Primitive::Decimal(n)),
|
|
..
|
|
} => {
|
|
outln!("{}", n);
|
|
}
|
|
|
|
Value { value: UntaggedValue::Primitive(Primitive::Binary(ref b)), .. } => {
|
|
if let Some(binary) = binary {
|
|
let mut stream = VecDeque::new();
|
|
stream.push_back(x);
|
|
let result = binary.run(raw.with_input(stream.into()), &context.commands);
|
|
result.collect::<Vec<_>>().await;
|
|
} else {
|
|
use pretty_hex::*;
|
|
outln!("{:?}", b.hex_dump());
|
|
}
|
|
}
|
|
|
|
Value { value: UntaggedValue::Error(e), .. } => {
|
|
yield Err(e);
|
|
}
|
|
Value { value: ref item, .. } => {
|
|
if let Some(table) = table {
|
|
let mut stream = VecDeque::new();
|
|
stream.push_back(x);
|
|
let result = table.run(raw.with_input(stream.into()), &context.commands);
|
|
result.collect::<Vec<_>>().await;
|
|
} else {
|
|
outln!("{:?}", item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_ => {
|
|
//outln!("<no results>");
|
|
}
|
|
}
|
|
|
|
// Needed for async_stream to type check
|
|
if false {
|
|
yield ReturnSuccess::value(UntaggedValue::nothing().into_untagged_value());
|
|
}
|
|
}))
|
|
}
|