use super::{AS, BODY, NOTE, TITLE};
const PRIORITY: &str = "-p";
const NO_PRIORITY: &str = "--no-priority";
const TAG: &str = "-t";
const NO_TAG: &str = "--no-tag";
const PARENT: &str = "--parent";
const NO_PARENT: &str = "--no-parent";
const NEEDS: &str = "--needs";
const NO_NEEDS: &str = "--no-needs";
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Field {
Priority(Option<i64>),
Tag { tag: String, on: bool },
Parent(Option<String>),
Needs { edge: String, on: bool },
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Create {
pub title: String,
pub body: Option<String>,
pub fields: Vec<Field>,
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Update {
pub title: Option<String>,
pub body: Option<String>,
pub note: Option<String>,
pub fields: Vec<Field>,
}
impl Field {
pub(crate) fn argv(&self, creating: bool) -> Vec<String> {
match self {
Self::Priority(Some(n)) => set(PRIORITY, &n.to_string()),
Self::Priority(None) => clear(NO_PRIORITY, creating),
Self::Parent(Some(id)) => set(PARENT, id),
Self::Parent(None) => clear(NO_PARENT, creating),
Self::Tag { tag, on } => pair(TAG, NO_TAG, tag, *on, creating),
Self::Needs { edge, on } => pair(NEEDS, NO_NEEDS, edge, *on, creating),
}
}
}
impl Create {
pub(crate) fn argv(&self, name: &str) -> Vec<String> {
let mut args = vec![self.title.clone(), AS.to_owned(), name.to_owned()];
push_opt(&mut args, BODY, self.body.as_ref());
push_fields(&mut args, &self.fields, true);
args
}
}
impl Update {
pub(crate) fn argv(&self, name: &str) -> Vec<String> {
let mut args = vec![AS.to_owned(), name.to_owned()];
for (flag, value) in [
(TITLE, self.title.as_ref()),
(BODY, self.body.as_ref()),
(NOTE, self.note.as_ref()),
] {
push_opt(&mut args, flag, value);
}
push_fields(&mut args, &self.fields, false);
args
}
}
fn push_opt(args: &mut Vec<String>, flag: &str, value: Option<&String>) {
if let Some(text) = value {
args.push(flag.to_owned());
args.push(text.clone());
}
}
fn push_fields(args: &mut Vec<String>, fields: &[Field], creating: bool) {
args.extend(fields.iter().flat_map(|field| field.argv(creating)));
}
fn set(flag: &str, value: &str) -> Vec<String> {
vec![flag.to_owned(), value.to_owned()]
}
fn clear(flag: &str, creating: bool) -> Vec<String> {
if creating {
Vec::new()
} else {
vec![flag.to_owned()]
}
}
fn pair(on_flag: &str, off_flag: &str, value: &str, on: bool, creating: bool) -> Vec<String> {
match (on, creating) {
(true, _) => set(on_flag, value),
(false, true) => Vec::new(),
(false, false) => set(off_flag, value),
}
}