about summary refs log tree commit diff
path: root/converge/src
diff options
context:
space:
mode:
authorgennyble <gen@nyble.dev>2024-12-18 00:27:34 -0600
committergennyble <gen@nyble.dev>2024-12-18 00:27:34 -0600
commit5ea6a13ead2a5cab0f578c8af5f0e0be88c3a08c (patch)
treef8ab97a0abeb03142da4c7a8ed859d6a408cd16a /converge/src
parentf6b441fe53dd75af5933c4456d92070ccb7bd8af (diff)
downloadcutie-main.tar.gz
cutie-main.zip
Ahhhhh HEAD main
Diffstat (limited to 'converge/src')
-rwxr-xr-x[-rw-r--r--]converge/src/main.rs39
-rwxr-xr-xconverge/src/timedb.rs97
2 files changed, 115 insertions, 21 deletions
diff --git a/converge/src/main.rs b/converge/src/main.rs
index 20f2683..74abe67 100644..100755
--- a/converge/src/main.rs
+++ b/converge/src/main.rs
@@ -1,32 +1,30 @@
 use std::str::FromStr;
 
 use camino::Utf8PathBuf;
+use scurvy::Argument;
 
 fn main() {
-	let mut args = std::env::args().skip(1);
-	let argc = args.len();
-	if argc == 0 {
-		eprintln!("usage: converge <content file> [supporting files ...]");
-		return;
+	let arguments = [
+		Argument::arg("timdb", "path").help("time database generated with whenwasit"),
+		Argument::arg("part", "path").help("part converge is supposed to build"),
+	];
+	let cli = scurvy::parse(&arguments);
+
+	let content: Utf8PathBuf = cli.parse_opt_or_die("part");
+	let supporting: Vec<Utf8PathBuf> = cli.free_opts().into_iter().map(Utf8PathBuf::from).collect();
+
+	let time = std::time::Instant::now();
+	for idx in 0..100 {
+		let supporting = supporting.clone();
+		let html = process(content.clone(), supporting);
 	}
+	println!("{}ms for 100", time.elapsed().as_millis());
 
-	let content = match args.next() {
-		None => {
-			eprintln!("usage: converge <content file> [supporting files ...]");
-			return;
-		}
-		Some(path) => Utf8PathBuf::from(path),
-	};
-
-	let supporting = args.map(Utf8PathBuf::from).collect();
-
-	let html = process(content, supporting);
-	println!("{html}")
+	//println!("{html}")
 }
 
 fn process(content_file: Utf8PathBuf, mut supporting: Vec<Utf8PathBuf>) -> cutie::Html {
-	println!("{content_file}");
-	let raw = std::fs::read_to_string(&content_file).unwrap();
+	let raw = std::fs::read_to_string(content_file).unwrap();
 
 	match Part::from_str(&raw) {
 		Err(PartError::NoSetup) => cutie::Html::parse(raw),
@@ -73,7 +71,7 @@ fn process(content_file: Utf8PathBuf, mut supporting: Vec<Utf8PathBuf>) -> cutie
 					html: &'a mut cutie::Html,
 					ident: &str,
 				) -> &'a mut cutie::Tag {
-					match html.get_parent_that_contains_tag_name_mut(&ident) {
+					match html.get_parent_that_contains_tag_name_mut(ident) {
 						None => {
 							eprintln!("error processing file");
 							eprintln!("failed to find element with tag {ident}");
@@ -93,7 +91,6 @@ fn process(content_file: Utf8PathBuf, mut supporting: Vec<Utf8PathBuf>) -> cutie
 						tag.children.extend(content_html.nodes);
 					}
 					Opcode::Before => {
-						println!("BEFORE");
 						let predicate = |node: &cutie::Node| -> bool {
 							if let cutie::Node::Tag(tag) = node {
 								if tag.name == ident {
diff --git a/converge/src/timedb.rs b/converge/src/timedb.rs
new file mode 100755
index 0000000..718115d
--- /dev/null
+++ b/converge/src/timedb.rs
@@ -0,0 +1,97 @@
+use std::path::Path;
+
+use time::OffsetDateTime;
+
+#[derive(Debug)]
+pub struct TimeDb {
+	data: Vec<TimedFile>,
+}
+
+impl TimeDb {
+	pub fn load<P: AsRef<Path>>(path: P) -> Self {
+		let file = std::fs::read_to_string(path).unwrap();
+
+		let mut data = vec![];
+		for line in file.lines() {
+			let it = TimedFile::parse_line(line);
+			data.push(it);
+		}
+
+		Self { data }
+	}
+
+	pub fn get_times(&self, path: &str) -> Option<&TimedFile> {
+		for file in &self.data {
+			if &file.path == path {
+				return Some(file);
+			}
+		}
+
+		None
+	}
+}
+
+#[derive(Debug)]
+pub struct TimedFile {
+	path: String,
+	pub creation: Option<OffsetDateTime>,
+	pub modification: Option<OffsetDateTime>,
+	pub access: Option<OffsetDateTime>,
+}
+
+impl TimedFile {
+	pub fn parse_line<S: AsRef<str>>(raw: S) -> Self {
+		let mut values = raw.as_ref().rsplitn(4, ",").collect::<Vec<&str>>();
+		values.reverse();
+
+		let to_odt = |str: &&str| -> Option<OffsetDateTime> {
+			str.parse::<u64>()
+				.ok()
+				.map(|t| OffsetDateTime::from_unix_timestamp(t as i64).unwrap())
+		};
+
+		let path = unescape(values[0]);
+		let creation = values.get(1).map(to_odt).flatten();
+		let modification = values.get(2).map(to_odt).flatten();
+		let access = values.get(3).map(to_odt).flatten();
+
+		Self {
+			path,
+			creation,
+			modification,
+			access,
+		}
+	}
+}
+
+// Permissive unescape. Everything that's not \\ or \, is passed
+// unchanged, while those get their slash removed
+fn unescape<S: AsRef<str>>(raw: S) -> String {
+	let raw = raw.as_ref();
+
+	if !raw.contains('\\') {
+		return raw.to_owned();
+	}
+
+	let mut unescape = String::with_capacity(raw.len());
+	let mut escaped = false;
+	for ch in raw.chars() {
+		match (escaped, ch) {
+			(false, '\\') => {
+				escaped = true;
+			}
+			(false, c) => unescape.push(c),
+			(true, '\\') | (true, ',') => {
+				unescape.push(ch);
+				escaped = false;
+			}
+			(true, c) => {
+				unescape.push('\\');
+				unescape.push(c);
+				escaped = false;
+			}
+		}
+	}
+
+	unescape
+}