inquire/terminal/
console.rs1use std::io::{Result, Write};
2
3use console::{Attribute, Color, Key, Style, Term};
4
5use crate::{
6 error::InquireResult,
7 ui::{Attributes, InputReader, StyleSheet, Styled},
8};
9
10use super::Terminal;
11
12#[derive(Clone)]
13pub struct ConsoleTerminal {
14 term: Term,
15}
16
17impl ConsoleTerminal {
18 #[allow(unused)]
19 pub fn new() -> Self {
20 Self {
21 term: Term::stderr(),
22 }
23 }
24}
25
26impl InputReader for ConsoleTerminal {
27 fn read_key(&mut self) -> InquireResult<crate::ui::Key> {
28 let key = self.term.read_key()?;
29 Ok(key.into())
30 }
31}
32
33impl Terminal for ConsoleTerminal {
34 fn cursor_up(&mut self, cnt: u16) -> Result<()> {
35 match cnt {
36 0 => Ok(()),
37 cnt => self.term.move_cursor_up(cnt as usize),
38 }
39 }
40
41 fn cursor_down(&mut self, cnt: u16) -> Result<()> {
42 match cnt {
43 0 => Ok(()),
44 cnt => self.term.move_cursor_down(cnt as usize),
45 }
46 }
47
48 fn cursor_left(&mut self, cnt: u16) -> Result<()> {
49 match cnt {
50 0 => Ok(()),
51 cnt => self.term.move_cursor_left(cnt as usize),
52 }
53 }
54
55 fn cursor_right(&mut self, cnt: u16) -> Result<()> {
56 match cnt {
57 0 => Ok(()),
58 cnt => self.term.move_cursor_right(cnt as usize),
59 }
60 }
61
62 fn cursor_move_to_column(&mut self, idx: u16) -> Result<()> {
63 self.term.move_cursor_left(1000)?;
65 self.term.move_cursor_right(idx as usize)?;
66
67 Ok(())
68 }
69
70 fn flush(&mut self) -> Result<()> {
71 self.term.flush()
72 }
73
74 fn get_size(&self) -> Result<Option<super::TerminalSize>> {
75 let (height, width) = self.term.size();
76
77 Ok(super::TerminalSize::new(width, height))
78 }
79
80 fn write<T: std::fmt::Display>(&mut self, val: T) -> Result<()> {
81 write!(self.term, "{}", val)
82 }
83
84 fn write_styled<T: std::fmt::Display>(&mut self, val: &Styled<T>) -> Result<()> {
85 let styled_object = Style::from(val.style).apply_to(&val.content);
86 write!(self.term, "{}", styled_object)
87 }
88
89 fn clear_line(&mut self) -> Result<()> {
90 self.term.clear_line()
91 }
92
93 fn clear_until_new_line(&mut self) -> Result<()> {
94 write!(self.term, "\x1b[K")
95 }
96
97 fn cursor_hide(&mut self) -> Result<()> {
98 self.term.hide_cursor()
99 }
100
101 fn cursor_show(&mut self) -> Result<()> {
102 self.term.show_cursor()
103 }
104}
105
106impl Drop for ConsoleTerminal {
107 fn drop(&mut self) {
108 let _unused = self.flush();
109 }
110}
111
112impl From<StyleSheet> for Style {
113 fn from(from: StyleSheet) -> Self {
114 let mut style = Style::new();
115
116 let bg = from.bg.and_then(crate::ui::Color::into_console_color);
117 if let Some(bg) = bg {
118 style = style.bg(bg);
119 }
120
121 let fg = from.fg.and_then(crate::ui::Color::into_console_color);
122 if let Some(fg) = fg {
123 style = style.fg(fg);
124 }
125
126 if from.att.contains(Attributes::BOLD) {
127 style = style.attr(Attribute::Bold);
128 }
129
130 if from.att.contains(Attributes::ITALIC) {
131 style = style.attr(Attribute::Italic);
132 }
133
134 style
135 }
136}
137
138impl crate::ui::Color {
139 fn into_console_color(self) -> Option<Color> {
140 use crate::ui::Color as C;
141 match self {
142 C::Black | C::DarkGrey => Some(Color::Black),
143 C::LightRed | C::DarkRed => Some(Color::Red),
144 C::LightGreen | C::DarkGreen => Some(Color::Green),
145 C::LightYellow | C::DarkYellow => Some(Color::Yellow),
146 C::LightBlue | C::DarkBlue => Some(Color::Blue),
147 C::LightMagenta | C::DarkMagenta => Some(Color::Magenta),
148 C::LightCyan | C::DarkCyan => Some(Color::Cyan),
149 C::White | C::Grey => Some(Color::White),
150 C::Rgb { r: _, g: _, b: _ } => None,
151 C::AnsiValue(v) => Some(Color::Color256(v)),
152 }
153 }
154}
155
156impl From<Key> for crate::ui::Key {
157 fn from(key: Key) -> Self {
158 use crate::ui::KeyModifiers;
159
160 match key {
161 Key::Escape => Self::Escape,
162 Key::Char('\n' | '\r') | Key::Enter => Self::Enter,
163 Key::Char('\t') | Key::Tab => Self::Tab,
164 Key::Backspace => Self::Backspace,
165 Key::Del => Self::Delete(KeyModifiers::empty()),
166 Key::Home => Self::Home,
167 Key::End => Self::End,
168 Key::PageUp => Self::PageUp(KeyModifiers::empty()),
169 Key::PageDown => Self::PageDown(KeyModifiers::empty()),
170 Key::ArrowUp => Self::Up(KeyModifiers::empty()),
171 Key::ArrowDown => Self::Down(KeyModifiers::empty()),
172 Key::ArrowLeft => Self::Left(KeyModifiers::empty()),
173 Key::ArrowRight => Self::Right(KeyModifiers::empty()),
174 Key::Char(c) => Self::Char(c, KeyModifiers::empty()),
175 #[allow(deprecated)]
176 _ => Self::Any,
177 }
178 }
179}