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