State -> StateFile

This commit is contained in:
mo8it 2024-04-07 19:01:08 +02:00
parent 8c31d38fa1
commit 3bd26c7a24
4 changed files with 24 additions and 23 deletions

View file

@ -14,7 +14,7 @@ use ratatui::{
}; };
use std::io; use std::io;
use crate::{exercise::Exercise, state::State}; use crate::{exercise::Exercise, state_file::StateFile};
struct UiState<'a> { struct UiState<'a> {
pub table: Table<'a>, pub table: Table<'a>,
@ -25,7 +25,7 @@ struct UiState<'a> {
impl<'a> UiState<'a> { impl<'a> UiState<'a> {
pub fn rows<'s, 'i>( pub fn rows<'s, 'i>(
state: &'s State, state_file: &'s StateFile,
exercises: &'a [Exercise], exercises: &'a [Exercise],
) -> impl Iterator<Item = Row<'a>> + 'i ) -> impl Iterator<Item = Row<'a>> + 'i
where where
@ -34,10 +34,10 @@ impl<'a> UiState<'a> {
{ {
exercises exercises
.iter() .iter()
.zip(state.progress()) .zip(state_file.progress())
.enumerate() .enumerate()
.map(|(ind, (exercise, done))| { .map(|(ind, (exercise, done))| {
let next = if ind == state.next_exercise_ind() { let next = if ind == state_file.next_exercise_ind() {
">>>>".bold().red() ">>>>".bold().red()
} else { } else {
Span::default() 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 header = Row::new(["Next", "State", "Name", "Path"]);
let max_name_len = exercises let max_name_len = exercises
@ -74,7 +74,7 @@ impl<'a> UiState<'a> {
Constraint::Fill(1), Constraint::Fill(1),
]; ];
let rows = Self::rows(state, exercises); let rows = Self::rows(state_file, exercises);
let table = Table::new(rows, widths) let table = Table::new(rows, widths)
.header(header) .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(); let mut stdout = io::stdout().lock();
stdout.execute(EnterAlternateScreen)?; stdout.execute(EnterAlternateScreen)?;
enable_raw_mode()?; 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))?; let mut terminal = Terminal::new(CrosstermBackend::new(&mut stdout))?;
terminal.clear()?; terminal.clear()?;
let mut ui_state = UiState::new(state, exercises); let mut ui_state = UiState::new(state_file, exercises);
'outer: loop { 'outer: loop {
terminal.draw(|frame| ui_state.draw(frame))?; 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::Home | KeyCode::Char('g') => ui_state.select_first(),
KeyCode::End | KeyCode::Char('G') => ui_state.select_last(), KeyCode::End | KeyCode::Char('G') => ui_state.select_last(),
KeyCode::Char('c') => { KeyCode::Char('c') => {
state.set_next_exercise_ind(ui_state.selected)?; state_file.set_next_exercise_ind(ui_state.selected)?;
ui_state.table = ui_state.table.rows(UiState::rows(state, exercises)); ui_state.table = ui_state.table.rows(UiState::rows(state_file, exercises));
} }
_ => (), _ => (),
} }

View file

@ -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 anyhow::{bail, Context, Result};
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use state::State; use state_file::StateFile;
use std::path::Path; use std::path::Path;
use std::process::exit; use std::process::exit;
use verify::VerifyState; use verify::VerifyState;
@ -16,10 +11,16 @@ mod exercise;
mod init; mod init;
mod list; mod list;
mod run; mod run;
mod state; mod state_file;
mod verify; mod verify;
mod watch; 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 /// Rustlings is a collection of small exercises to get you used to writing and reading Rust code
#[derive(Parser)] #[derive(Parser)]
#[command(version)] #[command(version)]
@ -85,7 +86,7 @@ If you are just starting with Rustlings, run the command `rustlings init` to ini
exit(1); exit(1);
} }
let mut state = State::read_or_default(&exercises); let mut state = StateFile::read_or_default(&exercises);
match args.command { match args.command {
None | Some(Subcommands::Watch) => { None | Some(Subcommands::Watch) => {

View file

@ -5,12 +5,12 @@ use std::fs;
use crate::exercise::Exercise; use crate::exercise::Exercise;
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct State { pub struct StateFile {
next_exercise_ind: usize, next_exercise_ind: usize,
progress: Vec<bool>, progress: Vec<bool>,
} }
impl State { impl StateFile {
fn read(exercises: &[Exercise]) -> Option<Self> { fn read(exercises: &[Exercise]) -> Option<Self> {
let file_content = fs::read(".rustlings.json").ok()?; let file_content = fs::read(".rustlings.json").ok()?;

View file

@ -18,7 +18,7 @@ use std::{
use crate::{ use crate::{
exercise::{self, Exercise}, exercise::{self, Exercise},
state::State, state_file::StateFile,
}; };
enum Event { 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 (tx, rx) = channel();
let mut debouncer = new_debouncer(Duration::from_secs(1), tx)?; let mut debouncer = new_debouncer(Duration::from_secs(1), tx)?;
debouncer debouncer
.watcher() .watcher()
.watch(Path::new("exercises"), RecursiveMode::Recursive)?; .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]; let exercise = &exercises[current_exercise_ind];