diff --git a/src/commands/enter.rs b/src/commands/enter.rs index dda96ab2e9..7b42793e12 100644 --- a/src/commands/enter.rs +++ b/src/commands/enter.rs @@ -38,11 +38,22 @@ impl PerItemCommand for Enter { let location = location.to_string(); let location_clone = location.to_string(); - if registry.has(&location) { - Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( - Value::string(location_clone).tagged(Tag::unknown()), - )))] - .into()) + if location.starts_with("help") { + let spec = location.split(":").collect::>(); + + let (_, command) = (spec[0], spec[1]); + + if registry.has(command) { + Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( + Value::string(command).tagged(Tag::unknown()), + )))] + .into()) + } else { + Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( + Value::nothing().tagged(Tag::unknown()), + )))] + .into()) + } } else if PathBuf::from(location).is_dir() { Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterShell( location_clone, diff --git a/src/commands/help.rs b/src/commands/help.rs index def2f33385..bfdd61173f 100644 --- a/src/commands/help.rs +++ b/src/commands/help.rs @@ -1,6 +1,7 @@ use crate::commands::command::CommandAction; use crate::commands::PerItemCommand; use crate::errors::ShellError; +use crate::object::{command_dict, TaggedDictBuilder}; use crate::parser::registry; use crate::prelude::*; @@ -22,34 +23,50 @@ impl PerItemCommand for Help { fn run( &self, call_info: &CallInfo, - _registry: &CommandRegistry, + registry: &CommandRegistry, _raw_args: &RawCommandArgs, _input: Tagged, ) -> Result { let span = call_info.name_span; if call_info.args.len() == 0 { - return Ok( - vec![ - Ok(ReturnSuccess::Action( - CommandAction::EnterHelpShell( - Tagged::from_simple_spanned_item(Value::nothing(), span) - )))].into() - ) + return Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( + Tagged::from_simple_spanned_item(Value::nothing(), span), + )))] + .into()); } match call_info.args.expect_nth(0)? { Tagged { item: Value::Primitive(Primitive::String(document)), - .. - } => Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( - Tagged::from_simple_spanned_item(Value::string(document), span) + tag, + } => { + if document == "commands" { + let mut specs = VecDeque::new(); + + for cmd in registry.names() { + let mut spec = TaggedDictBuilder::new(tag.clone()); + let value = command_dict(registry.get_command(&cmd).unwrap(), tag.clone()); + + spec.insert("name", cmd); + spec.insert( + "description", + value.get_data_by_key("usage").unwrap().as_string().unwrap(), + ); + spec.insert_tagged("details", value); + + specs.push_back(ReturnSuccess::value(spec.into_tagged_value())); + } + + return Ok(specs.to_output_stream()); + } + + Ok(OutputStream::empty()) + } + x => Ok(vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell( + x.clone(), )))] .into()), - x => Ok( - vec![Ok(ReturnSuccess::Action(CommandAction::EnterHelpShell(x.clone())))] - .into(), - ), } } } diff --git a/src/shell/value_shell.rs b/src/shell/value_shell.rs index 76be024dd4..1f6d6c7963 100644 --- a/src/shell/value_shell.rs +++ b/src/shell/value_shell.rs @@ -82,7 +82,9 @@ impl Shell for ValueShell { } fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result { - let path = match args.nth(0) { + let destination = args.nth(0); + + let path = match destination { None => "/".to_string(), Some(v) => { let target = v.as_path()?; @@ -108,6 +110,14 @@ impl Shell for ValueShell { value_system.walk_decorate(&self.value)?; if !value_system.exists(&PathBuf::from(&path)) { + if let Some(destination) = destination { + return Err(ShellError::labeled_error( + "Can not change to path inside", + "No such path exists", + destination.span(), + )); + } + return Err(ShellError::labeled_error( "Can not change to path inside", "No such path exists",