summaryrefslogtreecommitdiff
path: root/src/inquire.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/inquire.rs')
-rw-r--r--src/inquire.rs103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/inquire.rs b/src/inquire.rs
new file mode 100644
index 0000000..6dd2e3c
--- /dev/null
+++ b/src/inquire.rs
@@ -0,0 +1,103 @@
+use std::fmt::Display;
+
+use chrono::Local;
+use git2::{Signature, Time};
+
+use crate::Autosave;
+
+pub struct AutosaveFilters<'a> {
+ pub signature: &'a Signature<'a>,
+ pub branch: &'a str,
+ pub earliest_time: Time,
+ pub repo_id: &'a str,
+ pub all_users: bool,
+ pub all_branches: bool,
+ pub anytime: bool,
+ pub all_devices: bool,
+}
+
+struct AutosaveOption {
+ text: String,
+ value: Autosave,
+}
+
+impl Display for AutosaveOption {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.text.fmt(f)
+ }
+}
+
+pub fn filter_autosaves(
+ autosaves: impl IntoIterator<Item = Autosave>,
+ filters: AutosaveFilters<'_>,
+) -> impl Iterator<Item = Autosave> {
+ let AutosaveFilters {
+ all_users,
+ signature,
+ all_branches,
+ branch,
+ anytime,
+ earliest_time,
+ all_devices,
+ repo_id,
+ } = filters;
+ autosaves
+ .into_iter()
+ .filter(move |autosave| {
+ all_users
+ || signature
+ .name()
+ .zip(autosave.author.clone())
+ .is_some_and(|(a, b)| a == b)
+ || signature
+ .email()
+ .zip(autosave.email.clone())
+ .is_some_and(|(a, b)| a == b)
+ })
+ .filter(move |autosave| all_branches || autosave.branch_name == branch)
+ .filter(move |autosave| anytime || autosave.time > earliest_time)
+ .filter(move |autosave| all_devices || autosave.repo_id.as_bytes() != repo_id.as_bytes())
+}
+
+pub fn select_autosave(
+ mut autosaves: Vec<Autosave>,
+ all_branches: bool,
+ all_users: bool,
+) -> Result<Autosave, inquire::InquireError> {
+ if autosaves.len() > 1 {
+ let autosaves = autosaves
+ .into_iter()
+ .map(|autosave| {
+ let device = autosave.host_name.as_ref().unwrap_or(&autosave.repo_id);
+ let time = chrono::DateTime::from_timestamp(autosave.time.seconds(), 0)
+ .map(|time| time.with_timezone(&Local))
+ .map(|time| time.to_rfc2822())
+ .unwrap_or(autosave.time.seconds().to_string());
+ let branch = if all_branches {
+ format!(" on {}", &autosave.branch_name)
+ } else {
+ String::new()
+ };
+ let author = if let Some(author) =
+ autosave.author.as_ref().or(autosave.email.as_ref())
+ && all_users
+ {
+ format!(" by {author}")
+ } else {
+ String::new()
+ };
+ AutosaveOption {
+ text: format!("{device} ({time}{branch}{author})"),
+ value: autosave,
+ }
+ })
+ .collect();
+ Ok(inquire::Select::new("Select an autosave:", autosaves)
+ .prompt()?
+ .value)
+ } else {
+ Ok(autosaves
+ .pop()
+ .expect("There should be an autosave to select but there isn't. This is a bug!"))
+ }
+}