2024-01-04 23:28:47 +01:00
|
|
|
use std::{
|
|
|
|
error::Error,
|
|
|
|
fmt::{self, Debug, Display},
|
|
|
|
fs::{File, OpenOptions},
|
|
|
|
io::{Read, Seek, SeekFrom, Write},
|
|
|
|
path::Path,
|
|
|
|
};
|
2024-01-04 16:36:41 +01:00
|
|
|
|
2024-01-04 23:28:47 +01:00
|
|
|
use eframe::egui::{self, Key, TextEdit};
|
|
|
|
|
|
|
|
enum RunError {
|
|
|
|
HomeDir(homedir::GetHomeError),
|
|
|
|
NoHome,
|
|
|
|
OpenFile(std::io::Error),
|
|
|
|
EFrame(eframe::Error),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Debug for RunError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
Display::fmt(self, f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl Display for RunError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
Self::HomeDir(e) => f.write_fmt(format_args!("homedir error: {e}")),
|
|
|
|
Self::NoHome => f.write_fmt(format_args!("failed to find home directory")),
|
|
|
|
Self::OpenFile(e) => f.write_fmt(format_args!("error while opening todo.txt: {e}")),
|
|
|
|
Self::EFrame(e) => f.write_fmt(format_args!("eframe error: {e}")),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl Error for RunError {}
|
|
|
|
|
|
|
|
fn main() -> Result<(), RunError> {
|
2024-01-04 16:36:41 +01:00
|
|
|
std::env::set_var("WINIT_UNIX_BACKEND", "wayland");
|
2024-01-04 23:28:47 +01:00
|
|
|
let home_dir = homedir::get_my_home()
|
|
|
|
.map_err(RunError::HomeDir)?
|
|
|
|
.ok_or(RunError::NoHome)?;
|
|
|
|
let todo_file = OpenOptions::new()
|
|
|
|
.create(true)
|
|
|
|
.read(true)
|
|
|
|
.write(true)
|
|
|
|
.append(false)
|
|
|
|
.open(Path::join(&home_dir, "todo.txt"))
|
|
|
|
.map_err(RunError::OpenFile)?;
|
|
|
|
|
2024-01-04 16:36:41 +01:00
|
|
|
let native_options = eframe::NativeOptions::default();
|
2024-01-04 23:28:47 +01:00
|
|
|
eframe::run_native(
|
|
|
|
"To-DooDoo",
|
2024-01-04 16:36:41 +01:00
|
|
|
native_options,
|
2024-01-04 23:28:47 +01:00
|
|
|
Box::new(|_cc| Box::new(ToDooDooApp::new(todo_file))),
|
|
|
|
)
|
|
|
|
.map_err(RunError::EFrame)?;
|
|
|
|
Ok(())
|
2024-01-04 16:36:41 +01:00
|
|
|
}
|
|
|
|
|
2024-01-04 23:28:47 +01:00
|
|
|
struct ToDooDooApp {
|
|
|
|
notes: String,
|
|
|
|
file: File,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ToDooDooApp {
|
|
|
|
fn new(mut file: File) -> Self {
|
|
|
|
let mut notes = String::with_capacity(
|
|
|
|
file.metadata()
|
|
|
|
.expect("file metadata")
|
|
|
|
.len()
|
|
|
|
.try_into()
|
|
|
|
.expect("file too big"),
|
|
|
|
);
|
|
|
|
file.read_to_string(&mut notes)
|
|
|
|
.expect("failed to read file");
|
|
|
|
Self { file, notes }
|
|
|
|
}
|
2024-01-04 16:36:41 +01:00
|
|
|
|
2024-01-04 23:28:47 +01:00
|
|
|
fn save(&mut self) {
|
|
|
|
self.file.set_len(0).expect("failed to truncate file");
|
|
|
|
self.file.seek(SeekFrom::Start(0)).expect("failed to seek");
|
|
|
|
self.file
|
|
|
|
.write_all(self.notes.as_bytes())
|
|
|
|
.expect("failed to write file");
|
|
|
|
self.file.flush().expect("failed to flush");
|
2024-01-04 16:36:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-04 23:28:47 +01:00
|
|
|
impl eframe::App for ToDooDooApp {
|
2024-01-04 16:36:41 +01:00
|
|
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
|
|
|
egui::CentralPanel::default().show(ctx, |ui| {
|
2024-01-04 23:28:47 +01:00
|
|
|
if ctx.input(|i| i.key_pressed(Key::S) && i.modifiers.command) {
|
|
|
|
self.save();
|
|
|
|
}
|
|
|
|
ui.add_sized(ui.available_size(), TextEdit::multiline(&mut self.notes));
|
2024-01-04 16:36:41 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|