1/// An example how to use the ANSI escape sequence parser.
2use std::io::{Read, Result, Write};
3
4use anes::{
5 self, execute,
6 parser::{KeyCode, Parser, Sequence},
7 queue,
8};
9use libc::termios as Termios;
10
11const HELP: &str = r#"ANES parser example
12
13* Hit `Esc` to quit
14* Hit 'c' to ask for cursor position
15* Use your mouse or type anything
16"#;
17
18fn main() -> Result<()> {
19 let mut w = std::io::stdout();
20 queue!(
21 w,
22 anes::SwitchBufferToAlternate,
23 anes::HideCursor,
24 anes::EnableMouseEvents
25 )?;
26 for line in HELP.split('\n') {
27 queue!(w, line, anes::MoveCursorToNextLine(1))?;
28 }
29 w.flush()?;
30
31 let saved_attributes = get_termios()?;
32 let mut attributes = saved_attributes;
33 make_raw(&mut attributes);
34 set_termios(attributes)?;
35
36 let mut stdin = std::io::stdin();
37 let mut stdin_buffer = [0u8; 1024];
38 let mut parser = Parser::default();
39
40 loop {
41 if let Ok(size) = stdin.read(&mut stdin_buffer) {
42 parser.advance(&stdin_buffer[..size], false);
43
44 let mut break_outer_loop = false;
45
46 while let Some(sequence) = parser.next() {
47 match sequence {
48 Sequence::Key(KeyCode::Esc, _) => {
49 break_outer_loop = true;
50 break;
51 }
52 Sequence::Key(KeyCode::Char('c'), _) => {
53 execute!(w, anes::ReportCursorPosition)?
54 }
55 _ => execute!(
56 w,
57 anes::ClearLine::Left,
58 anes::MoveCursorToColumn(1),
59 format!("{:?}", sequence),
60 )?,
61 }
62 }
63
64 if break_outer_loop {
65 break;
66 }
67 }
68 }
69
70 set_termios(saved_attributes)?;
71
72 execute!(
73 w,
74 anes::DisableMouseEvents,
75 anes::ShowCursor,
76 anes::SwitchBufferToNormal
77 )?;
78 Ok(())
79}
80
81//
82// RAW mode
83//
84
85fn get_termios() -> Result<Termios> {
86 unsafe {
87 let mut termios = std::mem::zeroed();
88 if libc::tcgetattr(libc::STDIN_FILENO, &mut termios) != -1 {
89 Ok(termios)
90 } else {
91 Err(std::io::Error::last_os_error())
92 }
93 }
94}
95
96fn set_termios(termios: Termios) -> Result<()> {
97 if unsafe { libc::tcsetattr(libc::STDIN_FILENO, libc::TCSANOW, &termios) } != -1 {
98 Ok(())
99 } else {
100 Err(std::io::Error::last_os_error())
101 }
102}
103
104fn make_raw(termios: &mut Termios) {
105 unsafe { libc::cfmakeraw(termios) }
106}
107