• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /// An example how to use the ANSI escape sequence parser.
2 use std::io::{Read, Result, Write};
3 
4 use anes::{
5     self, execute,
6     parser::{KeyCode, Parser, Sequence},
7     queue,
8 };
9 use libc::termios as Termios;
10 
11 const 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 
main() -> Result<()>18 fn 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 
get_termios() -> Result<Termios>85 fn 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 
set_termios(termios: Termios) -> Result<()>96 fn 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 
make_raw(termios: &mut Termios)104 fn make_raw(termios: &mut Termios) {
105     unsafe { libc::cfmakeraw(termios) }
106 }
107