jag

typing_rust

public

A small typing test program in Rust

Star0
Watch0
12f039d6d5c5d3e475ce14c6dea6a9e1292ef3b2
1
ssh://git@git.jaglekon.de:30/jag/typing_rust.git
src/main.rsRust156 lines3.9 KB
1
use std::io;
2
3
use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind};
4
use ratatui::{
5
    buffer::Buffer,
6
    layout::{Rect, Layout, Direction, Constraint},
7
    style::Stylize,
8
    symbols::border,
9
    text::{Line, Text},
10
    widgets::{Block, Paragraph, Widget},
11
    DefaultTerminal, Frame,
12
};
13
14
#[derive(Debug, PartialEq, Eq)]
15
enum States {
16
    Running,
17
    Paused,
18
    Quit,
19
}
20
21
impl Default for States {
22
    fn default() -> Self {
23
        States::Running
24
    }
25
}
26
27
#[derive(Debug, Default)]
28
pub struct App {
29
    counter: u8,
30
    state: States,
31
}
32
33
impl Widget for &App {
34
    fn render(self, area: Rect, buf: &mut Buffer) {
35
36
        let title = Line::from(" Counter App Tutorial ".bold());
37
        let instructions = Line::from(vec![
38
            " Decrement ".into(),
39
            "<Left>".blue().bold(),
40
            " Increment ".into(),
41
            "<Right>".blue().bold(),
42
            " Pause ".into(),
43
            "<P>".blue().bold(),
44
            " Quit".into(),
45
            "<Q> ".blue().bold(),
46
        ]);
47
        let block = Block::bordered()
48
            .title(title.centered())
49
            .title_bottom(instructions.centered())
50
            .border_set(border::THICK);
51
52
        let counter_text = Text::from(vec![Line::from(vec![
53
            "Value: ".into(),
54
            self.counter.to_string().yellow(),
55
        ])]);
56
57
        Paragraph::new(counter_text)
58
            .centered()
59
            .block(block)
60
            .render(area, buf);
61
62
        if self.state == States::Paused {
63
            
64
            let pause_area = area.centered(
65
                Constraint::Length(20),
66
                Constraint::Length(5),
67
            );
68
69
            let pause_block = Block::bordered()
70
                .border_set(border::ROUNDED);
71
72
            let pause_text = Text::from("PAUSE");
73
            
74
            let pause_text_area = pause_area.centered(
75
                Constraint::Length(pause_text.width() as u16),
76
                Constraint::Length(1),
77
            );
78
            
79
            pause_block.render(pause_area, buf);
80
81
            Paragraph::new(pause_text)
82
                .render(pause_text_area, buf);
83
        }
84
    }
85
}
86
87
impl App {
88
89
    pub fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> {
90
        while self.state != States::Quit {
91
            terminal.draw(|frame| self.draw(frame))?;
92
            self.handle_events()?;
93
        }
94
        Ok(())
95
    }
96
97
    fn draw(&self, frame: &mut Frame) {
98
        frame.render_widget(self, frame.area());
99
    }
100
101
    fn handle_events(&mut self) -> io::Result<()> {
102
        match event::read()? {
103
            Event::Key(key_event) if key_event.kind == KeyEventKind::Press => {
104
                self.handle_key_event(key_event)
105
            },
106
            _ => {},
107
        };
108
        Ok(())
109
    }
110
111
    fn handle_key_event(&mut self, key_event: KeyEvent) {
112
        match self.state {
113
            States::Running => 
114
                match key_event.code {
115
                    KeyCode::Char('p') => self.pause(),
116
                    KeyCode::Char('q') => self.exit(),
117
                    KeyCode::Left => self.decrement_counter(),
118
                    KeyCode::Right => self.increment_counter(),
119
                    _ => {}
120
                },
121
            States::Paused => 
122
                match key_event.code {
123
                    KeyCode::Char('p') => self.pause(),
124
                    KeyCode::Char('q') => self.exit(),
125
                    _ => {},
126
                },
127
128
            States::Quit => {},
129
        }
130
    }
131
132
    fn pause(&mut self) {
133
        if self.state == States::Paused {
134
            self.state = States::Running;
135
        } else {
136
            self.state = States::Paused;
137
        }
138
    }
139
140
    fn exit(&mut self) {
141
        self.state = States::Quit;
142
    }
143
144
    fn increment_counter(&mut self) {
145
        self.counter += 1;
146
    }
147
148
    fn decrement_counter(&mut self) {
149
        self.counter -= 1;
150
    }
151
}
152
153
154
fn main() -> io::Result<()> {
155
    ratatui::run(|terminal| App::default().run(terminal))
156
}