1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-05-30 14:17:35 +02:00
Martin Geisler 618d8fe4e9 Introduce a cargo clippy run
Personally, I don’t always agree with Clippy, but it a very widely
recommended tool for writing idiomatic Rust. So on balance, I think
it’s overall a good idea to enable it for both our exercises and our
tooling.
2024-07-22 15:02:35 +02:00

94 lines
3.0 KiB
Rust

// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use clap::Command;
use mdbook::MDBook;
use mdbook_course::course::Courses;
use mdbook_course::markdown::duration;
fn main() {
pretty_env_logger::init();
let app = Command::new("mdbook-course")
.about("mdbook preprocessor for Comprehensive Rust")
.subcommand(Command::new("sessions").about("Show session summary (default)"))
.subcommand(Command::new("segments").about("Show segment summary"))
.subcommand(Command::new("pr").about("Show summary for a PR"));
let matches = app.get_matches();
let root_dir = ".";
let mdbook = MDBook::load(root_dir).expect("Unable to load the book");
let (courses, _) = Courses::extract_structure(mdbook.book)
.expect("Unable to extract course structure");
match matches.subcommand() {
Some(("session", _)) | None => session_summary(&courses),
Some(("pr", _)) => pr_summary(&courses),
_ => unreachable!(),
}
}
fn timediff(actual: u64, target: u64, slop: u64) -> String {
if actual > target + slop {
format!(
"{} (\u{23f0} *{} too long*)",
duration(actual),
duration(actual - target),
)
} else if actual + slop < target {
format!("{}: ({} short)", duration(actual), duration(target - actual),)
} else {
duration(actual).to_string()
}
}
fn session_summary(courses: &Courses) {
for course in courses {
if course.target_minutes() == 0 {
return;
}
for session in course {
println!("### {} // {}", course.name, session.name);
println!(
"_{}_",
timediff(session.minutes(), session.target_minutes(), 15)
);
println!();
for segment in session {
println!("* {} - _{}_", segment.name, duration(segment.minutes()));
}
println!();
}
}
}
fn pr_summary(courses: &Courses) {
println!("## Course Schedule");
println!("With this pull request applied, the course schedule is as follows:");
for course in courses {
if course.target_minutes() == 0 {
return;
}
println!("### {}", course.name);
println!("_{}_", timediff(course.minutes(), course.target_minutes(), 15));
for session in course {
println!(
"* {} - _{}_",
session.name,
timediff(session.minutes(), session.target_minutes(), 5)
);
}
}
}