use crate::prelude::{point, Point};
use is_terminal::IsTerminal;
use log::trace;
use rustix::fd::{self, AsFd};
use rustix::termios::{self, InputModes, LocalModes, OutputModes, Termios};
use std::{fs, io};
pub fn is_tty<FD>(fd: FD) -> Option<FD>
where
FD: AsFd,
{
if fd.is_terminal() {
Some(fd)
} else {
None
}
}
pub fn get_tty_attributes(control: impl AsFd) -> io::Result<Termios> {
Ok(termios::tcgetattr(&control)?)
}
pub fn set_tty_attributes(control: impl AsFd, tios: &Termios) -> io::Result<()> {
Ok(termios::tcsetattr(
&control,
termios::OptionalActions::Now,
tios,
)?)
}
pub fn is_raw(control: impl AsFd) -> io::Result<bool> {
let tios = get_tty_attributes(control)?;
Ok(false
== (tios
.local_modes
.intersects(LocalModes::ECHO | LocalModes::ICANON))
| (tios
.input_modes
.intersects(InputModes::ICRNL | InputModes::INLCR))
| (tios.output_modes.intersects(OutputModes::OPOST)))
}
#[must_use = "Resets on drop"]
pub fn enable_raw(control: impl AsFd) -> io::Result<()> {
let mut tios = termios::tcgetattr(&control)?;
trace!("switching to raw mode");
tios.make_raw();
termios::tcsetattr(&control, termios::OptionalActions::Now, &tios)?;
Ok(())
}
pub fn open_tty() -> io::Result<fs::File> {
fs::File::open("/dev/tty")
}
pub fn size_from_fd(fd: impl fd::AsFd) -> io::Result<Point> {
let ws = rustix::termios::tcgetwinsize(fd.as_fd())?;
Ok(point(ws.ws_col, ws.ws_row))
}