use std::{
env,
ffi::{OsStr, OsString},
marker::PhantomData,
path::{Path, PathBuf},
};
use anyhow::Ok;
#[derive(Debug, Clone, Copy, Default)]
pub struct ShellPromptState;
impl ShellPromptState {
pub fn get_current_dir(
provided_current_dir: Option<PathBuf>,
) -> anyhow::Result<CurrentDirState> {
let current_dir = if let Some(current_dir) = provided_current_dir {
current_dir
} else {
env::current_dir()?
};
Ok(CurrentDirState { current_dir })
}
}
#[derive(Debug, Clone)]
pub struct CurrentDirState {
current_dir: PathBuf,
}
impl CurrentDirState {
pub fn match_rcs<RC>(
self,
match_rcs_cb: impl Fn(&Path) -> anyhow::Result<Vec<RC>>,
) -> anyhow::Result<MatchRcs<RC>> {
let rcs = match_rcs_cb(&self.current_dir)?;
let match_rcs = if rcs.is_empty() {
MatchRcs::NoRcs(NoRcsState {
phantom: PhantomData,
})
} else {
MatchRcs::Rcs(RcsState { rcs })
};
Ok(match_rcs)
}
}
#[derive(Debug, Clone)]
pub enum MatchRcs<RC> {
NoRcs(NoRcsState),
Rcs(RcsState<RC>),
}
#[derive(Debug, Clone)]
pub struct NoRcsState {
phantom: PhantomData<()>,
}
impl NoRcsState {
pub fn get_env_state_var(
self,
env_state_var_key: impl AsRef<OsStr>,
) -> Option<ReadyForFullResetState> {
get_env_state_var(env_state_var_key).map(|env_state_var_value| ReadyForFullResetState {
env_state_var_value,
})
}
}
#[derive(Debug, Clone)]
pub struct ReadyForFullResetState {
env_state_var_value: OsString,
}
impl ReadyForFullResetState {
pub fn reset_env_vars(
self,
reset_env_vars_cb: impl Fn(OsString) -> anyhow::Result<()>,
) -> anyhow::Result<()> {
reset_env_vars_cb(self.env_state_var_value)?;
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct RcsState<RC> {
rcs: Vec<RC>,
}
impl<RC> RcsState<RC> {
pub fn get_env_state_var(self, env_state_var_key: impl AsRef<OsStr>) -> GetEnvStateVar<RC> {
let rcs = self.rcs;
if let Some(env_state_var_value) = get_env_state_var(env_state_var_key) {
GetEnvStateVar::EnvStateVar(EnvStateVarState {
rcs,
env_state_var_value,
})
} else {
GetEnvStateVar::NoEnvStateVar(NoEnvStateVarState { rcs })
}
}
}
#[derive(Debug, Clone)]
pub enum GetEnvStateVar<RC> {
NoEnvStateVar(NoEnvStateVarState<RC>),
EnvStateVar(EnvStateVarState<RC>),
}
#[derive(Debug, Clone)]
pub struct NoEnvStateVarState<RC> {
rcs: Vec<RC>,
}
impl<RC> NoEnvStateVarState<RC> {
pub fn set_new_env_state_var(
self,
set_new_env_state_var_cb: impl Fn(Vec<RC>) -> anyhow::Result<()>,
) -> anyhow::Result<()> {
set_new_env_state_var_cb(self.rcs)?;
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct EnvStateVarState<RC> {
rcs: Vec<RC>,
env_state_var_value: OsString,
}
impl<RC> EnvStateVarState<RC> {
pub fn reset_and_set_new_env_state_var<T>(
self,
reset_env_vars_cb: impl Fn(Vec<RC>, OsString) -> anyhow::Result<T>,
set_new_env_state_var_cb: impl Fn(T) -> anyhow::Result<()>,
) -> anyhow::Result<()> {
let state = reset_env_vars_cb(self.rcs, self.env_state_var_value)?;
set_new_env_state_var_cb(state)?;
Ok(())
}
}
fn get_env_state_var(env_state_var_key: impl AsRef<OsStr>) -> Option<OsString> {
env::var_os(env_state_var_key)
}