From 01a1e5e4f45dc80cd430d18492817b733fab5603 Mon Sep 17 00:00:00 2001 From: Joris Date: Sat, 26 Feb 2022 22:23:34 +0100 Subject: Fix linter warnings --- src/gui/gui.rs | 98 ----------------------------------------------------- src/gui/message.rs | 7 ++-- src/gui/mod.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/gui/question.rs | 90 +++++++++++++++++++++++------------------------- src/gui/util.rs | 2 +- 5 files changed, 140 insertions(+), 152 deletions(-) delete mode 100644 src/gui/gui.rs (limited to 'src/gui') diff --git a/src/gui/gui.rs b/src/gui/gui.rs deleted file mode 100644 index 92b1a72..0000000 --- a/src/gui/gui.rs +++ /dev/null @@ -1,98 +0,0 @@ -use crate::deck; -use crate::util::time; -use crate::{db::db, gui::message, gui::question, space_repetition, util::event::Events}; -use anyhow::Result; -use rusqlite::Connection; -use std::{fs, io, time::Duration}; -use termion::{raw::IntoRawMode, raw::RawTerminal, screen::AlternateScreen}; -use tui::{backend::TermionBackend, Terminal}; - -type Term = Terminal>>>; - -pub fn terminal() -> Result { - let stdout = io::stdout().into_raw_mode()?; - let stdout = AlternateScreen::from(stdout); - let backend = TermionBackend::new(stdout); - Ok(Terminal::new(backend)?) -} - -pub fn synchronize( - conn: &Connection, - term: &mut Term, - events: &Events, - deck_path: &str, - deck_name: &str, -) -> Result<()> { - let last_modified = time::seconds_since_unix_epoch_of(fs::metadata(deck_path)?.modified()?)?; - let last_deck_read = db::last_deck_read(&conn); - let must_synchronize = last_deck_read.map(|r| r < last_modified).unwrap_or(true); - - if must_synchronize { - let _ = message::show(term, events, &deck_name, "Synchronization du deck…", false); - time::wait_at_least( - || db::synchronize(&conn, deck::read(&deck_path)?), - Duration::from_secs(1), - )?; - } - - Ok(()) -} - -pub fn start( - conn: &Connection, - term: &mut Term, - events: &Events, - deck_name: &String, -) -> Result<()> { - let mut answers = 0; - - loop { - let now = time::seconds_since_unix_epoch()?; - let title = title(deck_name, answers, db::count_available(&conn).unwrap_or(0)); - - match db::pick_random_ready(&conn) { - Some(card) => { - let difficulty = question::ask(term, events, &title, &card)?; - answers += 1; - db::update( - &conn, - &card.question, - &space_repetition::update(card.state, difficulty), - )?; - } - None => { - let message = match db::next_ready(&conn) { - Some(ready) => format!( - "Prochaine carte disponible dans {}.", - time::pp_duration(ready - now) - ), - None => format!("Aucune carte n’est disponible. Votre deck est-il vide ?"), - }; - let _ = message::show(term, events, &title, &message, true); - break; - } - } - } - - Ok(()) -} - -fn title(deck_name: &String, answers: i32, available_cards: i32) -> String { - if answers == 0 && available_cards == 0 { - deck_name.to_string() - } else if available_cards == 0 { - format!( - "{} ({} / {})", - deck_name, - answers, - answers + available_cards - ) - } else { - format!( - "{} ({} / {})", - deck_name, - answers + 1, - answers + available_cards - ) - } -} diff --git a/src/gui/message.rs b/src/gui/message.rs index 28a1d2c..b938150 100644 --- a/src/gui/message.rs +++ b/src/gui/message.rs @@ -33,11 +33,8 @@ pub fn show( })?; if wait { - if let Event::Input(key) = events.next()? { - match key { - Key::Char('q') => break, - _ => (), - } + if let Event::Input(Key::Char('q')) = events.next()? { + break } } else { break; diff --git a/src/gui/mod.rs b/src/gui/mod.rs index f351eba..92cd943 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -1,4 +1,97 @@ -pub mod gui; pub mod message; pub mod question; pub mod util; + +use crate::deck; +use crate::util::time; +use crate::{db, space_repetition, util::event::Events}; +use anyhow::Result; +use rusqlite::Connection; +use std::{fs, io, time::Duration}; +use termion::{raw::IntoRawMode, raw::RawTerminal, screen::AlternateScreen}; +use tui::{backend::TermionBackend, Terminal}; + +type Term = Terminal>>>; + +pub fn terminal() -> Result { + let stdout = io::stdout().into_raw_mode()?; + let stdout = AlternateScreen::from(stdout); + let backend = TermionBackend::new(stdout); + Ok(Terminal::new(backend)?) +} + +pub fn synchronize( + conn: &Connection, + term: &mut Term, + events: &Events, + deck_path: &str, + deck_name: &str, +) -> Result<()> { + let last_modified = time::seconds_since_unix_epoch_of(fs::metadata(deck_path)?.modified()?)?; + let last_deck_read = db::last_deck_read(conn); + let must_synchronize = last_deck_read.map(|r| r < last_modified).unwrap_or(true); + + if must_synchronize { + let _ = message::show(term, events, deck_name, "Synchronization du deck…", false); + time::wait_at_least( + || db::synchronize(conn, deck::read(deck_path)?), + Duration::from_secs(1), + )?; + } + + Ok(()) +} + +pub fn start(conn: &Connection, term: &mut Term, events: &Events, deck_name: &str) -> Result<()> { + let mut answers = 0; + + loop { + let now = time::seconds_since_unix_epoch()?; + let title = title(deck_name, answers, db::count_available(conn).unwrap_or(0)); + + match db::pick_random_ready(conn) { + Some(card) => { + let difficulty = question::ask(term, events, &title, &card)?; + answers += 1; + db::update( + conn, + &card.question, + &space_repetition::update(card.state, difficulty), + )?; + } + None => { + let message = match db::next_ready(conn) { + Some(ready) => format!( + "Prochaine carte disponible dans {}.", + time::pp_duration(ready - now) + ), + None => "Aucune carte n’est disponible. Votre deck est-il vide ?".to_string(), + }; + let _ = message::show(term, events, &title, &message, true); + break; + } + } + } + + Ok(()) +} + +fn title(deck_name: &str, answers: i32, available_cards: i32) -> String { + if answers == 0 && available_cards == 0 { + deck_name.to_string() + } else if available_cards == 0 { + format!( + "{} ({} / {})", + deck_name, + answers, + answers + available_cards + ) + } else { + format!( + "{} ({} / {})", + deck_name, + answers + 1, + answers + available_cards + ) + } +} diff --git a/src/gui/question.rs b/src/gui/question.rs index 211bcda..5f060e3 100644 --- a/src/gui/question.rs +++ b/src/gui/question.rs @@ -28,7 +28,7 @@ enum Answer { pub fn ask( terminal: &mut Terminal, events: &Events, - title: &String, + title: &str, card: &Card, ) -> Result { let mut state = State { @@ -59,7 +59,7 @@ pub fn ask( let question = Paragraph::new(util::center_vertically(chunks[1], &card.question)) .style(match state.answer { Answer::Write => { - if state.input == "" { + if state.input.is_empty() { Style::default().fg(Color::Yellow) } else { Style::default() @@ -86,47 +86,44 @@ pub fn ask( .wrap(Wrap { trim: true }); f.render_widget(answer, chunks[2]); - match state.answer { - Answer::Difficulty { - difficulty: selected, - } => { - if !is_correct(&state.input, &card.responses) || card.responses.len() > 1 { - let paragraph = Paragraph::new(util::center_vertically( - chunks[3], - &serialization::words_to_line(&card.responses), - )) - .alignment(Alignment::Center); - f.render_widget(paragraph, chunks[3]); - }; + if let Answer::Difficulty { + difficulty: selected, + } = state.answer + { + if !is_correct(&state.input, &card.responses) || card.responses.len() > 1 { + let paragraph = Paragraph::new(util::center_vertically( + chunks[3], + &serialization::words_to_line(&card.responses), + )) + .alignment(Alignment::Center); + f.render_widget(paragraph, chunks[3]); + }; - let difficulties = card.state.difficulties(); - let l = difficulties.len(); - let sep = Span::styled(" • ", Style::default()); - let tabs = difficulties - .iter() - .enumerate() - .map(|(i, d)| { - let style = if *d == selected { - Style::default() - .fg(Color::Yellow) - .add_modifier(Modifier::UNDERLINED) - } else { - Style::default().add_modifier(Modifier::DIM) - }; - let d = Span::styled(difficulty::label(*d), style); - if i < l - 1 { - [d, sep.clone()].to_vec() - } else { - [d].to_vec() - } - }) - .collect::>>() - .concat(); - let p = - Paragraph::new(Text::from(Spans::from(tabs))).alignment(Alignment::Center); - f.render_widget(p, chunks[4]); - } - _ => {} + let difficulties = card.state.difficulties(); + let l = difficulties.len(); + let sep = Span::styled(" • ", Style::default()); + let tabs = difficulties + .iter() + .enumerate() + .map(|(i, d)| { + let style = if *d == selected { + Style::default() + .fg(Color::Yellow) + .add_modifier(Modifier::UNDERLINED) + } else { + Style::default().add_modifier(Modifier::DIM) + }; + let d = Span::styled(difficulty::label(*d), style); + if i < l - 1 { + [d, sep.clone()].to_vec() + } else { + [d].to_vec() + } + }) + .collect::>>() + .concat(); + let p = Paragraph::new(Text::from(Spans::from(tabs))).alignment(Alignment::Center); + f.render_widget(p, chunks[4]); } })?; @@ -171,15 +168,14 @@ pub fn ask( } } -fn is_correct(input: &String, responses: &Vec) -> bool { +fn is_correct(input: &str, responses: &[String]) -> bool { responses .iter() - .map(|r| r.split("(").collect::>()[0].trim()) - .collect::>() - .contains(&input.as_str()) + .map(|r| r.split('(').collect::>()[0].trim()) + .any(|x| x == input) } -fn relative_element(xs: &Vec, x: &T, ri: i32) -> Option { +fn relative_element(xs: &[T], x: &T, ri: i32) -> Option { let i = xs.iter().position(|t| t == x)? as i32 + ri; if i >= 0 && i < xs.len() as i32 { Some(xs[i as usize].clone()) diff --git a/src/gui/util.rs b/src/gui/util.rs index 38ed1e7..2314aba 100644 --- a/src/gui/util.rs +++ b/src/gui/util.rs @@ -12,7 +12,7 @@ pub fn title(str: &str) -> Paragraph { ) } -pub fn center_vertically(chunk: Rect, text: &String) -> String { +pub fn center_vertically(chunk: Rect, text: &str) -> String { let text_lines = text.lines().count(); let chunk_inner_lines: usize = (chunk.height - 2).into(); let blank_lines = chunk_inner_lines - text_lines; -- cgit v1.2.3