nushell/crates/nu-cli/src/commands/enter.rs

168 lines
6.2 KiB
Rust
Raw Normal View History

2019-08-31 02:59:21 +02:00
use crate::commands::UnevaluatedCallInfo;
use crate::commands::WholeStreamCommand;
use crate::context::CommandRegistry;
2019-08-07 19:49:11 +02:00
use crate::prelude::*;
use nu_errors::ShellError;
use nu_protocol::{
CommandAction, Primitive, ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value,
};
use nu_source::Tagged;
use std::path::PathBuf;
2019-08-07 19:49:11 +02:00
2019-08-14 19:02:39 +02:00
pub struct Enter;
2019-08-09 06:51:21 +02:00
#[derive(Deserialize)]
pub struct EnterArgs {
location: Tagged<PathBuf>,
}
impl WholeStreamCommand for Enter {
2019-08-14 19:02:39 +02:00
fn name(&self) -> &str {
"enter"
2019-08-07 19:49:11 +02:00
}
fn signature(&self) -> Signature {
2019-10-28 06:15:35 +01:00
Signature::build("enter").required(
"location",
SyntaxShape::Path,
"the location to create a new shell from",
)
2019-08-14 19:02:39 +02:00
}
fn usage(&self) -> &str {
"Create a new shell and begin at this path."
}
2019-08-14 19:02:39 +02:00
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
2019-08-24 21:36:19 +02:00
) -> Result<OutputStream, ShellError> {
enter(args, registry)
}
2020-05-12 07:17:17 +02:00
fn examples(&self) -> &[Example] {
&[
Example {
description: "Enter a path as a new shell",
example: "enter ../projectB",
},
Example {
description: "Enter a file as a new shell",
example: "enter package.json",
},
]
}
}
fn enter(raw_args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
let registry = registry.clone();
let stream = async_stream! {
let scope = raw_args.call_info.scope.clone();
let shell_manager = raw_args.shell_manager.clone();
let head = raw_args.call_info.args.head.clone();
let ctrl_c = raw_args.ctrl_c.clone();
let host = raw_args.host.clone();
let tag = raw_args.call_info.name_tag.clone();
let (EnterArgs { location }, _) = raw_args.process(&registry).await?;
let location_string = location.display().to_string();
let location_clone = location_string.clone();
if location_string.starts_with("help") {
let spec = location_string.split(':').collect::<Vec<&str>>();
if spec.len() == 2 {
let (_, command) = (spec[0], spec[1]);
if registry.has(command) {
yield Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
UntaggedValue::string(command).into_value(Tag::unknown()),
)));
return;
}
}
yield Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(
UntaggedValue::nothing().into_value(Tag::unknown()),
)));
} else if location.is_dir() {
yield Ok(ReturnSuccess::Action(CommandAction::EnterShell(
location_clone,
)));
} else {
// If it's a file, attempt to open the file as a value and enter it
let cwd = shell_manager.path();
2019-08-31 02:59:21 +02:00
let full_path = std::path::PathBuf::from(cwd);
2019-08-31 02:59:21 +02:00
let (file_extension, contents, contents_tag) =
crate::commands::open::fetch(
&full_path,
&PathBuf::from(location_clone),
tag.span,
).await?;
2019-08-31 02:59:21 +02:00
match contents {
UntaggedValue::Primitive(Primitive::String(_)) => {
let tagged_contents = contents.into_value(&contents_tag);
if let Some(extension) = file_extension {
let command_name = format!("from {}", extension);
if let Some(converter) =
registry.get_command(&command_name)
{
let new_args = RawCommandArgs {
host,
ctrl_c,
shell_manager,
call_info: UnevaluatedCallInfo {
args: nu_protocol::hir::Call {
head,
positional: None,
named: None,
span: Span::unknown(),
is_last: false,
},
name_tag: tag.clone(),
scope: scope.clone()
},
};
let mut result = converter.run(
new_args.with_input(vec![tagged_contents]),
&registry,
);
let result_vec: Vec<Result<ReturnSuccess, ShellError>> =
result.drain_vec().await;
for res in result_vec {
match res {
Ok(ReturnSuccess::Value(Value {
value,
..
})) => {
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(
Value {
value,
tag: contents_tag.clone(),
})));
2019-08-31 02:59:21 +02:00
}
x => yield x,
2019-08-31 02:59:21 +02:00
}
}
} else {
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
2019-08-31 02:59:21 +02:00
}
} else {
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
}
}
_ => {
let tagged_contents = contents.into_value(contents_tag);
yield Ok(ReturnSuccess::Action(CommandAction::EnterValueShell(tagged_contents)));
2019-08-31 02:59:21 +02:00
}
}
}
};
Ok(stream.to_output_stream())
2019-08-07 19:49:11 +02:00
}