use anki_bridge::{AnkiClient, AnkiRequestable, prelude::*}; use crossterm::{ cursor, event::{self, Event, KeyCode}, execute, style::*, terminal::*, }; use nanohtml2text::html2text; use std::io::stdout; const GOOD: char = '3'; const AGAIN: char = '1'; fn main() { let anki = AnkiClient::default(); init(&anki); loop { prompt(&anki); } } fn init(anki: &AnkiClient) { clear_screen(); let decks = anki.request(DeckNamesRequest {}).unwrap(); for (index, title) in decks.clone().into_iter().enumerate() { // 0th index is Default, which is not predictable if index > 0 { println!("{:?}: {}", index, title); } } display_prompt_text("deck index:"); let mut input = "".to_string(); loop { match event::read().unwrap() { Event::Key(e) => match e.code { KeyCode::Char(c) => input = input + &c.to_string(), KeyCode::Enter => break, _ => (), }, _ => (), } } anki.request(GuiDeckReviewRequest { name: decks[input.parse::().unwrap()].clone(), }) .unwrap(); } fn prompt(anki: &AnkiClient) { // needs to be done twice to account for lag on the other end anki.request(GuiCurrentCardRequest {}).unwrap(); let card = anki.request(GuiCurrentCardRequest {}).unwrap(); clear_with_bar(&anki, &card); display_html(&card.question); loop { match event::read().unwrap() { Event::Key(e) => match e.code { KeyCode::Enter => break, _ => (), }, e => (), }; } anki.request(GuiShowAnswerRequest {}).unwrap(); clear_with_bar(&anki, &card); { let length = html2text(&card.question).len(); let text = &html2text(&card.answer)[(2 + length)..]; display_text(&text); } display_prompt_text(":"); let ease = loop { let ease = match event::read().unwrap() { Event::Key(e) => match e.code { KeyCode::Char(AGAIN) => break Ease::Again, KeyCode::Char(GOOD) => break Ease::Good, _ => (), }, e => (), }; }; anki.request(GuiAnswerCardRequest { ease: ease }).unwrap(); event::read().unwrap(); } fn clear_with_bar(anki: &AnkiClient, current_card: &GuiCurrentCardResponse) { let deck_name = ¤t_card.deck_name; let deck_stats = anki .request(GetDeckStatsRequest { decks: vec![deck_name.to_string()], }) .unwrap() .into_iter() .next() .unwrap() .1; clear_screen(); execute!( stdout(), SetForegroundColor(Color::Blue), Print(&format!("{:?} ", deck_stats.new_count)), SetForegroundColor(Color::Red), Print(&format!("{:?} ", deck_stats.learn_count)), SetForegroundColor(Color::Green), Print(&format!("{:?}\n", deck_stats.review_count)), ResetColor ); } fn clear_screen() { execute!( stdout(), Clear(ClearType::All), cursor::MoveTo(0, 0), cursor::Hide ); } fn display_prompt_text(text: &str) { execute!( stdout(), SetForegroundColor(Color::Blue), Print(text), ResetColor ); } fn display_html(html: &str) { let text = html2text(html); display_text(&text); } fn display_text(text: &str) { execute!( stdout(), SetForegroundColor(Color::DarkYellow), Print(text), ResetColor ); }