mirror of
https://github.com/nushell/nushell
synced 2024-12-27 05:23:11 +00:00
Make g -
switch to the last used shell (#6249)
* Make `g -` switch to the last used shell Related #6223 Signed-off-by: nibon7 <nibon7@163.com> * simplify error handling Signed-off-by: nibon7 <nibon7@163.com> * update NUSHELL_LAST_SHELL environment Signed-off-by: nibon7 <nibon7@163.com> * add test Signed-off-by: nibon7 <nibon7@163.com> * fix description Signed-off-by: nibon7 <nibon7@163.com>
This commit is contained in:
parent
a871f2344a
commit
1ba5b25b29
8 changed files with 148 additions and 9 deletions
|
@ -395,9 +395,23 @@ pub fn evaluate_repl(
|
|||
0
|
||||
};
|
||||
|
||||
let last_shell = stack.get_env_var(engine_state, "NUSHELL_LAST_SHELL");
|
||||
let last_shell = if let Some(v) = last_shell {
|
||||
v.as_integer().unwrap_or_default() as usize
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
shells[current_shell] = Value::String { val: path, span };
|
||||
|
||||
stack.add_env_var("NUSHELL_SHELLS".into(), Value::List { vals: shells, span });
|
||||
stack.add_env_var(
|
||||
"NUSHELL_LAST_SHELL".into(),
|
||||
Value::Int {
|
||||
val: last_shell as i64,
|
||||
span,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
trace!("eval source: {}", s);
|
||||
|
||||
|
|
|
@ -66,6 +66,14 @@ impl Command for Enter {
|
|||
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 {
|
||||
val: current_shell as i64,
|
||||
span: call.head,
|
||||
},
|
||||
);
|
||||
|
||||
if current_shell + 1 > shells.len() {
|
||||
shells.push(new_path.clone());
|
||||
current_shell = shells.len();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{get_current_shell, get_shells};
|
||||
use super::{get_current_shell, get_last_shell, get_shells};
|
||||
use nu_engine::{current_dir, CallExt};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
|
@ -60,9 +60,14 @@ impl Command for Exit {
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -86,6 +91,13 @@ impl Command for Exit {
|
|||
span: call.head,
|
||||
},
|
||||
);
|
||||
stack.add_env_var(
|
||||
"NUSHELL_LAST_SHELL".into(),
|
||||
Value::Int {
|
||||
val: last_shell as i64,
|
||||
span: call.head,
|
||||
},
|
||||
);
|
||||
|
||||
stack.add_env_var("PWD".into(), new_path);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{get_current_shell, get_shells};
|
||||
use super::{get_current_shell, get_last_shell, get_shells};
|
||||
use nu_engine::{current_dir, CallExt};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
|
@ -20,7 +20,7 @@ impl Command for GotoShell {
|
|||
Signature::build("g")
|
||||
.optional(
|
||||
"shell_number",
|
||||
SyntaxShape::Int,
|
||||
SyntaxShape::String,
|
||||
"shell number to change to",
|
||||
)
|
||||
.category(Category::Shells)
|
||||
|
@ -38,7 +38,7 @@ impl Command for GotoShell {
|
|||
_input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let span = call.head;
|
||||
let new_shell: Option<Spanned<i64>> = call.opt(engine_state, stack, 0)?;
|
||||
let new_shell: Option<Spanned<String>> = call.opt(engine_state, stack, 0)?;
|
||||
|
||||
let cwd = current_dir(engine_state, stack)?;
|
||||
let cwd = Value::String {
|
||||
|
@ -50,12 +50,22 @@ impl Command for GotoShell {
|
|||
|
||||
match new_shell {
|
||||
Some(shell_span) => {
|
||||
let new_path = if let Some(v) = shells.get(shell_span.item as usize) {
|
||||
v.clone()
|
||||
let index = if shell_span.item == "-" {
|
||||
get_last_shell(engine_state, stack)
|
||||
} else {
|
||||
return Err(ShellError::NotFound(shell_span.span));
|
||||
shell_span
|
||||
.item
|
||||
.parse::<usize>()
|
||||
.map_err(|_| ShellError::NotFound(shell_span.span))?
|
||||
};
|
||||
|
||||
let new_path = shells
|
||||
.get(index)
|
||||
.ok_or(ShellError::NotFound(shell_span.span))?
|
||||
.to_owned();
|
||||
|
||||
let current_shell = get_current_shell(engine_state, stack);
|
||||
|
||||
stack.add_env_var(
|
||||
"NUSHELL_SHELLS".into(),
|
||||
Value::List {
|
||||
|
@ -66,7 +76,14 @@ impl Command for GotoShell {
|
|||
stack.add_env_var(
|
||||
"NUSHELL_CURRENT_SHELL".into(),
|
||||
Value::Int {
|
||||
val: shell_span.item,
|
||||
val: index as i64,
|
||||
span: call.head,
|
||||
},
|
||||
);
|
||||
stack.add_env_var(
|
||||
"NUSHELL_LAST_SHELL".into(),
|
||||
Value::Int {
|
||||
val: current_shell as i64,
|
||||
span: call.head,
|
||||
},
|
||||
);
|
||||
|
@ -114,6 +131,11 @@ impl Command for GotoShell {
|
|||
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,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,3 +34,12 @@ pub fn get_current_shell(engine_state: &EngineState, stack: &mut Stack) -> usize
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,13 @@ impl Command for NextShell {
|
|||
|
||||
let 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 {
|
||||
val: current_shell as i64,
|
||||
span: call.head,
|
||||
},
|
||||
);
|
||||
|
||||
current_shell += 1;
|
||||
|
||||
|
|
|
@ -36,6 +36,13 @@ impl Command for PrevShell {
|
|||
|
||||
let 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 {
|
||||
val: current_shell as i64,
|
||||
span: call.head,
|
||||
},
|
||||
);
|
||||
|
||||
if current_shell == 0 {
|
||||
current_shell = shells.len() - 1;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use nu_test_support::{nu, pipeline};
|
||||
use nu_test_support::{nu, pipeline, playground::Playground};
|
||||
|
||||
#[test]
|
||||
fn list_shells() {
|
||||
|
@ -29,3 +29,63 @@ fn enter_not_exist_shell() {
|
|||
|
||||
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");
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue