use crate::prompt::terminal::Terminal;
pub(crate) fn with_raw_mode<T, R>(
terminal: &mut T,
body: impl FnOnce(&mut T) -> rskit_errors::AppResult<R>,
) -> rskit_errors::AppResult<R>
where
T: Terminal + ?Sized,
{
terminal.begin_interactive()?;
let mut guard = RawModeGuard {
terminal,
armed: true,
};
let result = body(&mut *guard.terminal);
let teardown = guard.disarm();
match result {
Ok(value) => teardown.map(|()| value),
Err(error) => Err(error),
}
}
struct RawModeGuard<'a, T: Terminal + ?Sized> {
terminal: &'a mut T,
armed: bool,
}
impl<T: Terminal + ?Sized> RawModeGuard<'_, T> {
fn disarm(&mut self) -> rskit_errors::AppResult<()> {
let result = self.terminal.end_interactive();
if result.is_ok() {
self.armed = false;
}
result
}
}
impl<T: Terminal + ?Sized> Drop for RawModeGuard<'_, T> {
fn drop(&mut self) {
if self.armed {
let _ = self.terminal.end_interactive();
}
}
}