use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
pub const TERMINAL_CREATE_V1: &str = "terminal.create@1";
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TerminalCreateParams {
pub command: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub args: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cwd: Option<String>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub env: BTreeMap<String, String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub placement: Option<TerminalPlacement>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reuse_key: Option<String>,
}
impl TerminalCreateParams {
pub fn new(command: impl Into<String>) -> Self {
Self {
command: command.into(),
args: Vec::new(),
cwd: None,
env: BTreeMap::new(),
title: None,
placement: None,
reuse_key: None,
}
}
pub fn with_args(mut self, args: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.args = args.into_iter().map(Into::into).collect();
self
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TerminalPlacement {
Default,
SidePane,
BottomPane,
NewTab,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TerminalCreateResult {
pub terminal_id: String,
pub backend: String,
pub actual_placement: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub warnings: Vec<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn terminal_create_params_round_trip() {
let params = TerminalCreateParams {
command: "bookokrat".to_string(),
args: vec!["/tmp/book.epub".to_string()],
cwd: Some("/workspace".to_string()),
env: BTreeMap::from([("BOOKOKRAT_THEME".to_string(), "dark".to_string())]),
title: Some("Reader".to_string()),
placement: Some(TerminalPlacement::SidePane),
reuse_key: Some("reader".to_string()),
};
let json = serde_json::to_value(¶ms).unwrap();
assert_eq!(json["command"], "bookokrat");
assert_eq!(json["placement"], "side_pane");
let parsed: TerminalCreateParams = serde_json::from_value(json).unwrap();
assert_eq!(parsed, params);
}
#[test]
fn terminal_create_result_round_trip() {
let result = TerminalCreateResult {
terminal_id: "term_123".to_string(),
backend: "zellij".to_string(),
actual_placement: "background_session".to_string(),
warnings: vec!["placement degraded".to_string()],
};
let json = serde_json::to_value(&result).unwrap();
let parsed: TerminalCreateResult = serde_json::from_value(json).unwrap();
assert_eq!(parsed, result);
}
}