5 Commits

Author SHA1 Message Date
Bel LaPointe
33d318edd4 o that swap wasnt too bd 2024-08-08 13:25:38 -07:00
Bel LaPointe
a5f5013ef6 ew 2024-08-08 13:17:32 -07:00
Bel LaPointe
52977ff0a7 insert reveal i cannot handle no src db 2024-08-08 13:14:26 -07:00
Bel LaPointe
452b692c6a wipper 2024-08-08 12:58:21 -07:00
Bel LaPointe
5c74ec0c15 todo 2024-08-08 12:53:15 -07:00

View File

@@ -20,7 +20,7 @@ fn main() {
Some(sch) => Task::from_string_schedule(s, sch),
None => Task::from_string(s),
};
db.0[0].tasks.0.push(t);
db.tasks_and_metadatas[0].tasks.0.push(t);
},
_ => {},
};
@@ -63,8 +63,11 @@ impl Flags {
}
}
#[derive(Debug)]
pub struct DB(Vec<TasksAndMetadata>);
#[derive(Debug, PartialEq)]
pub struct DB {
tasks_and_metadatas: Vec<TasksAndMetadata>,
cwd: String,
}
impl DB {
pub fn new(path: String) -> Result<DB, String> {
@@ -95,12 +98,22 @@ impl DB {
let item = TasksAndMetadata::new(file)?;
result.push(item);
}
Ok(DB(result))
Ok(DB{
tasks_and_metadatas: result,
cwd: match metadata.is_file() {
true => std::path::Path::new(&path).parent().expect("root?").display().to_string(),
_ => path.clone(),
},
})
}
fn new_empty(cwd: String) -> DB {
DB{tasks_and_metadatas: vec![], cwd: cwd.clone()}
}
pub fn incomplete(&self) -> Tasks {
let mut result = Tasks::new();
for set in &self.0 {
for set in &self.tasks_and_metadatas {
result.0.extend(set.tasks.incomplete().0);
}
result
@@ -108,34 +121,39 @@ impl DB {
pub fn due(&self) -> Tasks {
let mut result = Tasks::new();
for set in &self.0 {
for set in &self.tasks_and_metadatas {
result.0.extend(set.tasks.due().0);
}
result
}
pub fn edit(&self) -> Result<DB, String> {
let d = TempDir::new(&TS::now().to_string()).expect("failed to create a temp dir");
for set in &self.0 {
let base = set.file.split("/").last().unwrap().to_string();
let f = d.path().join(base);
set.save_due_as(f.display().to_string())?;
}
loop {
self._edit(|cwd: &String| {
std::process::Command::new("/bin/sh")
.current_dir(d.path())
.current_dir(cwd)
.arg("-c")
.arg("vim -p ./*")
.spawn()
.expect("failed to start vim")
.wait()
.expect("failed to vim");
})
}
fn _edit(&self, edit: impl Fn(&String)) -> Result<DB, String> {
let d = TempDir::new(&TS::now().to_string()).expect("failed to create a temp dir");
for set in &self.tasks_and_metadatas {
let base = set.file.split("/").last().unwrap().to_string();
let f = d.path().join(base);
set.save_due_as(f.display().to_string())?;
}
loop {
let cwd = d.path().display().to_string();
edit(&cwd);
let mut ok = true;
for set in &self.0 {
let base = set.file.split("/").last().unwrap().to_string();
let f = d.path().join(base);
ok = ok && TasksAndMetadata::new(f.display().to_string()).is_ok();
for f in std::fs::read_dir(&cwd).expect("failed to list edited files") {
ok = ok && TasksAndMetadata::new(f.expect("failed to list edited file").path().display().to_string()).is_ok();
}
if ok {
break;
@@ -143,9 +161,23 @@ impl DB {
}
let mut result = vec![];
for set in &self.0 {
let base = set.file.split("/").last().unwrap().to_string();
let f = d.path().join(base);
for f in std::fs::read_dir(d.path()).expect("failed to list edited files") {
let f = f.expect("failed to list edited file").path();
let base = f.display().to_string().split("/").last().unwrap().to_string();
let set = match self.tasks_and_metadatas
.iter()
.filter(|tasks_and_metadata| tasks_and_metadata.file.ends_with(format!("/{}", base).as_str()))
.nth(0) {
Some(set) => set.clone(),
None => TasksAndMetadata::new_with(
format!("{}/{}",
self.cwd,
base,
),
TS::now(),
Tasks::new(),
),
};
let edited = TasksAndMetadata::new(f.display().to_string()).expect("failed to read edited tasks");
@@ -196,11 +228,11 @@ impl DB {
));
}
Ok(DB{0: result})
Ok(DB{tasks_and_metadatas: result, cwd: self.cwd.clone()})
}
pub fn save(&self, dry_run: bool) -> Result<(), String> {
for i in &self.0 {
for i in &self.tasks_and_metadatas {
i.save(dry_run)?;
}
Ok(())
@@ -208,13 +240,58 @@ impl DB {
}
#[cfg(test)]
mod test_taskss {
mod test_db {
use super::*;
#[test]
fn edit_insert_empty() {
let db = new_test_db(0, 0);
let db_after = db._edit(|cwd| {
assert_eq!(0, std::fs::read_dir(cwd).expect("failed to ls cwd").collect::<Vec<_>>().len());
assert_ne!("", cwd);
let mut f = std::fs::File::create(format!("{}/f", cwd)).expect("failed to open a file in cwd");
f.write_all(b"f").expect("failed to write a file in cwd");
let mut g = std::fs::File::create(format!("{}/g", cwd)).expect("failed to open a file in cwd");
g.write_all(b"- g: h\n- j: k").expect("failed to write a file in cwd");
}).expect("failed to not edit");
assert_ne!(db, db_after);
assert_eq!(2, db_after.tasks_and_metadatas.len());
assert_eq!(1, db_after.tasks_and_metadatas[1].tasks.len());
assert_eq!(2, db_after.tasks_and_metadatas[0].tasks.len());
}
#[test]
fn edit_noop_empty() {
let db = new_test_db(0, 0);
let db_after = db._edit(|_| {}).expect("failed to not edit");
assert_eq!(0, db.tasks_and_metadatas.len());
assert_eq!(db, db_after);
}
fn new_test_db(files: i32, tasks_per_file: i32) -> DB {
let mut db = DB::new_empty("".to_string());
for i in 0..files {
let mut tasks = Tasks::new();
for j in 0..tasks_per_file {
tasks.0.push(Task::from_string(format!("{{\"hello\": \"world[{}]\"}}", j)));
}
db.tasks_and_metadatas.push(TasksAndMetadata::new_with(
format!("{}.yaml", i),
TS::now(),
tasks,
));
}
db
}
#[test]
fn read_dir_files() {
let db = DB::new("./src/testdata/taskss.d/files.d".to_string()).expect("failed to construct from dir of files");
assert_eq!(2, db.0.len());
assert_eq!(2, db.tasks_and_metadatas.len());
assert_eq!(2, db.due().len());
assert_eq!(2, db.incomplete().len());
}
@@ -222,7 +299,7 @@ mod test_taskss {
#[test]
fn read_dir_file() {
let db = DB::new("./src/testdata/taskss.d/file.d".to_string()).expect("failed to construct from dir of a single file");
assert_eq!(1, db.0.len());
assert_eq!(1, db.tasks_and_metadatas.len());
assert_eq!(1, db.due().len());
assert_eq!(1, db.incomplete().len());
}
@@ -230,13 +307,13 @@ mod test_taskss {
#[test]
fn read_single_file() {
let db = DB::new("./src/testdata/taskss.d/single_file.yaml".to_string()).expect("failed to construct from single file");
assert_eq!(1, db.0.len());
assert_eq!(1, db.tasks_and_metadatas.len());
assert_eq!(1, db.due().len());
assert_eq!(2, db.incomplete().len());
}
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub struct TasksAndMetadata {
tasks: Tasks,
file: String,
@@ -329,7 +406,7 @@ fn file_version(file: String) -> Result<TS, String> {
}
}
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone)]
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
pub struct Tasks(Vec<Task>);
impl Tasks {