devela/ui/back/crossterm/service.rs
1// devela::ui::back::crossterm::service
2//
3//! Defines [`CrosstermService`].
4//
5// ISSUES
6// - WAIT: [add Event::Terminate](https://github.com/crossterm-rs/crossterm/issues/554)
7// - WAIT: [support ctrl+z + fg](https://github.com/crossterm-rs/crossterm/issues/494)
8//
9// TODO
10// - window refresh, render
11
12use ::crossterm::{event, execute, terminal};
13
14// use core::time::Duration;
15use std::io;
16
17use crate::{
18 IoError, UiCap, UiCapImage, /* Event, EventSource, */ UiCapInput,
19 /* Window, */ UiCapWindow, UiService,
20};
21
22/// `crossterm`'s UI backend service.
23//
24// https://docs.rs/crossterm/latest/crossterm/terminal/index.html
25pub struct CrosstermService;
26// { raw_mode: bool, }
27
28// TODO
29// impl Drop for CrosstermService {
30// fn drop(&mut self) {
31// if self.raw_mode {
32// self.set_raw_mode(false);
33// }
34// }
35// }
36
37impl CrosstermService {
38 /// Creates a new `CrosstermService`.
39 pub fn new() -> Result<Self, IoError> {
40 Ok(Self { /* raw_mode: false */ })
41 }
42
43 /// Tells whether the raw mode is enabled.
44 //
45 // https://docs.rs/crossterm/latest/crossterm/terminal/fn.is_raw_mode_enabled.html
46 #[inline]
47 pub fn is_raw_mode(&self) -> Result<bool, IoError> {
48 terminal::is_raw_mode_enabled()
49 }
50
51 /// Enables the raw mode.
52 //
53 // https://docs.rs/crossterm/latest/crossterm/terminal/fn.enable_raw_mode.html
54 #[inline]
55 pub fn enable_raw_mode(&self) -> Result<(), IoError> {
56 terminal::enable_raw_mode()
57 }
58
59 /// Disables the raw mode.
60 //
61 // https://docs.rs/crossterm/latest/crossterm/terminal/fn.disable_raw_mode.html
62 #[inline]
63 pub fn disable_raw_mode(&self) -> Result<(), IoError> {
64 terminal::disable_raw_mode()
65 }
66
67 /// Switches to the alternate screen.
68 //
69 // https://docs.rs/crossterm/latest/crossterm/terminal/struct.EnterAlternateScreen.html
70 pub fn enter_alternate_screen(&self) -> Result<(), IoError> {
71 Ok(execute!(io::stdout(), terminal::EnterAlternateScreen)?)
72 }
73
74 /// Switches back to the main screen.
75 //
76 // https://docs.rs/crossterm/latest/crossterm/terminal/struct.LeaveAlternateScreen.html
77 pub fn leave_alternate_screen(&self) -> Result<(), IoError> {
78 Ok(execute!(io::stdout(), terminal::EnterAlternateScreen)?)
79 }
80
81 /// Enables receiving mouse events.
82 //
83 // https://docs.rs/crossterm/latest/crossterm/event/struct.EnableMouseCapture.html
84 pub fn enable_mouse(&mut self) -> Result<(), IoError> {
85 Ok(execute!(io::stdout(), event::EnableMouseCapture)?)
86 }
87 /// Disables receiving mouse events.
88 //
89 // https://docs.rs/crossterm/latest/crossterm/event/struct.DisableMouseCapture.html
90 pub fn disable_mouse(&mut self) -> Result<(), IoError> {
91 Ok(execute!(io::stdout(), event::DisableMouseCapture)?)
92 }
93
94 // TODO
95 // /// Enables bracketed paste mode.
96 // //
97 // // https://docs.rs/crossterm/latest/crossterm/event/struct.EnableBracketedPaste.html
98 // pub fn enable_bracketed_paste(&self) -> Result<(), IoError> {
99 // Ok(execute!(io::stdout(), event::EnableBracketedPaste)?)
100 // }
101 //
102 // /// Disables bracketed paste mode.
103 // //
104 // // https://docs.rs/crossterm/latest/crossterm/event/struct.DisableBracketedPaste.html
105 // pub fn disable_bracketed_paste(&self) -> Result<(), IoError> {
106 // Ok(execute!(io::stdout(), event::DisableBracketedPaste)?)
107 // }
108
109 /// Enables focus change mode.
110 //
111 // https://docs.rs/crossterm/latest/crossterm/event/struct.EnableFocusChange.html
112 pub fn enable_focus_change(&self) -> Result<(), IoError> {
113 Ok(execute!(io::stdout(), event::EnableFocusChange)?)
114 }
115
116 /// Disables focus change mode.
117 //
118 // https://docs.rs/crossterm/latest/crossterm/event/struct.DisableFocusChange.html
119 pub fn disable_focus_change(&self) -> Result<(), IoError> {
120 Ok(execute!(io::stdout(), event::DisableFocusChange)?)
121 }
122}
123
124impl UiService for CrosstermService {
125 fn capabilities(&self) -> UiCap {
126 let image = Some(UiCapImage {
127 rgb: true,
128 // palette_change: false,
129 // palette_size: ::crossterm::style::available_color_count(),
130 ..Default::default()
131 });
132
133 let input = Some(UiCapInput { keyboard: true, mouse: true, ..Default::default() });
134
135 // let text_grid = Some(UiCapTextGridCap {
136 // // we don't unknown
137 // cell_size: None,
138 // // https://github.com/crossterm-rs/crossterm/issues/166
139 // // custom_cell_size: false,
140 // // // https://github.com/crossterm-rs/crossterm/issues/677
141 // // unicode: true,
142 // // ..Default::default()
143 // });
144
145 let window = Some(UiCapWindow { multi: false });
146
147 UiCap {
148 image,
149 input,
150 // text_grid,
151 window,
152 ..Default::default()
153 }
154 }
155
156 fn version(&self) -> (u32, u32, u32) {
157 (0, 28, 1)
158 }
159}