summaryrefslogtreecommitdiff
path: root/src/list.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/list.rs')
-rw-r--r--src/list.rs150
1 files changed, 79 insertions, 71 deletions
diff --git a/src/list.rs b/src/list.rs
index 6ff6959..754c5e2 100644
--- a/src/list.rs
+++ b/src/list.rs
@@ -1,95 +1,101 @@
use anyhow::{Context, Result};
-use ratatui::{
- backend::CrosstermBackend,
- crossterm::{
- event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind},
- terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
- QueueableCommand,
+use crossterm::{
+ cursor,
+ event::{
+ self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind, MouseEventKind,
},
- Terminal,
+ terminal::{
+ disable_raw_mode, enable_raw_mode, DisableLineWrap, EnableLineWrap, EnterAlternateScreen,
+ LeaveAlternateScreen,
+ },
+ QueueableCommand,
};
use std::io::{self, StdoutLock, Write};
use crate::app_state::AppState;
-use self::state::{Filter, UiState};
+use self::state::{Filter, ListState};
mod state;
fn handle_list(app_state: &mut AppState, stdout: &mut StdoutLock) -> Result<()> {
- let mut terminal = Terminal::new(CrosstermBackend::new(stdout))?;
- terminal.clear()?;
-
- let mut ui_state = UiState::new(app_state);
-
- 'outer: loop {
- terminal.try_draw(|frame| ui_state.draw(frame).map_err(io::Error::other))?;
-
- let key = loop {
- match event::read().context("Failed to read terminal event")? {
- Event::Key(key) => match key.kind {
- KeyEventKind::Press | KeyEventKind::Repeat => break key,
- KeyEventKind::Release => (),
- },
- // Redraw
- Event::Resize(_, _) => continue 'outer,
- // Ignore
- Event::FocusGained | Event::FocusLost | Event::Mouse(_) | Event::Paste(_) => (),
+ let mut list_state = ListState::new(app_state, stdout)?;
+
+ loop {
+ match event::read().context("Failed to read terminal event")? {
+ Event::Key(key) => {
+ match key.kind {
+ KeyEventKind::Release => continue,
+ KeyEventKind::Press | KeyEventKind::Repeat => (),
+ }
+
+ list_state.message.clear();
+
+ match key.code {
+ KeyCode::Char('q') => return Ok(()),
+ KeyCode::Down | KeyCode::Char('j') => list_state.select_next(),
+ KeyCode::Up | KeyCode::Char('k') => list_state.select_previous(),
+ KeyCode::Home | KeyCode::Char('g') => list_state.select_first(),
+ KeyCode::End | KeyCode::Char('G') => list_state.select_last(),
+ KeyCode::Char('d') => {
+ let message = if list_state.filter() == Filter::Done {
+ list_state.set_filter(Filter::None);
+ "Disabled filter DONE"
+ } else {
+ list_state.set_filter(Filter::Done);
+ "Enabled filter DONE │ Press d again to disable the filter"
+ };
+
+ list_state.message.push_str(message);
+ }
+ KeyCode::Char('p') => {
+ let message = if list_state.filter() == Filter::Pending {
+ list_state.set_filter(Filter::None);
+ "Disabled filter PENDING"
+ } else {
+ list_state.set_filter(Filter::Pending);
+ "Enabled filter PENDING │ Press p again to disable the filter"
+ };
+
+ list_state.message.push_str(message);
+ }
+ KeyCode::Char('r') => {
+ list_state.reset_selected()?;
+ }
+ KeyCode::Char('c') => {
+ return list_state.selected_to_current_exercise();
+ }
+ // Redraw to remove the message.
+ KeyCode::Esc => (),
+ _ => continue,
+ }
+
+ list_state.redraw(stdout)?;
}
- };
-
- ui_state.message.clear();
-
- match key.code {
- KeyCode::Char('q') => break,
- KeyCode::Down | KeyCode::Char('j') => ui_state.select_next(),
- KeyCode::Up | KeyCode::Char('k') => ui_state.select_previous(),
- KeyCode::Home | KeyCode::Char('g') => ui_state.select_first(),
- KeyCode::End | KeyCode::Char('G') => ui_state.select_last(),
- KeyCode::Char('d') => {
- let message = if ui_state.filter == Filter::Done {
- ui_state.filter = Filter::None;
- "Disabled filter DONE"
- } else {
- ui_state.filter = Filter::Done;
- "Enabled filter DONE │ Press d again to disable the filter"
- };
-
- ui_state = ui_state.with_updated_rows();
- ui_state.message.push_str(message);
+ Event::Mouse(event) => {
+ match event.kind {
+ MouseEventKind::ScrollDown => list_state.select_next(),
+ MouseEventKind::ScrollUp => list_state.select_previous(),
+ _ => continue,
+ }
+
+ list_state.redraw(stdout)?;
}
- KeyCode::Char('p') => {
- let message = if ui_state.filter == Filter::Pending {
- ui_state.filter = Filter::None;
- "Disabled filter PENDING"
- } else {
- ui_state.filter = Filter::Pending;
- "Enabled filter PENDING │ Press p again to disable the filter"
- };
-
- ui_state = ui_state.with_updated_rows();
- ui_state.message.push_str(message);
- }
- KeyCode::Char('r') => {
- ui_state = ui_state.with_reset_selected()?;
- }
- KeyCode::Char('c') => {
- ui_state.selected_to_current_exercise()?;
- break;
- }
- _ => (),
+ // Redraw
+ Event::Resize(_, _) => list_state.redraw(stdout)?,
+ // Ignore
+ Event::FocusGained | Event::FocusLost => (),
}
}
-
- Ok(())
}
pub fn list(app_state: &mut AppState) -> Result<()> {
let mut stdout = io::stdout().lock();
stdout
.queue(EnterAlternateScreen)?
- .queue(EnableMouseCapture)?
- .flush()?;
+ .queue(cursor::Hide)?
+ .queue(DisableLineWrap)?
+ .queue(EnableMouseCapture)?;
enable_raw_mode()?;
let res = handle_list(app_state, &mut stdout);
@@ -97,6 +103,8 @@ pub fn list(app_state: &mut AppState) -> Result<()> {
// Restore the terminal even if we got an error.
stdout
.queue(LeaveAlternateScreen)?
+ .queue(cursor::Show)?
+ .queue(EnableLineWrap)?
.queue(DisableMouseCapture)?
.flush()?;
disable_raw_mode()?;