Skip to content

Commit

Permalink
docs: Make tutorials windows friendly 📚
Browse files Browse the repository at this point in the history
  • Loading branch information
kdheepak committed Oct 7, 2023
1 parent 2375314 commit 0c8850f
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 18 deletions.
8 changes: 7 additions & 1 deletion src/tutorial/counter-app/event.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,13 @@ include keypresses, mouse movements, screen resizing, and regular time ticks.
```rust
if event::poll(timeout)? {
match event::read()? {
CrosstermEvent::Key(e) => sender.send(Event::Key(e))?,
CrosstermEvent::Key(e) => {
if e.kind == event::KeyEventKind::Press {
sender.send(Event::Key(e))
} else {
Ok(()) // ignore KeyEventKind::Release on windows
}
},
CrosstermEvent::Mouse(e) => sender.send(Event::Mouse(e))?,
CrosstermEvent::Resize(w, h) => sender.send(Event::Resize(w, h))?,
_ => unimplemented!(),
Expand Down
24 changes: 14 additions & 10 deletions src/tutorial/counter-app/multiple-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,13 @@ fn ui(app: &App, f: &mut Frame<'_>) {
fn update(app: &mut App) -> Result<()> {
if event::poll(std::time::Duration::from_millis(250))? {
if let Key(key) = event::read()? {
match key.code {
Char('j') => app.counter += 1,
Char('k') => app.counter -= 1,
Char('q') => app.should_quit = true,
_ => (),
if key.kind == event::KeyEventKind::Press {
match key.code {
Char('j') => app.counter += 1,
Char('k') => app.counter -= 1,
Char('q') => app.should_quit = true,
_ => (),
}
}
}
}
Expand Down Expand Up @@ -255,11 +257,13 @@ fn ui(app: &App, f: &mut Frame<'_>) {
fn update(app: &mut App) -> Result<()> {
if event::poll(std::time::Duration::from_millis(250))? {
if let Key(key) = event::read()? {
match key.code {
Char('j') => app.counter += 1,
Char('k') => app.counter -= 1,
Char('q') => app.should_quit = true,
_ => (),
if key.kind == event::KeyEventKind::Press {
match key.code {
Char('j') => app.counter += 1,
Char('k') => app.counter -= 1,
Char('q') => app.should_quit = true,
_ => (),
}
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/tutorial/counter-app/ratatui-counter-app/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ impl EventHandler {
///// ANCHOR: eventhandler_poll
if event::poll(timeout).expect("no events available") {
match event::read().expect("unable to read event") {
CrosstermEvent::Key(e) => sender.send(Event::Key(e)),
CrosstermEvent::Key(e) => {
if e.kind == event::KeyEventKind::Press {
sender.send(Event::Key(e))
} else {
Ok(()) // ignore KeyEventKind::Release on windows
}
},
CrosstermEvent::Mouse(e) => sender.send(Event::Mouse(e)),
CrosstermEvent::Resize(w, h) => sender.send(Event::Resize(w, h)),
_ => unimplemented!(),
Expand Down
36 changes: 30 additions & 6 deletions src/tutorial/counter-app/single-function.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
if crossterm::event::poll(std::time::Duration::from_millis(250))? {
// If a key event occurs, handle it
if let crossterm::event::Event::Key(key) = crossterm::event::read()? {
match key.code {
crossterm::event::KeyCode::Char('j') => counter += 1,
crossterm::event::KeyCode::Char('k') => counter -= 1,
crossterm::event::KeyCode::Char('q') => break,
_ => (),
if key.kind == crossterm::event::KeyEventKind::Press {
match key.code {
crossterm::event::KeyCode::Char('j') => counter += 1,
crossterm::event::KeyCode::Char('k') => counter -= 1,
crossterm::event::KeyCode::Char('q') => break,
_ => (),
}
}
}
}
Expand Down Expand Up @@ -146,9 +148,10 @@ Every 250 milliseconds, the application checks if the user has pressed a key:
- `k` decreases the counter
- `q` exits the application

Usually you'll be able to write code like the following:

```rust
if crossterm::event::poll(std::time::Duration::from_millis(250))? {
// If a key event occurs, handle it
if let crossterm::event::Event::Key(key) = crossterm::event::read()? {
match key.code {
crossterm::event::KeyCode::Char('j') => counter += 1,
Expand All @@ -160,6 +163,27 @@ Every 250 milliseconds, the application checks if the user has pressed a key:
}
```

However, on Windows, `crossterm` generates a key event for both `Press` and `Release`. This code
above will increment or decrement the counter twice.

All we need to do to fix this is check for `key.kind == crossterm::event::KeyEventKind::Press`:

```rust
if crossterm::event::poll(std::time::Duration::from_millis(250))? {
if let crossterm::event::Event::Key(key) = crossterm::event::read()? {
// check if key.kind is a `KeyEventKind::Press`
if key.kind == crossterm::event::KeyEventKind::Press {
match key.code {
crossterm::event::KeyCode::Char('j') => counter += 1,
crossterm::event::KeyCode::Char('k') => counter -= 1,
crossterm::event::KeyCode::Char('q') => break,
_ => (),
}
}
}
}
```

## Conclusion

By understanding the structure and components used in this simple counter application, you are set
Expand Down

0 comments on commit 0c8850f

Please sign in to comment.