keyfork-prompt: refactor to use lifetimes

This commit is contained in:
Ryan Heywood 2023-12-21 12:12:52 -05:00
parent d8f9fc216f
commit 0ea49109d1
Signed by: ryan
GPG Key ID: 8E401478A3FBEF72
3 changed files with 34 additions and 52 deletions

View File

@ -1,7 +1,6 @@
use std::{ use std::{
io::Write, io::Write,
os::fd::AsRawFd, os::fd::AsRawFd,
sync::{Arc, Mutex},
}; };
use crossterm::{ use crossterm::{
@ -12,50 +11,44 @@ use crossterm::{
use crate::Result; use crate::Result;
pub(crate) struct AlternateScreen<W> pub(crate) struct AlternateScreen<'a, W>
where where
W: Write + AsRawFd + Sized, W: Write + AsRawFd + Sized,
{ {
write: Arc<Mutex<W>>, write: &'a mut W,
} }
impl<W> AlternateScreen<W> impl<'a, W> AlternateScreen<'a, W>
where where
W: Write + AsRawFd + Sized, W: Write + AsRawFd + Sized,
{ {
pub(crate) fn new(write_handle: Arc<Mutex<W>>) -> Result<Self> { pub(crate) fn new(write_handle: &'a mut W) -> Result<Self> {
let mut write = write_handle.lock().unwrap(); write_handle.execute(EnterAlternateScreen)?.execute(MoveTo(0, 0))?;
write.execute(EnterAlternateScreen)?.execute(MoveTo(0, 0))?;
drop(write);
Ok(Self { Ok(Self {
write: write_handle, write: write_handle,
}) })
} }
pub(crate) fn arc_mutex(self) -> Arc<Mutex<Self>> {
Arc::new(Mutex::new(self))
}
} }
impl<W> Write for AlternateScreen<W> impl<W> Write for AlternateScreen<'_, W>
where where
W: Write + AsRawFd + Sized, W: Write + AsRawFd + Sized,
{ {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.write.lock().unwrap().write(buf) self.write.write(buf)
} }
fn flush(&mut self) -> std::io::Result<()> { fn flush(&mut self) -> std::io::Result<()> {
self.write.lock().unwrap().flush() self.write.flush()
} }
} }
impl<W> AsRawFd for AlternateScreen<W> impl<W> AsRawFd for AlternateScreen<'_, W>
where where
W: Write + AsRawFd + Sized, W: Write + AsRawFd + Sized,
{ {
fn as_raw_fd(&self) -> std::os::fd::RawFd { fn as_raw_fd(&self) -> std::os::fd::RawFd {
self.write.lock().unwrap().as_raw_fd() self.write.as_raw_fd()
} }
} }
@ -77,12 +70,11 @@ where
} }
*/ */
impl<W> Drop for AlternateScreen<W> impl<W> Drop for AlternateScreen<'_, W>
where where
W: Write + AsRawFd + Sized, W: Write + AsRawFd + Sized,
{ {
fn drop(&mut self) { fn drop(&mut self) {
let mut write_handle = self.write.lock().unwrap(); self.write.execute(LeaveAlternateScreen).unwrap();
write_handle.execute(LeaveAlternateScreen).unwrap();
} }
} }

View File

