From 3bd26c7a24a97f9b4b87c453fbdbb06fe9971920 Mon Sep 17 00:00:00 2001 From: mo8it Date: Sun, 7 Apr 2024 19:01:08 +0200 Subject: State -> StateFile --- src/list.rs | 20 +++++++++---------- src/main.rs | 17 ++++++++-------- src/state.rs | 59 ------------------------------------------------------- src/state_file.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/watch.rs | 6 +++--- 5 files changed, 81 insertions(+), 80 deletions(-) delete mode 100644 src/state.rs create mode 100644 src/state_file.rs diff --git a/src/list.rs b/src/list.rs index cff0a3d..c59b8d8 100644 --- a/src/list.rs +++ b/src/list.rs @@ -14,7 +14,7 @@ use ratatui::{ }; use std::io; -use crate::{exercise::Exercise, state::State}; +use crate::{exercise::Exercise, state_file::StateFile}; struct UiState<'a> { pub table: Table<'a>, @@ -25,7 +25,7 @@ struct UiState<'a> { impl<'a> UiState<'a> { pub fn rows<'s, 'i>( - state: &'s State, + state_file: &'s StateFile, exercises: &'a [Exercise], ) -> impl Iterator> + 'i where @@ -34,10 +34,10 @@ impl<'a> UiState<'a> { { exercises .iter() - .zip(state.progress()) + .zip(state_file.progress()) .enumerate() .map(|(ind, (exercise, done))| { - let next = if ind == state.next_exercise_ind() { + let next = if ind == state_file.next_exercise_ind() { ">>>>".bold().red() } else { Span::default() @@ -58,7 +58,7 @@ impl<'a> UiState<'a> { }) } - pub fn new(state: &State, exercises: &'a [Exercise]) -> Self { + pub fn new(state_file: &StateFile, exercises: &'a [Exercise]) -> Self { let header = Row::new(["Next", "State", "Name", "Path"]); let max_name_len = exercises @@ -74,7 +74,7 @@ impl<'a> UiState<'a> { Constraint::Fill(1), ]; - let rows = Self::rows(state, exercises); + let rows = Self::rows(state_file, exercises); let table = Table::new(rows, widths) .header(header) @@ -147,7 +147,7 @@ impl<'a> UiState<'a> { } } -pub fn list(state: &mut State, exercises: &[Exercise]) -> Result<()> { +pub fn list(state_file: &mut StateFile, exercises: &[Exercise]) -> Result<()> { let mut stdout = io::stdout().lock(); stdout.execute(EnterAlternateScreen)?; enable_raw_mode()?; @@ -155,7 +155,7 @@ pub fn list(state: &mut State, exercises: &[Exercise]) -> Result<()> { let mut terminal = Terminal::new(CrosstermBackend::new(&mut stdout))?; terminal.clear()?; - let mut ui_state = UiState::new(state, exercises); + let mut ui_state = UiState::new(state_file, exercises); 'outer: loop { terminal.draw(|frame| ui_state.draw(frame))?; @@ -183,8 +183,8 @@ pub fn list(state: &mut State, exercises: &[Exercise]) -> Result<()> { KeyCode::Home | KeyCode::Char('g') => ui_state.select_first(), KeyCode::End | KeyCode::Char('G') => ui_state.select_last(), KeyCode::Char('c') => { - state.set_next_exercise_ind(ui_state.selected)?; - ui_state.table = ui_state.table.rows(UiState::rows(state, exercises)); + state_file.set_next_exercise_ind(ui_state.selected)?; + ui_state.table = ui_state.table.rows(UiState::rows(state_file, exercises)); } _ => (), } diff --git a/src/main.rs b/src/main.rs index e82fc80..3d691b0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,6 @@ -use crate::consts::WELCOME; -use crate::embedded::{WriteStrategy, EMBEDDED_FILES}; -use crate::exercise::{Exercise, ExerciseList}; -use crate::run::run; -use crate::verify::verify; use anyhow::{bail, Context, Result}; use clap::{Parser, Subcommand}; -use state::State; +use state_file::StateFile; use std::path::Path; use std::process::exit; use verify::VerifyState; @@ -16,10 +11,16 @@ mod exercise; mod init; mod list; mod run; -mod state; +mod state_file; mod verify; mod watch; +use crate::consts::WELCOME; +use crate::embedded::{WriteStrategy, EMBEDDED_FILES}; +use crate::exercise::{Exercise, ExerciseList}; +use crate::run::run; +use crate::verify::verify; + /// Rustlings is a collection of small exercises to get you used to writing and reading Rust code #[derive(Parser)] #[command(version)] @@ -85,7 +86,7 @@ If you are just starting with Rustlings, run the command `rustlings init` to ini exit(1); } - let mut state = State::read_or_default(&exercises); + let mut state = StateFile::read_or_default(&exercises); match args.command { None | Some(Subcommands::Watch) => { diff --git a/src/state.rs b/src/state.rs deleted file mode 100644 index 5a64487..0000000 --- a/src/state.rs +++ /dev/null @@ -1,59 +0,0 @@ -use anyhow::{bail, Context, Result}; -use serde::{Deserialize, Serialize}; -use std::fs; - -use crate::exercise::Exercise; - -#[derive(Serialize, Deserialize)] -pub struct State { - next_exercise_ind: usize, - progress: Vec, -} - -impl State { - fn read(exercises: &[Exercise]) -> Option { - let file_content = fs::read(".rustlings.json").ok()?; - - let slf: Self = serde_json::de::from_slice(&file_content).ok()?; - - if slf.progress.len() != exercises.len() || slf.next_exercise_ind >= exercises.len() { - return None; - } - - Some(slf) - } - - pub fn read_or_default(exercises: &[Exercise]) -> Self { - Self::read(exercises).unwrap_or_else(|| Self { - next_exercise_ind: 0, - progress: vec![false; exercises.len()], - }) - } - - fn write(&self) -> Result<()> { - // TODO: Capacity - let mut buf = Vec::with_capacity(1024); - serde_json::ser::to_writer(&mut buf, self).context("Failed to serialize the state")?; - - Ok(()) - } - - #[inline] - pub fn next_exercise_ind(&self) -> usize { - self.next_exercise_ind - } - - pub fn set_next_exercise_ind(&mut self, ind: usize) -> Result<()> { - if ind >= self.progress.len() { - bail!("The next exercise index is higher than the number of exercises"); - } - - self.next_exercise_ind = ind; - self.write() - } - - #[inline] - pub fn progress(&self) -> &[bool] { - &self.progress - } -} diff --git a/src/state_file.rs b/src/state_file.rs new file mode 100644 index 0000000..ca7ed34 --- /dev/null +++ b/src/state_file.rs @@ -0,0 +1,59 @@ +use anyhow::{bail, Context, Result}; +use serde::{Deserialize, Serialize}; +use std::fs; + +use crate::exercise::Exercise; + +#[derive(Serialize, Deserialize)] +pub struct StateFile { + next_exercise_ind: usize, + progress: Vec, +} + +impl StateFile { + fn read(exercises: &[Exercise]) -> Option { + let file_content = fs::read(".rustlings.json").ok()?; + + let slf: Self = serde_json::de::from_slice(&file_content).ok()?; + + if slf.progress.len() != exercises.len() || slf.next_exercise_ind >= exercises.len() { + return None; + } + + Some(slf) + } + + pub fn read_or_default(exercises: &[Exercise]) -> Self { + Self::read(exercises).unwrap_or_else(|| Self { + next_exercise_ind: 0, + progress: vec![false; exercises.len()], + }) + } + + fn write(&self) -> Result<()> { + // TODO: Capacity + let mut buf = Vec::with_capacity(1024); + serde_json::ser::to_writer(&mut buf, self).context("Failed to serialize the state")?; + + Ok(()) + } + + #[inline] + pub fn next_exercise_ind(&self) -> usize { + self.next_exercise_ind + } + + pub fn set_next_exercise_ind(&mut self, ind: usize) -> Result<()> { + if ind >= self.progress.len() { + bail!("The next exercise index is higher than the number of exercises"); + } + + self.next_exercise_ind = ind; + self.write() + } + + #[inline] + pub fn progress(&self) -> &[bool] { + &self.progress + } +} diff --git a/src/watch.rs b/src/watch.rs index cc9668d..1503fdf 100644 --- a/src/watch.rs +++ b/src/watch.rs @@ -18,7 +18,7 @@ use std::{ use crate::{ exercise::{self, Exercise}, - state::State, + state_file::StateFile, }; enum Event { @@ -151,14 +151,14 @@ You can keep working on this exercise or jump into the next one by removing the } } -pub fn watch(state: &State, exercises: &[Exercise]) -> Result<()> { +pub fn watch(state_file: &StateFile, exercises: &[Exercise]) -> Result<()> { let (tx, rx) = channel(); let mut debouncer = new_debouncer(Duration::from_secs(1), tx)?; debouncer .watcher() .watch(Path::new("exercises"), RecursiveMode::Recursive)?; - let current_exercise_ind = state.next_exercise_ind(); + let current_exercise_ind = state_file.next_exercise_ind(); let exercise = &exercises[current_exercise_ind]; -- cgit v1.2.3