Skip to content

Commit 7a6f71f

Browse files
committed
Fix context of previous lines and improve readability
1 parent bdf826a commit 7a6f71f

File tree

1 file changed

+79
-73
lines changed

1 file changed

+79
-73
lines changed

src/exercise.rs

Lines changed: 79 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
33
use std::fs::{self, remove_file, File};
44
use std::io::{self, BufRead, BufReader};
55
use std::path::PathBuf;
6-
use std::process::{self, Command};
6+
use std::process::{self, exit, Command};
77
use std::{array, env, mem};
88
use winnow::ascii::{space0, Caseless};
99
use winnow::combinator::opt;
@@ -15,7 +15,8 @@ const RUSTC_NO_DEBUG_ARGS: &[&str] = &["-C", "strip=debuginfo"];
1515
const CONTEXT: usize = 2;
1616
const CLIPPY_CARGO_TOML_PATH: &str = "./exercises/22_clippy/Cargo.toml";
1717

18-
fn not_done(input: &str) -> bool {
18+
// Checks if the line contains the "I AM NOT DONE" comment.
19+
fn contains_not_done_comment(input: &str) -> bool {
1920
(
2021
space0::<_, ()>,
2122
"//",
@@ -219,12 +220,15 @@ path = "{}.rs""#,
219220

220221
pub fn state(&self) -> State {
221222
let source_file = File::open(&self.path).unwrap_or_else(|e| {
222-
panic!(
223-
"We were unable to open the exercise file {}! {e}",
224-
self.path.display()
225-
)
223+
println!(
224+
"Failed to open the exercise file {}: {e}",
225+
self.path.display(),
226+
);
227+
exit(1);
226228
});
227229
let mut source_reader = BufReader::new(source_file);
230+
231+
// Read the next line into `buf` without the newline at the end.
228232
let mut read_line = |buf: &mut String| -> io::Result<_> {
229233
let n = source_reader.read_line(buf)?;
230234
if buf.ends_with('\n') {
@@ -236,70 +240,72 @@ path = "{}.rs""#,
236240
Ok(n)
237241
};
238242

239-
let mut matched_line_ind: usize = 0;
243+
let mut current_line_number: usize = 1;
240244
let mut prev_lines: [_; CONTEXT] = array::from_fn(|_| String::with_capacity(256));
241245
let mut line = String::with_capacity(256);
242246

243247
loop {
244-
match read_line(&mut line) {
245-
Ok(0) => break,
246-
Ok(_) => {
247-
if not_done(&line) {
248-
let mut context = Vec::with_capacity(2 * CONTEXT + 1);
249-
for (ind, prev_line) in prev_lines
250-
.into_iter()
251-
.rev()
252-
.take(matched_line_ind)
253-
.enumerate()
254-
{
255-
context.push(ContextLine {
256-
line: prev_line,
257-
// TODO
258-
number: matched_line_ind - CONTEXT + ind + 1,
259-
important: false,
260-
});
261-
}
262-
263-
context.push(ContextLine {
264-
line,
265-
number: matched_line_ind + 1,
266-
important: true,
267-
});
268-
269-
for ind in 0..CONTEXT {
270-
let mut next_line = String::with_capacity(256);
271-
let Ok(n) = read_line(&mut next_line) else {
272-
break;
273-
};
274-
275-
if n == 0 {
276-
break;
277-
}
278-
279-
context.push(ContextLine {
280-
line: next_line,
281-
number: matched_line_ind + ind + 2,
282-
important: false,
283-
});
284-
}
285-
286-
return State::Pending(context);
287-
}
248+
let n = read_line(&mut line).unwrap_or_else(|e| {
249+
println!(
250+
"Failed to read the exercise file {}: {e}",
251+
self.path.display(),
252+
);
253+
exit(1);
254+
});
255+
256+
// Reached the end of the file and didn't find the comment.
257+
if n == 0 {
258+
return State::Done;
259+
}
260+
261+
if contains_not_done_comment(&line) {
262+
let mut context = Vec::with_capacity(2 * CONTEXT + 1);
263+
for (ind, prev_line) in prev_lines
264+
.into_iter()
265+
.take(current_line_number - 1)
266+
.enumerate()
267+
.rev()
268+
{
269+
context.push(ContextLine {
270+
line: prev_line,
271+
number: current_line_number - 1 - ind,
272+
important: false,
273+
});
274+
}
288275

289-
matched_line_ind += 1;
290-
for prev_line in &mut prev_lines {
291-
mem::swap(&mut line, prev_line);
276+
context.push(ContextLine {
277+
line,
278+
number: current_line_number,
279+
important: true,
280+
});
281+
282+
for ind in 0..CONTEXT {
283+
let mut next_line = String::with_capacity(256);
284+
let Ok(n) = read_line(&mut next_line) else {
285+
break;
286+
};
287+
288+
if n == 0 {
289+
break;
292290
}
293-
line.clear();
291+
292+
context.push(ContextLine {
293+
line: next_line,
294+
number: current_line_number + 1 + ind,
295+
important: false,
296+
});
294297
}
295-
Err(e) => panic!(
296-
"We were unable to read the exercise file {}! {e}",
297-
self.path.display()
298-
),
298+
299+
return State::Pending(context);
299300
}
300-
}
301301

302-
State::Done
302+
current_line_number += 1;
303+
// Recycle the buffers.
304+
for prev_line in &mut prev_lines {
305+
mem::swap(&mut line, prev_line);
306+
}
307+
line.clear();
308+
}
303309
}
304310

305311
// Check that the exercise looks to be solved using self.state()
@@ -428,17 +434,17 @@ mod test {
428434

429435
#[test]
430436
fn test_not_done() {
431-
assert!(not_done("// I AM NOT DONE"));
432-
assert!(not_done("/// I AM NOT DONE"));
433-
assert!(not_done("// I AM NOT DONE"));
434-
assert!(not_done("/// I AM NOT DONE"));
435-
assert!(not_done("// I AM NOT DONE "));
436-
assert!(not_done("// I AM NOT DONE!"));
437-
assert!(not_done("// I am not done"));
438-
assert!(not_done("// i am NOT done"));
439-
440-
assert!(!not_done("I AM NOT DONE"));
441-
assert!(!not_done("// NOT DONE"));
442-
assert!(!not_done("DONE"));
437+
assert!(contains_not_done_comment("// I AM NOT DONE"));
438+
assert!(contains_not_done_comment("/// I AM NOT DONE"));
439+
assert!(contains_not_done_comment("// I AM NOT DONE"));
440+
assert!(contains_not_done_comment("/// I AM NOT DONE"));
441+
assert!(contains_not_done_comment("// I AM NOT DONE "));
442+
assert!(contains_not_done_comment("// I AM NOT DONE!"));
443+
assert!(contains_not_done_comment("// I am not done"));
444+
assert!(contains_not_done_comment("// i am NOT done"));
445+
446+
assert!(!contains_not_done_comment("I AM NOT DONE"));
447+
assert!(!contains_not_done_comment("// NOT DONE"));
448+
assert!(!contains_not_done_comment("DONE"));
443449
}
444450
}

0 commit comments

Comments
 (0)