use serde::{Deserialize, Serialize};
use tatara_lisp::DeriveTataraDomain;
#[derive(DeriveTataraDomain, Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
#[serde(rename_all = "camelCase")]
#[tatara(keyword = "deftask")]
pub struct TaskSpec {
pub name: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub command: String,
#[serde(default)]
pub args: Vec<String>,
#[serde(default)]
pub cwd: String,
#[serde(default)]
pub env: Vec<String>,
#[serde(default)]
pub filetype: String,
#[serde(default)]
pub keybind: String,
#[serde(default)]
pub background: bool,
#[serde(default)]
pub timeout_ms: u64,
}
impl TaskSpec {
#[must_use]
pub fn env_pairs(&self) -> Vec<(String, String)> {
self.env
.iter()
.filter_map(|s| s.split_once('=').map(|(k, v)| (k.to_string(), v.to_string())))
.collect()
}
#[must_use]
pub fn display_command(&self) -> String {
if self.args.is_empty() {
self.command.clone()
} else {
format!("{} {}", self.command, self.args.join(" "))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn env_pairs_splits_on_equals() {
let t = TaskSpec {
name: "x".into(),
command: "ls".into(),
env: vec![
"RUST_LOG=warn".into(),
"CARGO_TERM_COLOR=always".into(),
"NO_EQ".into(), ],
..Default::default()
};
assert_eq!(t.env_pairs().len(), 2);
}
#[test]
fn display_command_handles_empty_args() {
let t = TaskSpec {
name: "x".into(),
command: "ls".into(),
..Default::default()
};
assert_eq!(t.display_command(), "ls");
let t = TaskSpec {
name: "x".into(),
command: "cargo".into(),
args: vec!["test".into(), "--workspace".into()],
..Default::default()
};
assert_eq!(t.display_command(), "cargo test --workspace");
}
}