use std::{
collections::{HashMap, HashSet, LinkedList},
env::current_dir,
path::{Path, PathBuf},
};
use shrs::prelude::*;
pub struct CdStackState {
down_stack: LinkedList<PathBuf>,
up_stack: LinkedList<PathBuf>,
}
impl CdStackState {
pub fn new() -> Self {
Self {
down_stack: LinkedList::new(),
up_stack: LinkedList::new(),
}
}
pub fn push(&mut self, path: &Path) {
self.down_stack.push_back(path.to_path_buf());
self.up_stack.clear();
}
pub fn down(&mut self) -> Option<PathBuf> {
let top = self.down_stack.pop_back();
if let Some(top) = top {
self.up_stack.push_back(top);
}
self.down_stack.back().cloned()
}
pub fn up(&mut self) -> Option<PathBuf> {
let top = self.up_stack.pop_back();
if let Some(top) = top.clone() {
self.down_stack.push_back(top);
}
top
}
}
fn change_dir_hook(
sh: &Shell,
ctx: &mut Context,
rt: &mut Runtime,
hook_ctx: &ChangeDirCtx,
) -> anyhow::Result<()> {
if let Some(state) = ctx.state.get_mut::<CdStackState>() {
state.push(&hook_ctx.new_dir);
}
Ok(())
}
pub struct CdStackPlugin;
impl Plugin for CdStackPlugin {
fn init(&self, shell: &mut ShellConfig) -> anyhow::Result<()> {
let mut cd_stack_state = CdStackState::new();
cd_stack_state.push(¤t_dir().unwrap());
shell.state.insert(cd_stack_state);
shell.hooks.insert(change_dir_hook);
Ok(())
}
}