aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/homework.rs121
-rw-r--r--src/lecture.rs7
-rw-r--r--src/main.rs65
3 files changed, 176 insertions, 17 deletions
diff --git a/src/homework.rs b/src/homework.rs
new file mode 100644
index 0000000..f67f9e4
--- /dev/null
+++ b/src/homework.rs
@@ -0,0 +1,121 @@
+use std::{
+ fs,
+ io,
+ path::PathBuf,
+};
+use tinytemplate::TinyTemplate;
+use regex::Regex;
+use serde::Serialize;
+
+use crate::{Course, Config, rofi_picker};
+
+#[derive(Serialize)]
+struct HomeworkContext<'a> {
+ course: &'a String,
+ number: u32,
+}
+
+fn display_name(name: &String) -> String {
+ let pattern = Regex::new(r"([a-z]+)(\d{3})").unwrap();
+ let caps = pattern.captures(name).unwrap();
+ let dept = caps.get(1).unwrap().as_str().to_uppercase();
+ let number = caps.get(2).unwrap().as_str();
+ let display_name = format!("{dept} {number}");
+ println!("{display_name}");
+
+ return display_name;
+}
+
+fn init_homework(course: &Course, config: &Config, context: &HomeworkContext) -> (PathBuf, String) {
+ let template_stream = fs::read(&config.homework_template)
+ .expect("Couldn't open template.");
+ let template_string = String::from_utf8_lossy(&template_stream);
+
+ let mut template = TinyTemplate::new();
+ template.add_template("main", &template_string)
+ .expect("Failed initializing template.");
+
+ let rendered = template.render("main", &context)
+ .expect("Failed applying template");
+
+ let homework_file = format!("homework{}.tex", context.number);
+ let homework_directory = config.root.join(&course.semester).join(&course.name)
+ .join(format!("homework{}", context.number));
+ fs::create_dir(&homework_directory).unwrap();
+ fs::write(homework_directory.join(homework_file.clone()), rendered)
+ .expect("Failed making main tex for course.");
+
+ return (homework_directory, homework_file);
+}
+
+fn detect_homeworks(path: &PathBuf) -> io::Result<Vec<u32>> {
+ let mut homework_numbers: Vec<u32> = Vec::new();
+ let dir_iter = fs::read_dir(path)?;
+ let pattern = Regex::new(r"homework(\d+)").unwrap();
+
+ for entry in dir_iter {
+ let entry_path = entry?.path();
+ let name = entry_path.file_name().unwrap().to_string_lossy();
+ if let Some(caps) = pattern.captures(&name) {
+ let homework_number = caps[1].parse::<u32>().unwrap();
+ homework_numbers.push(homework_number);
+ }
+ }
+
+ homework_numbers.sort();
+
+ return Ok(homework_numbers);
+}
+
+pub fn new_homework(course: &Course, config: &Config) -> (PathBuf, String) {
+ let course_directory = config.root.join(&course.semester).join(&course.name);
+
+ if !course_directory.try_exists().unwrap() {
+ fs::create_dir_all(&course_directory).unwrap();
+ }
+
+ let homeworks = detect_homeworks(&course_directory)
+ .expect("Could not make sense of the homeworks situation.");
+ let new_homework = homeworks.last().unwrap_or(&0).clone() + 1;
+
+ let name = display_name(&course.name);
+ let homework_context = HomeworkContext { course: &name, number: new_homework };
+ return init_homework(course, config, &homework_context);
+}
+
+pub fn recent_homework(course: &Course, config: &Config) -> (PathBuf, String) {
+ let course_directory = config.root.join(&course.semester).join(&course.name);
+
+ let homeworks = detect_homeworks(&course_directory)
+ .expect("Could not make sense of the homeworks situation.");
+ let most_recent = homeworks.last().expect("No homeworks.");
+
+ let homework_directory = course_directory.join(format!("homework{most_recent}"));
+ let homework_file = format!("homework{most_recent}.tex");
+
+ return (homework_directory, homework_file);
+}
+
+pub fn view_homeworks(course: &Course, config: &Config) -> Result<(PathBuf, String), &'static str> {
+ let course_directory = config.root.join(&course.semester).join(&course.name);
+ let homeworks = detect_homeworks(&course_directory)
+ .expect("Could not make sense of the homeworks situation.");
+
+ let mut homeworks_string = String::new();
+
+ for (idx, hw) in homeworks.iter().enumerate() {
+ if idx != 0 {
+ homeworks_string.push_str("\n");
+ }
+ homeworks_string.push_str(&format!("Homework {hw}").to_string());
+ }
+
+ let hw_idx = rofi_picker("Homeworks", homeworks_string)?;
+
+ let picked_homework = homeworks[hw_idx as usize];
+
+ let homework_directory = course_directory.join(format!("homework{picked_homework}"));
+ let homework_file = format!("homework{picked_homework}.tex");
+
+ return Ok((homework_directory, homework_file));
+}
diff --git a/src/lecture.rs b/src/lecture.rs
index 89acea0..3cb054f 100644
--- a/src/lecture.rs
+++ b/src/lecture.rs
@@ -9,7 +9,7 @@ use regex::Regex;
use crate::{Course, CourseContext, Config};
fn init_lecture(course: &Course, config: &Config) {
- let template_stream = fs::read(&config.template)
+ let template_stream = fs::read(&config.lecture_template)
.expect("Couldn't open template.");
let template_string = String::from_utf8_lossy(&template_stream);
@@ -59,7 +59,7 @@ fn update_main(main_path: &PathBuf, new_lessons: String) -> io::Result<()> {
Ok(())
}
-pub fn new_lesson(course: &Course, config: &Config) -> String {
+pub fn new_lesson(course: &Course, config: &Config) -> (PathBuf, String) {
let lecture_directory = config.root.join(&course.semester).join(&course.name)
.join("lecture");
@@ -85,7 +85,8 @@ pub fn new_lesson(course: &Course, config: &Config) -> String {
lessons_string.push_str(format!(" \\input{{les{num}.tex}}\n").as_str());
}
+ println!("{lecture_directory:?}");
update_main(&lecture_directory.join("main.tex"), lessons_string)
.expect("Unable to update main.tex");
- return lesson_file;
+ return (lecture_directory, lesson_file);
}
diff --git a/src/main.rs b/src/main.rs
index 847d096..0a02206 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,10 +6,12 @@ use std::{
fs,
};
use lecture::new_lesson;
+use homework::{new_homework, recent_homework, view_homeworks};
use serde::{Deserialize, Serialize};
use clap::{Parser, Subcommand, Args};
mod lecture;
+mod homework;
#[derive(Parser)]
struct Cli {
@@ -54,7 +56,8 @@ struct OpenArgs {
#[derive(Deserialize, Serialize)]
struct Config {
root: PathBuf,
- template: PathBuf,
+ lecture_template: PathBuf,
+ homework_template: PathBuf,
}
#[derive(Deserialize, Serialize)]
@@ -110,8 +113,9 @@ fn create_config(path: &PathBuf) -> Config {
root = PathBuf::from(input.trim());
resolve_home(&mut root);
- let template = path.join("lecture_template.tex");
- let config = Config { root, template };
+ let lecture_template = path.join("lecture_template.tex");
+ let homework_template = path.join("lecture_template.tex");
+ let config = Config { root, lecture_template, homework_template };
let toml = toml::to_string(&config)
.expect("Unable to convert config struct to toml string.");
@@ -208,6 +212,13 @@ fn launch_tex(directory: &PathBuf, file_name: &String) {
xoppdog.kill().expect("Couldn't kill xoppdog.");
}
+fn launch_pdf(directory: &PathBuf, file_name: &String) {
+ Command::new("zathura")
+ .arg(directory.join(file_name).as_os_str())
+ .spawn()
+ .expect("Failed to start zathura.");
+}
+
fn init_command(args: InitArgs, config: &Config) -> Course {
let course = Course {
name: args.name,
@@ -216,8 +227,7 @@ fn init_command(args: InitArgs, config: &Config) -> Course {
semester: args.semester
};
- let lecture_directory = config.root.join(&course.semester).join(&course.name)
- .join("lecture");
+ let lecture_directory = config.root.join(&course.semester).join(&course.name);
fs::create_dir_all(&lecture_directory)
.expect("Failed creating course dir.");
@@ -230,15 +240,43 @@ fn open_command(args: OpenArgs, courses: &HashMap<String, Course>, config: &Conf
None => pick_course(courses)?,
};
- let in_lecture = rofi_picker("Type", String::from("Lecture\nHomework"))? == 0;
- let new_file = rofi_picker("Action", String::from("New\nEdit"))? == 0;
-
- let course_directory = config.root.join(&course.semester).join(&course.name).join("lecture");
- let file_name = match (in_lecture, new_file) {
- (true, true) => new_lesson(&course, &config),
- (_, _) => String::from("main.tex"),
+ let in_lecture = rofi_picker("Type", String::from("Lecture\nHomework"))?;
+
+ let _ = match in_lecture {
+ 0 => open_lecture(&course, &config),
+ _ => open_homework(&course, &config),
};
-
+
+ Ok(())
+}
+
+fn open_lecture(course: &Course, config: &Config) -> Result<(), &'static str>{
+ let action = rofi_picker("Action", String::from("New Lesson\nEdit Notes\nView"))?;
+
+ let course_directory = config.root.join(&course.semester).join(&course.name);
+ let (course_directory, file_name) = match action {
+ 0 => new_lesson(&course, &config),
+ 1 => (course_directory.join("lecture"), String::from("main.tex")),
+ _ => (course_directory.join("lecture"), String::from("main.pdf")),
+ };
+
+ match action {
+ 2 => launch_pdf(&course_directory, &file_name),
+ _ => launch_tex(&course_directory, &file_name),
+ };
+
+ Ok(())
+}
+
+fn open_homework(course: &Course, config: &Config) -> Result<(), &'static str>{
+ let action = rofi_picker("Action", String::from("Edit Recent\nNew Homework\nView Previous"))?;
+
+ let (course_directory, file_name) = match action {
+ 0 => recent_homework(&course, &config),
+ 1 => new_homework(&course, &config),
+ _ => view_homeworks(&course, &config)?,
+ };
+
launch_tex(&course_directory, &file_name);
Ok(())
@@ -266,6 +304,5 @@ fn main() {
save_courses(&courses, &config_path);
},
Commands::Open(args) => open_command(args, &courses, &config).unwrap(),
-
};
}