2019-12-07 03:46:05 +00:00
|
|
|
use crate::commands::UnevaluatedCallInfo;
|
2019-11-24 22:19:12 +00:00
|
|
|
use crate::prelude::*;
|
|
|
|
use log::{log_enabled, trace};
|
2019-11-21 17:18:00 +00:00
|
|
|
use nu_errors::ShellError;
|
2019-11-24 22:19:12 +00:00
|
|
|
use nu_parser::InternalCommand;
|
2019-11-21 17:18:00 +00:00
|
|
|
use nu_protocol::{CommandAction, Primitive, ReturnSuccess, UntaggedValue, Value};
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-11-24 22:19:12 +00:00
|
|
|
pub(crate) async fn run_internal_command(
|
|
|
|
command: InternalCommand,
|
|
|
|
context: &mut Context,
|
2020-01-10 06:31:44 +00:00
|
|
|
input: Option<InputStream>,
|
2019-11-24 22:19:12 +00:00
|
|
|
source: Text,
|
2020-01-10 06:31:44 +00:00
|
|
|
) -> Result<Option<InputStream>, ShellError> {
|
2019-11-24 22:19:12 +00:00
|
|
|
if log_enabled!(log::Level::Trace) {
|
|
|
|
trace!(target: "nu::run::internal", "->");
|
|
|
|
trace!(target: "nu::run::internal", "{}", command.name);
|
|
|
|
trace!(target: "nu::run::internal", "{}", command.args.debug(&source));
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
|
|
|
|
2020-01-10 06:31:44 +00:00
|
|
|
let objects: InputStream = if let Some(input) = input {
|
|
|
|
trace_stream!(target: "nu::trace_stream::internal", "input" = input)
|
|
|
|
} else {
|
|
|
|
InputStream::empty()
|
|
|
|
};
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-11-24 22:19:12 +00:00
|
|
|
let internal_command = context.expect_command(&command.name);
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-11-24 22:19:12 +00:00
|
|
|
let result = {
|
|
|
|
context.run_command(
|
2020-01-02 07:07:17 +00:00
|
|
|
internal_command?,
|
2019-11-24 22:19:12 +00:00
|
|
|
command.name_tag.clone(),
|
2019-12-07 03:46:05 +00:00
|
|
|
command.args.clone(),
|
2019-11-24 22:19:12 +00:00
|
|
|
&source,
|
|
|
|
objects,
|
|
|
|
)
|
|
|
|
};
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-11-24 22:19:12 +00:00
|
|
|
let result = trace_out_stream!(target: "nu::trace_stream::internal", "output" = result);
|
|
|
|
let mut result = result.values;
|
|
|
|
let mut context = context.clone();
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-11-24 22:19:12 +00:00
|
|
|
let stream = async_stream! {
|
|
|
|
let mut soft_errs: Vec<ShellError> = vec![];
|
|
|
|
let mut yielded = false;
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-11-24 22:19:12 +00:00
|
|
|
while let Some(item) = result.next().await {
|
|
|
|
match item {
|
|
|
|
Ok(ReturnSuccess::Action(action)) => match action {
|
|
|
|
CommandAction::ChangePath(path) => {
|
2020-01-03 21:11:21 +00:00
|
|
|
context.shell_manager.set_path(path)?;
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
|
|
|
CommandAction::Exit => std::process::exit(0), // TODO: save history.txt
|
|
|
|
CommandAction::Error(err) => {
|
2020-01-03 21:11:21 +00:00
|
|
|
context.error(err)?;
|
2019-11-24 22:19:12 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-12-07 03:46:05 +00:00
|
|
|
CommandAction::AutoConvert(tagged_contents, extension) => {
|
|
|
|
let contents_tag = tagged_contents.tag.clone();
|
|
|
|
let command_name = format!("from-{}", extension);
|
|
|
|
let command = command.clone();
|
2020-01-02 17:51:20 +00:00
|
|
|
if let Some(converter) = context.registry.get_command(&command_name)? {
|
2019-12-07 03:46:05 +00:00
|
|
|
let new_args = RawCommandArgs {
|
|
|
|
host: context.host.clone(),
|
|
|
|
ctrl_c: context.ctrl_c.clone(),
|
|
|
|
shell_manager: context.shell_manager.clone(),
|
|
|
|
call_info: UnevaluatedCallInfo {
|
|
|
|
args: nu_parser::hir::Call {
|
|
|
|
head: command.args.head,
|
|
|
|
positional: None,
|
|
|
|
named: None,
|
|
|
|
span: Span::unknown()
|
|
|
|
},
|
|
|
|
source: source.clone(),
|
|
|
|
name_tag: command.name_tag,
|
|
|
|
}
|
|
|
|
};
|
|
|
|
let mut result = converter.run(new_args.with_input(vec![tagged_contents]), &context.registry);
|
|
|
|
let result_vec: Vec<Result<ReturnSuccess, ShellError>> = result.drain_vec().await;
|
|
|
|
for res in result_vec {
|
|
|
|
match res {
|
|
|
|
Ok(ReturnSuccess::Value(Value { value: UntaggedValue::Table(list), ..})) => {
|
|
|
|
for l in list {
|
|
|
|
yield Ok(l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(ReturnSuccess::Value(Value { value, .. })) => {
|
|
|
|
yield Ok(value.into_value(contents_tag.clone()));
|
|
|
|
}
|
|
|
|
Err(e) => yield Err(e),
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2019-12-07 06:24:58 +00:00
|
|
|
} else {
|
|
|
|
yield Ok(tagged_contents)
|
2019-12-07 03:46:05 +00:00
|
|
|
}
|
|
|
|
}
|
2019-11-24 22:19:12 +00:00
|
|
|
CommandAction::EnterHelpShell(value) => {
|
|
|
|
match value {
|
|
|
|
Value {
|
|
|
|
value: UntaggedValue::Primitive(Primitive::String(cmd)),
|
|
|
|
tag,
|
|
|
|
} => {
|
2020-01-03 21:11:21 +00:00
|
|
|
let result = context.shell_manager.insert_at_current(Box::new(
|
2019-11-24 22:19:12 +00:00
|
|
|
HelpShell::for_command(
|
2019-12-04 19:52:31 +00:00
|
|
|
UntaggedValue::string(cmd).into_value(tag),
|
2019-11-24 22:19:12 +00:00
|
|
|
&context.registry(),
|
2020-01-02 17:51:20 +00:00
|
|
|
)?,
|
2019-11-24 22:19:12 +00:00
|
|
|
));
|
2020-01-03 21:11:21 +00:00
|
|
|
|
|
|
|
result?
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
2019-11-24 22:19:12 +00:00
|
|
|
_ => {
|
2020-01-03 21:11:21 +00:00
|
|
|
let result = context.shell_manager.insert_at_current(Box::new(
|
|
|
|
HelpShell::index(&context.registry())?,
|
2019-11-24 22:19:12 +00:00
|
|
|
));
|
2020-01-03 21:11:21 +00:00
|
|
|
|
|
|
|
result?
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-24 22:19:12 +00:00
|
|
|
CommandAction::EnterValueShell(value) => {
|
|
|
|
context
|
|
|
|
.shell_manager
|
2020-01-03 21:11:21 +00:00
|
|
|
.insert_at_current(Box::new(ValueShell::new(value)))?;
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
|
|
|
CommandAction::EnterShell(location) => {
|
|
|
|
context.shell_manager.insert_at_current(Box::new(
|
2020-01-04 06:44:17 +00:00
|
|
|
FilesystemShell::with_location(location, context.registry().clone()),
|
2020-01-03 21:11:21 +00:00
|
|
|
))?;
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
|
|
|
CommandAction::PreviousShell => {
|
2020-01-03 21:11:21 +00:00
|
|
|
context.shell_manager.prev()?;
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
|
|
|
CommandAction::NextShell => {
|
2020-01-03 21:11:21 +00:00
|
|
|
context.shell_manager.next()?;
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
|
|
|
CommandAction::LeaveShell => {
|
2020-01-03 21:11:21 +00:00
|
|
|
context.shell_manager.remove_at_current()?;
|
|
|
|
if context.shell_manager.is_empty()? {
|
2019-11-24 22:19:12 +00:00
|
|
|
std::process::exit(0); // TODO: save history.txt
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-11-24 22:19:12 +00:00
|
|
|
Ok(ReturnSuccess::Value(v)) => {
|
|
|
|
yielded = true;
|
|
|
|
yield Ok(v);
|
|
|
|
}
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-11-24 22:19:12 +00:00
|
|
|
Ok(ReturnSuccess::DebugValue(v)) => {
|
|
|
|
yielded = true;
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-11-24 22:19:12 +00:00
|
|
|
let doc = PrettyDebug::pretty_doc(&v);
|
|
|
|
let mut buffer = termcolor::Buffer::ansi();
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2020-01-02 05:24:41 +00:00
|
|
|
let _ = doc.render_raw(
|
2020-01-03 21:11:21 +00:00
|
|
|
context.with_host(|host| host.width() - 5)?,
|
2019-11-24 22:19:12 +00:00
|
|
|
&mut nu_source::TermColored::new(&mut buffer),
|
2020-01-02 05:24:41 +00:00
|
|
|
);
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-11-24 22:19:12 +00:00
|
|
|
let value = String::from_utf8_lossy(buffer.as_slice());
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2019-12-04 19:52:31 +00:00
|
|
|
yield Ok(UntaggedValue::string(value).into_untagged_value())
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Err(err) => {
|
2020-01-03 21:11:21 +00:00
|
|
|
context.error(err)?;
|
2019-11-24 22:19:12 +00:00
|
|
|
break;
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
|
|
|
}
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|
|
|
|
};
|
2019-11-24 22:19:12 +00:00
|
|
|
|
2020-01-10 06:31:44 +00:00
|
|
|
Ok(Some(stream.to_input_stream()))
|
2019-11-24 22:19:12 +00:00
|
|
|
}
|