mirror of
https://github.com/rust-lang/rustlings.git
synced 2024-12-25 23:10:30 +00:00
Separate initialization with a struct
This commit is contained in:
parent
fc5fc0920f
commit
ea73af9ba3
2 changed files with 74 additions and 64 deletions
|
@ -20,7 +20,7 @@ use crate::{
|
||||||
embedded::EMBEDDED_FILES,
|
embedded::EMBEDDED_FILES,
|
||||||
exercise::{Exercise, RunnableExercise},
|
exercise::{Exercise, RunnableExercise},
|
||||||
info_file::ExerciseInfo,
|
info_file::ExerciseInfo,
|
||||||
term::{self, show_exercises_check_progress},
|
term::{self, ExercisesCheckProgressVisualizer},
|
||||||
};
|
};
|
||||||
|
|
||||||
const STATE_FILE_NAME: &str = ".rustlings-state.txt";
|
const STATE_FILE_NAME: &str = ".rustlings-state.txt";
|
||||||
|
@ -409,13 +409,12 @@ impl AppState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_all_exercises_impl(&mut self, stdout: &mut StdoutLock) -> Result<Option<usize>> {
|
fn check_all_exercises_impl(&mut self, stdout: &mut StdoutLock) -> Result<Option<usize>> {
|
||||||
stdout.write_all("Checking all exercises…\n".as_bytes())?;
|
|
||||||
let next_exercise_ind = AtomicUsize::new(0);
|
|
||||||
let term_width = terminal::size()
|
let term_width = terminal::size()
|
||||||
.context("Failed to get the terminal size")?
|
.context("Failed to get the terminal size")?
|
||||||
.0;
|
.0;
|
||||||
clear_terminal(stdout)?;
|
let mut progress_visualizer = ExercisesCheckProgressVisualizer::build(stdout, term_width)?;
|
||||||
|
|
||||||
|
let next_exercise_ind = AtomicUsize::new(0);
|
||||||
let mut progresses = vec![ExerciseCheckProgress::None; self.exercises.len()];
|
let mut progresses = vec![ExerciseCheckProgress::None; self.exercises.len()];
|
||||||
|
|
||||||
thread::scope(|s| {
|
thread::scope(|s| {
|
||||||
|
@ -464,7 +463,7 @@ impl AppState {
|
||||||
|
|
||||||
while let Ok((exercise_ind, progress)) = exercise_progress_receiver.recv() {
|
while let Ok((exercise_ind, progress)) = exercise_progress_receiver.recv() {
|
||||||
progresses[exercise_ind] = progress;
|
progresses[exercise_ind] = progress;
|
||||||
show_exercises_check_progress(stdout, &progresses, term_width)?;
|
progress_visualizer.update(&progresses)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok::<_, Error>(())
|
Ok::<_, Error>(())
|
||||||
|
@ -487,7 +486,7 @@ impl AppState {
|
||||||
// it could be because we exceeded the limit of open file descriptors.
|
// it could be because we exceeded the limit of open file descriptors.
|
||||||
// Therefore, try running exercises with errors sequentially.
|
// Therefore, try running exercises with errors sequentially.
|
||||||
progresses[exercise_ind] = ExerciseCheckProgress::Checking;
|
progresses[exercise_ind] = ExerciseCheckProgress::Checking;
|
||||||
show_exercises_check_progress(stdout, &progresses, term_width)?;
|
progress_visualizer.update(&progresses)?;
|
||||||
|
|
||||||
let exercise = &self.exercises[exercise_ind];
|
let exercise = &self.exercises[exercise_ind];
|
||||||
let success = exercise.run_exercise(None, &self.cmd_runner)?;
|
let success = exercise.run_exercise(None, &self.cmd_runner)?;
|
||||||
|
@ -501,7 +500,7 @@ impl AppState {
|
||||||
}
|
}
|
||||||
self.set_status(exercise_ind, success)?;
|
self.set_status(exercise_ind, success)?;
|
||||||
|
|
||||||
show_exercises_check_progress(stdout, &progresses, term_width)?;
|
progress_visualizer.update(&progresses)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
125
src/term.rs
125
src/term.rs
|
@ -87,6 +87,74 @@ impl<'a> CountedWrite<'a> for StdoutLock<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ExercisesCheckProgressVisualizer<'a, 'b> {
|
||||||
|
stdout: &'a mut StdoutLock<'b>,
|
||||||
|
n_cols: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> ExercisesCheckProgressVisualizer<'a, 'b> {
|
||||||
|
pub fn build(stdout: &'a mut StdoutLock<'b>, term_width: u16) -> io::Result<Self> {
|
||||||
|
clear_terminal(stdout)?;
|
||||||
|
stdout.write_all("Checking all exercises…\n".as_bytes())?;
|
||||||
|
|
||||||
|
// Legend
|
||||||
|
stdout.write_all(b"Color of exercise number: ")?;
|
||||||
|
stdout.queue(SetForegroundColor(Color::Blue))?;
|
||||||
|
stdout.write_all(b"Checking")?;
|
||||||
|
stdout.queue(ResetColor)?;
|
||||||
|
stdout.write_all(b" - ")?;
|
||||||
|
stdout.queue(SetForegroundColor(Color::Green))?;
|
||||||
|
stdout.write_all(b"Done")?;
|
||||||
|
stdout.queue(ResetColor)?;
|
||||||
|
stdout.write_all(b" - ")?;
|
||||||
|
stdout.queue(SetForegroundColor(Color::Red))?;
|
||||||
|
stdout.write_all(b"Pending")?;
|
||||||
|
stdout.queue(ResetColor)?;
|
||||||
|
stdout.write_all(b"\n")?;
|
||||||
|
|
||||||
|
// Exercise numbers with up to 3 digits.
|
||||||
|
// +1 because the last column doesn't end with a whitespace.
|
||||||
|
let n_cols = usize::from(term_width + 1) / 4;
|
||||||
|
|
||||||
|
Ok(Self { stdout, n_cols })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, progresses: &[ExerciseCheckProgress]) -> io::Result<()> {
|
||||||
|
self.stdout.queue(MoveTo(0, 2))?;
|
||||||
|
|
||||||
|
let mut exercise_num = 1;
|
||||||
|
for exercise_progress in progresses {
|
||||||
|
match exercise_progress {
|
||||||
|
ExerciseCheckProgress::None => (),
|
||||||
|
ExerciseCheckProgress::Checking => {
|
||||||
|
self.stdout.queue(SetForegroundColor(Color::Blue))?;
|
||||||
|
}
|
||||||
|
ExerciseCheckProgress::Done => {
|
||||||
|
self.stdout.queue(SetForegroundColor(Color::Green))?;
|
||||||
|
}
|
||||||
|
ExerciseCheckProgress::Pending => {
|
||||||
|
self.stdout.queue(SetForegroundColor(Color::Red))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(self.stdout, "{exercise_num:<3}")?;
|
||||||
|
self.stdout.queue(ResetColor)?;
|
||||||
|
|
||||||
|
if exercise_num != progresses.len() {
|
||||||
|
if exercise_num % self.n_cols == 0 {
|
||||||
|
self.stdout.write_all(b"\n")?;
|
||||||
|
} else {
|
||||||
|
self.stdout.write_all(b" ")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
exercise_num += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.stdout.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn progress_bar<'a>(
|
pub fn progress_bar<'a>(
|
||||||
writer: &mut impl CountedWrite<'a>,
|
writer: &mut impl CountedWrite<'a>,
|
||||||
progress: u16,
|
progress: u16,
|
||||||
|
@ -137,63 +205,6 @@ pub fn progress_bar<'a>(
|
||||||
write!(stdout, "] {progress:>3}/{total}")
|
write!(stdout, "] {progress:>3}/{total}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_exercises_check_progress(
|
|
||||||
stdout: &mut StdoutLock,
|
|
||||||
progresses: &[ExerciseCheckProgress],
|
|
||||||
term_width: u16,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
stdout.queue(MoveTo(0, 0))?;
|
|
||||||
|
|
||||||
// Legend
|
|
||||||
stdout.write_all(b"Color of exercise number: ")?;
|
|
||||||
stdout.queue(SetForegroundColor(Color::Blue))?;
|
|
||||||
stdout.write_all(b"Checking")?;
|
|
||||||
stdout.queue(ResetColor)?;
|
|
||||||
stdout.write_all(b" - ")?;
|
|
||||||
stdout.queue(SetForegroundColor(Color::Green))?;
|
|
||||||
stdout.write_all(b"Done")?;
|
|
||||||
stdout.queue(ResetColor)?;
|
|
||||||
stdout.write_all(b" - ")?;
|
|
||||||
stdout.queue(SetForegroundColor(Color::Red))?;
|
|
||||||
stdout.write_all(b"Pending")?;
|
|
||||||
stdout.queue(ResetColor)?;
|
|
||||||
stdout.write_all(b"\n")?;
|
|
||||||
|
|
||||||
// Exercise numbers with up to 3 digits.
|
|
||||||
let n_cols = usize::from(term_width + 1) / 4;
|
|
||||||
|
|
||||||
let mut exercise_num = 1;
|
|
||||||
for exercise_progress in progresses {
|
|
||||||
match exercise_progress {
|
|
||||||
ExerciseCheckProgress::None => (),
|
|
||||||
ExerciseCheckProgress::Checking => {
|
|
||||||
stdout.queue(SetForegroundColor(Color::Blue))?;
|
|
||||||
}
|
|
||||||
ExerciseCheckProgress::Done => {
|
|
||||||
stdout.queue(SetForegroundColor(Color::Green))?;
|
|
||||||
}
|
|
||||||
ExerciseCheckProgress::Pending => {
|
|
||||||
stdout.queue(SetForegroundColor(Color::Red))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(stdout, "{exercise_num:<3}")?;
|
|
||||||
stdout.queue(ResetColor)?;
|
|
||||||
|
|
||||||
if exercise_num != progresses.len() {
|
|
||||||
if exercise_num % n_cols == 0 {
|
|
||||||
stdout.write_all(b"\n")?;
|
|
||||||
} else {
|
|
||||||
stdout.write_all(b" ")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
exercise_num += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stdout.flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_terminal(stdout: &mut StdoutLock) -> io::Result<()> {
|
pub fn clear_terminal(stdout: &mut StdoutLock) -> io::Result<()> {
|
||||||
stdout
|
stdout
|
||||||
.queue(MoveTo(0, 0))?
|
.queue(MoveTo(0, 0))?
|
||||||
|
|
Loading…
Reference in a new issue