I created a Screen
struct with methods to manipulate stdout
. For example, to show the cursor or display prompts (in the terminal).
I created the handle_input()
and handle_input_result()
to make main()
smaller and prevent code duplication. These methods control the flow of the code based on the value of prompt
and variants of Input
.
Note: this is mock code that shows the structure of the actual application.
use std::io::Write;
#[derive(Debug)]
pub enum Input {
Text(String),
None,
Exit,
}
struct Screen {
stdout: Vec<u8>,
}
impl Write for Screen {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.stdout.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.stdout.flush()
}
}
impl Screen {
fn new(stdout: Vec<u8>) -> Self {
Screen { stdout }
}
fn show_cursor(&mut self) {
write!(self.stdout, "Show cursor!").unwrap();
}
fn show_prompt(&mut self, message: &str) {
write!(self.stdout, "{}\r\n", message).unwrap();
}
fn handle_input(&mut self, prompt: Option<String>) -> Result<Input, std::io::Error> {
match prompt {
Some(_) => {
self.show_prompt(&prompt.unwrap());
let input = get_input()?;
Ok(input)
}
None => {
self.show_cursor();
Ok(Input::None)
}
}
}
fn handle_input_result(&mut self, input: Input) {
match input {
Input::Text(text) => {
self.show_cursor();
println!("{}", &text);
}
Input::None => {
self.show_cursor();
println!("None");
}
Input::Exit => {
println!("Exit");
}
}
}
}
fn get_input() -> Result<Input, std::io::Error> {
let input = "This is some text".to_owned();
// In the actual application, this may return other variants of `Input`.
Ok(Input::Text(input))
}
fn main() {
let mut screen = Screen::new(Vec::new());
// In the actual application, `prompt` belongs to a struct called `Keymap`.
let prompt = Some("This is a prompt".to_string());
let input = screen.handle_input(prompt);
screen.handle_input_result(input.unwrap());
}
Design-wise, do handle_input()
and handle_input_result()
belong to Screen
? If not, what should I do with them?