aboutsummaryrefslogtreecommitdiffstats
path: root/src/local/import.rs
diff options
context:
space:
mode:
authorEllie Huxtable <e@elm.sh>2021-02-13 19:37:00 +0000
committerEllie Huxtable <e@elm.sh>2021-02-13 19:37:31 +0000
commit099afe66ecfb569a8a04b66425ded29665e6a37c (patch)
tree7bb1baadb9304fa0d4f353d0849f962e2af209e3 /src/local/import.rs
parentRecord command exit code and duration (diff)
downloadatuin-099afe66ecfb569a8a04b66425ded29665e6a37c.zip
Implement history import
Diffstat (limited to 'src/local/import.rs')
-rw-r--r--src/local/import.rs101
1 files changed, 86 insertions, 15 deletions
diff --git a/src/local/import.rs b/src/local/import.rs
index 8db8f0e3..ce141c52 100644
--- a/src/local/import.rs
+++ b/src/local/import.rs
@@ -4,38 +4,109 @@
use std::fs::File;
use std::io::{BufRead, BufReader};
-use eyre::Result;
+use chrono::{TimeZone, Utc};
+use eyre::{eyre, Result};
-use crate::models::history::History;
+use crate::local::history::History;
-pub struct ImportBash {
+#[derive(Debug)]
+pub struct ImportZsh {
file: BufReader<File>,
+
+ pub loc: u64,
}
-impl ImportBash {
- pub fn new(path: &str) -> Result<ImportBash> {
+// this could probably be sped up
+fn count_lines(path: &str) -> Result<usize> {
+ let file = File::open(path)?;
+ let buf = BufReader::new(file);
+
+ Ok(buf.lines().count())
+}
+
+impl ImportZsh {
+ pub fn new(path: &str) -> Result<ImportZsh> {
+ let loc = count_lines(path)?;
+
let file = File::open(path)?;
let buf = BufReader::new(file);
- Ok(ImportBash { file: buf })
+ Ok(ImportZsh {
+ file: buf,
+ loc: loc as u64,
+ })
}
}
-impl Iterator for ImportBash {
- type Item = History;
+fn trim_newline(s: &str) -> String {
+ let mut s = String::from(s);
+
+ if s.ends_with('\n') {
+ s.pop();
+ if s.ends_with('\r') {
+ s.pop();
+ }
+ }
+
+ s
+}
- fn next(&mut self) -> Option<History> {
+fn parse_extended(line: String) -> History {
+ let line = line.replacen(": ", "", 2);
+ let mut split = line.splitn(2, ":");
+
+ let time = split.next().unwrap_or("-1");
+ let time = time
+ .parse::<i64>()
+ .unwrap_or(chrono::Utc::now().timestamp_nanos());
+
+ let duration = split.next().unwrap(); // might be 0;the command
+ let mut split = duration.split(";");
+
+ let duration = split.next().unwrap_or("-1"); // should just be the 0
+ let duration = duration.parse::<i64>().unwrap_or(-1);
+
+ let command = split.next().unwrap();
+
+ // use nanos, because why the hell not? we won't display them.
+ History::new(
+ Utc.timestamp(time, 0).timestamp_nanos(),
+ trim_newline(command),
+ String::from("unknown"),
+ -1,
+ duration * 1_000_000_000,
+ )
+}
+
+impl Iterator for ImportZsh {
+ type Item = Result<History>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ // ZSH extended history records the timestamp + command duration
+ // These lines begin with :
+ // So, if the line begins with :, parse it. Otherwise it's just
+ // the command
let mut line = String::new();
match self.file.read_line(&mut line) {
Ok(0) => None,
- Err(_) => None,
+ Err(e) => Some(Err(eyre!("failed to parse line: {}", e))),
+
+ Ok(_) => {
+ let extended = line.starts_with(":");
- Ok(_) => Some(History {
- cwd: "none".to_string(),
- command: line,
- timestamp: -1,
- }),
+ if extended {
+ Some(Ok(parse_extended(line)))
+ } else {
+ Some(Ok(History::new(
+ chrono::Utc::now().timestamp_nanos(), // what else? :/
+ trim_newline(line.as_str()),
+ String::from("unknown"),
+ -1,
+ -1,
+ )))
+ }
+ }
}
}
}