endbasic_std/console/
trivial.rs1use crate::console::{
19 CharsXY, ClearType, Console, Key, get_env_var_as_u16, read_key_from_stdin, remove_control_chars,
20};
21use async_trait::async_trait;
22use std::collections::VecDeque;
23use std::io::{self, StdoutLock, Write};
24
25const DEFAULT_COLUMNS: u16 = 80;
27
28const DEFAULT_LINES: u16 = 24;
30
31#[derive(Default)]
33pub struct TrivialConsole {
34 buffer: VecDeque<Key>,
36
37 sync_enabled: bool,
39}
40
41impl TrivialConsole {
42 fn maybe_flush(&self, mut lock: StdoutLock<'_>) -> io::Result<()> {
44 if self.sync_enabled { lock.flush() } else { Ok(()) }
45 }
46}
47
48#[async_trait(?Send)]
49impl Console for TrivialConsole {
50 fn clear(&mut self, _how: ClearType) -> io::Result<()> {
51 Ok(())
52 }
53
54 fn color(&self) -> (Option<u8>, Option<u8>) {
55 (None, None)
56 }
57
58 fn set_color(&mut self, _fg: Option<u8>, _bg: Option<u8>) -> io::Result<()> {
59 Ok(())
60 }
61
62 fn enter_alt(&mut self) -> io::Result<()> {
63 Ok(())
64 }
65
66 fn hide_cursor(&mut self) -> io::Result<()> {
67 Ok(())
68 }
69
70 fn is_interactive(&self) -> bool {
71 true
72 }
73
74 fn leave_alt(&mut self) -> io::Result<()> {
75 Ok(())
76 }
77
78 #[cfg_attr(not(debug_assertions), allow(unused))]
79 fn locate(&mut self, pos: CharsXY) -> io::Result<()> {
80 #[cfg(debug_assertions)]
81 {
82 let size = self.size_chars()?;
83 assert!(pos.x < size.x);
84 assert!(pos.y < size.y);
85 }
86 Ok(())
87 }
88
89 fn move_within_line(&mut self, _off: i16) -> io::Result<()> {
90 Ok(())
91 }
92
93 fn print(&mut self, text: &str) -> io::Result<()> {
94 let text = remove_control_chars(text);
95
96 let stdout = io::stdout();
97 let mut stdout = stdout.lock();
98 stdout.write_all(text.as_bytes())?;
99 stdout.write_all(b"\n")?;
100 Ok(())
101 }
102
103 async fn poll_key(&mut self) -> io::Result<Option<Key>> {
104 Ok(None)
105 }
106
107 async fn read_key(&mut self) -> io::Result<Key> {
108 read_key_from_stdin(&mut self.buffer)
109 }
110
111 fn show_cursor(&mut self) -> io::Result<()> {
112 Ok(())
113 }
114
115 fn size_chars(&self) -> io::Result<CharsXY> {
116 let lines = get_env_var_as_u16("LINES").unwrap_or(DEFAULT_LINES);
117 let columns = get_env_var_as_u16("COLUMNS").unwrap_or(DEFAULT_COLUMNS);
118 Ok(CharsXY::new(columns, lines))
119 }
120
121 fn write(&mut self, text: &str) -> io::Result<()> {
122 let text = remove_control_chars(text);
123
124 let stdout = io::stdout();
125 let mut stdout = stdout.lock();
126 stdout.write_all(text.as_bytes())?;
127 self.maybe_flush(stdout)
128 }
129
130 fn sync_now(&mut self) -> io::Result<()> {
131 if self.sync_enabled { Ok(()) } else { io::stdout().flush() }
132 }
133
134 fn set_sync(&mut self, enabled: bool) -> io::Result<bool> {
135 if !self.sync_enabled {
136 io::stdout().flush()?;
137 }
138 let previous = self.sync_enabled;
139 self.sync_enabled = enabled;
140 Ok(previous)
141 }
142}