termion/src/raw.rs

98 lines
2.5 KiB
Rust
Raw Normal View History

2016-03-07 21:19:35 +00:00
use std::io::Write;
use std::ops::{Deref, DerefMut};
2016-03-07 15:01:20 +00:00
2016-03-07 21:19:35 +00:00
use TerminalError;
2016-03-07 15:01:20 +00:00
2016-03-07 21:19:35 +00:00
/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
#[cfg(target_os = "redox")]
pub struct TerminalRestorer<W> {
output: W,
2016-03-07 15:01:20 +00:00
}
2016-03-07 21:19:35 +00:00
#[cfg(target_os = "redox")]
impl<W: Write> Drop for TerminalRestorer<W> {
fn drop(&mut self) {
use TermControl;
self.csi(b"R");
2016-03-07 15:01:20 +00:00
}
}
2016-03-07 21:19:35 +00:00
#[cfg(not(target_os = "redox"))]
use termios::Termios;
2016-03-07 15:01:20 +00:00
/// A terminal restorer, which keeps the previous state of the terminal, and restores it, when
/// dropped.
2016-03-07 21:19:35 +00:00
#[cfg(not(target_os = "redox"))]
pub struct TerminalRestorer<W> {
prev_ios: Termios,
output: W,
2016-03-07 15:01:20 +00:00
}
2016-03-07 21:19:35 +00:00
#[cfg(not(target_os = "redox"))]
impl<W> Drop for TerminalRestorer<W> {
2016-03-07 15:01:20 +00:00
fn drop(&mut self) {
2016-03-07 21:19:35 +00:00
use termios::set_terminal_attr;
2016-03-07 15:01:20 +00:00
set_terminal_attr(&mut self.prev_ios as *mut _);
}
}
2016-03-07 21:19:35 +00:00
impl<W> Deref for TerminalRestorer<W> {
type Target = W;
fn deref(&self) -> &W {
&self.output
}
}
impl<W> DerefMut for TerminalRestorer<W> {
fn deref_mut(&mut self) -> &mut W {
&mut self.output
}
}
pub trait IntoRawMode: Sized {
/// Switch to raw mode.
///
/// Raw mode means that stdin won't be printed (it will instead have to be written manually by the
/// program). Furthermore, the input isn't canonicalised or buffered (that is, you can read from
/// stdin one byte of a time). The output is neither modified in any way.
fn into_raw_mode(self) -> Result<TerminalRestorer<Self>, TerminalError>;
}
impl<W: Write> IntoRawMode for W {
#[cfg(not(target_os = "redox"))]
fn into_raw_mode(self) -> Result<TerminalRestorer<W>, TerminalError> {
use termios::{cfmakeraw, get_terminal_attr, set_terminal_attr};
let (mut ios, err) = get_terminal_attr();
let prev_ios = ios.clone();
if err != 0 {
return Err(TerminalError::LoadAttrError);
}
unsafe {
cfmakeraw(&mut ios);
}
if set_terminal_attr(&mut ios as *mut _) != 0 {
Err(TerminalError::SetAttrError)
} else {
Ok(TerminalRestorer {
prev_ios: prev_ios,
output: self,
})
}
}
#[cfg(target_os = "redox")]
fn into_raw_mode(self) -> Result<TerminalRestorer<W>, TerminalError> {
2016-03-07 21:22:25 +00:00
use TermControl;
2016-03-07 21:19:35 +00:00
if let Err(_) = self.csi("r") {
Err(TerminalError::StdoutError)
} else {
Ok(TerminalRestorer {
output: self,
})
}
}
}