Merge pull request #313 from jonathandturner/fix_shell_ring

Fix shell-ring to rotate as expected
This commit is contained in:
Jonathan Turner 2019-08-20 05:04:44 +12:00 committed by GitHub
commit 154a45bbd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 43 deletions

View File

@ -140,19 +140,21 @@ impl InternalCommand {
} }
CommandAction::Exit => std::process::exit(0), CommandAction::Exit => std::process::exit(0),
CommandAction::EnterValueShell(value) => { CommandAction::EnterValueShell(value) => {
context.shell_manager.push(Box::new(ValueShell::new(value))); context
.shell_manager
.insert_at_current(Box::new(ValueShell::new(value)));
} }
CommandAction::EnterShell(location) => { CommandAction::EnterShell(location) => {
let path = std::path::Path::new(&location); let path = std::path::Path::new(&location);
if path.is_dir() { if path.is_dir() {
// If it's a directory, add a new filesystem shell // If it's a directory, add a new filesystem shell
context context.shell_manager.insert_at_current(Box::new(
.shell_manager FilesystemShell::with_location(
.push(Box::new(FilesystemShell::with_location(
location, location,
context.registry().clone(), context.registry().clone(),
)?)); )?,
));
} else { } else {
// If it's a file, attempt to open the file as a value and enter it // If it's a file, attempt to open the file as a value and enter it
let cwd = context.shell_manager.path(); let cwd = context.shell_manager.path();
@ -180,11 +182,13 @@ impl InternalCommand {
Span::unknown(), Span::unknown(),
)?; )?;
context.shell_manager.push(Box::new(ValueShell::new(value))); context
.shell_manager
.insert_at_current(Box::new(ValueShell::new(value)));
} }
value => context value => context.shell_manager.insert_at_current(Box::new(
.shell_manager ValueShell::new(value.tagged(contents_tag)),
.push(Box::new(ValueShell::new(value.tagged(contents_tag)))), )),
} }
} }
} }
@ -195,7 +199,7 @@ impl InternalCommand {
context.shell_manager.next(); context.shell_manager.next();
} }
CommandAction::LeaveShell => { CommandAction::LeaveShell => {
context.shell_manager.pop(); context.shell_manager.remove_at_current();
if context.shell_manager.is_empty() { if context.shell_manager.is_empty() {
std::process::exit(0); std::process::exit(0);
} }

View File

@ -6,12 +6,10 @@ pub fn shells(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputSt
let mut shells_out = VecDeque::new(); let mut shells_out = VecDeque::new();
let span = args.call_info.name_span; let span = args.call_info.name_span;
let shells_len = args.shell_manager.shells.lock().unwrap().len();
for (index, shell) in args.shell_manager.shells.lock().unwrap().iter().enumerate() { for (index, shell) in args.shell_manager.shells.lock().unwrap().iter().enumerate() {
let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(span)); let mut dict = TaggedDictBuilder::new(Tag::unknown_origin(span));
if index == (shells_len - 1) { if index == args.shell_manager.current_shell {
dict.insert(" ", "X".to_string()); dict.insert(" ", "X".to_string());
} else { } else {
dict.insert(" ", " ".to_string()); dict.insert(" ", " ".to_string());

View File

@ -9,25 +9,44 @@ use std::sync::{Arc, Mutex};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ShellManager { pub struct ShellManager {
crate current_shell: usize,
crate shells: Arc<Mutex<Vec<Box<dyn Shell + Send>>>>, crate shells: Arc<Mutex<Vec<Box<dyn Shell + Send>>>>,
} }
impl ShellManager { impl ShellManager {
pub fn basic(commands: CommandRegistry) -> Result<ShellManager, Box<dyn Error>> { pub fn basic(commands: CommandRegistry) -> Result<ShellManager, Box<dyn Error>> {
Ok(ShellManager { Ok(ShellManager {
current_shell: 0,
shells: Arc::new(Mutex::new(vec![Box::new(FilesystemShell::basic( shells: Arc::new(Mutex::new(vec![Box::new(FilesystemShell::basic(
commands, commands,
)?)])), )?)])),
}) })
} }
pub fn push(&mut self, shell: Box<dyn Shell + Send>) { pub fn insert_at_current(&mut self, shell: Box<dyn Shell + Send>) {
self.shells.lock().unwrap().push(shell); self.shells.lock().unwrap().push(shell);
self.current_shell = self.shells.lock().unwrap().len() - 1;
self.set_path(self.path()); self.set_path(self.path());
} }
pub fn pop(&mut self) { pub fn remove_at_current(&mut self) {
self.shells.lock().unwrap().pop(); {
let mut shells = self.shells.lock().unwrap();
if shells.len() > 0 {
if self.current_shell == shells.len() - 1 {
shells.pop();
let new_len = shells.len();
if new_len > 0 {
self.current_shell = new_len - 1;
} else {
return;
}
} else {
shells.remove(self.current_shell);
}
}
}
self.set_path(self.path());
} }
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
@ -35,16 +54,11 @@ impl ShellManager {
} }
pub fn path(&self) -> String { pub fn path(&self) -> String {
self.shells.lock().unwrap().last().unwrap().path() self.shells.lock().unwrap()[self.current_shell].path()
} }
pub fn set_path(&mut self, path: String) { pub fn set_path(&mut self, path: String) {
self.shells self.shells.lock().unwrap()[self.current_shell].set_path(path)
.lock()
.unwrap()
.last_mut()
.unwrap()
.set_path(path)
} }
pub fn complete( pub fn complete(
@ -53,37 +67,33 @@ impl ShellManager {
pos: usize, pos: usize,
ctx: &rustyline::Context<'_>, ctx: &rustyline::Context<'_>,
) -> Result<(usize, Vec<rustyline::completion::Pair>), rustyline::error::ReadlineError> { ) -> Result<(usize, Vec<rustyline::completion::Pair>), rustyline::error::ReadlineError> {
self.shells self.shells.lock().unwrap()[self.current_shell].complete(line, pos, ctx)
.lock()
.unwrap()
.last()
.unwrap()
.complete(line, pos, ctx)
} }
pub fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> { pub fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
self.shells self.shells.lock().unwrap()[self.current_shell].hint(line, pos, ctx)
.lock()
.unwrap()
.last()
.unwrap()
.hint(line, pos, ctx)
} }
pub fn next(&mut self) { pub fn next(&mut self) {
{ {
let mut x = self.shells.lock().unwrap(); let shell_len = self.shells.lock().unwrap().len();
let shell = x.remove(0); if self.current_shell == (shell_len - 1) {
x.push(shell); self.current_shell = 0;
} else {
self.current_shell += 1;
}
} }
self.set_path(self.path()); self.set_path(self.path());
} }
pub fn prev(&mut self) { pub fn prev(&mut self) {
{ {
let mut x = self.shells.lock().unwrap(); let shell_len = self.shells.lock().unwrap().len();
let shell = x.pop().unwrap(); if self.current_shell == 0 {
x.insert(0, shell); self.current_shell = shell_len - 1;
} else {
self.current_shell -= 1;
}
} }
self.set_path(self.path()); self.set_path(self.path());
} }
@ -91,11 +101,11 @@ impl ShellManager {
pub fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> { pub fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
let env = self.shells.lock().unwrap(); let env = self.shells.lock().unwrap();
env.last().unwrap().ls(args) env[self.current_shell].ls(args)
} }
pub fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> { pub fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError> {
let env = self.shells.lock().unwrap(); let env = self.shells.lock().unwrap();
env.last().unwrap().cd(args) env[self.current_shell].cd(args)
} }
} }

View File

@ -48,6 +48,7 @@ fn knows_the_filesystems_entered() {
cd .. cd ..
rm red_pill --recursive rm red_pill --recursive
exit exit
n
rm blue_pill --recursive rm blue_pill --recursive
exit exit
"# "#