@ -1,7 +1,6 @@
use std::{ use std::{
io::{BufRead, BufReader, Read, Write}, io::{BufRead, BufReader, Read, Write},
os::fd::AsRawFd, os::fd::AsRawFd,
sync::{Arc, Mutex},
}; };
use crossterm::{ use crossterm::{
@ -29,8 +28,8 @@ pub enum Error {
pub type Result<T, E = Error> = std::result::Result<T, E>; pub type Result<T, E = Error> = std::result::Result<T, E>;
pub struct PromptManager<R, W> { pub struct PromptManager<R, W> {
read: Arc<Mutex<BufReader<R>>>, read: BufReader<R>,
write: Arc<Mutex<W>>, write: W,
} }
impl<R, W> PromptManager<R, W> impl<R, W> PromptManager<R, W>
@ -43,31 +42,27 @@ where
return Err(Error::NotATTY); return Err(Error::NotATTY);
} }
Ok(Self { Ok(Self {
read: Arc::new(Mutex::new(BufReader::new(read_handle))), read: BufReader::new(read_handle),
write: Arc::new(Mutex::new(write_handle)), write: write_handle,
}) })
} }
fn alt_screen(&self) -> Result<AlternateScreen<W>> {
AlternateScreen::new(self.write.clone())
}
pub fn prompt_input(&mut self, prompt: &str) -> Result<String> { pub fn prompt_input(&mut self, prompt: &str) -> Result<String> {
let mut alt_screen = self.alt_screen()?; let mut terminal = AlternateScreen::new(&mut self.write)?;
alt_screen terminal
.execute(terminal::Clear(terminal::ClearType::All))? .execute(terminal::Clear(terminal::ClearType::All))?
.execute(Print(prompt))?; .execute(Print(prompt))?;
let mut line = String::new(); let mut line = String::new();
self.read.lock().unwrap().read_line(&mut line)?; self.read.read_line(&mut line)?;
Ok(line) Ok(line)
} }
// TODO: return secrecy::Secret<String> // TODO: return secrecy::Secret<String>
// TODO: write a guard drop system for raw mode // TODO: write a guard drop system for raw mode
pub fn prompt_passphrase(&mut self, prompt: &str) -> Result<String> { pub fn prompt_passphrase(&mut self, prompt: &str) -> Result<String> {
let write = AlternateScreen::new(self.write.clone())?; let mut terminal = AlternateScreen::new(&mut self.write)?;
let mut write = RawMode::new(write.arc_mutex())?; let mut terminal = RawMode::new(&mut terminal)?;
write terminal
.execute(terminal::Clear(terminal::ClearType::All))? .execute(terminal::Clear(terminal::ClearType::All))?
.execute(Print(prompt))?; .execute(Print(prompt))?;
let mut passphrase = String::new(); let mut passphrase = String::new();
@ -79,7 +74,7 @@ where
break; break;
} }
KeyCode::Char(c) => { KeyCode::Char(c) => {
write.execute(Print("*"))?; terminal.execute(Print("*"))?;
passphrase.push(c); passphrase.push(c);
} }
_ => (), _ => (),

View File

@ -1,56 +1,51 @@
use std::{ use std::{
io::Write, io::Write,
os::fd::AsRawFd, os::fd::AsRawFd,
sync::{Arc, Mutex},
}; };
use crossterm::{terminal, ExecutableCommand}; use crossterm::terminal;
use crate::Result; use crate::Result;
pub(crate) struct RawMode<W> pub(crate) struct RawMode<'a, W>
where where
W: Write + AsRawFd + Sized, W: Write + AsRawFd + Sized,
{ {
write: Arc<Mutex<W>>, write: &'a mut W,
} }
// TODO: fork crossterm to allow using FD from as_raw_fd() // TODO: fork crossterm to allow using FD from as_raw_fd()
impl<W> RawMode<W> impl<'a, W> RawMode<'a, W>
where where
W: Write + AsRawFd + Sized, W: Write + AsRawFd + Sized,
{ {
pub(crate) fn new(write_handle: Arc<Mutex<W>>) -> Result<Self> { pub(crate) fn new(write_handle: &'a mut W) -> Result<Self> {
terminal::enable_raw_mode()?; terminal::enable_raw_mode()?;
Ok(Self { Ok(Self {
write: write_handle, write: write_handle,
}) })
} }
pub(crate) fn arc_mutex(self) -> Arc<Mutex<Self>> {
Arc::new(Mutex::new(self))
}
} }
impl<W> Write for RawMode<W> impl<W> Write for RawMode<'_, W>
where where
W: Write + AsRawFd + Sized, W: Write + AsRawFd + Sized,
{ {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.write.lock().unwrap().write(buf) self.write.write(buf)
} }
fn flush(&mut self) -> std::io::Result<()> { fn flush(&mut self) -> std::io::Result<()> {
self.write.lock().unwrap().flush() self.write.flush()
} }
} }
impl<W> AsRawFd for RawMode<W> impl<W> AsRawFd for RawMode<'_, W>
where where
W: Write + AsRawFd + Sized, W: Write + AsRawFd + Sized,
{ {
fn as_raw_fd(&self) -> std::os::fd::RawFd { fn as_raw_fd(&self) -> std::os::fd::RawFd {
self.write.lock().unwrap().as_raw_fd() self.write.as_raw_fd()
} }
} }
@ -72,7 +67,7 @@ where
} }
*/ */
impl<W> Drop for RawMode<W> impl<W> Drop for RawMode<'_, W>
where where
W: Write + AsRawFd + Sized, W: Write + AsRawFd + Sized,
{ {