From bf86cd50a5928d86dce0e9b5b52a269cec35595f Mon Sep 17 00:00:00 2001 From: Antoine Stevan <44101798+amtoine@users.noreply.github.com> Date: Sat, 13 May 2023 19:40:11 +0200 Subject: [PATCH] REFACTOR: remove the shell commands (#8415) Related to #8368. # Description as planned in #8311, the `enter`, `shells`, `g`, `n` and `p` commands have been re-implemented in pure-`nushell` in the standard library. this PR removes the `rust` implementations of these commands. - all the "shells" tests have been removed from `crates/nu-commnand/tests/commands/` in 2cc6a82da6f77c01f2a0d06847eabde168a2e56b, except for the `exit` command - `cd` does not use the `shells` feature in its source code anymore => that does not change its single-shell behaviour - all the command implementations have been removed from `crates/nu-command/src/shells/`, except for `exit.rs` => `mod.rs` has been modified accordingly - the `exit` command now does not compute any "shell" related things - the `--now` option has been removed from `exit`, as it does not serve any purpose without sub-shells # User-Facing Changes users may now not use `enter`, `shells`, `g`, `n` and `p` now they would have to use the standard library to have access to equivalent features, thanks to the `dirs.nu` module introduced by @bobhy in #8368 # Tests + Formatting - :green_circle: `toolkit fmt` - :green_circle: `toolkit clippy` - :black_circle: `toolkit test` - :black_circle: `toolkit test stdlib` # After Submitting the website will have to be regenerated to reflect the removed commands :+1: --- crates/nu-command/src/default_context.rs | 5 - crates/nu-command/src/filesystem/cd.rs | 18 --- crates/nu-command/src/shells/enter.rs | 103 --------------- crates/nu-command/src/shells/exit.rs | 76 ++--------- crates/nu-command/src/shells/g.rs | 97 -------------- crates/nu-command/src/shells/mod.rs | 144 --------------------- crates/nu-command/src/shells/n.rs | 49 ------- crates/nu-command/src/shells/p.rs | 49 ------- crates/nu-command/src/shells/shells_.rs | 49 ------- crates/nu-command/tests/commands/enter.rs | 73 ----------- crates/nu-command/tests/commands/g.rs | 91 ------------- crates/nu-command/tests/commands/mod.rs | 5 - crates/nu-command/tests/commands/n.rs | 31 ----- crates/nu-command/tests/commands/p.rs | 31 ----- crates/nu-command/tests/commands/shells.rs | 31 ----- crates/nu-std/lib/dirs.nu | 33 +++++ crates/nu-std/src/lib.rs | 8 ++ src/tests/test_parser.rs | 9 -- 18 files changed, 49 insertions(+), 853 deletions(-) delete mode 100644 crates/nu-command/src/shells/enter.rs delete mode 100644 crates/nu-command/src/shells/g.rs delete mode 100644 crates/nu-command/src/shells/n.rs delete mode 100644 crates/nu-command/src/shells/p.rs delete mode 100644 crates/nu-command/src/shells/shells_.rs delete mode 100644 crates/nu-command/tests/commands/enter.rs delete mode 100644 crates/nu-command/tests/commands/g.rs delete mode 100644 crates/nu-command/tests/commands/n.rs delete mode 100644 crates/nu-command/tests/commands/p.rs delete mode 100644 crates/nu-command/tests/commands/shells.rs diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 3e9b6b65a..da9d56bce 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -277,12 +277,7 @@ pub fn create_default_context() -> EngineState { // Shells bind_command! { - Enter, Exit, - GotoShell, - NextShell, - PrevShell, - Shells, }; // Formats diff --git a/crates/nu-command/src/filesystem/cd.rs b/crates/nu-command/src/filesystem/cd.rs index 1438f3cae..15d745980 100644 --- a/crates/nu-command/src/filesystem/cd.rs +++ b/crates/nu-command/src/filesystem/cd.rs @@ -1,5 +1,4 @@ use crate::filesystem::cd_query::query; -use crate::{get_current_shell, get_shells}; #[cfg(unix)] use libc::gid_t; use nu_engine::{current_dir, CallExt}; @@ -164,23 +163,6 @@ impl Command for Cd { val: path.clone(), span, }; - let cwd = Value::string(cwd.to_string_lossy(), call.head); - - let mut shells = get_shells(engine_state, stack, cwd); - let current_shell = get_current_shell(engine_state, stack); - shells[current_shell] = path_value.clone(); - - stack.add_env_var( - "NUSHELL_SHELLS".into(), - Value::List { - vals: shells, - span: call.head, - }, - ); - stack.add_env_var( - "NUSHELL_CURRENT_SHELL".into(), - Value::int(current_shell as i64, call.head), - ); if let Some(oldpwd) = stack.get_env_var(engine_state, "PWD") { stack.add_env_var("OLDPWD".into(), oldpwd) diff --git a/crates/nu-command/src/shells/enter.rs b/crates/nu-command/src/shells/enter.rs deleted file mode 100644 index 2bf7e9f31..000000000 --- a/crates/nu-command/src/shells/enter.rs +++ /dev/null @@ -1,103 +0,0 @@ -use super::{get_current_shell, get_shells}; -use nu_engine::{current_dir, CallExt}; -use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, Stack}; -use nu_protocol::{ - Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value, -}; - -/// Source a file for environment variables. -#[derive(Clone)] -pub struct Enter; - -impl Command for Enter { - fn name(&self) -> &str { - "enter" - } - - fn signature(&self) -> Signature { - Signature::build("enter") - .input_output_types(vec![(Type::Nothing, Type::Nothing)]) - .required( - "path", - SyntaxShape::Filepath, - "the path to enter as a new shell", - ) - .category(Category::Shells) - } - - fn usage(&self) -> &str { - "Enters a new shell at the given path." - } - - fn run( - &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - _input: PipelineData, - ) -> Result { - let new_path: Value = call.req(engine_state, stack, 0)?; - let path_span = new_path.span()?; - - let new_path = new_path.as_path()?; - - let cwd = current_dir(engine_state, stack)?; - let new_path = nu_path::canonicalize_with(new_path, &cwd)?; - - if !new_path.exists() { - return Err(ShellError::DirectoryNotFound(path_span, None)); - } - - if !new_path.is_dir() { - return Err(ShellError::DirectoryNotFoundCustom( - "not a directory".to_string(), - path_span, - )); - } - - let new_path = Value::string(new_path.to_string_lossy(), call.head); - - let cwd = Value::string(cwd.to_string_lossy(), call.head); - - let mut shells = get_shells(engine_state, stack, cwd); - let mut current_shell = get_current_shell(engine_state, stack); - - stack.add_env_var( - "NUSHELL_LAST_SHELL".into(), - Value::int(current_shell as i64, call.head), - ); - - if current_shell + 1 > shells.len() { - shells.push(new_path.clone()); - current_shell = shells.len(); - } else { - shells.insert(current_shell + 1, new_path.clone()); - current_shell += 1; - } - - stack.add_env_var( - "NUSHELL_SHELLS".into(), - Value::List { - vals: shells, - span: call.head, - }, - ); - stack.add_env_var( - "NUSHELL_CURRENT_SHELL".into(), - Value::int(current_shell as i64, call.head), - ); - - stack.add_env_var("PWD".into(), new_path); - - Ok(PipelineData::empty()) - } - - fn examples(&self) -> Vec { - vec![Example { - description: "Enter a new shell at path '../dir-foo'", - example: r#"enter ../dir-foo"#, - result: None, - }] - } -} diff --git a/crates/nu-command/src/shells/exit.rs b/crates/nu-command/src/shells/exit.rs index df947776f..8573fa11b 100644 --- a/crates/nu-command/src/shells/exit.rs +++ b/crates/nu-command/src/shells/exit.rs @@ -1,10 +1,7 @@ -use super::{get_current_shell, get_last_shell, get_shells}; -use nu_engine::{current_dir, CallExt}; +use nu_engine::CallExt; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EngineState, Stack}; -use nu_protocol::{ - Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value, -}; +use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type}; #[derive(Clone)] pub struct Exit; @@ -22,11 +19,6 @@ impl Command for Exit { SyntaxShape::Int, "Exit code to return immediately with", ) - .switch( - "now", - "Exit out of all shells immediately (exiting Nu)", - Some('n'), - ) .category(Category::Shells) } @@ -51,66 +43,14 @@ impl Command for Exit { std::process::exit(exit_code as i32); } - if call.has_flag("now") { - std::process::exit(0); - } - - let cwd = current_dir(engine_state, stack)?; - let cwd = Value::string(cwd.to_string_lossy(), call.head); - - let mut shells = get_shells(engine_state, stack, cwd); - let mut current_shell = get_current_shell(engine_state, stack); - let mut last_shell = get_last_shell(engine_state, stack); - - shells.remove(current_shell); - - if current_shell <= last_shell { - last_shell = 0; - } - - if current_shell == shells.len() && !shells.is_empty() { - current_shell -= 1; - } - - if shells.is_empty() { - std::process::exit(0); - } else { - let new_path = shells[current_shell].clone(); - - stack.add_env_var( - "NUSHELL_SHELLS".into(), - Value::List { - vals: shells, - span: call.head, - }, - ); - stack.add_env_var( - "NUSHELL_CURRENT_SHELL".into(), - Value::int(current_shell as i64, call.head), - ); - stack.add_env_var( - "NUSHELL_LAST_SHELL".into(), - Value::int(last_shell as i64, call.head), - ); - - stack.add_env_var("PWD".into(), new_path); - - Ok(PipelineData::empty()) - } + std::process::exit(0); } fn examples(&self) -> Vec { - vec![ - Example { - description: "Exit the current shell", - example: "exit", - result: None, - }, - Example { - description: "Exit all shells (exiting Nu)", - example: "exit --now", - result: None, - }, - ] + vec![Example { + description: "Exit the current shell", + example: "exit", + result: None, + }] } } diff --git a/crates/nu-command/src/shells/g.rs b/crates/nu-command/src/shells/g.rs deleted file mode 100644 index 570600582..000000000 --- a/crates/nu-command/src/shells/g.rs +++ /dev/null @@ -1,97 +0,0 @@ -use super::{list_shells, switch_shell, SwitchTo}; -use nu_engine::CallExt; -use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, Stack}; -use nu_protocol::{ - Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type, Value, -}; - -/// Source a file for environment variables. -#[derive(Clone)] -pub struct GotoShell; - -impl Command for GotoShell { - fn name(&self) -> &str { - "g" - } - - fn signature(&self) -> Signature { - Signature::build("g") - .input_output_types(vec![ - (Type::Nothing, Type::Nothing), - (Type::Nothing, Type::Table(vec![])), - ]) - .optional( - "shell_number", - SyntaxShape::OneOf(vec![SyntaxShape::Int, SyntaxShape::String]), - "shell number to change to", - ) - .category(Category::Shells) - } - - fn usage(&self) -> &str { - "Switch to a given shell, or list all shells if no given shell number." - } - - fn run( - &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - _input: PipelineData, - ) -> Result { - let new_shell: Option = call.opt(engine_state, stack, 0)?; - - match new_shell { - Some(shell_span) => match &shell_span { - Value::String { val, span } => { - if val == "-" { - switch_shell(engine_state, stack, call, *span, SwitchTo::Last) - } else { - Err(ShellError::TypeMismatch { - err_message: "int or '-'".into(), - span: *span, - }) - } - } - Value::Int { val, span } => switch_shell( - engine_state, - stack, - call, - *span, - SwitchTo::Nth(*val as usize), - ), - _ => Err(ShellError::TypeMismatch { - err_message: "int or '-'".into(), - span: call.head, - }), - }, - None => list_shells(engine_state, stack, call.head), - } - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Lists all open shells", - example: r#"g"#, - result: None, - }, - Example { - description: "Make two directories and enter new shells for them, use `g` to jump to the specific shell", - example: r#"mkdir foo bar; enter foo; enter ../bar; g 1"#, - result: None, - }, - Example { - description: "Use `shells` to show all the opened shells and run `g 2` to jump to the third one", - example: r#"shells; g 2"#, - result: None, - }, - Example { - description: "Make two directories and enter new shells for them, use `g -` to jump to the last used shell", - example: r#"mkdir foo bar; enter foo; enter ../bar; g -"#, - result: None, - }, - ] - } -} diff --git a/crates/nu-command/src/shells/mod.rs b/crates/nu-command/src/shells/mod.rs index 19f76d996..11d875e64 100644 --- a/crates/nu-command/src/shells/mod.rs +++ b/crates/nu-command/src/shells/mod.rs @@ -1,147 +1,3 @@ -mod enter; mod exit; -mod g; -mod n; -mod p; -mod shells_; -pub use enter::Enter; pub use exit::Exit; -pub use g::GotoShell; -pub use n::NextShell; -use nu_engine::current_dir; -use nu_protocol::ast::Call; -use nu_protocol::engine::{EngineState, Stack}; -use nu_protocol::{IntoInterruptiblePipelineData, PipelineData, ShellError, Span, Value}; -pub use p::PrevShell; -pub use shells_::Shells; - -enum SwitchTo { - Next, - Prev, - Last, - Nth(usize), -} - -pub fn get_shells(engine_state: &EngineState, stack: &mut Stack, cwd: Value) -> Vec { - let shells = stack.get_env_var(engine_state, "NUSHELL_SHELLS"); - let shells = if let Some(v) = shells { - v.as_list() - .map(|x| x.to_vec()) - .unwrap_or_else(|_| vec![cwd]) - } else { - vec![cwd] - }; - shells -} - -pub fn get_current_shell(engine_state: &EngineState, stack: &mut Stack) -> usize { - let current_shell = stack.get_env_var(engine_state, "NUSHELL_CURRENT_SHELL"); - if let Some(v) = current_shell { - v.as_integer().unwrap_or_default() as usize - } else { - 0 - } -} - -fn get_last_shell(engine_state: &EngineState, stack: &mut Stack) -> usize { - let last_shell = stack.get_env_var(engine_state, "NUSHELL_LAST_SHELL"); - if let Some(v) = last_shell { - v.as_integer().unwrap_or_default() as usize - } else { - 0 - } -} - -fn switch_shell( - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - span: Span, - switch_to: SwitchTo, -) -> Result { - let cwd = current_dir(engine_state, stack)?; - let cwd = Value::string(cwd.to_string_lossy(), call.head); - - let shells = get_shells(engine_state, stack, cwd); - let current_shell = get_current_shell(engine_state, stack); - - let new_shell = match switch_to { - SwitchTo::Next => { - let mut new_shell = current_shell + 1; - - if new_shell == shells.len() { - new_shell = 0; - } - - new_shell - } - SwitchTo::Prev => { - if current_shell == 0 { - shells.len() - 1 - } else { - current_shell - 1 - } - } - SwitchTo::Last => get_last_shell(engine_state, stack), - SwitchTo::Nth(n) => n, - }; - - let new_path = shells - .get(new_shell) - .ok_or(ShellError::NotFound { span })? - .to_owned(); - - stack.add_env_var( - "NUSHELL_SHELLS".into(), - Value::List { - vals: shells, - span: call.head, - }, - ); - - stack.add_env_var( - "NUSHELL_CURRENT_SHELL".into(), - Value::int(new_shell as i64, call.head), - ); - - stack.add_env_var( - "NUSHELL_LAST_SHELL".into(), - Value::int(current_shell as i64, call.head), - ); - - stack.add_env_var("PWD".into(), new_path); - - Ok(PipelineData::empty()) -} - -fn list_shells( - engine_state: &EngineState, - stack: &mut Stack, - span: Span, -) -> Result { - let cwd = current_dir(engine_state, stack)?; - let cwd = Value::String { - val: cwd.to_string_lossy().to_string(), - span, - }; - - let shells = get_shells(engine_state, stack, cwd); - let current_shell = get_current_shell(engine_state, stack); - - Ok(shells - .into_iter() - .enumerate() - .map(move |(idx, val)| Value::Record { - cols: vec!["active".to_string(), "path".to_string()], - vals: vec![ - Value::Bool { - val: idx == current_shell, - span, - }, - val, - ], - span, - }) - .into_pipeline_data(None)) -} diff --git a/crates/nu-command/src/shells/n.rs b/crates/nu-command/src/shells/n.rs deleted file mode 100644 index c30045cf9..000000000 --- a/crates/nu-command/src/shells/n.rs +++ /dev/null @@ -1,49 +0,0 @@ -use super::{switch_shell, SwitchTo}; -use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, Stack}; -use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Type}; - -/// Source a file for environment variables. -#[derive(Clone)] -pub struct NextShell; - -impl Command for NextShell { - fn name(&self) -> &str { - "n" - } - - fn signature(&self) -> Signature { - Signature::build("n") - .category(Category::Shells) - .input_output_types(vec![(Type::Nothing, Type::Nothing)]) - } - - fn usage(&self) -> &str { - "Switch to the next shell." - } - - fn run( - &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - _input: PipelineData, - ) -> Result { - switch_shell(engine_state, stack, call, call.head, SwitchTo::Next) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Make two directories and enter new shells for them, use `n` to jump to the next shell", - example: r#"mkdir foo bar; enter foo; enter ../bar; n"#, - result: None, - }, - Example { - description: "Run `n` several times and note the changes of current directory", - example: r#"n"#, - result: None, - }, - ] - } -} diff --git a/crates/nu-command/src/shells/p.rs b/crates/nu-command/src/shells/p.rs deleted file mode 100644 index 794b7a201..000000000 --- a/crates/nu-command/src/shells/p.rs +++ /dev/null @@ -1,49 +0,0 @@ -use super::{switch_shell, SwitchTo}; -use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, Stack}; -use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Type}; - -/// Source a file for environment variables. -#[derive(Clone)] -pub struct PrevShell; - -impl Command for PrevShell { - fn name(&self) -> &str { - "p" - } - - fn signature(&self) -> Signature { - Signature::build("p") - .category(Category::Shells) - .input_output_types(vec![(Type::Nothing, Type::Nothing)]) - } - - fn usage(&self) -> &str { - "Switch to the previous shell." - } - - fn run( - &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - _input: PipelineData, - ) -> Result { - switch_shell(engine_state, stack, call, call.head, SwitchTo::Prev) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Make two directories and enter new shells for them, use `p` to jump to the previous shell", - example: r#"mkdir foo bar; enter foo; enter ../bar; p"#, - result: None, - }, - Example { - description: "Run `p` several times and note the changes of current directory", - example: r#"p"#, - result: None, - }, - ] - } -} diff --git a/crates/nu-command/src/shells/shells_.rs b/crates/nu-command/src/shells/shells_.rs deleted file mode 100644 index 50cb3a767..000000000 --- a/crates/nu-command/src/shells/shells_.rs +++ /dev/null @@ -1,49 +0,0 @@ -use super::list_shells; -use nu_protocol::ast::Call; -use nu_protocol::engine::{Command, EngineState, Stack}; -use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, Type}; - -/// Source a file for environment variables. -#[derive(Clone)] -pub struct Shells; - -impl Command for Shells { - fn name(&self) -> &str { - "shells" - } - - fn signature(&self) -> Signature { - Signature::build("shells") - .category(Category::Shells) - .input_output_types(vec![(Type::Nothing, Type::Table(vec![]))]) - } - - fn usage(&self) -> &str { - "Lists all open shells." - } - - fn run( - &self, - engine_state: &EngineState, - stack: &mut Stack, - call: &Call, - _input: PipelineData, - ) -> Result { - list_shells(engine_state, stack, call.head) - } - - fn examples(&self) -> Vec { - vec![ - Example { - description: "Enter a new shell at parent path '..' and show all opened shells", - example: r#"enter ..; shells"#, - result: None, - }, - Example { - description: "Show currently active shell", - example: r#"shells | where active == true"#, - result: None, - }, - ] - } -} diff --git a/crates/nu-command/tests/commands/enter.rs b/crates/nu-command/tests/commands/enter.rs deleted file mode 100644 index 86b88ed6c..000000000 --- a/crates/nu-command/tests/commands/enter.rs +++ /dev/null @@ -1,73 +0,0 @@ -use nu_test_support::fs::{files_exist_at, Stub::EmptyFile}; -use nu_test_support::nu; -use nu_test_support::playground::Playground; -use std::path::Path; - -#[test] -fn knows_the_filesystems_entered() { - Playground::setup("enter_test_1", |dirs, sandbox| { - sandbox - .within("red_pill") - .with_files(vec![ - EmptyFile("andres.nu"), - EmptyFile("jtnu"), - EmptyFile("yehuda.nu"), - ]) - .within("blue_pill") - .with_files(vec![ - EmptyFile("bash.nxt"), - EmptyFile("korn.nxt"), - EmptyFile("powedsh.nxt"), - ]) - .mkdir("expected"); - - let red_pill_dir = dirs.test().join("red_pill"); - let blue_pill_dir = dirs.test().join("blue_pill"); - let expected = dirs.test().join("expected"); - let expected_recycled = expected.join("recycled"); - - nu!( - cwd: dirs.test(), - " - enter expected - mkdir recycled - enter ../red_pill - mv jtnu ../expected - enter ../blue_pill - cp *.nxt ../expected/recycled - p - p - mv ../red_pill/yehuda.nu . - n - mv andres.nu ../expected/andres.nu - exit - cd .. - rm red_pill --recursive - exit - n - rm blue_pill --recursive - exit - " - ); - - assert!(!red_pill_dir.exists()); - assert!(files_exist_at( - vec![ - Path::new("andres.nu"), - Path::new("jtnu"), - Path::new("yehuda.nu"), - ], - expected - )); - - assert!(!blue_pill_dir.exists()); - assert!(files_exist_at( - vec![ - Path::new("bash.nxt"), - Path::new("korn.nxt"), - Path::new("powedsh.nxt"), - ], - expected_recycled - )); - }) -} diff --git a/crates/nu-command/tests/commands/g.rs b/crates/nu-command/tests/commands/g.rs deleted file mode 100644 index aabf507ad..000000000 --- a/crates/nu-command/tests/commands/g.rs +++ /dev/null @@ -1,91 +0,0 @@ -use nu_test_support::{nu, pipeline, playground::Playground}; - -#[test] -fn list_shells() { - let actual = nu!( - cwd: ".", pipeline( - r#"g | get path | length "# - )); - - assert_eq!(actual.out, "1"); -} - -#[test] -fn enter_shell() { - let actual = nu!( - cwd: ".", pipeline( - r#"g 0"# - )); - - assert!(actual.err.is_empty()); -} - -#[test] -fn enter_not_exist_shell() { - let actual = nu!( - cwd: ".", pipeline( - r#"g 1"# - )); - - assert!(actual.err.contains("Not found")); -} - -#[test] -fn switch_to_last_used_shell_1() { - Playground::setup("switch_last_used_shell_1", |dirs, sandbox| { - sandbox.mkdir("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#"enter foo; enter ../bar; g 0; g -;g | get active.2"# - )); - - assert_eq!(actual.out, "true"); - }) -} - -#[test] -fn switch_to_last_used_shell_2() { - Playground::setup("switch_last_used_shell_2", |dirs, sandbox| { - sandbox.mkdir("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#"enter foo; enter ../bar; n; g -;g | get active.2"# - )); - - assert_eq!(actual.out, "true"); - }) -} - -#[test] -fn switch_to_last_used_shell_3() { - Playground::setup("switch_last_used_shell_3", |dirs, sandbox| { - sandbox.mkdir("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#"enter foo; enter ../bar; p; g -;g | get active.2"# - )); - - assert_eq!(actual.out, "true"); - }) -} - -#[test] -fn switch_to_last_used_shell_4() { - Playground::setup("switch_last_used_shell_4", |dirs, sandbox| { - sandbox.mkdir("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#"enter foo; enter ../bar; g 2; exit; g -;g | get active.0"# - )); - - assert_eq!(actual.out, "true"); - }) -} diff --git a/crates/nu-command/tests/commands/mod.rs b/crates/nu-command/tests/commands/mod.rs index 9bff39c3b..8da49708b 100644 --- a/crates/nu-command/tests/commands/mod.rs +++ b/crates/nu-command/tests/commands/mod.rs @@ -18,7 +18,6 @@ mod drop; mod each; mod echo; mod empty; -mod enter; mod error_make; mod every; #[cfg(not(windows))] @@ -30,7 +29,6 @@ mod first; mod flatten; mod for_; mod format; -mod g; mod get; mod glob; mod group_by; @@ -54,11 +52,9 @@ mod merge; mod mkdir; mod move_; mod mut_; -mod n; mod network; mod nu_check; mod open; -mod p; mod par_each; mod parse; mod path; @@ -84,7 +80,6 @@ mod select; mod semicolon; mod seq; mod seq_char; -mod shells; mod skip; mod sort; mod sort_by; diff --git a/crates/nu-command/tests/commands/n.rs b/crates/nu-command/tests/commands/n.rs deleted file mode 100644 index 682bd4b2e..000000000 --- a/crates/nu-command/tests/commands/n.rs +++ /dev/null @@ -1,31 +0,0 @@ -use nu_test_support::{nu, pipeline, playground::Playground}; - -#[test] -fn switch_to_next_shell_1() { - Playground::setup("switch_to_next_shell_1", |dirs, sandbox| { - sandbox.mkdir("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#"enter foo; enter ../bar; n; g | get active.0"# - )); - - assert_eq!(actual.out, "true"); - }) -} - -#[test] -fn switch_to_next_shell_2() { - Playground::setup("switch_to_next_shell_2", |dirs, sandbox| { - sandbox.mkdir("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#"enter foo; enter ../bar; n; n; g | get active.1"# - )); - - assert_eq!(actual.out, "true"); - }) -} diff --git a/crates/nu-command/tests/commands/p.rs b/crates/nu-command/tests/commands/p.rs deleted file mode 100644 index d8b3c4979..000000000 --- a/crates/nu-command/tests/commands/p.rs +++ /dev/null @@ -1,31 +0,0 @@ -use nu_test_support::{nu, pipeline, playground::Playground}; - -#[test] -fn switch_to_prev_shell_1() { - Playground::setup("switch_to_next_shell_1", |dirs, sandbox| { - sandbox.mkdir("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#"enter foo; enter ../bar; p; g | get active.1"# - )); - - assert_eq!(actual.out, "true"); - }) -} - -#[test] -fn switch_to_prev_shell_2() { - Playground::setup("switch_to_next_shell_2", |dirs, sandbox| { - sandbox.mkdir("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#"enter foo; enter ../bar; p; p; p; g | get active.2"# - )); - - assert_eq!(actual.out, "true"); - }) -} diff --git a/crates/nu-command/tests/commands/shells.rs b/crates/nu-command/tests/commands/shells.rs deleted file mode 100644 index 3f3cf23c5..000000000 --- a/crates/nu-command/tests/commands/shells.rs +++ /dev/null @@ -1,31 +0,0 @@ -use nu_test_support::{nu, pipeline, playground::Playground}; - -#[test] -fn list_shells_1() { - Playground::setup("list_shells_1", |dirs, sandbox| { - sandbox.mkdir("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#"enter foo; enter ../bar; g| get active.2"# - )); - - assert_eq!(actual.out, "true"); - }) -} - -#[test] -fn list_shells_2() { - Playground::setup("list_shells_2", |dirs, sandbox| { - sandbox.mkdir("foo").mkdir("bar"); - - let actual = nu!( - cwd: dirs.test(), - pipeline( - r#"enter foo; enter ../bar; shells| get active.2"# - )); - - assert_eq!(actual.out, "true"); - }) -} diff --git a/crates/nu-std/lib/dirs.nu b/crates/nu-std/lib/dirs.nu index d2e966446..b43e0e508 100644 --- a/crates/nu-std/lib/dirs.nu +++ b/crates/nu-std/lib/dirs.nu @@ -27,6 +27,8 @@ export def-env "dirs add" [ _fetch 0 } +export alias enter = dirs add + # Advance to the next directory in the list or wrap to beginning. export def-env "dirs next" [ N:int = 1 # number of positions to move. @@ -34,6 +36,8 @@ export def-env "dirs next" [ _fetch $N } +export alias n = dirs next + # Back up to the previous directory or wrap to the end. export def-env "dirs prev" [ N:int = 1 # number of positions to move. @@ -41,6 +45,8 @@ export def-env "dirs prev" [ _fetch (-1 * $N) } +export alias p = dirs prev + # Drop the current directory from the list, if it's not the only one. # PWD becomes the next working directory export def-env "dirs drop" [] { @@ -54,6 +60,8 @@ export def-env "dirs drop" [] { _fetch 0 } +export alias dexit = dirs drop + # Display current working directories. export def-env "dirs show" [] { mut out = [] @@ -67,6 +75,31 @@ export def-env "dirs show" [] { $out } +export alias shells = dirs show + +export def-env "dirs goto" [shell?: int] { + if $shell == null { + return (dirs show) + } + + if $shell < 0 or $shell >= ($env.DIRS_LIST | length) { + let span = (metadata $shell | get span) + error make { + msg: $"(ansi red_bold)invalid_shell_index(ansi reset)" + label: { + text: $"`shell` should be between 0 and (($env.DIRS_LIST | length) - 1)" + start: $span.start + end: $span.end + } + } + } + let-env DIRS_POSITION = $shell + + cd ($env.DIRS_LIST | get $env.DIRS_POSITION) +} + +export alias g = dirs goto + # fetch item helper def-env _fetch [ offset: int, # signed change to position diff --git a/crates/nu-std/src/lib.rs b/crates/nu-std/src/lib.rs index d81054873..b25f4e747 100644 --- a/crates/nu-std/src/lib.rs +++ b/crates/nu-std/src/lib.rs @@ -88,6 +88,7 @@ pub fn load_standard_library( // Conventionally, for a command implemented as `std foo`, the name added // is either `std foo` or bare `foo`, not some arbitrary rename. + #[rustfmt::skip] let prelude = vec![ ("std help", "help"), ("std help commands", "help commands"), @@ -95,6 +96,13 @@ pub fn load_standard_library( ("std help modules", "help modules"), ("std help externs", "help externs"), ("std help operators", "help operators"), + + ("enter", "enter"), + ("shells", "shells"), + ("g", "g"), + ("n", "n"), + ("p", "p"), + ("dexit", "dexit"), ]; let mut working_set = StateWorkingSet::new(engine_state); diff --git a/src/tests/test_parser.rs b/src/tests/test_parser.rs index ab5b4f0a4..b34058156 100644 --- a/src/tests/test_parser.rs +++ b/src/tests/test_parser.rs @@ -179,15 +179,6 @@ fn bad_short_flag() -> TestResult { fail_test(r#"def foo3 [-l?:int] { $l }"#, "short flag") } -#[test] -fn alias_with_error_doesnt_panic() -> TestResult { - fail_test( - r#"alias s = shells - s ."#, - "extra positional", - ) -} - #[test] fn quotes_with_equals() -> TestResult { run_test(