diff --git a/crates/nu-command/src/commands/shells/goto.rs b/crates/nu-command/src/commands/shells/goto.rs new file mode 100644 index 0000000000..d1396c2dc6 --- /dev/null +++ b/crates/nu-command/src/commands/shells/goto.rs @@ -0,0 +1,51 @@ +use crate::prelude::*; +use nu_engine::WholeStreamCommand; +use nu_errors::ShellError; +use nu_protocol::{CommandAction, ReturnSuccess, Signature, SyntaxShape}; + +pub struct Goto; + +impl WholeStreamCommand for Goto { + fn name(&self) -> &str { + "g" + } + + fn signature(&self) -> Signature { + Signature::build("g").required("index", SyntaxShape::Int, "the shell's index to go to") + } + + fn usage(&self) -> &str { + "Go to specified shell." + } + + fn run_with_actions(&self, args: CommandArgs) -> Result { + goto(args) + } + + fn examples(&self) -> Vec { + vec![Example { + description: "Enter the first shell", + example: "g 0", + result: None, + }] + } +} + +fn goto(args: CommandArgs) -> Result { + Ok(ActionStream::one(ReturnSuccess::action( + CommandAction::GotoShell(args.req(0)?), + ))) +} + +#[cfg(test)] +mod tests { + use super::Goto; + use super::ShellError; + + #[test] + fn examples_work_as_expected() -> Result<(), ShellError> { + use crate::examples::test as test_examples; + + test_examples(Goto {}) + } +} diff --git a/crates/nu-command/src/commands/shells/mod.rs b/crates/nu-command/src/commands/shells/mod.rs index f41b3e954a..7c4897b1f0 100644 --- a/crates/nu-command/src/commands/shells/mod.rs +++ b/crates/nu-command/src/commands/shells/mod.rs @@ -1,11 +1,13 @@ mod command; mod enter; mod exit; +mod goto; mod next; mod prev; pub use command::Shells; pub use enter::Enter; pub use exit::Exit; +pub use goto::Goto; pub use next::Next; pub use prev::Previous; diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index fa9d405a4c..dfec8ff1fb 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -77,6 +77,7 @@ pub fn create_default_context(interactive: bool) -> Result { self.context.shell_manager().next(); } + CommandAction::GotoShell(i) => { + self.context.shell_manager().goto(i); + } CommandAction::LeaveShell(code) => { self.context.shell_manager().remove_at_current(); if self.context.shell_manager().is_empty() { diff --git a/crates/nu-engine/src/shell/shell_manager.rs b/crates/nu-engine/src/shell/shell_manager.rs index 90b080bb5f..d1430ef2ca 100644 --- a/crates/nu-engine/src/shell/shell_manager.rs +++ b/crates/nu-engine/src/shell/shell_manager.rs @@ -136,6 +136,16 @@ impl ShellManager { self.set_path(self.path()) } + pub fn goto(&self, i: usize) { + { + let shell_len = self.shells.lock().len(); + if i < shell_len { + self.current_shell.store(i, Ordering::SeqCst); + } + } + self.set_path(self.path()) + } + pub fn homedir(&self) -> Option { let env = self.shells.lock(); diff --git a/crates/nu-protocol/src/return_value.rs b/crates/nu-protocol/src/return_value.rs index f097c60443..34a80c54a5 100644 --- a/crates/nu-protocol/src/return_value.rs +++ b/crates/nu-protocol/src/return_value.rs @@ -28,6 +28,8 @@ pub enum CommandAction { PreviousShell, /// Go to the next shell in the shell ring buffer NextShell, + /// Jump to the specified shell in the shell ring buffer + GotoShell(usize), /// Leave the current shell. If it's the last shell, exit out of Nu LeaveShell(i32), } @@ -51,6 +53,7 @@ impl PrettyDebug for CommandAction { CommandAction::AddPlugins(..) => DbgDocBldr::description("add plugins"), CommandAction::PreviousShell => DbgDocBldr::description("previous shell"), CommandAction::NextShell => DbgDocBldr::description("next shell"), + CommandAction::GotoShell(_) => DbgDocBldr::description("goto shell"), CommandAction::LeaveShell(_) => DbgDocBldr::description("leave shell"), CommandAction::UnloadConfig(cfg) => { DbgDocBldr::description(format!("unload config {:?}", cfg))