1use std::io::{self, Write};
26use std::ops;
27
28use sys::Termios;
29use sys::attr::{get_terminal_attr, raw_terminal_attr, set_terminal_attr};
30
31pub const CONTROL_SEQUENCE_TIMEOUT: u64 = 100;
33
34pub struct RawTerminal<W: Write> {
39 prev_ios: Termios,
40 output: W,
41}
42
43impl<W: Write> Drop for RawTerminal<W> {
44 fn drop(&mut self) {
45 set_terminal_attr(&self.prev_ios).unwrap();
46 }
47}
48
49impl<W: Write> ops::Deref for RawTerminal<W> {
50 type Target = W;
51
52 fn deref(&self) -> &W {
53 &self.output
54 }
55}
56
57impl<W: Write> ops::DerefMut for RawTerminal<W> {
58 fn deref_mut(&mut self) -> &mut W {
59 &mut self.output
60 }
61}
62
63impl<W: Write> Write for RawTerminal<W> {
64 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
65 self.output.write(buf)
66 }
67
68 fn flush(&mut self) -> io::Result<()> {
69 self.output.flush()
70 }
71}
72
73pub trait IntoRawMode: Write + Sized {
80 fn into_raw_mode(self) -> io::Result<RawTerminal<Self>>;
86}
87
88impl<W: Write> IntoRawMode for W {
89 fn into_raw_mode(self) -> io::Result<RawTerminal<W>> {
90 let mut ios = get_terminal_attr()?;
91 let prev_ios = ios;
92
93 raw_terminal_attr(&mut ios);
94
95 set_terminal_attr(&ios)?;
96
97 Ok(RawTerminal {
98 prev_ios: prev_ios,
99 output: self,
100 })
101 }
102}
103
104impl<W: Write> RawTerminal<W> {
105 pub fn suspend_raw_mode(&self) -> io::Result<()> {
106 set_terminal_attr(&self.prev_ios)?;
107 Ok(())
108 }
109
110 pub fn activate_raw_mode(&self) -> io::Result<()> {
111 let mut ios = get_terminal_attr()?;
112 raw_terminal_attr(&mut ios);
113 set_terminal_attr(&ios)?;
114 Ok(())
115 }
116}
117
118#[cfg(test)]
119mod test {
120 use super::*;
121 use std::io::{Write, stdout};
122
123 #[test]
124 fn test_into_raw_mode() {
125 let mut out = stdout().into_raw_mode().unwrap();
126
127 out.write_all(b"this is a test, muahhahahah\r\n").unwrap();
128
129 drop(out);
130 }
131}